这题很好玩。首先是PEID查壳,32位的无壳程序,拖入IDA,找到关键代码
char *sub_401020()
{
char *result; // eax@19
char v1; // [sp+Ch] [bp-110h]@1
char v2; // [sp+4Ch] [bp-D0h]@11
char *v3; // [sp+50h] [bp-CCh]@1
char v4; // [sp+54h] [bp-C8h]@1
char v5; // [sp+5Dh] [bp-BFh]@1
char v6; // [sp+94h] [bp-88h]@15
char v7; // [sp+98h] [bp-84h]@1
char v8; // [sp+99h] [bp-83h]@1
__int16 v9; // [sp+10Dh] [bp-Fh]@1
char v10; // [sp+10Fh] [bp-Dh]@1
char v11; // [sp+110h] [bp-Ch]@11
char v12; // [sp+114h] [bp-8h]@5
int v13; // [sp+118h] [bp-4h]@4
memset(&v1, 0xCCu, 0x110u);
v7 = 0;
memset(&v8, 0, 0x74u);
v9 = 0;
v10 = 0;
qmemcpy(&v4, "********* * ** * ** ** * ** ** * #* ** **** ** *********", 0x41u);
v3 = &v5;
printf("Please input your key:\n");
gets(&v7);
if ( strlen(&v7) != 22 ) // 长度为22
{
printf("Sorry you are wrong!\n");
system("pause");
exit(1);
}
v13 = 0;
do
{
v12 = *(&v7 + v13);
if ( v12 != 107 && v12 != 106 && v12 != 104 && v12 != 108 ) // 只能输入这几个数
{
printf("Sorry you are wrong!\n");
system("pause");
exit(2);
}
v11 = *(&v7 + v13);
v2 = v11;
// 不同的输入对应不同的走法
if ( v11 == 104 )
{
if ( --v3 < &v4 || v3 > &v6 || (result = (char *)*v3, result == (char *)42) )
{
printf("Sorry you are wrong!\n");
system("pause");
exit(3);
}
if ( *v3 == 35 )
{
LABEL_41:
printf("Good!\n");
system("pause");
exit(0);
}
}
else if ( v2 == 106 )
{
v3 += 8;
if ( v3 < &v4 || v3 > &v6 || *v3 == 42 )
{
printf("Sorry you are wrong!\n");
system("pause");
exit(3);
}
result = (char *)*v3;
if ( result == (char *)35 )
goto LABEL_41;
}
else if ( v2 == 107 )
{
v3 -= 8;
if ( v3 < &v4 || v3 > &v6 || *v3 == 42 )
{
printf("Sorry you are wrong!\n");
system("pause");
exit(3);
}
result = v3;
if ( *v3 == 35 )
goto LABEL_41;
}
else
{
if ( ++v3 < &v4 || v3 > &v6 || *v3 == 42 )
{
printf("Sorry you are wrong!\n");
system("pause");
exit(4);
}
result = v3;
if ( *v3 == 35 )
goto LABEL_41;
}
++v13;
}
while ( v13 < 25 );
return result;
}
上面的代码首先给出了一段字符********* * ** * ** ** * ** ** * #* ** **** ** *********,现在要求输入一段字符串,只能包含四种字符,分别是h,j,k,l,长度是22位。这四种字符都对应一种走法。现在我们的起始地址在第十位,要求通过这几种走法,不可以经过*,走到#,我们要找的就是这样一种走法。可以通过深度优先搜索解决(DFS),遍历所有可能走法,最后跳出一种满足条件的走法,给出代码:
#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
using namespace std;
char num[25];
int dfsmap[70]={1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,1,1,0,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,0,0,1,0,1,1,0,1,1,1,1,0,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1};
void dfs(int x,int sumn)
{
int i,j,k;
if(sumn==22)
{
if(x==36) // 满足条件就输出
{
for(i=0;i<=21;i++)
{
cout<<num[i];
}
cout<<endl;
}
return;
}
// 四种走法
if(x-1>=0&&dfsmap[x-1]!=1)
{
num[sumn]='h';
dfs(x-1,sumn+1);
num[sumn]=0;
}
if(x+8<=63&&dfsmap[x+8]!=1)
{
num[sumn]='j';
dfs(x+8,sumn+1);
num[sumn]=0;
}
if(x-8>=0&&dfsmap[x-8]!=1)
{
num[sumn]='k';
dfs(x-8,sumn+1);
num[sumn]=0;
}
if(x+1<=63&&dfsmap[x+1]!=1)
{
num[sumn]='l';
dfs(x+1,sumn+1);
num[sumn]=0;
}
return;
}
int main()
{
dfs(9,0);
return 0;
}
结果是******kkkhhhjjjl
转自实验吧,原文作者实验吧ID chih1e