(gdb) disas main
Dump of assembler code for function main:
0x080483f2 <main+0>: push %ebp
0x080483f3 <main+1>: mov %esp,%ebp
0x080483f5 <main+3>: call 0x80483d4 <return_input>
0x080483fa <main+8>: mov $0x0,%eax
0x080483ff <main+13>: pop %ebp
0x08048400 <main+14>: ret
End of assembler dump.
[root@centos shellcode]# printf "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD\xf5\x83\x04\x08" | ./stack
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD▒
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD▒
#include <stdio.h> #include <stdlib.h> int return_input (void) { printf ("Please input your serial code: "); char array[30]; int ok = 0; gets (array); if (array[0] == 'b' && array[1] == 'e' && array[2] == 'y' && array[3] == 'e' && array[4] == 's') ok = 1; return (ok); } int register_ok (void) { printf ("register ok! "); exit (EXIT_SUCCESS); } int register_invalid(void) { printf ("register failed! "); exit (EXIT_FAILURE); } int main() { if (return_input()) register_ok(); else register_invalid(); return (0); }
[root@centos shellcode]# gcc -mpreferred-stack-boundary=2 -g stack2.c -o stack2
/tmp/ccO3INgh.o: In function `return_input':
/root/shellcode/stack2.c:9: warning: the `gets' function is dangerous and should not be used.
[root@centos shellcode]# ./stack2
Please input your serial code:
dfadsfa
register failed!
[root@centos shellcode]# ./stack2
Please input your serial code:
beyes
register ok!
(gdb) disas main
Dump of assembler code for function main:
0x08048498 <main+0>: push %ebp
0x08048499 <main+1>: mov %esp,%ebp
0x0804849b <main+3>: call 0x8048404 <return_input>
0x080484a0 <main+8>: test %eax,%eax
0x080484a2 <main+10>: je 0x80484ab <main+19>
0x080484a4 <main+12>: call 0x804845c <register_ok>
0x080484a9 <main+17>: jmp 0x80484b0 <main+24>
0x080484ab <main+19>: call 0x804847a <register_invalid>
0x080484b0 <main+24>: mov $0x0,%eax
0x080484b5 <main+29>: pop %ebp
0x080484b6 <main+30>: ret
End of assembler dump.
上面,地址 0x080484a4 处调用了 register_ok 函数表明注册成功。这里,我们可以通过缓冲区溢出,修改 return_input() 的返回地址,使之直接跳转到此,从而达到成功注册的目的。如下面构造的输入: |
[root@centos shellcode]# printf "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDD\xa4\x84\x04\x08" ./stack2 Please input your serial code: register ok!
可见,成功注册了。 |
[/table] |
[table=100%,#f9f7ed]这里需要再提及一点,如果主程序中不是调用注册成功函数(register_ok),而是直接打印出成功或失败信息。那么这样修改缓冲区,虽然会看到注册成功的信息(register ok!),但是也还会看到段错误。原因是,当我们输入超长字符串时,也覆盖了 EBP,这个 EBP 在返回时是在 main() 中仍会用来动态的寻找 main 栈中的数据 。如在 printf() 函数执行时,里面的字符串参数地址就是通过 EBP 来寻得。 |
欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) | Powered by Discuz! X3.2 |