先看文件信息,没有加壳
运行,又是字符串比较的题目
IDA32位打开,打开string窗口,跟随跳转
读入字符串
size_t __cdecl read(char *Str)
{
size_t result; // eax
printf("string:");
scanf("%s", Str);
result = strlen(Str);
if ( result != 15 )
{
puts("WRONG!\n");
exit(0);
}
return result;
}
主函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4[117]; // [esp+18h] [ebp-1D4h] BYREF
__main();
qmemcpy(v4, &unk_403040, 0x1C8u);
vm_operad(v4, 114);
puts("good,The answer format is:flag {}");
return 0;
}
重点就是== vm_operad==里面对字符串进行变换了
int __cdecl vm_operad(int *a1, int a2)
{
int result; // eax
char Str[200]; // [esp+13h] [ebp-E5h] BYREF
char v4; // [esp+DBh] [ebp-1Dh]
int v5; // [esp+DCh] [ebp-1Ch]
int v6; // [esp+E0h] [ebp-18h]
int v7; // [esp+E4h] [ebp-14h]
int v8; // [esp+E8h] [ebp-10h]
int v9; // [esp+ECh] [ebp-Ch]
v9 = 0;
v8 = 0;
v7 = 0;
v6 = 0;
v5 = 0;
while ( 1 )
{
result = v9;
if ( v9 >= a2 )
return result;
switch ( a1[v9] )
{
case 1:
Str[v6 + 100] = v4;
++v9;
++v6;
++v8;
break;
case 2:
v4 = a1[v9 + 1] + Str[v8];
v9 += 2;
break;
case 3:
v4 = Str[v8] - LOBYTE(a1[v9 + 1]);
v9 += 2;
break;
case 4:
v4 = a1[v9 + 1] ^ Str[v8];
v9 += 2;
break;
case 5:
v4 = a1[v9 + 1] * Str[v8];
v9 += 2;
break;
case 6:
++v9;
break;
case 7:
if ( Str[v7 + 100] != a1[v9 + 1] )
{
printf("what a shame...");
exit(0);
}
++v7;
v9 += 2;
break;
case 8:
Str[v5] = v4;
++v9;
++v5;
break;
case 10:
read(Str);
++v9;
break;
case 11:
v4 = Str[v8] - 1;
++v9;
break;
case 12:
v4 = Str[v8] + 1;
++v9;
break;
default:
continue;
}
}
}
unk_40340里的值,这里0可以去掉
转到hex窗口,复制出来批量替换一下,得到
0x0A,0x04,0x10,0x08, 0x03,0x05,0x01,0x04, 0x20,0x08,0x05,0x03, 0x01,0x03,0x02,0x08,
0x0B,0x01,0x0C,0x08, 0x04,0x04,0x01,0x05, 0x03,0x08,0x03,0x21, 0x01,0x0B,0x08,0x0B,
0x01,0x04,0x09,0x08, 0x03,0x20,0x01,0x02, 0x51,0x08,0x04,0x24, 0x01,0x0C,0x08,0x0B,
0x01,0x05,0x02,0x08, 0x02,0x25,0x01,0x02, 0x36,0x08,0x04,0x41, 0x01,0x02,0x20,0x08,
0x05,0x01,0x01,0x05, 0x03,0x08,0x02,0x25, 0x01,0x04,0x09,0x08, 0x03,0x20,0x01,0x02,
0x41,0x08,0x0C,0x01, 0x07,0x22,0x07,0x3F, 0x07,0x34,0x07,0x32, 0x07,0x72,0x07,0x33,
0x07,0x18,0x07,0xA7,0xFF,0xFF,0xFF, 0x07,0x31,0x07,0xF1,0xFF,0xFF,0xFF,
0x07,0x28,0x07,0x84,0xFF,0xFF,0xFF, 0x07,0xC1,0xFF,0xFF,0xFF,0x07,0x1E, 0x07,0x7A
看这个case7,以及这个case1,这个是将每个v4存储到v6+100的下标中,然后与a1[v9+1]进行比较,如果不同则退出,说明这里的a1[v9+1]存储的就是输入字符串变化后的值
case 7:
if ( Str[v7 + 100] != a1[v9 + 1] )
{
printf("what a shame...");
exit(0);
}
case 1:
Str[v6 + 100] = v4;
++v9;
++v6;
++v8;
break;
而要当case1才会将变化后的值存储,说明每个1后面的一位数就是变换后的字符,得到
v[15] = {0x22,0x3f,0x34,0x32,0x72,0x33,0x18,0xa7,0x31,0xf1,0x28,0x84,0xc1,0x1e,0x7a}; //v4的值
然后直接暴力破解flag,改一些代码,写出脚本
#include
#include
#include
int v9 = 0;
int v8 = 0;
int v7 = 0;
int v6 = 0;
int v5 = 0;
int v4 = 0;
int last_v9 = 0,last_v8 = 0,last_v7 = 0,last_v6 = 0 ,last_v5 = 0,last_v4 = 0;
int f(int a1[],int k,int v[])
{
v4 = k;
while(1)
{
switch ( a1[v9] )
{
case 1:
if(v[v6] == v4)
{
printf("k = %d,v6 = %d\n",k,v6);
++v9;
++v6;
++v8;
last_v9 = v9;
last_v8 = v8;
//last_v7 = v7;
last_v6 = v6;
//last_v5 = v5;
return 1;
}
else
{
v9 = last_v9; //找不到则返回上一个v9
v8 = last_v8;
// v7 = last_v7;
v6 = last_v6;
// v5 = last_v5;
return 0;
}
break;
case 2:
v4 = a1[v9 + 1] + v4;
v9 += 2;
break;
case 3:
v4 = v4 - a1[v9 + 1];
v9 += 2;
break;
case 4:
v4 = a1[v9 + 1] ^ v4;
v9 += 2;
break;
case 5:
v4 = a1[v9 + 1] * v4;
v9 += 2;
break;
case 6:
++v9;
break;
/*case 7:
if ( Str[v7 + 100] != a1[v9 + 1] )
{
printf("what a shame...");
exit(0);
}
++v7;
v9 += 2;
break;
/*case 8: //这里把v4的值赋给了Str[v5],上面也有用到,所以上面的Str[v8]直接代换成v4就行
Str[v5] = v4;
++v9;
++v5;
break;*/
/*case 10: //可以不用读取
read(Str);
++v9;
break;*/
case 11:
v4 = v4 - 1;
++v9;
break;
case 12:
v4 = v4 + 1;
++v9;
break;
default:
v9++;
break;
}
}
}
int main()
{
int v[16] = {0x22,0x3f,0x34,0x32,0x72,0x33,0x18,0xa7,0x31,0xf1,0x28,0x84,0xc1,0x1e,0x7a}; //v4的值
int a1[] = {0x04,0x10,0x08,0x03,0x05,0x01,0x04, 0x20,0x08,0x05,0x03, 0x01,0x03,0x02,0x08,
0x0B,0x01,0x0C,0x08, 0x04,0x04,0x01,0x05, 0x03,0x08,0x03,0x21, 0x01,0x0B,0x08,0x0B,
0x01,0x04,0x09,0x08, 0x03,0x20,0x01,0x02, 0x51,0x08,0x04,0x24, 0x01,0x0C,0x08,0x0B,
0x01,0x05,0x02,0x08, 0x02,0x25,0x01,0x02, 0x36,0x08,0x04,0x41, 0x01,0x02,0x20,0x08,
0x05,0x01,0x01,0x05, 0x03,0x08,0x02,0x25, 0x01,0x04,0x09,0x08, 0x03,0x20,0x01,0x02,
0x41,0x08,0x0C,0x01}; //0x07后面的值都是变换后的flag,可以不用管
int i,j,k = 0;
/*int a1[] = {0x04,0x10,0x08, 0x03,0x05,0x01,0x04, 0x20,0x08,0x05,0x03, 0x01,0x03,0x02,0x08,
0x0B,0x01,0x0C,0x08, 0x04,0x04,0x01,0x05, 0x03,0x08,0x03,0x21, 0x01,0x0B,0x08,0x0B,
0x01,0x04,0x09,0x08, 0x03,0x20,0x01,0x02, 0x51,0x08,0x04,0x24, 0x01,0x0C,0x08,0x0B,
0x01,0x05,0x02,0x08, 0x02,0x25,0x01,0x02, 0x36,0x08,0x04,0x41, 0x01,0x02,0x20,0x08,
0x05,0x01,0x01,0x05, 0x03,0x08,0x02,0x25, 0x01,0x04,0x09,0x08, 0x03,0x20,0x01,0x02,
0x41,0x08,0x0C,0x01, 0x07,0x22,0x07,0x3F, 0x07,0x34,0x07,0x32, 0x07,0x72,0x07,0x33,
0x07,0x18,0x07,0xA7,0xFF,0xFF,0xFF, 0x07,0x31,0x07,0xF1,0xFF,0xFF,0xFF, 0x07,0x28,0x07,
0x84,0xFF,0xFF,0xFF, 0x07,0xC1,0xFF,0xFF,0xFF,0x07,0x1E, 0x07,0x7A,0};*/
int flag[15] = {0};
for(i = 0 ; i < 15 ; i++)
{
for(k = 33 ; k <= 'z'; k ++) //暴力破解flag
{
if(f(a1,k,v))
{
flag[i] = k;
break;
}
}
}
printf("flag{");
for(i = 0 ; i < 15 ; i++)
{
printf("%c",flag[i]);
}
printf("}\n");
return 0;
}
运行结果
得到flag: flag{757515121f3d478}