我有一个小技巧,我必须用蛮力获取密码。程序中有函数usleep();当我有正确的长度并且当一个字母正确时它正在改变。这不是问题,但是睡眠时间大约是一分钟,这是相当长的时间。有没有办法让睡眠定时器更快?
ELF 64 位 LSB 可执行文件,x86-64,版本 1 (SYSV),动态链接(使用共享库)
我有一个小技巧,我必须用蛮力获取密码。程序中有函数usleep();当我有正确的长度并且当一个字母正确时它正在改变。这不是问题,但是睡眠时间大约是一分钟,这是相当长的时间。有没有办法让睡眠定时器更快?
ELF 64 位 LSB 可执行文件,x86-64,版本 1 (SYSV),动态链接(使用共享库)
LD_PRELOAD
您可以使用指令覆盖库函数。
假设您有以下程序代码,然后将其编译为二进制 elf 文件。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /* for usleep() */
int main(int argc, char* argv[]) {
printf("Entry point. We'll now wait 10 seconds.\n");
system("date +\"%H:%M:%S\""); //Output time
usleep(10*1000*1000);
printf("Woke up again.\n");
system("date +\"%H:%M:%S\""); //Output time
return 0;
}
正常运行它会给你
root@kali:~/so# gcc -o prog prog.c
root@kali:~/so# ./prog
Entry point. We'll now wait 10 seconds.
20:31:10
Woke up again.
20:31:20
现在编写您自己的usleep()
.
#include <unistd.h>
#include <stdio.h>
int usleep(useconds_t usec){
printf("Nope, you're not sleeping today :)\n");
return 0;
}
将其编译为共享库。
root@kali:~/so# gcc -Wall -fPIC -shared -o usleep_override.so usleep_override.c
现在在执行原始程序之前预加载该库函数。
root@kali:~/so# LD_PRELOAD=./usleep_override.so ./prog
Entry point. We'll now wait 10 seconds.
20:35:28
Nope, you're not sleeping today :)
Woke up again.
20:35:28
正如您在查看date
输出时看到的那样,它执行了挂钩函数而不是原始函数,然后立即返回。
修改二进制。特别是修改指令,使usleep()
函数不被执行。
当我们转储 with 函数的指令时,main()
我们得到:prog
objdump
root@kali:~/so# objdump -d -Mintel prog | grep -A20 "<main>"
0000000000400596 <main>:
400596: 55 push rbp
400597: 48 89 e5 mov rbp,rsp
40059a: 48 83 ec 10 sub rsp,0x10
40059e: 89 7d fc mov DWORD PTR [rbp-0x4],edi
4005a1: 48 89 75 f0 mov QWORD PTR [rbp-0x10],rsi
4005a5: bf 68 06 40 00 mov edi,0x400668
4005aa: e8 a1 fe ff ff call 400450 <puts@plt>
4005af: bf 90 06 40 00 mov edi,0x400690
4005b4: e8 a7 fe ff ff call 400460 <system@plt>
4005b9: bf 80 96 98 00 mov edi,0x989680
4005be: e8 cd fe ff ff call 400490 <usleep@plt>
4005c3: bf a2 06 40 00 mov edi,0x4006a2
4005c8: e8 83 fe ff ff call 400450 <puts@plt>
4005cd: bf 90 06 40 00 mov edi,0x400690
4005d2: e8 89 fe ff ff call 400460 <system@plt>
4005d7: b8 00 00 00 00 mov eax,0x0
4005dc: c9 leave
4005dd: c3 ret
4005de: 66 90 xchg ax,ax
我们可以看到负责usleep(10*1000*1000)
调用的违规行:
4005b9: bf 80 96 98 00 mov edi,0x989680
4005be: e8 cd fe ff ff call 400490 <usleep@plt>
由于0x989680
十进制等于 10000000,我们可以推断这是usleep()
函数的参数。所以,我们可以只修改二进制文件(搜索字节序列bf 80 96 98 00 e8 cd fe ff ff
),然后把它放在0x90
那里寻找一条NOP
指令,它什么都不做。
当我们现在转储指令时:
root@kali:~/so# objdump -d -Mintel prog_cracked | grep -A28 "<main>"
0000000000400596 <main>:
400596: 55 push rbp
400597: 48 89 e5 mov rbp,rsp
40059a: 48 83 ec 10 sub rsp,0x10
40059e: 89 7d fc mov DWORD PTR [rbp-0x4],edi
4005a1: 48 89 75 f0 mov QWORD PTR [rbp-0x10],rsi
4005a5: bf 68 06 40 00 mov edi,0x400668
4005aa: e8 a1 fe ff ff call 400450 <puts@plt>
4005af: bf 90 06 40 00 mov edi,0x400690
4005b4: e8 a7 fe ff ff call 400460 <system@plt>
4005b9: 90 nop
4005ba: 90 nop
4005bb: 90 nop
4005bc: 90 nop
4005bd: 90 nop
4005be: 90 nop
4005bf: 90 nop
4005c0: 90 nop
4005c1: 90 nop
4005c2: 90 nop
4005c3: bf a2 06 40 00 mov edi,0x4006a2
4005c8: e8 83 fe ff ff call 400450 <puts@plt>
4005cd: bf 90 06 40 00 mov edi,0x400690
4005d2: e8 89 fe ff ff call 400460 <system@plt>
4005d7: b8 00 00 00 00 mov eax,0x0
4005dc: c9 leave
4005dd: c3 ret
4005de: 66 90 xchg ax,ax
太好了,电话没了。运行,我们得到:
root@kali:~/so# chmod +x prog_cracked
root@kali:~/so# ./prog_cracked
Entry point. We'll now wait 10 seconds.
21:11:18
Woke up again.
21:11:18
因此,程序再次被“破解”。