很久之前就想着要复现,结果忘记了...一直拖到现在...
找到关键函数:vm_operad()
点进去看看:
int __cdecl vm_operad(int *a1, int a2)
{
int result; // eax
char v3[100]; // [esp+13h] [ebp-E5h]
char v4[100]; // [esp+77h] [ebp-81h]
char v5; // [esp+DBh] [ebp-1Dh]
int v6; // [esp+DCh] [ebp-1Ch]
int v7; // [esp+E0h] [ebp-18h]
int v8; // [esp+E4h] [ebp-14h]
int v9; // [esp+E8h] [ebp-10h]
int v10; // [esp+ECh] [ebp-Ch]
v10 = 0;
v9 = 0;
v8 = 0;
v7 = 0;
v6 = 0;
while ( 1 )
{
result = v10;
if ( v10 >= a2 )
return result;
switch ( a1[v10] )
{
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] )
{
printf("what a shame...");
exit(0);
}
++v8;
v10 += 2;
break;
case 8:
v3[v6] = v5;
++v10;
++v6;
break;
case 10:
read(v3);
++v10;
break;
case 11:
v5 = v3[v9] - 1;
++v10;
break;
case 12:
v5 = v3[v9] + 1;
++v10;
break;
default:
continue;
}
}
}
a1:
然后就主要分析一下这几个case都是做什么的:
- 第一类:判断验证
(这里的a1是固定的值,与v4进行比较的数据可以理解为由上图内存中每个0x07后的数据构成的数组,v4是我们输入的字符串经过一系列操作存放的位置,v3为我们输入的字符串)
case 7:
if ( v4[v8] != a1[v10 + 1] )
{
printf("what a shame...");
exit(0);
}
++v8;
v10 += 2;
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 11:
v5 = v3[v9] - 1;
++v10;
break;
case 12:
v5 = v3[v9] + 1;
++v10;
break;
- 第三类:中转赋值
这里v5其实就是一个中间值,把我们输入的字符串在第二类case经过一系列操作存在v5中,然后遇到case1就把v5赋值给v4,最后用v4去和a1比较,都相同就get flag!
case 1:
v4[v7] = v5;
++v10;
++v7;
++v9;
break;
case 6:
++v10;
break;
case 8:
v3[v6] = v5;
++v10;
++v6;
break;
逻辑就挺清楚的了,具体这些case是做什么的就不多说了(一些加减异或基本操作,自行理解),直接上脚本吧:
exp
这里用的是爆破的方法,也可以直接写出其逆过程+逆运算,从结果直接推出flag
encrypts = [0x22, 0x3F, 0x34, 0x32, 0x72, 0x33, 0x18, 0xA7, 0x31, 0xF1, 0x28, 0x84, 0xC1, 0x1E, 0x7A]
data = [[4, 0x10, 8, 3, 5, 1]
, [4, 0x20, 8, 5, 3, 1]
, [3, 2, 8, 0x0B, 1]
, [0x0C, 8, 4, 4, 1]
, [5, 3, 8, 3, 0x21, 1]
, [0x0B, 8, 0x0B, 1]
, [4, 9, 8, 3, 0x20, 1]
, [2, 0x51, 8, 4, 0x24, 1]
, [0x0C, 8, 0x0B, 1]
, [5, 2, 8, 2, 0x25, 1]
, [2, 0x36, 8, 4, 0x41, 1]
, [2, 0x20, 8, 5, 1, 1]
, [5, 3, 8, 2, 0x25, 1]
, [4, 9, 8, 3, 0x20, 1]
, [2, 0x41, 8, 0x0C, 1]]
for_each = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
def encrypted(c, li):
# print(li)
x = 0
while x < len(li):
if li[x] == 2:
c = c + li[x + 1]
x += 2
elif li[x] == 3:
c = c - li[x + 1]
x += 2
elif li[x] == 4:
c = c ^ li[x + 1]
x += 2
elif li[x] == 5:
c = c * li[x + 1]
x += 2
elif li[x] == 11:
c = c - 1
x += 1
elif li[x] == 12:
c = c + 1
x += 1
elif li[x] == 8:
x += 1
elif li[x] == 1:
break
res = c
return res
if __name__ == '__main__':
flag = ''
for x in range(len(encrypts)):
for i in for_each:
tmp = encrypted(ord(i), data[x])
if tmp == encrypts[x]:
flag += i
break
else:
continue
print('flag{%s}' % flag)
# flag{757515121f3d478}