RiK's Blog - Misc
type: channel
link: https://pwnerik.cn/tag/Misc/
items: 第18届全国大学生软件创新大赛——软件系统安全赛（攻防赛）Pwn Writeup

第18届全国大学生软件创新大赛——软件系统安全赛（攻防赛）Pwn Writeup
type: item
date: 2025-01-08T11:09:00+00:00
description: vm通过 read_vm 函数还原出 main 函数以及 VM 结构体：void __fastcall __noreturn main(__int64 a1, char **a2, char **a3) { initit(); vmdata = mmap((void *)0x64617461000LL, 0x30000uLL, 3, 34, -1, 0LL); vmcode = (__int64)mmap((void *)0x7063000, 0x10000uLL, 3, 34, -1, 0LL); stack = (__int64)mmap((void *)0x73746163000LL, 0x20000uLL, 3, 34, -1, 0LL) + 0x10000; read_vm((struct vm *)&vmdata); execute((vm *)&vmdata); }00000000 struct vm // sizeof=0x58 00000000 { 00000000 char *vmdata; 00000008 char *pc; 00000010 uint64_t *regs[6]; 00000040 char *stack; 00000048 __int64 base; 00000050 __int64 field_50; 00000058 };其中 regs、stack、base 字段在 execute 内部逆向过程中得出。进入 execute 中的 decode 可以看出指令由指令最低 2 位分为四种：11 - 加载立即数至寄存器、10 - 两个形式地址、01 - 一个形式地址、00 - 带参数的隐含寻址，每种指令每个形式地址有直接寻址和寄存器间接寻址方式排列组合。__int64 __fastcall decode(struct vm *vm, char *reading_code) { char *vmcode0; // rax int low2; // eax char *pc; // rax char *_opcode1; // rax __int64 result; // rax char *__code1; // rax char *_code2; // rax char *vmcode1; // rax unsigned __int8 v10; // [rsp+17h] [rbp-9h] unsigned int i; // [rsp+18h] [rbp-8h] vmcode0 = vm->pc; vm->pc = vmcode0 + 1; *reading_code = *vmcode0; reading_code[1] = *reading_code & 3; low2 = (unsigned __int8)reading_code[1]; if ( low2 == 3 ) { vmcode1 = vm->pc; vm->pc = vmcode1 + 1; *((_DWORD *)reading_code + 1) = (unsigned __int8)*vmcode1; if ( check_reg(*((_DWORD *)reading_code + 1)) ) return 0xFFFFFFFFLL; *((_DWORD *)reading_code + 2) = *(_QWORD *)vm->pc; vm->pc += 8; } else if ( (unsigned __int8)reading_code[1] <= 3u ) { if ( low2 == 2 ) // 2 { __code1 = vm->pc; vm->pc = __code1 + 1; *((_DWORD *)reading_code + 1) = (unsigned __int8)*__code1; _code2 = vm->pc; vm->pc = _code2 + 1; *((_DWORD *)reading_code + 2) = (unsigned __int8)*_code2; if ( check_reg(*((_DWORD *)reading_code + 1)) && check_reg(*((_DWORD *)reading_code + 2)) ) return 0xFFFFFFFFLL; } else if ( reading_code[1] ) // 1 { _opcode1 = vm->pc; vm->pc = _opcode1 + 1; v10 = *_opcode1; if ( check_reg((unsigned __int8)*_opcode1) ) return 0…