S1mpleVM

1 | if ( (unsigned int)sub_140001D30(v30, v8) ) |
可以找到最关键的函数 sub_140001D30 就是 VM 入口
查看这个函数有很明显的 vm_handler
1 | __int64 __fastcall vmrun(char *input, char *vmcode) |
恢复结构体之后这个 vm 还是很一目了然的,下面解释一下各个 opcode 的作用。
- 0:取模操作(先弹出的值在运算符左侧)
- 1:push 操作
- 2:pop 操作
- 3:乘法操作
- 4:加法操作
- 5:输出
- 6:取输入指针
- 7:右移位后取最低位(先弹出的值在运算符右侧)
- 8:异或操作
- 9:输入指针+1
- 10:返回
- 11:减法操作(先弹出的值在运算符左侧)
- 12:除法操作(先弹出的值在运算符左侧)
运行根据程序写的cpp文件,
1 | g++ test.cpp -o test |
节选一段log:
1 | get 1 input |
最前面输出了一句话:Thank for providing passcode, my ultimate secret box is checking…
跳过之后,发现它在频繁的取输入字符并做 (x>>y)&1 的运算,y 从 0~7。这是在一个一个取出输入字节的每一位,每一位都对应了一个权值。第一个字节可以看出来,从低位到高位权值分别为
1 | 2 3 67 37 41 11 13 89 |
得到权值的方法:在 * 运算中加入 fprintf(stderr,"%d,",reg2);
最后,它将所有权值相加,得到的结果和 70 做异或运算得到 24,将该值存入栈底。
得到异或目标值:在异或的 opcode 中加入 fprintf(stderr,"%d,",reg2);
看log的最后
1 | calc 137+71=208 |
计算的第一个异或值,在最后被加起来返回了。
最终根据逻辑,写出还原 passcode 的逻辑。
1 | #include<stdio.h> |
输入得到flag



