Delphi逆向工程筆記[1]

看雪資料發表於2004-10-27

一直是用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     ebpesp
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     eaxds:hInstance
0000:004053A2                 push    eax
0000:004053A3                 call    LoadCursorA
0000:004053A8                 mov     ds:hCursor, eax
0000:004053AD                 push    64h
0000:004053AF                 mov     eaxds: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     ecxecx
0000:004053C6                 mov     edx, 3E8h
0000:004053CB                 mov     eaxds: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     ecxecx
0000:004053E5                 mov     edx, 7D0h
0000:004053EA                 mov     eaxds:hInstance
0000:004053EF                 call    sub_403CCC
0000:004053F4
0000:004053F4 loc_4053F4:
0000:004053F4                 mov     eaxds: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     ebpesp
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裡!

相關文章