首先在第二十六行可以判断出,我们需要输入的字符数量为22个
发现 judge 方法是判断的主要逻辑,在第 15 行时调用判断。但是静态分析时不能生成 judge
的伪代码。
原来是因为其代码做了加密,在前面的第 7-11 行先进行 smc 自解密,后面才能正常运行。
为了可能生成 judge 的伪代码,有两种办法:
方法一:按第 7-11 行的逻辑逆向 patch 程序,再静态生成伪代码。Patch 脚本如下:
Patch 后,将有红色报错的代码按 U(取消原来定义),再按 C(重新生成汇编代码),选中
600B00-600BB5(judge 的起止位置)按 P(重新生成 function)。这时就可以
按 F5 生成 judge 的伪代码了。
方法二:在第 12 行设置断点(即自解密完成后),动态调试运行到这个位置时,程序已解密,
查看 600B00-600BB5(judge 的起止位置)的代码,按上述同样方式修复出错的
地方(用 U C P 键)。将有红色报错的代码按 U(取消原来定义),再按 C(重新生成汇
编代码),选中 600B00-600BB5(judge 的起止位置)按 P(重新生成 function)。
这时就可以按 F5 生成 judge 的伪代码了。
伪代码:
之后就是简单的逆向
先看代码
输入的passwd1必须是6位数,然后把"@DBApp"连接在passwd1后面
进入sub_40100A
这里查阅官方文档得知是sha1加密
最终得到的密文为
6E32D0943418C2C33385BC35A1470250DD8923A9
那么就可以爆出来passwd1
mport hashlib
key = "@DBApp"
for i in range(100000,1000000):
a = str(i)+key
s = hashlib.sha1(a.encode())
h = s.hexdigest()
if "6e32d0943418c2c33385bc35a1470250dd8923a9" in h:
print(h)
print(a)
#passwd1 = 123321
#123321@DBApp
往下看
和前面的passwd1是大同小异,输入的passwd2与"123321@DBApp"链接起来传进去加密,不过这次选择了MD5加密得到密文
27019e688a4e62a649fd99cadaafdb4e
爆破不太实际,接着进sub_40100F
第14行可以看到从"AAA"拿出来字符,和变化过的字符一起传入到22行的sub_401005
在sub_401005中,变化过的字符和AAA拿出来的字符之间进行异或
然后输出一个叫:dbapp.rtf的文件。
现在主要是得知道AAA里面的字符是什么
用一个叫:Resource Hacker的工具可以看到文件内的资源
因为我们需要的是前6位的passwd2,所以选择AAA的前6位与rtf文件头的前6位进行异或,就可以得到输入的passwd2
AAA=[0x05,0x7D,0x41,0x15,0x26,0x01]
rtf = "{\\rtf1"
passwd2 = ''
for i in range(0,len(rtf)):
c = ord(rtf[i])^AAA[i]
passwd2 += chr(c)
print(passwd2)
#passwd2 = ~!3a@0
打开程序输入两个passwd就可以得到dbapp.rtf,得到flag
比较简单算法逆向打开IDA分析主函数
找到关键点:
这里可以看出我们输入的值经过位移再取余再位移,最终得到上面的数组。
那么就可以选择ascii码表爆破,但是我选择和%刚一刚。。。
#include<stdio.h>
#include<stdlib.h>
int main(){
int code[]={81,115,119,51,115,106,95,108,122,52,95,85,106,119,64,108,0};
for (int j = 0; j <= 15; j++ ){
if(code[j]> 64 && code[j] <= 90){
code[j] = code[j]-65+51;
}
if(code[j] > 96 && code[j] <= 122 ){
if(code[j]>=98 &&code[j]<115){
code[j]= code[j]-97+26+79;
}else if(code[j]>=115){
code[j] = code[j]-97+79;
}
}
printf("%c",code[j]);
}
return 0;
}