1 ; int __cdecl main(int argc, const char **argv, const char **envp) 2 _main proc near 3 4 Buf= byte ptr -114h 5 var_110= dword ptr -110h 6 var_10C= dword ptr -10Ch 7 var_108= dword ptr -108h 8 Filename= byte ptr -104h 9 argc= dword ptr 4 10 argv= dword ptr 8 11 envp= dword ptr 0Ch 12 13 sub esp, 114h 14 push ebx 15 push esi 16 push edi 17 push offset Format ; "欢迎各位来到52pojie,欢迎各位来尝试我的"... 18 call _printf 19 push offset aUZScQT ; "最近重新再学一遍C语言,就写了这个,就当练"... 20 call _printf 21 push offset aByTk2012513 ; "by TK 2012-5-13\n" 22 call _printf 23 push offset asc_4090A0 ; "\n\n" 24 call _printf 25 add esp, 10h 26 lea eax, [esp+120h+Filename] 27 push 104h ; nSize,装载到缓冲区lpFileName的最大值,这里为260,在编程中为MAX_PATH 28 push eax ; lpFilename,一个指针,这里是存放获取到程序目录所在的位置的地址 29 push 0 ; hModule,实例的句柄,这里为本实例的句柄 30 call ds:GetModuleFileNameA 31 lea ecx, [esp+120h+Filename] 32 push '\' ; Ch 33 push ecx ; Str 34 call _strrchr ;查找一个字符c在另一个字符串str中末次出现的位置 35 mov byte ptr [eax], 0 36 mov edi, offset aNot_key_dat ; "\\not_key.dat" 37 or ecx, 0FFFFFFFFh 38 xor eax, eax 39 repne scasb 40 not ecx 41 sub edi, ecx 42 lea edx, [esp+128h+Filename] 43 mov esi, edi 44 mov ebx, ecx 45 mov edi, edx 46 or ecx, 0FFFFFFFFh 47 repne scasb 48 mov ecx, ebx 49 dec edi 50 shr ecx, 2 51 rep movsd 52 mov ecx, ebx 53 lea eax, [esp+128h+Filename] 54 and ecx, 3 55 push offset Mode ; "r" 56 rep movsb 57 push eax ; Filename 58 call _fopen ;读取一个文件,文件名在参数中,读取方式也在参数中 59 mov edi, eax ;读取结果放入eax,然后又复制到edi中 60 add esp, 10h 61 test edi, edi 62 jnz short loc_4010AA
总的来说,这段程序的目的就是打开keyfile文件,如果打开失败,就跳转到失败提示的地方。(这样,我们就在程序当前的目录下新建一个keyfile文件,文件名为not_key.dat)
如果要爆破这个程序,先要把这里改为jmp或nop掉。
如果打开文件成功,则继续判断。
通过IDA的F5功能,一些修改,变成了下面这样:
1 fp = fopen(&Filename, "r"); 2 fp_same = fp; 3 if ( fp ) 4 { 5 *(_DWORD *)Buf = 0; 6 v16 = 0; 7 v17 = 0; 8 v18 = 0; 9 fgets(Buf, 16, fp); 10 if ( strcmp(Buf, "Hello World") ) 11 v14 = "You didn't pass the test\n"; 12 else 13 v14 = "Congratulations! You are the best one!\n"; 14 printf(v14); 15 fclose(fp_same); 16 } 17 else 18 { 19 printf("You didn't pass the test\n"); 20 } 21 printf("\n\n"); 22 return system("pause");
通过打开文件,读取文件的16个字节,然后与Hello World进行对比。
总结:这个程序的思路是很清晰的,读取keyfile,如果连keyfile都没有,那就不可能注册了。
如果存在keyfile的话,那么从keyfile中读取16个字节,看它是否为我们所对应的key,如果正确,则提示正确
如果不正确,那就显示不正确呗。
我对这个程序做了爆破测试,结果发现会出现异常,那么是什么原因呢?一,文件没有读取成功,而我们使用fgets函数,二,文件没有打开,也就是fopen没有返回
而我们又调用了fclose,所以爆破的时候要记得把这两个函数nop掉。