Rwctf 2020 Baby Escape
r -L ./dependency -kernel ./vmlinuz-5.4.0-58-generic -initrd ./rootfs.cpio -cpu kvm64,+smep -m 64M -monitor none -device fun -append "root=/dev/ram rw console=ttyS0 oops=panic panic=1 quiet kaslr" -nographic
struct FunState{ |
fun_mmio_read和fun_mmio_write
进入函数以后有一波相同的操作,根据size来计算一个rax进行跳转
根据size的值, 4位一组进行操作
mov rax, [rbp+addr] ;size = 10/9/8, rax = 8, size = 7/6/5/4, rax = 4, size=3/2/1/0, rax = 0, 盲猜一个size=12/13/14/15, rax=12 |
pwndbg> x/30gx 0x56401a18706c
0x56401a18706c: 0xffa8cd2effa8ccb0 0xffa8cd2effa8cd2e
0x56401a18707c: 0xffa8cd2effa8ccc2 0xffa8cd2effa8cd2e
0x56401a18708c: 0xffa8cd2effa8ccd4 0xffa8cd2effa8cd2e
0x56401a18709c: 0xffa8cd2effa8cce6 0xffa8cd2effa8cd2e
0x56401a1870ac: 0xffa8cd46ffa8ccf8 0xffa8ce38ffa8ce38
0x56401a1870bc: 0xffa8cd58ffa8ce38 0xffa8ce38ffa8ce38
0x56401a1870cc: 0xffa8cd6affa8ce38 0xffa8ce38ffa8ce38
0x56401a1870dc: 0xffa8cd7cffa8ce38 0xffa8ce38ffa8ce38
0x56401a1870ec: 0xffa8cd8effa8ce38 0xffa8ce38ffa8ce38
0x56401a1870fc: 0xffa8cdc8ffa8ce38 0xffa8ce38ffa8ce38
0x56401a18710c: 0xffa8cdf6ffa8ce38 0x696d2f77682f2e2e
0x56401a18711c: 0x632e6e75662f6373 0x6e7566006e756600
0x56401a18712c: 0x0000006f696d6d2d 0x0000000000000000
0x56401a18713c: 0x5f69637000000000 0x6c6165725f6e7566
0xb0 + 0x6c = 0x11c
0xc2 + 0x6c = 0x12e
0xd4 + 0x6c = 0x140
0xe6 + 0x6c = 0x152
0xf8 + 0x6c = 0x164
- get size: 0x4d1d1c 0
- get addr: 0x4d1d2e 4
- getraddr: 0x4d1d40 8
- get idx : 0x4d1d52 12
- write : 0x4d1d64 16
- return : 0x4d1d9a 20
再看fun_mmio_write, const=0x55d9ef87c0b0
0x55d9ef87c0b0: 0xffa8ce38ffa8cd46 0xffa8ce38ffa8ce38
0x55d9ef87c0c0: 0xffa8ce38ffa8cd58 0xffa8ce38ffa8ce38
0x55d9ef87c0d0: 0xffa8ce38ffa8cd6a 0xffa8ce38ffa8ce38
0x55d9ef87c0e0: 0xffa8ce38ffa8cd7c 0xffa8ce38ffa8ce38
0x55d9ef87c0f0: 0xffa8ce38ffa8cd8e 0xffa8ce38ffa8ce38
0x55d9ef87c100: 0xffa8ce38ffa8cdc8 0xffa8ce38ffa8ce38
0x55d9ef87c110: 0x682f2e2effa8cdf6 0x662f6373696d2f77
0x55d9ef87c120: 0x6e756600632e6e75 0x696d6d2d6e756600
- set size: 0x4D1DF6, 0x1000055d9ef308df6 - 0x55d9ef87c0b0 = 0xffffffffffa8cd46 <- 0x55d9ef87c0b0 - 0x55d9ef87c0b0 = 0x00 / 4 = 0
- set addr: 0x4D1E08, 0x1000055d9ef308e08 - 0x55d9ef87c0b0 = 0xffffffffffa8cd58 <- 0x55d9ef87c0c0 - 0x55d9ef87c0b0 = 0x10 / 4 = 4
- setraddr: 0x4D1E1A, 0x1000055d9ef308e1a - 0x55d9ef87c0b0 = 0xffffffffffa8cd6a <- 0x55d9ef87c0d0 - 0x55d9ef87c0b0 = 0x20 / 4 = 8
- set idx: 0x4D1E2C, 0x1000055d9ef308e2c - 0x55d9ef87c0b0 = 0xffffffffffa8cd7c <- 0x55d9ef87c0e0 - 0x55d9ef87c0b0 = 0x30 / 4 = 12
- read : 0x4D1E3E, 0x1000055d9ef308e3e - 0x55d9ef87c0b0 = 0xffffffffffa8cd8e <- 0x55d9ef87c0f0 - 0x55d9ef87c0b0 = 0x40 / 4 = 16
- create: 0x4D1E78, 0x1000055d9ef308e78 - 0x55d9ef87c0b0 = 0xffffffffffa8cdc8 <- 0x55d9ef87c100 - 0x55d9ef87c0b0 = 0x50 / 4 = 20
- delete: 0x4D1EA6, 0x1000055d9ef308da6 - 0x55d9ef87c0b0 = 0xffffffffffa8cdf6 <- 0x55d9ef87c110 - 0x55d9ef87c0b0 = 0x60 / 4 = 24
那么先调用create, , 可以看到130047作为val进入了fun_mmio_write函数
之后再用mmio_write(20, 0)创建req
调用mmio_write(16, 0)来触发read
fun_mmio_read函数
- 读FunState的各种数据到val, 包括addr, size, idx, result_addr
- handle_data_write, dma_memory_write_9(fun->as, (val << 10) + fun->addr, req->list[val], 0x400uLL); 应该是用来将req里指定val的数据写入到Address_Space, 可以用来修改堆块数据
fun_mmio_write
- 向FunStatus的addr, size, idx, result_addr写入val中的数据
- create_req, 传入FunStatus的size, 创建FunReq的对象, 设置它的total_size
- delete_req, 根据total_size free list
- handle_data_read, dma_memory_read_9(fun->as, (val << 10) + fun->addr, req->list[val], 0x400uLL); 用来把Address_Space的东西读取到req里,用来读取堆块数据
具体再看handle_data_write函数, 首先检查req对象是否为空, 然后将fun->idx作为val, 调用handle(fun, req, fun->idx), 判断req->total_size != 0, val <= 0x7e, val < (req->total_size) >> 10 + 1
create的时候, size最大是0x1fbff, 会创建0x1fbff >> 10 + 1 = 126 + 1 = 127个req->list, 编号为0-0x7e, 设置total_size = size = 0x1fbff
而handle_data_read和handle_data_write的时候, val的条件是小于等于0x7e, 若此时val = 0x7e < (0x1fbff >> 10) + 1 = 0x7f, 是可以通过if的, 在调用dmm_memory_read和write的时候, 第二个参数的值为0x7e << 10 + fun->addr, 0x7e个堆块的地址分别是0-0x3ff, 0x400-0x7ff, 以此类推, 最后一个堆块的地址 是(0x7e - 1 * 0x400) = 0x1f400 - 0x1f7ff, 但是0x7e << 10 = 0x1f800, 再加上我们可控的fun->addr, 会有一个任意读写
- set size = 0x1fbff
- create 0x1fbff: mmio_write(0, 130047)
- set idx = 0x7e mmio_write(12, 0x7e)
- set fun->addr =
- handle_data_read
size = 0x1fbff
req->total_size = 0x1fbff
t = 126 + 1 = 127
b fun_mmio_read
b fun_mmio_write
r -L ./dependency -kernel ./vmlinuz-5.4.0-58-generic -initrd ./rootfs.cpio -cpu kvm64,+smep -m 64M -monitor none -device fun -append “root=/dev/ram rw console=ttyS0 oops=panic panic=1 quiet kaslr” -nographic
io_regions = {{
addr = 4273934336,
size = 4096,
type = 0 '\000',
memory = 0x55920cc61460,
address_space = 0x55920bd0b900
}, {
addr = 0,
size = 130047,
idx = 0,
result_addr = 0,
req = 0x0,
as = 0x55920a73fe00
-L ./dependency -kernel ./vmlinuz-5.4.0-58-generic -initrd ./rootfs.cpio -cpu kvm64,+smep -m 64M -monitor none -device fun -append “root=/dev/ram rw console=ttyS0 oops=panic panic=1 quiet kaslr” -nographic
► 0x56463441ebb6
rdi: 0x564635076e00 (address_space_memory) ◂— 0x0
rsi: 0x1001f800
rdx: 0x7f0ec4857bd0 ◂— 0x0
rcx: 0x400
mmio_mem: 0x7fe32d058000
userbuf_va: 0x7fe32d057000
userbuf_pa: 0x2b22000