虚拟机简单结构
使用while和switch构成的虚拟机
hagem-week4-easyvm
工具
IDA+虚拟机逆向
思路展开
通过查找字符串,找到关键函数,关键函数整体逻辑简单,取输入的字符串,然后定义一个大数组,输入和大数组经过函数运算后,与一个已知字符串比较
关键聚集到函数上。
已知字符串可用idc脚本导出
auto addr=0x140004000;
auto x,i;
for(i=0;i<48;i++){
x=byte(addr);
Message("%x,",x);
addr=addr+1;
}
//3a,54,2f,2a,2f,36,13,1,2e,3,35,40,47,e,5f,59,1,69,27,8,3d,4c,33,1a,2d,b,40,e,4b,24,41,27,25,28,29,2a,2,2,5d,24,0,0,0,0,0,0,0,0,
函数(我把名字改成了vm)
是一个经典的使用while和switch构成的虚拟机的样子
sub_140001000定义一个栈的结构
while()里的参数是定义的大数组,switch()是遍历数组里的每个值。
sub_140001000函数里还有两个函数,涉及到栈的操作(自己菜,看不懂),选择动调解决。
输入字符,下断点,看输出字符与输入字符的关系(看汇编推测验证,通常是异或),本题调试前也盲猜异或。
x64dbg 动态调试
输入一串a
在函数下断点
点进去函数,里面果真是异或(原因:1.汇编命令里看到xor 2.这次输一串a下一次书一串b,发现结果都是与某个固定值异或)
现在就是拿到和那些个值异或,我采用 ida+windbg本地调试exe,然后用idc脚本取出输出结果(一开始输入40个a),接着和a异或,得到需要异或的值
windbg注意点:1.ida7.0自带windbg调试 2.被调试程序的路径不能有中文
//idc脚本取输出
auto addr=0x1cf6e0; //函数处理后的位置
auto x,i;
for(i=0;i<48;i++){
x=byte(addr);
Message("0x%x,",x);
addr=addr+1;
}
//输入一串'a'时
//输出 0x33,0x52,0x2f,0x26,0x2b,0x2c,0x6,0x8,0x26,0x11,0xb,0x57,0x4b,0x30,0x57,0x4b,0x3f,0x57,0x35,0x6,0x2f,0x42,0x21,0x14,0x3f,0x5,0x52,0x0,0x59,0x2a,0x53,0x29,0x37,0x26,0x17,0x2e,0x2,0x10,0x45,0x38,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
输出的值再和‘a’异或,得到要异或的值
下面直接给出最终脚本:
cipher = [58, 84, 47, 42, 47, 54, 19, 1, 46, 3,
53, 64, 71, 14, 95, 89, 1, 105, 39, 8,
61, 76, 51, 26, 45, 11, 64, 14, 75, 36,
65, 39, 37, 40, 41, 42, 2, 2, 93, 36]
xor = [82, 51, 78, 71, 74, 77, 103, 105, 71, 112, 106, 54, 42, 81, 54, 42, 94, 54, 84, 103, 78, 35, 64, 117, 94, 100, 51, 97, 56, 75, 50, 72, 86, 71, 118, 79, 99, 113, 36, 89]
for i in range(40):
print(chr(cipher[i] ^ xor[i]), end='')
hgame{this_vm_is__sosososososososo_easy}
同样的vm逆向在虎符ctf遇到,当时是懵住了,后来才知道vm是啥(=゚Д゚=)。
vm逆向 虎符CTF
这个题对于栈的理解要更强,移动栈顶就可遍历和操作数据。
先留着,日后跟进。
令则师傅tql_虎符ctf vm逆向