该crackme一开始还有个验证keyfile的操作,
比较隐蔽,只有验证成功才有提示
00401000 >/$ 6A 00 push 0 ; /hTemplateFile = NULL
00401002 |. 68 80000000 push 80 ; |Attributes = NORMAL
00401007 |. 6A 03 push 3 ; |Mode = OPEN_EXISTING
00401009 |. 6A 00 push 0 ; |pSecurity = NULL
0040100B |. 6A 00 push 0 ; |ShareMode = 0
0040100D |. 68 00000080 push 80000000 ; |Access = GENERIC_READ
00401012 |. 68 6B234000 push 0040236B ; |FileName = "ACG.key"
00401017 |. E8 84040000 call <jmp.&KERNEL32.CreateFileA> ; \CreateFileA
0040101C |. 83F8 FF cmp eax, -1 ; 由上可知keyfile名叫"ACG.key"
0040101F |. 0F84 59010000 je 0040117E
00401025 |. A3 73234000 mov [402373], eax
0040102A |. 6A 00 push 0 ; /pFileSizeHigh = NULL
0040102C |. FF35 73234000 push dword ptr [402373] ; |hFile = NULL
00401032 |. E8 51040000 call <jmp.&KERNEL32.GetFileSize> ; \GetFileSize
00401037 |. 83F8 0C cmp eax, 0C ; keyfile文件长0C个字节
0040103A |. 0F85 3E010000 jnz 0040117E
00401040 |. 6A 0C push 0C ; /MemSize = C (12.)
00401042 |. 6A 00 push 0 ; |Flags = GMEM_FIXED
00401044 |. E8 39040000 call <jmp.&KERNEL32.GlobalAlloc> ; \GlobalAlloc
00401049 |. A3 7B234000 mov [40237B], eax
0040104E |. 6A 00 push 0 ; /pOverlapped = NULL
00401050 |. 68 77234000 push 00402377 ; |pBytesRead = crcme1.00402377
00401055 |. 6A 0C push 0C ; |BytesToRead = C (12.)
00401057 |. FF35 7B234000 push dword ptr [40237B] ; |Buffer = NULL
0040105D |. FF35 73234000 push dword ptr [402373] ; |hFile = NULL
00401063 |. E8 14040000 call <jmp.&KERNEL32.ReadFile> ; \ReadFile
00401068 |. 8B3D 7B234000 mov edi, [40237B]
edi指向从ACG.key文件读取的字符串指针的首地址
0040106E |. 33DB xor ebx, ebx
00401070 |. 8A1F mov bl, [edi]
取该字符串的字符,bl当前指向的是第一个字符
00401072 |. 80F3 1B xor bl, 1B
00401075 |. C1C3 02 rol ebx, 2
00401078 |. 81F3 68010000 xor ebx, 168
0040107E |. 85DB test ebx, ebx
00401080 |. 0F85 F8000000 jnz 0040117E ; 跳就验证keyfile失败
00401080 |. 0F85 F8000000 jnz 0040117E ; 跳就验证keyfile失败
jnz就失败,可见
0040107E |. 85DB test ebx, ebx
的值必须为0,所以
00401078 |. 81F3 68010000 xor ebx, 168
就可以推导出此时ebx值为168,只有168 xor 168 = 0,继续向上逆推
00401075 |. C1C3 02 rol ebx, 2
ebx << 2 = 168H,所以ebx = 168H >> 2 =168H /4 = 5A,请不要忘记这里的数字都是16进制的
00401072 |. 80F3 1B xor bl, 1B
bl xor 1B = 5A => bl = 5A xor 1B => bl = 41H,41H对应的ASCII码是字母'A',所以keyfile的第一个字符为'A',同理可以推导出其它字符,最后得到keyfile的内容为"ACG The Best",哈王婆卖瓜呐,保存为ACG.key,重新运行程序,哈,看到提示了吧“Key File OK teraz tylko Name/Serial!”