这是我们下载拿到的程序,双击运行
要输入密码
1.查壳
是32位exe文件,没有壳
2.用32位IDA打开
找到主函数_main_0
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
DWORD v3; // eax
DWORD v4; // eax
char Str[260]; // [esp+4Ch] [ebp-310h] BYREF
int v7; // [esp+150h] [ebp-20Ch]
char String1[260]; // [esp+154h] [ebp-208h] BYREF
char Destination[260]; // [esp+258h] [ebp-104h] BYREF
memset(Destination, 0, sizeof(Destination));
memset(String1, 0, sizeof(String1));
v7 = 0;
printf("pls input the first passwd(1): ");
scanf("%s", Destination);
if ( strlen(Destination) != 6 )
{
printf("Must be 6 characters!\n");
ExitProcess(0);
}
v7 = atoi(Destination);
if ( v7 < 100000 )
ExitProcess(0);
strcat(Destination, "@DBApp");
v3 = strlen(Destination);
sub_40100A((BYTE *)Destination, v3, String1);
if ( !_strcmpi(String1, "6E32D0943418C2C33385BC35A1470250DD8923A9") )
{
printf("continue...\n\n");
printf("pls input the first passwd(2): ");
memset(Str, 0, sizeof(Str));
scanf("%s", Str);
if ( strlen(Str) != 6 )
{
printf("Must be 6 characters!\n");
ExitProcess(0);
}
strcat(Str, Destination);
memset(String1, 0, sizeof(String1));
v4 = strlen(Str);
sub_401019((BYTE *)Str, v4, String1);
if ( !_strcmpi("27019e688a4e62a649fd99cadaafdb4e", String1) )
{
if ( !(unsigned __int8)sub_40100F(Str) )
{
printf("Error!!\n");
ExitProcess(0);
}
printf("bye ~~\n");
}
}
return 0;
}
分析发现,要输入两次密码
第一次输入是Destination
,atoi
函数将字符串转换成整数,赋值给v7
,v7
小于100000则程序退出,所以它是大于100000的。strcat
函数在Destination
后面追加了一段字符串@DBApp
。
这里出现一个sub_40100A
函数,进去看看
这里出现一堆函数,上网去查,知道这些是用来进行哈希加密的,0x8003u
是标识符,对应加密方式,这里是sha1
加密。
知道了这些我们可以使用脚本把密码爆破出来
import hashlib
string='@DBApp'
for i in range(100000, 999999): #根据v7可以知道密码的范围
flag=str(i)+string
x=hashlib.sha1(flag.encode("utf-8"))
y=x.hexdigest()
if "6e32d0943418c2c33385bc35a1470250dd8923a9" == y:
print(flag)
break
>>>123321@DBApp
第一次输入的密码是123321
往下分析第二次输入的密码
第二次的输入是Str
,然后经过strcat
把Destination
追加在了str
后面。
又出现一个函数sub_401019
跟进去看看
还是哈希加密,不过这里的标识符是0x8003u
,是MD5
加密。
但这次并没有给Str
,我们不能使用暴力破解。
往后看,发现在加密之后有一个判断sub_40100F
,跟Str
有关
跟进去看看
这里又出现了一堆不认识的函数,那只能一个一个查了
FindResourceA
是一个Windows API函数,用于在指定的模块中查找指定类型和名称的资源。这里的作用就是在AAA
文件中查找字符e
。
我们用Rscourse Hacker打开下载的程序
没什么发现,接着往下看,有一个sub_401005
函数,跟进去看看
是一个异或函数,a2
是从前面一堆函数返回的指针,应该是指向AAA
文件中的位置,文件首指针,然后把它和Str
异或,结果输出为一个.rtf
文件。
我们只需要知道Str
的前六位即可,因为我们输入的密码长度是6位。
我们在桌面上创建一个.rtf
文件,用Rscourse Hacker打开
前六位是'{\rtf1'
,发现任意rtf
文件都是这样的结构,把.rtf
和AAA
文件前六位异或,就可以得到Str
的前六位。
写脚本
a2=[0x05, 0x7D, 0x41, 0x15, 0x26, 0x01]
rtf='{\\rtf1'
rtf=list(rtf)
for i in range(0,len(rtf)):
rtf[i]=ord(rtf[i])
v5=6
flag=''
for i in range(0,6):
flag+=chr(a2[i] ^ rtf[i])
print(flag)
>>>~!3a@0
然后我们把两次密码都输入进去
会生成一个.rtf
文件
打开之后
flag{N0_M0re_Free_Bugs}
提交,成功!!!
补充
atoi
函数
atoi函数是将字符串转换成整数。
int atoi (const char * str);
该函数的返回值为int类型的整数,转换后的值不可超出int可表示的范围。