第一次逆向來個簡單的增強信心,http://www.crackmes.de/users/lucifer/first_c_crackme/。(這個圖片裏有crackme,右鍵保存下圖標,把後綴改成zip,便可。)ios
1. 用OllyDbg加載停在程序開始處:00401000,接着在00401013處調用了call 00401080,跟進去,看到這個過程當中各類SetXXX,再往下發現一個ExitProcess,而這之上有調用00401165處的call 004014E2,全部的處理應該都在這裏面了,進入004014E2過程。序列號的運算都在這裏面了。算法
2. 看了別人的解決方案是,直接在"Searce for -> All referenced text strings"中查找"Your Name:",直接定位到004014E2過程當中,更加快捷有效。spa
3. 核心代碼以下:code
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++寫了以下算號器:orm
// 在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; }