Delphi逆向工程筆記[7](終結篇)
今天是列寧格勒保衛戰中,偉大的“生命之路”開通的日子。紀念一下。
本以為About沒有什麼的,但分析下來才發現絲毫不亞於那個標題欄漸變。還好,
長長的路就要到盡頭了……
================================================================================
下面就是最後的AboutProc。
0000:004045F0 DialogFunc proc near
0000:004045F0
0000:004045F0 Rect = tagRECT ptr -58h
0000:004045F0 Paint = PAINTSTRUCT ptr -48h
0000:004045F0 pt = POINT ptr -8
0000:004045F0 hWnd = dword ptr 8
0000:004045F0 arg_4 = dword ptr 0Ch
0000:004045F0 arg_8 = dword ptr 10h
0000:004045F0 arg_C = word ptr 14h
0000:004045F0
0000:004045F0 push ebp
0000:004045F1 mov ebp, esp
0000:004045F3 add esp, 0FFFFFFA8h
//100h-A8h=58h
0000:004045F6 push ebx
0000:004045F7 push esi
0000:004045F8 mov esi, [ebp+hWnd]
0000:004045FB xor ebx, ebx
0000:004045FD mov eax, [ebp+arg_4]
0000:00404600 cmp eax, 113h ; WM_TIMER
0000:00404605 jg short loc_404632
0000:00404607 jz loc_4047B8
0000:0040460D sub eax, 0Fh ; WM_PAINT
0000:00404610 jz loc_404867
0000:00404616 sub eax, 1Ch ; WM_DRAWITEM
0000:00404619 jz loc_4048D7
0000:0040461F sub eax, 0E5h ; WM_INITDIALOG
0000:00404624 jz short loc_404656
0000:00404626 dec eax ; WM_COMMAND
0000:00404627 jz loc_40489C
0000:0040462D jmp loc_404925
0000:00404632 loc_404632:
0000:00404632 sub eax, 136h ; WM_CTLCOLORDLG
0000:00404637 jz loc_4048E3
0000:0040463D sub eax, 2 ; WM_CTLCOLORSTATIC
0000:00404640 jz loc_404904
0000:00404646 sub eax, 0C9h ; WM_LBUTTONDOWN
0000:0040464B jz loc_404826
0000:00404651 jmp loc_404925
...
0000:00404925 loc_404925:
0000:00404925 xor ebx, ebx
0000:00404927 loc_404927:
0000:00404927 mov eax, ebx
0000:00404929 pop esi
0000:0040492A pop ebx
0000:0040492B mov esp, ebp
0000:0040492D pop ebp
0000:0040492E retn 10h
0000:0040492E DialogFunc endp
框架及大致相同處:
Function AboutProc(hDlg:HWND;Msg,wParam,lParam:DWORD):LRESULT;stdcall;
Var
sRect:TRect;
sPaint:PAINTSTRUCT;
sPoint:TPoint;
Begin
Result:=0;
Case Msg of
WM_COMMAND:
Begin
Case wParam of
ABOUT_OK:
Begin
KillTimer(hDlg,$A8);
EndDialog(hDlg,0);
End;
ABOUT_CLOSE:
Begin
KillTimer(hDlg,$A8);
EndDialog(hDlg,0);
End;
End;
End;
WM_PAINT:
Begin
Paint(BeginPaint(hDlg,sPaint),h_Icon,szMainCaption,$767676,0,sRectA);
EndPaint(hDlg,sPaint);
End;
WM_DRAWITEM:
Begin
ItemDraw(PDrawItemStruct(lParam));
Result:=0;
End;
WM_INITDIALOG:
Begin
End;
WM_CTLCOLORDLG:
Begin
SetTextColor(wParam,$A0A0A0);
SetBkMode(wParam,TRANSPARENT);
Result:=h_Brush;
End;
WM_CTLCOLORSTATIC:
Begin
SetTextColor(wParam,$A0A0A0);
SetBkMode(wParam,TRANSPARENT);
Result:=h_Brush;
End;
WM_LBUTTONDOWN:
Begin
sPoint.x:=lParam AND $FFFF;
sPoint.y:=lParam SHR 16;
If PtInRect(sRectA,sPoint) Then
Begin
PostMessage(hDlg,WM_NCLBUTTONDOWN,2,0);
End;
End;
WM_TIMER:
Begin
End;
End;
End;
下面是WM_INITDIALOG部分:
0000:00404656 loc_404656:
0000:00404656 push offset Rect ; lpRect
//注意,一共有3個Rect,分別對應3個Dlg。這裡很容易混淆。
//我的做法是在IDA註釋里加上地址。要麼重新命名也可。
0000:0040465B push esi ; hWnd
0000:0040465C call GetClientRect
0000:00404661 mov eax, ds:Rect.top
0000:00404666 add eax, 14h
0000:00404669 mov ds:Rect.bottom, eax
0000:0040466E push 0BBDh ; nIDDlgItem
0000:00404673 push esi ; hDlg
0000:00404674 call GetDlgItem
0000:00404679 mov ds:hWnd, eax
//滾動字幕框的HWND,因為Timer的callback要的。
0000:0040467E push 0BBBh ; nIDDlgItem
0000:00404683 push esi ; hDlg
0000:00404684 call GetDlgItem
0000:00404689 mov ebx, eax
0000:0040468B push offset nullsub_3 ; LPCSTR
//其實不僅是IDA,Sourcer也有這毛病
0000:00404690 push 0 ; DWORD
0000:00404692 push 0 ; DWORD
0000:00404694 push 0 ; DWORD
0000:00404696 push 0 ; DWORD
0000:00404698 push 1 ; DWORD
0000:0040469A push 0 ; DWORD
0000:0040469C push 0 ; DWORD
0000:0040469E push 0 ; DWORD
0000:004046A0 push 2BCh ; int
0000:004046A5 push 0 ; int
0000:004046A7 push 0 ; int
0000:004046A9 push 0 ; int
0000:004046AB push 0FFFFFFF4h ; int
0000:004046AD call CreateFontA
0000:004046B2 push 0 ; lParam
0000:004046B4 push eax ; wParam
0000:004046B5 push 30h ; Msg
0000:004046B7 push ebx ; hWnd
0000:004046B8 call SendMessageA
//設定字型了
0000:004046BD push offset dword_40493C ; lpString
0000:004046C2 push 0BBBh ; nIDDlgItem
0000:004046C7 push esi ; hDlg
0000:004046C8 call SetDlgItemTextA
0000:004046CD push offset dword_404954 ; lpString
0000:004046D2 push 0BBCh ; nIDDlgItem
0000:004046D7 push esi ; hDlg
0000:004046D8 call SetDlgItemTextA
0000:004046DD push offset dword_40496C ; lpString
0000:004046E2 push esi ; hWnd
0000:004046E3 call SetWindowTextA
0000:004046E8 lea eax, [ebp+Rect]
0000:004046EB push eax ; lpRect
0000:004046EC mov eax, ds:hWnd
0000:004046F1 push eax ; hWnd
0000:004046F2 call GetClientRect
//得到滾動字幕的Rect
0000:004046F7 mov ax, word ptr [ebp+Rect.right]
0000:004046FB sub ax, word ptr [ebp+Rect.left]
0000:004046FF mov ds:word_4060C8, ax
//寬
0000:00404705 mov ax, word ptr [ebp+Rect.bottom]
0000:00404709 sub ax, word ptr [ebp+Rect.top]
0000:0040470D mov ds:word_4060CC, ax
//高度
0000:00404713 mov ax, ds:word_4060CC
//這裡的話,如果檢視xref就知道,4060CC只在這裡有賦值
0000:00404719 mov ds:word_4060C4, ax
//4060C4在其他地方有變化(dec),所以應該是類似計數器的作用
//請注意,有時xref在確定變數用途的時候很有用。
0000:0040471F mov eax, offset dword_40497C
//滾動字幕內容的地址
0000:00404724 call sub_403F94
0000:00404729 mov ds:word_4060D8, ax
//字串裡的換行數+1。注意這裡的初始值為1。就是說,即使是空字串,也
//應該在末尾加個換行。但是這裡用了mov,聯絡到sub_403F94裡有SEH,
//很容易想到在異常情況下,初始值起作用的。
0000:0040472F push 0 ; lpParam
0000:00404731 movsx eax, ds:word_4060CC
0000:00404738 push eax ; hInstance
0000:00404739 movsx eax, ds:word_4060C8
0000:00404740 push eax ; hMenu
0000:00404741 movsx eax, ds:word_4060D8
0000:00404748 shl eax, 2
0000:0040474B lea eax, [eax+eax*2]
0000:0040474E push eax ; hWndParent
0000:0040474F mov eax, ds:hWnd
0000:00404754 push eax ; nHeight
0000:00404755 push 0 ; nWidth
0000:00404757 mov eax, ds:hInstance
0000:0040475C push eax ; Y
0000:0040475D push 0 ; X
//留意一下,IDA已經第三次發飈了。而且這次跟前兩次不一樣。
//如果真按照註釋對引數是要死人的!反正……push的引數順序全部倒了……
0000:0040475F mov edx, offset dword_404A28 ; lpWindowName
0000:00404764 mov eax, offset dword_404A2C ; lpClassName
//象上面這樣只有一個引用的lpstr就直接寫字串吧。
0000:00404769 mov ecx, 50000001h ; dwStyle
//這裡的值是3個值的組合。由於該視窗是Static,所以那個1是SS_CENTER
0000:0040476E call sub_403C98
//呼叫CreateWindowEx
0000:00404773 mov ds:dword_4060D4, eax
0000:00404778 push offset sub_404484 ; dwNewLong
//專用的callback
0000:0040477D push 0FFFFFFFCh ; nIndex
0000:0040477F mov eax, ds:dword_4060D4
0000:00404784 push eax ; hWnd
0000:00404785 call SetWindowLongA
0000:0040478A push eax ; dwNewLong
0000:0040478B push 0FFFFFFEBh ; nIndex
0000:0040478D mov eax, ds:dword_4060D4
0000:00404792 push eax ; hWnd
0000:00404793 call SetWindowLongA
0000:00404798 mov eax, esi ; hWnd
0000:0040479A call sub_404358
//還好,是那個視窗特效……
0000:0040479F push 0 ; lpTimerFunc
0000:004047A1 push 3Ch ; uElapse
0000:004047A3 push 0A8h ; nIDEvent
0000:004047A8 push esi ; hWnd
0000:004047A9 call SetTimer
0000:004047AE mov ebx, 1
0000:004047B3 jmp loc_404927
sub_403F94實際是統計$0A數目的。
0000:00403F94 sub_403F94 proc near
0000:00403F94
0000:00403F94 var_4 = dword ptr -4
0000:00403F94
0000:00403F94 push ebp
0000:00403F95 mov ebp, esp
0000:00403F97 push ecx
0000:00403F98 push ebx
0000:00403F99 mov [ebp+var_4], eax
0000:00403F9C mov eax, [ebp+var_4]
//var_4裡是地址
0000:00403F9F call @System@@LStrAddRef$qqrv ; System::__linkproc__ LStrAddRef(void)
//增加引用計數
0000:00403FA4 xor eax, eax
0000:00403FA6 push ebp
0000:00403FA7 push offset loc_403FEB
0000:00403FAC push dword ptr fs:[eax]
0000:00403FAF mov fs:[eax], esp
//設定SEH
0000:00403FB2 mov bx, 1
0000:00403FB6 mov eax, [ebp+var_4]
//仍然是地址
0000:00403FB9 call @System@_16823 ; System::_16823
//取字串的淨長度。透過檢視dword_40497C附近的資料可以發現,
//dword_40497C前面的4個位元組,內容是$A8。dword_40497C的最後部分,有一個
//dword的0,加上這個0,總長度是$AC。$AC-$A8=4,恰好是一個dword。
0000:00403FBE dec eax
0000:00403FBF test eax, eax
0000:00403FC1 jl short loc_403FD5
//判斷空字串
0000:00403FC3 inc eax
//加回來
0000:00403FC4 xor edx, edx
//此時bx=1,edx=0
0000:00403FC6
0000:00403FC6 loc_403FC6:
0000:00403FC6 mov ecx, [ebp+var_4]
//字串的開頭地址
0000:00403FC9 cmp byte ptr [ecx+edx-1], 0Ah
//應該是用edx做索引,但是開始時edx=0,ecx+edw-1=(Var_4)-1,這樣
//就到了長度位元組。
0000:00403FCE jnz short loc_403FD1
0000:00403FD0 inc ebx
0000:00403FD1
0000:00403FD1 loc_403FD1:
0000:00403FD1 inc edx
0000:00403FD2 dec eax
0000:00403FD3 jnz short loc_403FC6
0000:00403FD5
0000:00403FD5 loc_403FD5:
//ebx裡應該是換行的數目+1
0000:00403FD5 xor eax, eax
0000:00403FD7 pop edx
0000:00403FD8 pop ecx
0000:00403FD9 pop ecx
0000:00403FDA mov fs:[eax], edx
//恢復SEH
0000:00403FDD push offset loc_403FF2
//實際和retn配套
//不得不說,雖然開始看到403FC6的迴圈就猜到這個是計算$0A的,但是因為是分析
//模板,開始時沒想到裡面居然會有push/ret這個變形的jmp。懷疑這個東西不是
//Delphi生成的。但是看403FE2又發現不像是手寫的,真是!@#$
0000:00403FE2
0000:00403FE2 loc_403FE2:
0000:00403FE2 lea eax, [ebp+var_4]
0000:00403FE5 call @System@@LStrClr$qqrr17System@AnsiString ; System::__linkproc__ LStrClr(System::AnsiString &)
//這裡沒有改變eax,eax還是那個地址
//清除字串?
0000:00403FEA retn
0000:00402EE8 @System@_16823 proc near
0000:00402EE8 test eax, eax
0000:00402EEA jz short locret_402EEF
0000:00402EEC mov eax, [eax-4]
0000:00402EEF
0000:00402EEF locret_402EEF:
0000:00402EEF retn
0000:00402EEF @System@_16823 endp
0000:00403FF2 loc_403FF2:
0000:00403FF2 mov eax, ebx
//返回值就是ebx
0000:00403FF4 pop ebx
0000:00403FF5 pop ecx
0000:00403FF6 pop ebp
0000:00403FF7 retn
0000:00403FF7 sub_403F94 endp
CreateWindowEx的外套:
0000:00403C98 sub_403C98 proc near
0000:00403C98
0000:00403C98 lpParam = dword ptr 8
0000:00403C98 hInstance = dword ptr 0Ch
0000:00403C98 hMenu = dword ptr 10h
0000:00403C98 hWndParent = dword ptr 14h
0000:00403C98 nHeight = dword ptr 18h
0000:00403C98 nWidth = dword ptr 1Ch
0000:00403C98 Y = dword ptr 20h
0000:00403C98 X = dword ptr 24h
0000:00403C98
0000:00403C98 push ebp
0000:00403C99 mov ebp, esp
0000:00403C9B push ebx
0000:00403C9C mov ebx, [ebp+lpParam]
0000:00403C9F push ebx ; lpParam
0000:00403CA0 mov ebx, [ebp+hInstance]
0000:00403CA3 push ebx ; hInstance
0000:00403CA4 mov ebx, [ebp+hMenu]
0000:00403CA7 push ebx ; hMenu
0000:00403CA8 mov ebx, [ebp+hWndParent]
0000:00403CAB push ebx ; hWndParent
0000:00403CAC mov ebx, [ebp+nHeight]
0000:00403CAF push ebx ; nHeight
0000:00403CB0 mov ebx, [ebp+nWidth]
0000:00403CB3 push ebx ; nWidth
0000:00403CB4 mov ebx, [ebp+Y]
0000:00403CB7 push ebx ; Y
0000:00403CB8 mov ebx, [ebp+X]
0000:00403CBB push ebx ; X
0000:00403CBC push ecx ; dwStyle
0000:00403CBD push edx ; lpWindowName
0000:00403CBE push eax ; lpClassName
0000:00403CBF push 0 ; dwExStyle
0000:00403CC1 call CreateWindowExA
0000:00403CC6 pop ebx
0000:00403CC7 pop ebp
0000:00403CC8 retn 20h
0000:00403CC8 sub_403C98 endp
滾動框的callback,有點眼熟:
0000:00404484 sub_404484 proc near
0000:00404484
0000:00404484 Rect = tagRECT ptr -50h
0000:00404484 Paint = PAINTSTRUCT ptr -40h
0000:00404484 hWnd = dword ptr 8
0000:00404484 arg_4 = dword ptr 0Ch
0000:00404484 wParam = dword ptr 10h
0000:00404484 lParam = dword ptr 14h
0000:00404484
0000:00404484 push ebp
0000:00404485 mov ebp, esp
0000:00404487 add esp, 0FFFFFFB0h
0000:0040448A push ebx
0000:0040448B push esi
0000:0040448C push edi
0000:0040448D mov esi, [ebp+arg_4]
0000:00404490 mov ebx, [ebp+hWnd]
0000:00404493 mov eax, esi
0000:00404495 sub eax, 0Fh
//如果還不能直接看出是WM_PAINT,那也就太遜了。好歹也到這裡了……總該有點長
//進吧。
0000:00404498 jnz short loc_404515
//結合下面可以看到,是典型的if then else結構
//往下就是純粹的API呼叫,實在沒什麼好說的。只是要注意暫存器變化。
0000:0040449A lea eax, [ebp+Paint]
0000:0040449D push eax ; lpPaint
0000:0040449E push ebx ; hWnd
0000:0040449F call BeginPaint
0000:004044A4 mov esi, eax
0000:004044A6 lea eax, [ebp+Rect]
0000:004044A9 push eax ; lpRect
0000:004044AA push ebx ; hWnd
0000:004044AB call GetClientRect
0000:004044B0 push 0A0A0A0h ; COLORREF
0000:004044B5 push esi ; HDC
0000:004044B6 call SetTextColor
0000:004044BB push 1 ; int
0000:004044BD push esi ; HDC
0000:004044BE call SetBkMode
0000:004044C3 push offset nullsub_2 ; LPCSTR
0000:004044C8 push 0 ; DWORD
0000:004044CA push 0 ; DWORD
0000:004044CC push 0 ; DWORD
0000:004044CE push 0 ; DWORD
0000:004044D0 push 1 ; DWORD
0000:004044D2 push 0 ; DWORD
0000:004044D4 push 0 ; DWORD
0000:004044D6 push 0 ; DWORD
0000:004044D8 push 0 ; int
0000:004044DA push 0 ; int
0000:004044DC push 0 ; int
0000:004044DE push 0 ; int
0000:004044E0 push 0FFFFFFF4h ; int
0000:004044E2 call CreateFontA
0000:004044E7 mov edi, eax
0000:004044E9 push edi ; HGDIOBJ
0000:004044EA push esi ; HDC
0000:004044EB call SelectObject
0000:004044F0 push 1 ; uFormat
0000:004044F2 lea eax, [ebp+Rect]
0000:004044F5 push eax ; lpRect
0000:004044F6 push 0FFFFFFFFh ; nCount
0000:004044F8 push offset dword_404544 ; lpString
0000:004044FD push esi ; hDC
0000:004044FE call DrawTextA
0000:00404503 lea eax, [ebp+Paint]
0000:00404506 push eax ; lpPaint
0000:00404507 push ebx ; hWnd
0000:00404508 call EndPaint
0000:0040450D push edi ; HGDIOBJ
0000:0040450E call DeleteObject
0000:00404513 jmp short loc_40452D
0000:00404515 loc_404515:
0000:00404515 push 0FFFFFFEBh ; nIndex
0000:00404517 push ebx ; hWnd
0000:00404518 call GetWindowLongA
0000:0040451D mov edx, [ebp+lParam]
0000:00404520 push edx ; lParam
0000:00404521 mov edx, [ebp+wParam]
0000:00404524 push edx ; wParam
0000:00404525 push esi ; Msg
0000:00404526 push ebx ; hWnd
0000:00404527 push eax ; lpPrevWndFunc
0000:00404528 call CallWindowProcA
0000:0040452D loc_40452D:
0000:0040452D mov eax, 1
0000:00404532 pop edi
0000:00404533 pop esi
0000:00404534 pop ebx
0000:00404535 mov esp, ebp
0000:00404537 pop ebp
0000:00404538 retn 10h
0000:00404538 sub_404484 endp
0000:004047B8 loc_4047B8:
0000:004047B8 push 14h ; dwMilliseconds
0000:004047BA call Sleep
0000:004047BF dec ds:word_4060C4
0000:004047C6 push 0 ; uFlags
0000:004047C8 movsx eax, ds:word_4060D8
0000:004047CF shl eax, 2
0000:004047D2 lea eax, [eax+eax*2]
0000:004047D5 push eax ; cy
0000:004047D6 movsx eax, ds:word_4060C8
0000:004047DD push eax ; cx
0000:004047DE movsx eax, ds:word_4060C4
0000:004047E5 push eax ; Y
0000:004047E6 push 0 ; X
0000:004047E8 push 0 ; hWndInsertAfter
0000:004047EA mov eax, ds:dword_4060D4
0000:004047EF push eax ; hWnd
0000:004047F0 call SetWindowPos
0000:004047F5 movsx eax, ds:word_4060C4
0000:004047FC movsx edx, ds:word_4060D8
0000:00404803 shl edx, 2
0000:00404806 lea edx, [edx+edx*2]
0000:00404809 add eax, edx
0000:0040480B neg eax
0000:0040480D test eax, eax
0000:0040480F jle loc_404927
0000:00404815 mov ax, ds:word_4060CC
0000:0040481B mov ds:word_4060C4, ax
0000:00404821 jmp loc_404927
看來About是這個程式的華彩樂章。滾動字幕是使用了建立子視窗,然後改變其
位置的方法。
下面就給出最後的幾個部分:
WM_INITDIALOG:
Begin
GetClientRect(hDlg,sRectA);
sRectA.Bottom:=sRectA.Top+$14;
h_ScrollParent:=GetDlgItem(hDlg,$BBD);
SendMessage(GetDlgItem(hDlg,$BBB),WM_SETFONT,CreateFont(-$C,0,0,0,$2BC,0,0,0,1,0,0,0,0,'宋體'),0);
SetDlgItemText(hDlg,$BBB,szKeyGenName);
SetDlgItemText(hDlg,$BBC,szCracker);
SetWindowText(hDlg,'關於');
GetClientRect(h_ScrollParent,sRect);
ScrollWidth:=sRect.right-sRect.left;
ScrollHeight:=sRect.bottom-sRect.top;
xCount:=ScrollHeight;
LineCount:=CountCRLF(szScroll);
h_Scroll:=CreateWindowEx(WS_EX_LEFT,'Static','',WS_CHILD OR WS_VISIBLE OR SS_CENTER,0,ScrollHeight,ScrollWidth,LineCount*12,h_ScrollParent,0,h_Inst,nil);
SetWindowLong(h_Scroll,GWL_USERDATA,SetWindowLong(h_Scroll,GWL_WNDPROC,LongWord(@ScrollProc)));
DialogInit(hDlg);
SetTimer(hDlg,$A8,60,NIL);
Result:=1;
End;
WM_TIMER:
Begin
Sleep(20);
Dec(xCount);
SetWindowPos(h_Scroll,HWND_TOP,0,xCount,ScrollWidth,LineCount*12,0);
If xCount<(0-LineCount*12) Then
Begin
xCount:=ScrollHeight;
End;
End;
Function CountCRLF(Str:String):Word;
Var
Count:Word;
i:Word;
Begin
Count:=1;
For i:=1 to Length(Str) Do
Begin
If Str[i]=#$0A Then Inc(Count);
End;
CountCRLF:=Count;
End;
Function ScrollProc(hDlg:HWND;Msg,wParam,lParam:DWORD):LRESULT;stdcall;
Var
sRect:TRect;
sPaint:PAINTSTRUCT;
DC:HDC;
LFont:HFONT;
Begin
If Msg=WM_PAINT Then
Begin
DC:=BeginPaint(hDlg,sPaint);
GetClientRect(hDlg,sRect);
SetTextColor(DC,$A0A0A0);
SetBkMode(DC,TRANSPARENT);
LFont:=CreateFont(-$C,0,0,0,0,0,0,0,1,0,0,0,0,'宋體');
SelectObject(DC,LFont);
DrawText(DC,szScroll,-1,sRect,DT_CENTER);
EndPaint(hDlg,sPaint);
DeleteObject(LFont);
End
Else
Begin
CallWindowProc(Pointer(GetWindowLong(hDlg,GWL_USERDATA)),hDlg,Msg,wParam,lParam);
End;
Result:=1;
End;
這樣,整個程式就分析完了。下面作一下總結。
從程式設計方面看,該程式有幾處地方值得借鑑:1、按鈕的三維邊框;2、漸變標題
欄;3、滾動字幕的方法。
從逆向工程的角度看,難點主要在漸變標題欄和滾動字幕的處理上。主要是這兩
個地方有較多的運算。
另外,在分析過程中,有幾點是值得注意的:
1、注意區分全域性變數和區域性變數。區域性變數一般用ebx引用。在分析滾動字幕時,
由於把一個全域性變數當作區域性變數,造成字幕無法重複滾動。不過,如果將該區域性變
量用Const說明,還是可以達到目的的。
2、注意變數的型別和地址。這樣就不會弄錯變數。
3、API中的常量。這些常量一般可以在SDK中找到,但有些是組合值,比如
CreateWindowEx裡使用的$50000001,這就需要仔細分析。
4、有符號數的處理。在本例中直接體現在漸變標題欄上。
5、不要迷信反彙編程式。
另外,你必須熟悉該程式使用的語言(尤其是內部結構,而不是僅僅會寫幾行程
序就可以的),這樣才能夠得心應手。但偽編譯語言(VB、Java、.NET)除外。當然,
你還必須熟悉組合語言。什麼?不熟悉?臨時學習?呃,算了吧。逆向工程只是手段
而不是目的,而且這對閣下來說也不好玩。倒是交誼舞對於閣下更實際點兒……閣下
35以上?那……當我什麼都沒說好了……
OK,這個筆記系列就基本結束了。但是有個缺憾:漸變標題欄沒有作到原程式那
樣的效果。也許以後我會分析出來的。不過現在只能說聲抱歉了。
謝謝各位觀賞,也謝謝各位的耐心。
PS:不要輕易決定做逆向工程,更不要輕易說你要做逆向工程並要寫下心得以供分
享。但是如果你決定了,那麼無論如何要完成它。特別是在第一篇心得貼出來以
後……想想那些網路上的“太監書”,再想想曹老先生的半部《紅樓夢》……
===========================================================================
原以為About不會很複雜,沒想到裡面居然套了那麼多東西。直接後果就是這篇文章
比以前貼的任何一篇都長,開啟的速度肯定要慢點。不過你既然都看到這裡了,就
別抱怨了,OK?
附:
關於Delphi逆向工程筆記系列的說明
事情的起因是我看到laoqian的一篇文章,他提到了FCG的KG模板,但是礙於FCG的規矩不能放出來,只是給了編譯過的程式。但是我又比較喜歡收集這個。本來嘛,加入FCG就可以了,但是本人不會脫殼,破解又只能到明碼比較的水平,估計沒有哪個組織會要。很幸運,那個模板是Delphi的,而且laoqian只用upx加了殼,這樣我才可以很方便地把它脫掉。不過他還是給我找了點小麻煩,破壞了upx頭部的校驗位元組,拿upx就脫不掉了。
更幸運的是KG是用SDK寫的(這也是慣例)……大家肯定都知道SDK程式編譯出來是什麼樣子。也正是如此,我才可以做這個RE。如果是VCL的話,我也只有去找非明碼比較的麻煩了。
做了半天,發現有些很有趣的東西。於是想拿出來。原以為這些東西肯定不太入眼,特別是對於在pediy混的人。但發現反響比較好,這是我始料不及的。
=================================================================
相關文章
- Delphi逆向工程筆記[1]2004-10-27筆記
- Delphi逆向工程筆記[2]2004-10-27筆記
- Delphi逆向工程筆記[3]2004-10-27筆記
- Delphi逆向工程筆記[4]2004-10-28筆記
- Delphi逆向工程筆記[5]2004-11-11筆記
- Delphi逆向工程筆記[6]――關於String區域性變數2004-11-15筆記變數
- 筆記:MyBatis逆向工程 - Win/Mac2018-09-28筆記MyBatisMac
- 【翻譯】Delphi中類的逆向工程2015-11-15
- iOS逆向工程 iOS工具篇2018-06-19iOS
- ios逆向工程連結2017-08-09iOS
- 終、《圖解HTTP》讀書筆記 - 彙總篇(總結)2022-11-24圖解HTTP筆記
- iOS逆向筆記2018-02-28iOS筆記
- Delphi TMSMQTT使用筆記2024-05-19MQQT筆記
- mysql總結筆記 -- 索引篇2022-01-04MySql筆記索引
- 逆向之彙編筆記2020-12-30筆記
- disruptor筆記之八:知識點補充(終篇)2021-10-08筆記
- iOS逆向工程2016-08-31iOS
- Mybatis逆向工程2024-03-10MyBatis
- 逆向與安全學習筆記2018-09-09筆記
- js逆向課20.12.27筆記2020-12-27JS筆記
- 逆向工程核心原理(1)逆向基礎2023-03-16
- mybatis的逆向工程2020-10-03MyBatis
- Delphi程式碼最佳化 完結篇 (轉)2007-12-06
- Delphi5學習筆記之五2007-05-05筆記
- Delphi5學習筆記之四2007-04-03筆記
- Delphi5學習筆記之三2007-03-01筆記
- LightGCN實踐2——GPU記憶體爆炸終結篇2020-10-23GCGPU記憶體
- 軟體工程個人最終總結2016-06-01軟體工程
- 【面試】實習求職終結篇2016-04-15面試求職
- 『高階篇』docker之CICD(終結篇)(44)2019-03-13Docker
- 旅行青蛙(旅かえる)逆向筆記2018-05-05筆記
- 小白的MyBatis逆向工程2020-05-01MyBatis
- 滴水逆向筆記系列-c語言總結2-10.變數-11.if逆向-12.正向基礎2024-03-14筆記C語言變數
- 7數的逆向操作(7)2020-03-22
- Mybatis逆向工程和新版本MybatisPlus3.4逆向工程的使用2021-10-01MyBatisS3
- 安卓學習筆記---開篇(目錄結構)2018-11-29安卓筆記
- Activiti7 結束/終止流程2021-08-05
- AQS系列(七)- 終篇:AQS總結2020-04-19AQS