-
-
[原创] 看雪 2025 KCTF 第八题 暗云涌动
-
发表于: 2025-8-31 04:58 3008
-
程序不大,将反编译的代码稍微修一修后,整体喂给AI,得到回答:
这里AI直接给出了VM结构体的字段定义、虚拟机指令8字节的编码格式,甚至还包括每种虚拟指令的opcode以及相应的功能
人工在补一下8字节虚拟指令的结构体定义,连同AI给出的VM结构体定义,可以得到一份非常易读的伪代码:
(p.s.以往分析到这种程序需要耗费大量时间,而现今的AI已经可以瞬间完成了)
注意到虚拟指令提供了读写内存的功能,那么题目预埋的漏洞点应该就是设法获得范围外的任意内存读写。
虚拟机的访存指令校验且只校验虚拟寄存器保存的地址的最高位为1,然后直接将剩下的部分作为裸指针访问内存。
(不知道本题的设计灵感是否有参考ARM的MTE(Memory Tagging Extension)机制)
那么,如果要达成任意内存读写原语,则需要做到让虚拟机寄存器的最高位为1的同时低63位自由可控。
常规的movimm/pushptr虚拟指令只能加载32bit的立即数,因此必须依靠算术指令才能影响高32位。
所有的算术指令都有对虚拟寄存器最高位指针标记的判断处理。假定最高位为1的为指针,为0的为数值,那么规则是:数值与数值运算结果仍为数值;指针与指针运算结果变为数值(确实存在这种现实用法,例如指针减法计算数组长度等);指针与数值运算结果仍为指针,但要经过check_and_mark_ptr(sub_128B)的范围检查,在保留标记的情况下强制让结果位于虚拟机的内存范围内。
算术指令的指针标记传播规则从逻辑上是不存在问题的,且check_and_mark_ptr的检查是严谨且无法绕过的,看起来只要想获得高位标记就比如要经过范围检查?
但是从题目的角度看,一定是需要获得任意读写原语的,而且过程必然绕开算术指令,另外绝对不能触碰到调用check_and_mark_ptr的代码路径。
以这个思路重新审视各个算术指令的实现,最终发现题目算术指令对指针标记检查的缺陷:指针标记检查只有在原始的两个运算数至少有一个含有标记的时候才会启用,而标记自身只是虚拟寄存器的最高位,会参与到运算中。对于加/减/乘指令,很容易利用进位使得两个63位的操作数在运算后的第64位变为1(例如最简单的0x7fffffffffffffff+0x1=0x8000000000000000),这样既不会触碰到检查,又可以在低位可控的情况下设置到高位,从而能够利用访存指令实现全地址空间的任意读写。
下一步,获得任意地址读写能力后仍需要找到一个能帮助获得shell的可写地址。程序保护全开(NX、PIE、FULL RELRO),且libc2.35的高版本已不存在malloc_hook/free_hook,剩下比较简单的可劫持控制流的内存写入地方是栈上的返回地址。
栈地址可以通过libc全局变量environ获得,而写栈构造ROP也需要来自libc的gadget和目标函数,因此必须获取到libc的基地址。
虚拟机指令本身无法间接造成堆的分配和释放,且程序初始分配堆块时也有意清零,因此堆上不存在任何来自libc的地址残留。
check_and_mark_ptr(sub_128B)在校验超出范围时会强制将虚拟寄存器的值设为vm->dmem,而初始化时dmem是mmap到0x200000的固定值,并没有任何帮助。
但是,check_and_mark_ptr(sub_128B)校验范围时,还同时校验了值是否位于vm->stack的范围内,而vm->stack是在堆上分配的内存。
通过判断算术指令经过check_and_mark_ptr后的虚拟寄存器的值是否等于0x8000000000200000可以获知是否虚拟寄存器的值是否位于vm->dmem或vm->stack的范围内,如果为位于vm->stack的范围内,那么就得到了一个堆地址。
VM结构自身也分配在堆上,且堆结构稳定各个堆块偏移固定,在得到堆地址后可以获取VM结构的各个字段的值。其中vm->imem是未指定地址方式mmap的内存,在同一个环境下,这种方式mmap的地址与libc的相对偏移通常是固定的。
(p.s.这部分漏洞发现和利用最终是靠人工分析出来的。可能是提示词写的不好,并没有成功的让AI分析出来,虽然体感上AI应该能做的到)
至此,通过逐步推理和审查代码,打通了本题的全部利用路径:
具体到写exp,为了方便调试,先针对题目的虚拟指令集写了一个小汇编器(支持跳转和注释)。
63位立即数的加载可以通过先加载高位到低位置,再通过乘法移位到高位置,最后加上低位到低位置。
最高位(第64位)为1且低63位可控的虚拟寄存器值的构建,可以在低63位设定好后加1再加0x7fffffffffffffff得到。
其他各种偏移可以静态以及动态调试获得。
堆区的随机范围大致在0x555550000000-0x565550000000左右,为了稳妥,放大一些范围,从0x550000000000开始以0x800为步长,平均30多秒能探测到,程序里alarm给了100秒的时间,本地完全够用(但最后打通远程的时候还是缩小了范围到0x555500000800开始且以0x1000为步长,详情见下)
然后,陷入到了pwn题经典:本地打通远程死活不通……
问题就出在vm->imem的mmap地址和libc基地址的偏移上(下方exp里的heap_imem_mmap_pointer_offset),这个偏移虽然在同一个环境下反复启动一般是不变的,但不同环境下值可能是不同的,且影响因素非常玄学。
先后尝试了本地ubuntu24.04裸机patchelf换libc、本地ubuntu24.04 libc2.39裸跑、开启or关闭aslr、ubuntu22.04 libc2.35裸跑、ubuntu22.04 docker内手动启动、ubuntu22.04 docker内xinetd直接启动,发现偏移量都不全一样(前三个环境不考虑,后两个环境下发现大致在0x260000附近变化)
(尝试过多开exp爆破,但总是不成功,后来本地测试发现也不太行,感觉可能是爆破并行度太高?亦或者是最初堆地址的探测范围太大导致高并发下因cpu限制无法在100秒内完成?总之投机行为没有成功)
最后参考了去年第八题的dockerfile,在ubuntu22.04 docker+题目给的libc2.35覆盖+xinetd在chroot下启动,得到偏移0x262000,试探性的打远程,在多次重试中终于偶然有一次打通了(然后,第一次打通时由于爆破的遗留没开log没开interactive也没打印flag只打印了ls……然后又跑了很多遍才打通第二次拿到了flag)
(最后还是疑惑,又测试了几遍,发现自己测试时相同环境下偏移量是固定的且exp能稳定打通(包括部署到另一台vps上从本地打),但是打远程总是要尝试很多次才能成功一次,不知道具体原因是什么以及出题人验题时有没有遇到过)
最终exp:
一、结构体与内存布局(修正类型)// 依据用法还原typedef struct VM { uint32_t pc; // ctx->pc 程序计数器(按“指令”为单位) uint32_t sp; // ctx->field_4 栈指针(元素个数,单位=8字节槽) uint64_t *stack; // ctx->field_8 (256 个 QWORD,大小 0x800) uint8_t *dmem; // ctx->field_10 (mmap 到 0x200000, 0x1000 字节) uint8_t *imem; // ctx->instructions (0x1000 字节, 512条 * 8B) uint64_t *regs; // ctx->field_20 (8个 QWORD,大小 0x40) } VM;initcontext() 布置:imem = zmmap(NULL, 0x1000)(随机基址)dmem = zmmap((void*)0x200000, 0x1000)(必须成功映射到固定地址 0x200000,否则退出)regs = zalloc(0x40)(8×8B)stack = zalloc(0x800)(256×8B)pc = 0; sp = 0;read(0, imem, 0x1000) 直接把字节码读入 imem。freecontext() 会相应 unmap/free。关键说明:run() 里这句v2 = &ctx->instructions[ctx->pc++]; ctx->pc = bound(ctx->pc, 0x200);结合 instructions 在反编译里被误识别为 _BYTE **,使得索引按 8 字节步长移动(指令宽度 8B)。正确语义应是:取 imem + 8*pc 为当前 8 字节指令,然后 pc++。这和各指令内部通过 a1+1/2/4 取操作数完全吻合。二、工具函数 & 语义bound(x, lim):若 x < lim 返回 x,否则返回 0。用于寄存器号(<8)、栈指针(<256)、pc(<512) 的包回 0式“限幅”。这不是饱和(saturate),而是越界就变 0。指针标记与校验标记位:最高位(bit63)=1 表示“被 VM 认可的指针”。sub_12FE(v)=v>>63 判断是否是“指针”。打标函数 sub_128B(p)(核心)若 p 落在 dmem(ctx->field_10,0x1000 大小)的 [..+0xFF8] 或落在 stack(0x800 大小)的 [..+0x7F8],返回 p | 0x8000_0000_0000_0000;否则返回 dmem_base | 0x8000...(即强行变成指向 0x200000 的“有效指针”)。算术/位运算后的指针传播规则(见各算术/位运算指令):若两个操作数都带标:清掉最高位(结果变“非指针”);若只一个带标:对去掉标记位后的数值调用 sub_128B 重新打标(确保仍指向 dmem 或 stack;若不在范围则被改成指向 dmem_base)。三、指令编码与效果(每条 8 字节)通用 8B 格式:[0]: opcode | [1]: r1(dst) | [2]: r2(src) | [3]: 未用/保留(0) | [4..7]: imm32 (LE)寄存器:8 个(0..7),每个 64 位。r = bound(byte,8),越界自动变 0。栈:256 槽(QWORD),sp 是“已用槽数”;越界/下溢同样回 0。数据移动0x00 pushr : push regs[r2]0x01 pushimm : push (uint32_t)imm0x02 pushptr : push sub_128B((uint32_t)imm)(生成“指针”)0x03 popr : regs[r1] = pop()0x04 mov : regs[r1] = regs[r2]0x05 movimm : regs[r1] = (uint32_t)imm算术(带“指针传播规则”)0x06 add : r1 += r20x07 addi : r1 += imm320x08 sub : r1 -= r20x09 subi : r1 -= imm320x0A mul : r1 *= r20x0B muli : r1 *= imm320x0C div : r1 /= r2 (无除零检查)0x0D divi : r1 /= imm32(无除零检查)位运算(同样套用“指针传播规则”)0x0E and : r1 &= r20x0F andi : r1 &= imm320x10 or : r1 |= r20x11 ori : r1 |= imm320x12 xor : r1 ^= r20x13 xori : r1 ^= imm32内存读写(需“带标”指针)0x14 load : 若 regs[r2] 带标 → regs[r1] = *(uint64_t*)(regs[r2]&~MSB);否则打印报错0x15 store : 若 regs[r1] 带标 → *(uint64_t*)(regs[r1]&~MSB) = regs[r2];否则打印报错条件跳(无符号比较),pc += imm32 后 pc = bound(pc, 0x200)0x16 jg : if regs[r1] > regs[r2] 跳0x17 jl : if regs[r1] < regs[r2] 跳0x18 je : if regs[r1] == regs[r2] 跳结束0x19 halt一、结构体与内存布局(修正类型)// 依据用法还原typedef struct VM { uint32_t pc; // ctx->pc 程序计数器(按“指令”为单位) uint32_t sp; // ctx->field_4 栈指针(元素个数,单位=8字节槽) uint64_t *stack; // ctx->field_8 (256 个 QWORD,大小 0x800) uint8_t *dmem; // ctx->field_10 (mmap 到 0x200000, 0x1000 字节) uint8_t *imem; // ctx->instructions (0x1000 字节, 512条 * 8B) uint64_t *regs; // ctx->field_20 (8个 QWORD,大小 0x40) } VM;initcontext() 布置:imem = zmmap(NULL, 0x1000)(随机基址)dmem = zmmap((void*)0x200000, 0x1000)(必须成功映射到固定地址 0x200000,否则退出)regs = zalloc(0x40)(8×8B)stack = zalloc(0x800)(256×8B)pc = 0; sp = 0;read(0, imem, 0x1000) 直接把字节码读入 imem。freecontext() 会相应 unmap/free。关键说明:run() 里这句v2 = &ctx->instructions[ctx->pc++]; ctx->pc = bound(ctx->pc, 0x200);结合 instructions 在反编译里被误识别为 _BYTE **,使得索引按 8 字节步长移动(指令宽度 8B)。正确语义应是:取 imem + 8*pc 为当前 8 字节指令,然后 pc++。这和各指令内部通过 a1+1/2/4 取操作数完全吻合。二、工具函数 & 语义bound(x, lim):若 x < lim 返回 x,否则返回 0。用于寄存器号(<8)、栈指针(<256)、pc(<512) 的包回 0式“限幅”。这不是饱和(saturate),而是越界就变 0。指针标记与校验标记位:最高位(bit63)=1 表示“被 VM 认可的指针”。sub_12FE(v)=v>>63 判断是否是“指针”。打标函数 sub_128B(p)(核心)若 p 落在 dmem(ctx->field_10,0x1000 大小)的 [..+0xFF8] 或落在 stack(0x800 大小)的 [..+0x7F8],返回 p | 0x8000_0000_0000_0000;否则返回 dmem_base | 0x8000...(即强行变成指向 0x200000 的“有效指针”)。算术/位运算后的指针传播规则(见各算术/位运算指令):若两个操作数都带标:清掉最高位(结果变“非指针”);若只一个带标:对去掉标记位后的数值调用 sub_128B 重新打标(确保仍指向 dmem 或 stack;若不在范围则被改成指向 dmem_base)。三、指令编码与效果(每条 8 字节)通用 8B 格式:[0]: opcode | [1]: r1(dst) | [2]: r2(src) | [3]: 未用/保留(0) | [4..7]: imm32 (LE)寄存器:8 个(0..7),每个 64 位。r = bound(byte,8),越界自动变 0。栈:256 槽(QWORD),sp 是“已用槽数”;越界/下溢同样回 0。数据移动0x00 pushr : push regs[r2]0x01 pushimm : push (uint32_t)imm0x02 pushptr : push sub_128B((uint32_t)imm)(生成“指针”)0x03 popr : regs[r1] = pop()0x04 mov : regs[r1] = regs[r2]0x05 movimm : regs[r1] = (uint32_t)imm算术(带“指针传播规则”)0x06 add : r1 += r20x07 addi : r1 += imm320x08 sub : r1 -= r20x09 subi : r1 -= imm320x0A mul : r1 *= r20x0B muli : r1 *= imm320x0C div : r1 /= r2 (无除零检查)0x0D divi : r1 /= imm32(无除零检查)位运算(同样套用“指针传播规则”)0x0E and : r1 &= r20x0F andi : r1 &= imm320x10 or : r1 |= r20x11 ori : r1 |= imm320x12 xor : r1 ^= r20x13 xori : r1 ^= imm32内存读写(需“带标”指针)0x14 load : 若 regs[r2] 带标 → regs[r1] = *(uint64_t*)(regs[r2]&~MSB);否则打印报错0x15 store : 若 regs[r1] 带标 → *(uint64_t*)(regs[r1]&~MSB) = regs[r2];否则打印报错条件跳(无符号比较),pc += imm32 后 pc = bound(pc, 0x200)0x16 jg : if regs[r1] > regs[r2] 跳0x17 jl : if regs[r1] < regs[r2] 跳0x18 je : if regs[r1] == regs[r2] 跳结束0x19 haltstruct Inst // sizeof=0x8{ _BYTE op; unsigned __int8 dst; unsigned __int8 src; _BYTE reserved; unsigned int imm;};struct Inst // sizeof=0x8{ _BYTE op; unsigned __int8 dst; unsigned __int8 src; _BYTE reserved; unsigned int imm;};/* This file was generated by the Hex-Rays decompiler version 9.2.0.250718. Copyright (c) 2007-2021 Hex-Rays <info@hex-rays.com> Detected compiler: GNU C++*/#include <defs.h>//-------------------------------------------------------------------------// Function declarations// int puts(const char *s);// void __noreturn exit(int status);__int64 __fastcall bound(unsigned int, unsigned int);unsigned __int64 __fastcall check_and_mark_ptr(unsigned __int64 a1);unsigned __int64 __fastcall highestbit(unsigned __int64);void pushr(struct Inst *a1);void pushimm(struct Inst *a1);void pushptr(struct Inst *a1);void popr(struct Inst *a1);void mov(struct Inst *a1);void movimm(struct Inst *a1);void add(struct Inst *a1);void addi(struct Inst *a1);void sub(struct Inst *a1);void subi(struct Inst *a1);void mul(struct Inst *a1);void muli(struct Inst *a1);void div(struct Inst *a1);void divi(struct Inst *a1);void and(struct Inst *a1);void andi(struct Inst *a1);void or(struct Inst *a1);void ori(struct Inst *a1);void xor(struct Inst *a1);void xori(struct Inst *a1);void load_data(struct Inst *a1);void store_data(struct Inst *a1);void __fastcall jg(struct Inst *a1);void __fastcall jl(struct Inst *a1);void __fastcall je(struct Inst *a1);void run();//-------------------------------------------------------------------------// Data declarationsstruct VM *vm;//----- (0000000000001000) ----------------------------------------------------__int64 (**init_proc())(void){ __int64 (**result)(void); // rax result = &_gmon_start__; if ( &_gmon_start__ ) return (__int64 (**)(void))_gmon_start__(); return result;}// 50C0: using guessed type __int64 _gmon_start__(void);//----- (0000000000001020) ----------------------------------------------------void sub_1020(){ JUMPOUT(0);}// 1026: control flows out of bounds to 0//----- (0000000000001030) ----------------------------------------------------void sub_1030(){ sub_1020();}//----- (0000000000001040) ----------------------------------------------------void sub_1040(){ sub_1020();}//----- (0000000000001050) ----------------------------------------------------void sub_1050(){ sub_1020();}//----- (0000000000001060) ----------------------------------------------------void sub_1060(){ sub_1020();}//----- (0000000000001070) ----------------------------------------------------void sub_1070(){ sub_1020();}//----- (0000000000001080) ----------------------------------------------------void sub_1080(){ sub_1020();}//----- (0000000000001090) ----------------------------------------------------void sub_1090(){ sub_1020();}//----- (00000000000010A0) ----------------------------------------------------void sub_10A0(){ sub_1020();}//----- (00000000000010B0) ----------------------------------------------------void sub_10B0(){ sub_1020();}//----- (00000000000010C0) ----------------------------------------------------void sub_10C0(){ sub_1020();}//----- (0000000000001180) ----------------------------------------------------// positive sp value has been detected, the output may be wrong!void __fastcall __noreturn start(__int64 a1, __int64 a2, void (*a3)(void)){ __int64 v3; // rax int v4; // esi __int64 v5; // [rsp-8h] [rbp-8h] BYREF char *retaddr; // [rsp+0h] [rbp+0h] BYREF v4 = v5; v5 = v3; _libc_start_main((int (*)(int, char **, char **))main, v4, &retaddr, 0, 0, a3, &v5); __halt();}// 118A: positive sp value 8 has been found// 1191: variable 'v3' is possibly undefined//----- (00000000000011B0) ----------------------------------------------------void *sub_11B0(){ return &unk_5010;}//----- (00000000000011E0) ----------------------------------------------------__int64 sub_11E0(){ return 0;}// 11E0: using guessed type __int64 sub_11E0();//----- (0000000000001220) ----------------------------------------------------void *sub_1220(){ void *result; // rax if ( !byte_5048 ) { if ( &__cxa_finalize ) _cxa_finalize(off_5008); result = sub_11B0(); byte_5048 = 1; } return result;}// 5048: using guessed type char byte_5048;//----- (0000000000001260) ----------------------------------------------------// attributes: thunk__int64 sub_1260(){ return sub_11E0();}// 11E0: using guessed type __int64 sub_11E0(void);//----- (0000000000001269) ----------------------------------------------------__int64 __fastcall bound(unsigned int a1, unsigned int a2){ if ( a1 < a2 ) return a1; else return 0;}//----- (000000000000128B) ----------------------------------------------------unsigned __int64 __fastcall check_and_mark_ptr(unsigned __int64 a1){ if ( a1 - (unsigned __int64)vm->dmem <= 0xFF8 || a1 - (unsigned __int64)vm->stack <= 0x7F8 ) return a1 | 0x8000000000000000LL; else return (unsigned __int64)vm->dmem | 0x8000000000000000LL;}//----- (00000000000012FE) ----------------------------------------------------unsigned __int64 __fastcall highestbit(unsigned __int64 a1){ return a1 >> 63;}//----- (0000000000001314) ----------------------------------------------------void pushr(struct Inst *a1){ uint64_t *regs; // rbx _QWORD *stack; // rsi uint32_t sp; // edx struct VM *v4; // rbx uint64_t v5; // [rsp+10h] [rbp-10h] regs = vm->regs; v5 = regs[(unsigned int)bound(a1->src, 8u)]; stack = vm->stack; sp = vm->sp; vm->sp = sp + 1; stack[sp] = v5; v4 = vm; v4->sp = bound(vm->sp, 0x100u);}//----- (00000000000013AA) ----------------------------------------------------void pushimm(struct Inst *a1){ _QWORD *stack; // rsi uint32_t sp; // edx struct VM *v3; // rbx __int64 imm; // [rsp+10h] [rbp-10h] imm = a1->imm; stack = vm->stack; sp = vm->sp; vm->sp = sp + 1; stack[sp] = imm; v3 = vm; v3->sp = bound(vm->sp, 0x100u);}//----- (000000000000141B) ----------------------------------------------------void pushptr(struct Inst *a1){ _QWORD *stack; // rsi uint32_t sp; // edx struct VM *v3; // rbx unsigned __int64 v4; // [rsp+10h] [rbp-10h] v4 = check_and_mark_ptr(a1->imm); stack = vm->stack; sp = vm->sp; vm->sp = sp + 1; stack[sp] = v4; v3 = vm; v3->sp = bound(vm->sp, 0x100u);}//----- (0000000000001494) ----------------------------------------------------void popr(struct Inst *a1){ struct VM *v1; // rbx uint64_t *v2; // rbx uint64_t *regs; // r12 --vm->sp; v1 = vm; v1->sp = bound(vm->sp, 0x100u); v2 = &vm->stack[vm->sp]; regs = vm->regs; regs[(unsigned int)bound(a1->dst, 8u)] = *v2;}//----- (0000000000001532) ----------------------------------------------------void mov(struct Inst *a1){ uint64_t *regs; // rbx uint64_t *v2; // rbx uint64_t *v3; // r12 regs = vm->regs; v2 = ®s[(unsigned int)bound(a1->src, 8u)]; v3 = vm->regs; v3[(unsigned int)bound(a1->dst, 8u)] = *v2;}//----- (00000000000015AC) ----------------------------------------------------void movimm(struct Inst *a1){ unsigned int imm; // ebx uint64_t *regs; // r12 imm = a1->imm; regs = vm->regs; regs[(unsigned int)bound(a1->dst, 8u)] = imm;}//----- (0000000000001600) ----------------------------------------------------void add(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+14h] [rbp-Ch] char v3; // [rsp+15h] [rbp-Bh] unsigned __int8 v4; // [rsp+16h] [rbp-Ah] char v5; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); v3 = highestbit(vm->regs[v2]); v4 = bound(a1->src, 8u); v5 = highestbit(vm->regs[v4]); vm->regs[v2] += vm->regs[v4]; if ( v3 || v5 ) { if ( v3 && v5 ) { vm->regs[v2] &= ~0x8000000000000000LL; } else { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); } }}//----- (0000000000001787) ----------------------------------------------------void addi(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); vm->regs[v2] += a1->imm; if ( (unsigned __int8)highestbit(vm->regs[v2]) ) { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); }}//----- (0000000000001864) ----------------------------------------------------void sub(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+14h] [rbp-Ch] char v3; // [rsp+15h] [rbp-Bh] unsigned __int8 v4; // [rsp+16h] [rbp-Ah] char v5; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); v3 = highestbit(vm->regs[v2]); v4 = bound(a1->src, 8u); v5 = highestbit(vm->regs[v4]); vm->regs[v2] -= vm->regs[v4]; if ( v3 || v5 ) { if ( v3 && v5 ) { vm->regs[v2] &= ~0x8000000000000000LL; } else { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); } }}//----- (00000000000019EB) ----------------------------------------------------void subi(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); vm->regs[v2] -= a1->imm; if ( (unsigned __int8)highestbit(vm->regs[v2]) ) { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); }}//----- (0000000000001AC8) ----------------------------------------------------void mul(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+14h] [rbp-Ch] char v3; // [rsp+15h] [rbp-Bh] unsigned __int8 v4; // [rsp+16h] [rbp-Ah] char v5; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); v3 = highestbit(vm->regs[v2]); v4 = bound(a1->src, 8u); v5 = highestbit(vm->regs[v4]); vm->regs[v2] *= vm->regs[v4]; if ( v3 || v5 ) { if ( v3 && v5 ) { vm->regs[v2] &= ~0x8000000000000000LL; } else { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); } }}//----- (0000000000001C53) ----------------------------------------------------void muli(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); vm->regs[v2] *= a1->imm; if ( (unsigned __int8)highestbit(vm->regs[v2]) ) { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); }}//----- (0000000000001D34) ----------------------------------------------------void div(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+14h] [rbp-Ch] char v3; // [rsp+15h] [rbp-Bh] unsigned __int8 v4; // [rsp+16h] [rbp-Ah] char v5; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); v3 = highestbit(vm->regs[v2]); v4 = bound(a1->src, 8u); v5 = highestbit(vm->regs[v4]); vm->regs[v2] /= vm->regs[v4]; if ( v3 || v5 ) { if ( v3 && v5 ) { vm->regs[v2] &= ~0x8000000000000000LL; } else { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); } }}//----- (0000000000001EC0) ----------------------------------------------------void divi(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); vm->regs[v2] /= a1->imm; if ( (unsigned __int8)highestbit(vm->regs[v2]) ) { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); }}//----- (0000000000001FA2) ----------------------------------------------------void and(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+14h] [rbp-Ch] char v3; // [rsp+15h] [rbp-Bh] unsigned __int8 v4; // [rsp+16h] [rbp-Ah] char v5; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); v3 = highestbit(vm->regs[v2]); v4 = bound(a1->src, 8u); v5 = highestbit(vm->regs[v4]); vm->regs[v2] &= vm->regs[v4]; if ( v3 || v5 ) { if ( v3 && v5 ) { vm->regs[v2] &= ~0x8000000000000000LL; } else { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); } }}//----- (0000000000002129) ----------------------------------------------------void andi(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); vm->regs[v2] &= a1->imm; if ( (unsigned __int8)highestbit(vm->regs[v2]) ) { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); }}//----- (0000000000002206) ----------------------------------------------------void or(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+14h] [rbp-Ch] char v3; // [rsp+15h] [rbp-Bh] unsigned __int8 v4; // [rsp+16h] [rbp-Ah] char v5; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); v3 = highestbit(vm->regs[v2]); v4 = bound(a1->src, 8u); v5 = highestbit(vm->regs[v4]); vm->regs[v2] |= vm->regs[v4]; if ( v3 || v5 ) { if ( v3 && v5 ) { vm->regs[v2] &= ~0x8000000000000000LL; } else { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); } }}//----- (000000000000238D) ----------------------------------------------------void ori(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); vm->regs[v2] |= a1->imm; if ( (unsigned __int8)highestbit(vm->regs[v2]) ) { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); }}//----- (000000000000246A) ----------------------------------------------------void xor(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+14h] [rbp-Ch] char v3; // [rsp+15h] [rbp-Bh] unsigned __int8 v4; // [rsp+16h] [rbp-Ah] char v5; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); v3 = highestbit(vm->regs[v2]); v4 = bound(a1->src, 8u); v5 = highestbit(vm->regs[v4]); vm->regs[v2] ^= vm->regs[v4]; if ( v3 || v5 ) { if ( v3 && v5 ) { vm->regs[v2] &= ~0x8000000000000000LL; } else { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); } }}//----- (00000000000025F1) ----------------------------------------------------void xori(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); vm->regs[v2] ^= a1->imm; if ( (unsigned __int8)highestbit(vm->regs[v2]) ) { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); }}//----- (00000000000026CE) ----------------------------------------------------void load_data(struct Inst *a1){ uint64_t *regs; // rbx uint64_t *v2; // r12 unsigned __int64 v3; // [rsp+18h] [rbp-18h] regs = vm->regs; v3 = regs[(unsigned int)bound(a1->src, 8u)]; if ( (unsigned __int8)highestbit(v3) ) { v2 = vm->regs; v2[(unsigned int)bound(a1->dst, 8u)] = *(_QWORD *)(v3 & 0x7FFFFFFFFFFFFFFFLL); } else { puts("Can't load data from the invalid pointer."); }}//----- (0000000000002782) ----------------------------------------------------void store_data(struct Inst *a1){ uint64_t *regs; // rbx uint64_t *v2; // rbx unsigned __int64 v3; // [rsp+18h] [rbp-18h] regs = vm->regs; v3 = regs[(unsigned int)bound(a1->dst, 8u)]; if ( (unsigned __int8)highestbit(v3) ) { v2 = vm->regs; *(_QWORD *)(v3 & 0x7FFFFFFFFFFFFFFFLL) = v2[(unsigned int)bound(a1->src, 8u)]; } else { puts("Can't store data to the invalid address."); }}//----- (0000000000002831) ----------------------------------------------------void __fastcall jg(struct Inst *a1){ struct VM *v1; // rbx unsigned __int8 v2; // [rsp+16h] [rbp-Ah] v2 = bound(a1->dst, 8u); if ( vm->regs[v2] > vm->regs[(unsigned __int8)bound(a1->src, 8u)] ) { vm->pc += a1->imm; v1 = vm; v1->pc = bound(vm->pc, 0x200u); }}//----- (00000000000028ED) ----------------------------------------------------void __fastcall jl(struct Inst *a1){ struct VM *v1; // rbx unsigned __int8 v2; // [rsp+16h] [rbp-Ah] v2 = bound(a1->dst, 8u); if ( vm->regs[v2] < vm->regs[(unsigned __int8)bound(a1->src, 8u)] ) { vm->pc += a1->imm; v1 = vm; v1->pc = bound(vm->pc, 0x200u); }}//----- (00000000000029A9) ----------------------------------------------------void __fastcall je(struct Inst *a1){ struct VM *v1; // rbx unsigned __int8 v2; // [rsp+16h] [rbp-Ah] v2 = bound(a1->dst, 8u); if ( vm->regs[v2] == vm->regs[(unsigned __int8)bound(a1->src, 8u)] ) { vm->pc += a1->imm; v1 = vm; v1->pc = bound(vm->pc, 0x200u); }}//----- (0000000000002A65) ----------------------------------------------------void *__fastcall zalloc(size_t a1){ void *s; // [rsp+18h] [rbp-8h] s = malloc(a1); if ( !s ) { puts("Failed to zalloc."); exit(0); } memset(s, 0, a1); return s;}//----- (0000000000002AC0) ----------------------------------------------------void __fastcall zfree(void *a1, size_t a2){ memset(a1, 0, a2); free(a1);}//----- (0000000000002AF8) ----------------------------------------------------void *__fastcall zmmap(void *a1, size_t a2){ void *v3; // [rsp+18h] [rbp-8h] v3 = mmap(a1, a2, 3, 34, -1, 0); if ( !v3 || a1 && a1 != v3 ) { puts("Failed to zmmap."); exit(0); } return v3;}//----- (0000000000002B6D) ----------------------------------------------------int __fastcall zmunmap(void *a1, size_t a2){ return munmap(a1, a2);}//----- (0000000000002B97) ----------------------------------------------------void run(){ struct VM *v0; // rbx char v1; // [rsp+7h] [rbp-19h] struct Inst *a1; // [rsp+8h] [rbp-18h] v1 = 0; while ( !v1 ) { a1 = &vm->imem[vm->pc++]; v0 = vm; v0->pc = bound(vm->pc, 0x200u); switch ( a1->op ) { case 0: pushr(a1); break; case 1: pushimm(a1); break; case 2: pushptr(a1); break; case 3: popr(a1); break; case 4: mov(a1); break; case 5: movimm(a1); break; case 6: add(a1); break; case 7: addi(a1); break; case 8: sub(a1); break; case 9: subi(a1); break; case 0xA: mul(a1); break; case 0xB: muli(a1); break; case 0xC: div(a1); break; case 0xD: divi(a1); break; case 0xE: and(a1); break; case 0xF: andi(a1); break; case 0x10: or(a1); break; case 0x11: ori(a1); break; case 0x12: xor(a1); break; case 0x13: xori(a1); break; case 0x14: load_data(a1); break; case 0x15: store_data(a1); break; case 0x16: jg(a1); break; case 0x17: jl(a1); break; case 0x18: je(a1); break; case 0x19: v1 = 1; break; default: puts("Invalid instruction."); exit(0); } }}//----- (0000000000002DF5) ----------------------------------------------------void freecontext(){ zmunmap(vm->?, 0x1000u); zmunmap((void *)vm->?, 0x1000u); zfree((void *)vm->?, 0x40u); zfree((void *)vm->?, 0x800u); zfree(vm, 0x28u);}//----- (0000000000002E74) ----------------------------------------------------struct VM *initcontext(){ struct VM *v0; // rbx struct VM *v1; // rbx struct VM *v2; // rbx struct VM *v3; // rbx struct VM *result; // rax alarm(100u); vm = (struct VM *)zalloc(0x28u); vm->pc = 0; v0 = vm; v0->imem = (uint64_t *)zmmap(0, 0x1000u); v1 = vm; v1->dmem = (uint8_t *)zmmap((void *)0x200000, 0x1000u); v2 = vm; v2->regs = (uint64_t *)zalloc(0x40u); v3 = vm; v3->stack = (uint8_t *)zalloc(0x800u); result = vm; vm->sp = 0; return result;}//----- (0000000000002F1C) ----------------------------------------------------void setio(){ setbuf(stdin, 0); setbuf(stdout, 0); setbuf(stderr, 0);}//----- (0000000000002F63) ----------------------------------------------------__int64 __fastcall main(__int64 a1, char **a2, char **a3){ setio(); initcontext(); read(0, vm->imem, 0x1000u); run(); freecontext(); return 0;}//----- (0000000000002FB8) ----------------------------------------------------void term_proc(){ ;}// nfuncs=79 queued=55 decompiled=55 lumina nreq=0 worse=0 better=0// ALL OK, 55 function(s) have been successfully decompiled/* This file was generated by the Hex-Rays decompiler version 9.2.0.250718. Copyright (c) 2007-2021 Hex-Rays <info@hex-rays.com> Detected compiler: GNU C++*/#include <defs.h>//-------------------------------------------------------------------------// Function declarations// int puts(const char *s);// void __noreturn exit(int status);__int64 __fastcall bound(unsigned int, unsigned int);unsigned __int64 __fastcall check_and_mark_ptr(unsigned __int64 a1);unsigned __int64 __fastcall highestbit(unsigned __int64);void pushr(struct Inst *a1);void pushimm(struct Inst *a1);void pushptr(struct Inst *a1);void popr(struct Inst *a1);void mov(struct Inst *a1);void movimm(struct Inst *a1);void add(struct Inst *a1);void addi(struct Inst *a1);void sub(struct Inst *a1);void subi(struct Inst *a1);void mul(struct Inst *a1);void muli(struct Inst *a1);void div(struct Inst *a1);void divi(struct Inst *a1);void and(struct Inst *a1);void andi(struct Inst *a1);void or(struct Inst *a1);void ori(struct Inst *a1);void xor(struct Inst *a1);void xori(struct Inst *a1);void load_data(struct Inst *a1);void store_data(struct Inst *a1);void __fastcall jg(struct Inst *a1);void __fastcall jl(struct Inst *a1);void __fastcall je(struct Inst *a1);void run();//-------------------------------------------------------------------------// Data declarationsstruct VM *vm;//----- (0000000000001000) ----------------------------------------------------__int64 (**init_proc())(void){ __int64 (**result)(void); // rax result = &_gmon_start__; if ( &_gmon_start__ ) return (__int64 (**)(void))_gmon_start__(); return result;}// 50C0: using guessed type __int64 _gmon_start__(void);//----- (0000000000001020) ----------------------------------------------------void sub_1020(){ JUMPOUT(0);}// 1026: control flows out of bounds to 0//----- (0000000000001030) ----------------------------------------------------void sub_1030(){ sub_1020();}//----- (0000000000001040) ----------------------------------------------------void sub_1040(){ sub_1020();}//----- (0000000000001050) ----------------------------------------------------void sub_1050(){ sub_1020();}//----- (0000000000001060) ----------------------------------------------------void sub_1060(){ sub_1020();}//----- (0000000000001070) ----------------------------------------------------void sub_1070(){ sub_1020();}//----- (0000000000001080) ----------------------------------------------------void sub_1080(){ sub_1020();}//----- (0000000000001090) ----------------------------------------------------void sub_1090(){ sub_1020();}//----- (00000000000010A0) ----------------------------------------------------void sub_10A0(){ sub_1020();}//----- (00000000000010B0) ----------------------------------------------------void sub_10B0(){ sub_1020();}//----- (00000000000010C0) ----------------------------------------------------void sub_10C0(){ sub_1020();}//----- (0000000000001180) ----------------------------------------------------// positive sp value has been detected, the output may be wrong!void __fastcall __noreturn start(__int64 a1, __int64 a2, void (*a3)(void)){ __int64 v3; // rax int v4; // esi __int64 v5; // [rsp-8h] [rbp-8h] BYREF char *retaddr; // [rsp+0h] [rbp+0h] BYREF v4 = v5; v5 = v3; _libc_start_main((int (*)(int, char **, char **))main, v4, &retaddr, 0, 0, a3, &v5); __halt();}// 118A: positive sp value 8 has been found// 1191: variable 'v3' is possibly undefined//----- (00000000000011B0) ----------------------------------------------------void *sub_11B0(){ return &unk_5010;}//----- (00000000000011E0) ----------------------------------------------------__int64 sub_11E0(){ return 0;}// 11E0: using guessed type __int64 sub_11E0();//----- (0000000000001220) ----------------------------------------------------void *sub_1220(){ void *result; // rax if ( !byte_5048 ) { if ( &__cxa_finalize ) _cxa_finalize(off_5008); result = sub_11B0(); byte_5048 = 1; } return result;}// 5048: using guessed type char byte_5048;//----- (0000000000001260) ----------------------------------------------------// attributes: thunk__int64 sub_1260(){ return sub_11E0();}// 11E0: using guessed type __int64 sub_11E0(void);//----- (0000000000001269) ----------------------------------------------------__int64 __fastcall bound(unsigned int a1, unsigned int a2){ if ( a1 < a2 ) return a1; else return 0;}//----- (000000000000128B) ----------------------------------------------------unsigned __int64 __fastcall check_and_mark_ptr(unsigned __int64 a1){ if ( a1 - (unsigned __int64)vm->dmem <= 0xFF8 || a1 - (unsigned __int64)vm->stack <= 0x7F8 ) return a1 | 0x8000000000000000LL; else return (unsigned __int64)vm->dmem | 0x8000000000000000LL;}//----- (00000000000012FE) ----------------------------------------------------unsigned __int64 __fastcall highestbit(unsigned __int64 a1){ return a1 >> 63;}//----- (0000000000001314) ----------------------------------------------------void pushr(struct Inst *a1){ uint64_t *regs; // rbx _QWORD *stack; // rsi uint32_t sp; // edx struct VM *v4; // rbx uint64_t v5; // [rsp+10h] [rbp-10h] regs = vm->regs; v5 = regs[(unsigned int)bound(a1->src, 8u)]; stack = vm->stack; sp = vm->sp; vm->sp = sp + 1; stack[sp] = v5; v4 = vm; v4->sp = bound(vm->sp, 0x100u);}//----- (00000000000013AA) ----------------------------------------------------void pushimm(struct Inst *a1){ _QWORD *stack; // rsi uint32_t sp; // edx struct VM *v3; // rbx __int64 imm; // [rsp+10h] [rbp-10h] imm = a1->imm; stack = vm->stack; sp = vm->sp; vm->sp = sp + 1; stack[sp] = imm; v3 = vm; v3->sp = bound(vm->sp, 0x100u);}//----- (000000000000141B) ----------------------------------------------------void pushptr(struct Inst *a1){ _QWORD *stack; // rsi uint32_t sp; // edx struct VM *v3; // rbx unsigned __int64 v4; // [rsp+10h] [rbp-10h] v4 = check_and_mark_ptr(a1->imm); stack = vm->stack; sp = vm->sp; vm->sp = sp + 1; stack[sp] = v4; v3 = vm; v3->sp = bound(vm->sp, 0x100u);}//----- (0000000000001494) ----------------------------------------------------void popr(struct Inst *a1){ struct VM *v1; // rbx uint64_t *v2; // rbx uint64_t *regs; // r12 --vm->sp; v1 = vm; v1->sp = bound(vm->sp, 0x100u); v2 = &vm->stack[vm->sp]; regs = vm->regs; regs[(unsigned int)bound(a1->dst, 8u)] = *v2;}//----- (0000000000001532) ----------------------------------------------------void mov(struct Inst *a1){ uint64_t *regs; // rbx uint64_t *v2; // rbx uint64_t *v3; // r12 regs = vm->regs; v2 = ®s[(unsigned int)bound(a1->src, 8u)]; v3 = vm->regs; v3[(unsigned int)bound(a1->dst, 8u)] = *v2;}//----- (00000000000015AC) ----------------------------------------------------void movimm(struct Inst *a1){ unsigned int imm; // ebx uint64_t *regs; // r12 imm = a1->imm; regs = vm->regs; regs[(unsigned int)bound(a1->dst, 8u)] = imm;}//----- (0000000000001600) ----------------------------------------------------void add(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+14h] [rbp-Ch] char v3; // [rsp+15h] [rbp-Bh] unsigned __int8 v4; // [rsp+16h] [rbp-Ah] char v5; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); v3 = highestbit(vm->regs[v2]); v4 = bound(a1->src, 8u); v5 = highestbit(vm->regs[v4]); vm->regs[v2] += vm->regs[v4]; if ( v3 || v5 ) { if ( v3 && v5 ) { vm->regs[v2] &= ~0x8000000000000000LL; } else { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); } }}//----- (0000000000001787) ----------------------------------------------------void addi(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); vm->regs[v2] += a1->imm; if ( (unsigned __int8)highestbit(vm->regs[v2]) ) { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); }}//----- (0000000000001864) ----------------------------------------------------void sub(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+14h] [rbp-Ch] char v3; // [rsp+15h] [rbp-Bh] unsigned __int8 v4; // [rsp+16h] [rbp-Ah] char v5; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); v3 = highestbit(vm->regs[v2]); v4 = bound(a1->src, 8u); v5 = highestbit(vm->regs[v4]); vm->regs[v2] -= vm->regs[v4]; if ( v3 || v5 ) { if ( v3 && v5 ) { vm->regs[v2] &= ~0x8000000000000000LL; } else { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); } }}//----- (00000000000019EB) ----------------------------------------------------void subi(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); vm->regs[v2] -= a1->imm; if ( (unsigned __int8)highestbit(vm->regs[v2]) ) { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); }}//----- (0000000000001AC8) ----------------------------------------------------void mul(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+14h] [rbp-Ch] char v3; // [rsp+15h] [rbp-Bh] unsigned __int8 v4; // [rsp+16h] [rbp-Ah] char v5; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); v3 = highestbit(vm->regs[v2]); v4 = bound(a1->src, 8u); v5 = highestbit(vm->regs[v4]); vm->regs[v2] *= vm->regs[v4]; if ( v3 || v5 ) { if ( v3 && v5 ) { vm->regs[v2] &= ~0x8000000000000000LL; } else { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); } }}//----- (0000000000001C53) ----------------------------------------------------void muli(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); vm->regs[v2] *= a1->imm; if ( (unsigned __int8)highestbit(vm->regs[v2]) ) { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); }}//----- (0000000000001D34) ----------------------------------------------------void div(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+14h] [rbp-Ch] char v3; // [rsp+15h] [rbp-Bh] unsigned __int8 v4; // [rsp+16h] [rbp-Ah] char v5; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); v3 = highestbit(vm->regs[v2]); v4 = bound(a1->src, 8u); v5 = highestbit(vm->regs[v4]); vm->regs[v2] /= vm->regs[v4]; if ( v3 || v5 ) { if ( v3 && v5 ) { vm->regs[v2] &= ~0x8000000000000000LL; } else { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); } }}//----- (0000000000001EC0) ----------------------------------------------------void divi(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); vm->regs[v2] /= a1->imm; if ( (unsigned __int8)highestbit(vm->regs[v2]) ) { v1 = &vm->regs[v2]; *v1 = check_and_mark_ptr(*v1 & 0x7FFFFFFFFFFFFFFFLL); }}//----- (0000000000001FA2) ----------------------------------------------------void and(struct Inst *a1){ uint64_t *v1; // rbx unsigned __int8 v2; // [rsp+14h] [rbp-Ch] char v3; // [rsp+15h] [rbp-Bh] unsigned __int8 v4; // [rsp+16h] [rbp-Ah] char v5; // [rsp+17h] [rbp-9h] v2 = bound(a1->dst, 8u); v3 = highestbit(vm->regs[v2]); v4 = bound(a1->src, 8u); v5 = highestbit(vm->regs[v4]); vm->regs[v2] &= vm->regs[v4]; if ( v3 || v5 ) { if ( v3 && v5 ) { vm->regs[v2] &= ~0x8000000000000000LL; } else[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!