一直是用TP/Delphi的。平時也喜歡玩玩彙編。沒事破破軟體玩,不過水平只能對付明碼比較……faint
最近看見一個Keygen挺好玩的,可是人家不給模板,只好自己動手了。反了幾天,挺有心得。於是就寫下來,大牛們不要扔板磚。
如需ZT,請先聯絡我
====================================================================
發現自己有個特別的愛好,喜歡收集KeyGen的模板。怎麼說呢?感覺那些玩意既
小巧又精緻,特別是一些破解組織的KeyGen,還有一些特效在裡面。不過很明顯,他
們是不大會把模板放出來的。這樣,只有試著從KeyGen的反彙編結果入手,嘗試恢復
出原始碼了。所幸的是,為了減少最終檔案的大小,KeyGen一般是用SDK寫的,所用
語言不外乎ASM、Delphi、VC。做個逆向還不算太難。
OK,先選個犧牲品。首先執行,出來個協議框,點同意,出主介面。脫殼,修復
資源,用peid可以看出是Delphi的。用IDA反一下。
0000:00405370 start:
0000:00405370 push ebp
0000:00405371 mov ebp, esp
0000:00405373 add esp, 0FFFFFFF4h
0000:00405376 mov eax, offset dword_405338
0000:0040537B call @Sysinit@@InitExe$qqrv ; Sysinit::__linkproc__ InitExe(void)
0000:00405380 push 0
0000:00405382 call GetModuleHandleA_0
0000:00405387 mov ds:hInstance, eax
//注意,這是一個全域性變數
0000:0040538C push 1F1F1Fh
0000:00405391 call CreateSolidBrush
0000:00405396 mov ds:hbr, eax
0000:0040539B push 70h
0000:0040539D mov eax, ds:hInstance
0000:004053A2 push eax
0000:004053A3 call LoadCursorA
0000:004053A8 mov ds:hCursor, eax
0000:004053AD push 64h
0000:004053AF mov eax, ds:hInstance
0000:004053B4 push eax
0000:004053B5 call LoadIconA
0000:004053BA mov ds:dword_4076E8, eax
//這裡應該是把得到的Handle存放起來,IDA有時有點問題的
0000:004053BF push offset sub_404DD4
//非常明顯,這裡是一個Callback。還有其他的地方需要一個sub的地址嗎?
//當然,這是指下面沒有跟ret的情況!
0000:004053C4 xor ecx, ecx
0000:004053C6 mov edx, 3E8h
0000:004053CB mov eax, ds:hInstance
0000:004053D0 call sub_403CCC
//跟進去!
0000:004053D5 cmp ds:dword_4060B0, 0
0000:004053DC jz short loc_4053F4
0000:004053DE push offset sub_404A44
0000:004053E3 xor ecx, ecx
0000:004053E5 mov edx, 7D0h
0000:004053EA mov eax, ds:hInstance
0000:004053EF call sub_403CCC
0000:004053F4
0000:004053F4 loc_4053F4:
0000:004053F4 mov eax, ds:hbr
0000:004053F9 push eax
0000:004053FA call DeleteObject
0000:004053FF push 0
0000:00405401 call ExitProcess_0
0000:00405406 call @System@@Halt0$qqrv ; System::__linkproc__ Halt0(void)
可以看到,開頭和結尾的兩個call很有意思,其實是System裡的東西。這裡可以
看到,主程式很短,而且退出時用了ExitProcess而不是自然結束,有5個全域性變數(
在ds段裡的)。sub_403CCC和sub_404A44分別進去看看,是一段呼叫
DialogBoxParamA的子程式。OK,sub_403CCC看來就是協議框,而sub_404A44應該就
是主對話方塊了。這裡把sub_403CCC列出來:
0000:00403CCC sub_403CCC proc near
0000:00403CCC
0000:00403CCC
0000:00403CCC lpDialogFunc = dword ptr 8
0000:00403CCC
0000:00403CCC push ebp
0000:00403CCD mov ebp, esp
0000:00403CCF push ebx
0000:00403CD0 push 0 ; dwInitParam
0000:00403CD2 mov ebx, [ebp+lpDialogFunc]
//就是Callback
0000:00403CD5 push ebx ; lpDialogFunc
0000:00403CD6 push ecx ; hWndParent
0000:00403CD7 push edx ; lpTemplateName
0000:00403CD8 push eax ; hInstance
0000:00403CD9 call DialogBoxParamA
0000:00403CDE pop ebx
0000:00403CDF pop ebp
0000:00403CE0 retn 4
0000:00403CE0 sub_403CCC endp
結合上面呼叫此程式的程式碼,可以得到主程式的src:
Var
h_Icon:HICON;
h_Inst:HMODULE;
h_Cur:hCursor;
h_Brush:HBRUSH;
Flag:Boolean;
Begin
h_Inst:=GetModuleHandle(nil);
h_Brush:=CreateSolidBrush($1F1F1F);
h_Cur:=LoadCursor(h_Inst,MAKEINTRESOURCE(LINKCURSOR));
h_Icon:=LoadIcon(h_Inst,MAKEINTRESOURCE(MAINICON));
//顯示協議對話方塊
DialogBox(h_Inst,LPCTSTR(IDD_LICENSEDLG),0,@LicenseProc);
If Flag Then DialogBox(h_Inst,LPCTSTR(IDD_MAINDLG),0,@MainProc);
DeleteObject(h_Brush);
//退出程式
ExitProcess(0);
End.
有趣的地方出來了:Flag沒有賦值?答案是:在LicenseProc裡!