第一次逆向来个简单的加强信心,http://www.crackmes.de/users/lucifer/first_c_crackme/。(这个图片里有crackme,右键保存下图标,把后缀改为zip,即可。)
1. 用OllyDbg加载停在程序开始处:00401000,接着在00401013处调用了call 00401080,跟进去,看到这个过程中各种SetXXX,再往下发现一个ExitProcess,而这之上有调用00401165处的call 004014E2,所有的处理应该都在这里面了,进入004014E2过程。序列号的运算都在这里面了。
2. 看了别人的解决方案是,直接在"Searce for -> All referenced text strings"中查找"Your Name:",直接定位到004014E2过程中,更加快捷有效。
3. 核心代码如下:
00401668 |. 8D85 F8FEFFFF lea eax, dword ptr [ebp-108] ; | 0040166E |. 890424 mov dword ptr [esp], eax ; | 00401671 |. E8 5AF60000 call <jmp.&msvcrt.strlen> ; strlen 00401676 |. 89C2 mov edx, eax ; 得到了name的长度存放在eax中,然后赋给edx 00401678 |. 69D2 CD750800 imul edx, edx, 875CD ; 将长度乘以0x875CD 0040167E |. B8 1F85EB51 mov eax, 51EB851F 00401683 |. F7E2 mul edx 00401685 |. 89D0 mov eax, edx 00401687 |. C1E8 05 shr eax, 5 ; 这一段4行代码为用edx/0x64,结果放在eax中 0040168A |. 69C0 90FCFFFF imul eax, eax, -370 ; 在将eax乘以-0x370 00401690 |. BA 00000000 mov edx, 0 00401695 |. 52 push edx ; ||format => NULL 00401696 |. 50 push eax ; ||s 00401697 |. DF2C24 fild qword ptr [esp] ; ||将上面计算得到的eax值转为双精度浮点数8字节 0040169A |. 8D6424 08 lea esp, dword ptr [esp+8] ; || 0040169E |. DD9D F0FBFFFF fstp qword ptr [ebp-410] ; ||浮点数保存下来 004016A4 |. DD85 F0FBFFFF fld qword ptr [ebp-410] ; ||再进入浮点寄存器中 004016AA |. DD5C24 08 fstp qword ptr [esp+8] ; ||浮点数放入堆栈待用,下面%i只用到了前面4字节 004016AE |. C74424 04 691>mov dword ptr [esp+4], 00401469 ; ||ASCII "%i-x019871" 004016B6 |. 8D85 F8FCFFFF lea eax, dword ptr [ebp-308] ; || 004016BC |. 890424 mov dword ptr [esp], eax ; || 004016BF |. E8 FCF50000 call <jmp.&msvcrt.sprintf> ; |sprintf
4. 根据算法,用C++写了如下算号器:
// 在Microsoft Visual C++ 2008中编译 #include <iostream> #include <string> using namespace std; int main() { cout << "Input your name: "; string strName; cin >> strName; int iTemp = strName.length(); iTemp *= 0x875CD; iTemp /= 0x64; iTemp *= -0x370; unsigned unTemp = iTemp; double dTemp = unTemp; int *piTemp = (int*) &dTemp; cout << "Serial Number: " << *piTemp << "-x019871" << endl;; system("pause"); return 0; }