这个题目方法有很多,目的是练习算法的分析和vm练习,尝试了静态直接逆算法和动态静态结合的方法
方法1
拖入ida找到main函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [sp+18h] [bp-1D4h]@1
__main();
qmemcpy(&v4, &unk_403040, 0x1C8u);//拷贝opcode表
vm_operad(&v4, 114);//关键函数
puts("good,The answer format is:flag {}");
return 0;
}
找到关键函数
int __cdecl vm_operad(int *a1, int a2)
{
int result; // eax@2
char v3[100]; // [sp+13h] [bp-E5h]@4
char v4[100]; // [sp+77h] [bp-81h]@5
char v5; // [sp+DBh] [bp-1Dh]@5
int v6; // [sp+DCh] [bp-1Ch]@1
int v7; // [sp+E0h] [bp-18h]@1
int v8; // [sp+E4h] [bp-14h]@1
int v9; // [sp+E8h] [bp-10h]@1
int v10; // [sp+ECh] [bp-Ch]@1
v10 = 0;
v9 = 0;
v8 = 0;
v7 = 0;
v6 = 0;
while ( 1 )
{
result = v10;
if ( v10 >= a2 )
return result;
switch ( a1[v10] ) // a1是opcode v10是索引
{
case 10: // 输入点
read(v3);
++v10;
break;
case 1:
v4[v7] = v5;
++v10;
++v7;
++v9;
break;
case 2:
v5 = a1[v10 + 1] + v3[v9];
v10 += 2;
break;
case 3:
v5 = v3[v9] - LOBYTE(a1[v10 + 1]);
v10 += 2;
break;
case 4:
v5 = a1[v10 + 1] ^ v3[v9];
v10 += 2;
break;
case 5:
v5 = a1[v10 + 1] * v3[v9];
v10 += 2;
break;
case 6:
++v10;
break;
case 7:
if ( v4[v8] != a1[v10 + 1] ) // 最终判断 a1->v5->v4
{
printf("what a shame...");
exit(0);
}
++v8;
v10 += 2;
break;
case 11:
v5 = v3[v9] - 1;
++v10;
break;
case 12:
v5 = v3[v9] + 1;
++v10;
break;
case 8:
v3[v6] = v5;
++v10;
++v6;
break;
default:
continue;
}
}
}
可以判断这是一个vm逆向,分析逻辑,输入点是case 10最后的判断位置是case 7。v4由v5得到,且必经过case 1,v5由opcode经过运算得到,所以我们可以模拟算法,先找出每次switch使用哪个索引值v10和整个过程中进行比较的opcode v4。
逆向算法如下
#include <stdio.h>
#include <string.h>
unsigned char opcode[] =
{
0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00,
0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00,
0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x04