其实此题并非很难的嘛,宝宝这就讲一下啦~
首先用IDA载入,审阅左侧函数名列表,看到第一个函数就是DialogFunc,顾名思义为“对话函数”,极有可能负责了交互界面的相关功能,我们双击它,看到右侧汇编区域中出现“密钥无效”(“密钥无效”存储在变量aZgb里)等敏感字符串,这正是出现在交互窗口中的信息,我们自然而然想到去分析返回“密钥无效”这一信息的逻辑判断的相关算法,我们F5看看DialogFunc的源码:
发现这里有一个if判断(这里当然指的是内层那个啦),在!sub_4011D0()的值为false 即0时,就会弹出消息框,内容是aZgb即密钥无效,也就是说,当输入正确的注册码(即flag)时,!sub_4011D0()值就会是1,即sub_4011D0()的返回值为0,我们要做的就是分析一下怎么才能让sub_4011D0()返回0。
查看sub_4011D0()的源码:
其中,有两个GetDlgItemTextA,第一个是读取用户名,第二个是读取注册码;我们现在来看返回值,是result,我们期望result的值是0,那么执行外层if时,条件应成立,实际上用户名是hello时已经能保证成立了,这个很明显,所以关键就是分析内层的逻辑,内层的那个if其实又是句没用的废话…这里真正关键的问题在于,让result的值是0,即:
lstrcmpA(&String1, String) != 0的值是0,即lstrcmpA(&String1, String)的值是0,即string1等于string,此处lstrcmp函数的功能大家自己查百度不难了解到,不懂的朋友自己去看一下很容易就看懂了。那么string1就是输入的注册码也就是我们的flag,也就是说正确的flag就是string,我们只要分析出string这一字符串到底是什么就OK了。注意,开始的时候string就是用户名hello,但是就在最后关头,一个字符串尾接函数lstrcatA已经将string改变了,所做的改变就是在原来的“hello”后面接上了字符串string2,于是,现在的任务又变成了确定string2的值,那么string2的值是怎么确定的呢?正是上面那段while循环的算法,我们下面给出这段的截图:
算法对string的每个字符进行计算,结果赋给string2的对应字符,就把string2算出来了,我写出了对应的C语言代码:
#include <stdio.h>
int main(){
int a[5];
int r[5];
int i;
for(i=0;i<=4;i++){
a[i]=getchar();
r[i]=0;
}
for(i=0;i<=4;i++){
r[i]=(i+ i*a[i]*a[i]) % 66 + 33;
}
printf("\n");
for(i=0;i<=4;i++){
printf("%c",r[i]);
}
}
运行程序输入“hello”,就会打印正确的string2:
所以string的值就是“hello!GAOU”,即flag~~~
转自实验吧,原文作者实验吧ID Diyah Velly-Magpie