答复
对[FCG]KeyGen2.0按钮特效的分析5
这个过程应该比较简单。
seg000:00406CA5 sub_406CA5 proc near ; CODE XREF: sub_4070D9+18D
seg000:00406CA5
seg000:00406CA5 Rect = tagRECT ptr -10h
seg000:00406CA5 arg_0 = dword ptr 8
seg000:00406CA5
seg000:00406CA5 push ebp
seg000:00406CA6 mov ebp, esp
seg000:00406CA8 add esp, 0FFFFFFF0h
seg000:00406CAB push ebx
seg000:00406CAC mov ebx, [ebp+arg_0]
seg000:00406CAF cmp dword ptr [ebx+0Ch], 1
//arg_0又是指针
seg000:00406CB3 jnz short loc_406CE6
seg000:00406CB5 lea eax, [ebp+Rect]
seg000:00406CB8 push eax ; lpRect
seg000:00406CB9 push dword ptr [ebx] ; hWnd
seg000:00406CBB call GetWindowRect
seg000:00406CC0 push 0CC0020h ; DWORD
seg000:00406CC5 push 0 ; int
seg000:00406CC7 push 0 ; int
seg000:00406CC9 push dword ptr [ebx+8] ; HDC
seg000:00406CCC mov edx, [ebp+Rect.bottom]
seg000:00406CCF sub edx, [ebp+Rect.top]
seg000:00406CD2 push edx ; int
seg000:00406CD3 mov ecx, [ebp+Rect.right]
seg000:00406CD6 sub ecx, [ebp+Rect.left]
seg000:00406CD9 push ecx ; int
seg000:00406CDA push 0 ; int
seg000:00406CDC push 0 ; int
seg000:00406CDE push dword ptr [ebx+4] ; HDC
seg000:00406CE1 call BitBlt
seg000:00406CE6
seg000:00406CE6 loc_406CE6: ; CODE XREF: sub_406CA5+E
seg000:00406CE6 cmp dword ptr [ebx+10h], 0
seg000:00406CEA jz short loc_406CFD
seg000:00406CEC push dword ptr [ebx+10h] ; HGDIOBJ
seg000:00406CEF push dword ptr [ebx+8] ; HDC
seg000:00406CF2 call SelectObject
seg000:00406CF7 push eax ; HGDIOBJ
seg000:00406CF8 call DeleteObject
seg000:00406CFD
seg000:00406CFD loc_406CFD: ; CODE XREF: sub_406CA5+45
seg000:00406CFD push dword ptr [ebx+8] ; HDC
seg000:00406D00 call DeleteDC
seg000:00406D05 push dword ptr [ebx+4] ; hDC
seg000:00406D08 push dword ptr [ebx] ; hWnd
seg000:00406D0A call ReleaseDC
seg000:00406D0F pop ebx
seg000:00406D10 mov esp, ebp
seg000:00406D12 pop ebp
seg000:00406D13 retn 4
seg000:00406D13 sub_406CA5 endp
实在没有什么难度,注释都不必写。唯一值得注意的是,arg_0是个什么玩意。对照一下sub_406C06的分析,可以看出,arg_0就是WindowsDCInfo的指针。
Procedure sub_406CA5(DCInfo:PWindowsDCInfo); Var Rect:TRect; Begin If DCInfo^.unknown=1 Then Begin GetWindowRect(DCInfo.hWindow,Rect); BitBlt(DCInfo.WinDC,0,0,Rect.right-Rect.left,Rect.bottom-Rect.top,DCInfo.CompDC,0,0,SRCCOPY); End; If DCInfo^.hBitmap<>0 Then Begin DeleteObject(SelectObject(DCInfo.CompDC,DCInfo.hBitmap)); End; DeleteDC(DCInfo.CompDC); ReleaseDC(DCInfo.hWindow,DCInfo.WinDC); End;
终于开始分析sub_4070D9了:
seg000:004070D9 sub_4070D9 proc near ; CODE XREF: sub_406D7D+5C
seg000:004070D9 ; sub_406D7D+89 ...
seg000:004070D9
seg000:004070D9 String = byte ptr -124h
seg000:004070D9 var_24 = dword ptr -24h
seg000:004070D9 hDC = dword ptr -1Ch
seg000:004070D9 var_18 = dword ptr -18h
seg000:004070D9 var_14 = dword ptr -14h
seg000:004070D9 var_10 = dword ptr -10h
seg000:004070D9 arg_0 = dword ptr 8
seg000:004070D9
seg000:004070D9 push ebp
seg000:004070DA mov ebp, esp
seg000:004070DC add esp, 0FFFFFEDCh
seg000:004070E2 push ebx
seg000:004070E3 push esi
seg000:004070E4 push edi
seg000:004070E5 mov ebx, [ebp+arg_0]
seg000:004070E8 lea edi, [ebp+var_10]
seg000:004070EB mov eax, [ebx]
//arg_0仍然是指针
seg000:004070ED mov [ebp+var_24], eax
//联系004070FE处代码,这里eax即arg_0^应该是窗口句柄。
seg000:004070F0 xor edx, edx
seg000:004070F2 mov [ebp+var_18], edx
//unknown
seg000:004070F5 xor ecx, ecx
seg000:004070F7 mov [ebp+var_14], ecx
//hBitmap
seg000:004070FA lea eax, [ebp+var_24]
seg000:004070FD push eax
seg000:004070FE call sub_406C06
//内部调用
seg000:00407103 push edi ; lpRect
seg000:00407104 push dword ptr [ebx] ; hWnd
seg000:00407106 call GetWindowRect
//var_10就是Rect了
seg000:0040710B mov edx, [edi]
seg000:0040710D sub [edi+8], edx
//var_10.right-=var_10.left
seg000:00407110 mov ecx, [edi+4]
seg000:00407113 sub [edi+0Ch], ecx
//var_10.bottom-=var_10.top
seg000:00407116 xor eax, eax
seg000:00407118 mov [edi+4], eax
//var_10.top=0
seg000:0040711B mov [edi], eax
//var_10.left=0
seg000:0040711D test byte ptr [ebx+8], 1
seg000:00407121 jz short loc_407131
//if arg_0^[8] and 1 =0 then goto loc_407131
seg000:00407123 push 0Fh ; nIndex
//COLOR_3DFACE
seg000:00407125 call GetSysColor
seg000:0040712A sub eax, 202020h
seg000:0040712F jmp short loc_407136
seg000:00407131
seg000:00407131 loc_407131: ; CODE XREF: sub_4070D9+48
seg000:00407131 mov eax, 733C00h
seg000:00407136
seg000:00407136 loc_407136: ; CODE XREF: sub_4070D9+56
seg000:00407136 push eax ; COLORREF
seg000:00407137 call CreateSolidBrush
seg000:0040713C mov esi, eax
//esi=hBrush
seg000:0040713E push esi ; hbr
seg000:0040713F push edi ; lprc
seg000:00407140 push [ebp+hDC] ; hDC
seg000:00407143 call FrameRect
//这里的hDC实际是CompDC
seg000:00407148 push esi ; HGDIOBJ
seg000:00407149 call DeleteObject
seg000:0040714E push 0FFFFFFFFh ; dy
seg000:00407150 push 0FFFFFFFFh ; dx
seg000:00407152 push edi ; lprc
seg000:00407153 call InflateRect
seg000:00407158 test byte ptr [ebx+8], 1
seg000:0040715C jz short loc_40717C
//if arg_0^[8] and 1 =0 then goto loc_40717C
seg000:0040715E push 0EAF4F5h ; COLORREF
seg000:00407163 call CreateSolidBrush
seg000:00407168 mov esi, eax
seg000:0040716A push esi ; hbr
seg000:0040716B push edi ; lprc
seg000:0040716C push [ebp+hDC] ; hDC
seg000:0040716F call FillRect
seg000:00407174 push esi ; HGDIOBJ
seg000:00407175 call DeleteObject
seg000:0040717A jmp short loc_4071BA
seg000:0040717C
seg000:0040717C loc_40717C: ; CODE XREF: sub_4070D9+83
seg000:0040717C test byte ptr [ebx+8], 2
//看来arg_0^[8]应该是位组合
seg000:00407180 jz short loc_407186
seg000:00407182 xor eax, eax
seg000:00407184 jmp short loc_4071A8
seg000:00407186
seg000:00407186 loc_407186: ; CODE XREF: sub_4070D9+A7
seg000:00407186 test byte ptr [ebx+8], 4
seg000:0040718A jz short loc_407190
seg000:0040718C xor eax, eax
seg000:0040718E jmp short loc_4071A8
seg000:00407190
seg000:00407190 loc_407190: ; CODE XREF: sub_4070D9+B1
seg000:00407190 test byte ptr [ebx+8], 8
seg000:00407194 jnz short loc_40719C
seg000:00407196 test byte ptr [ebx+8], 10h
seg000:0040719A jz short loc_4071A3
seg000:0040719C
seg000:0040719C loc_40719C: ; CODE XREF: sub_4070D9+BB
seg000:0040719C mov eax, 2
seg000:004071A1 jmp short loc_4071A8
seg000:004071A3
seg000:004071A3 loc_4071A3: ; CODE XREF: sub_4070D9+C1
seg000:004071A3 mov eax, 2
//上面这一段代码有点奇怪。特别是40719A。怀疑是原作者削掉了一些条件值。
seg000:004071A8
seg000:004071A8 loc_4071A8: ; CODE XREF: sub_4070D9+AB
seg000:004071A8 ; sub_4070D9+B5 ...
seg000:004071A8 shl eax, 4
seg000:004071AB add eax, offset dword_40A19C
//dword_40A19C应该是数组首地址。注意这里的eax计算,暗示这是3*4的AlphaRGB
seg000:004071B0 push eax ; int
seg000:004071B1 push edi ; int
seg000:004071B2 push [ebp+hDC] ; HDC
seg000:004071B5 call sub_406F99
seg000:004071BA
seg000:004071BA loc_4071BA: ; CODE XREF: sub_4070D9+A1
seg000:004071BA test byte ptr [ebx+8], 2
seg000:004071BE jz short loc_4071CE
seg000:004071C0 push offset dword_40A1CC ; int
seg000:004071C5 push edi ; int
seg000:004071C6 push [ebp+hDC] ; HDC
seg000:004071C9 call sub_406F99
seg000:004071CE
seg000:004071CE loc_4071CE: ; CODE XREF: sub_4070D9+E5
seg000:004071CE test byte ptr [ebx+8], 8
seg000:004071D2 jz short loc_4071E7
seg000:004071D4 push 0FFFFFFFFh ; dy
seg000:004071D6 push 0FFFFFFFFh ; dx
seg000:004071D8 push edi ; lprc
seg000:004071D9 call InflateRect
seg000:004071DE push edi ; lprc
seg000:004071DF push [ebp+hDC] ; hDC
seg000:004071E2 call DrawFocusRect
seg000:004071E7
seg000:004071E7 loc_4071E7: ; CODE XREF: sub_4070D9+F9
seg000:004071E7 push 100h ; nMaxCount
seg000:004071EC lea edx, [ebp+String]
seg000:004071F2 push edx ; lpString
seg000:004071F3 push dword ptr [ebx] ; hWnd
seg000:004071F5 call GetWindowTextA
//取得窗口标题,最多256字节
seg000:004071FA test eax, eax
seg000:004071FC jz short loc_40725B
seg000:004071FE test byte ptr [ebx+8], 2
seg000:00407202 jz short loc_40720E
seg000:00407204 push 1 ; dy
seg000:00407206 push 1 ; dx
seg000:00407208 push edi ; lprc
seg000:00407209 call OffsetRect
seg000:0040720E
seg000:0040720E loc_40720E: ; CODE XREF: sub_4070D9+129
seg000:0040720E test byte ptr [ebx+8], 1
seg000:00407212 jz short loc_40721B
seg000:00407214 mov ecx, 94A2A5h
seg000:00407219 jmp short loc_40721D
seg000:0040721B
seg000:0040721B loc_40721B: ; CODE XREF: sub_4070D9+139
seg000:0040721B xor ecx, ecx
seg000:0040721D
seg000:0040721D loc_40721D: ; CODE XREF: sub_4070D9+140
seg000:0040721D push ecx ; COLORREF
seg000:0040721E push [ebp+hDC] ; HDC
seg000:00407221 call SetTextColor
seg000:00407226 push 0
seg000:00407228 push 0
seg000:0040722A push 31h
//WM_GETFONT
seg000:0040722C push dword ptr [ebx]
seg000:0040722E call SendMessageA_0
seg000:00407233 push eax ; HGDIOBJ
seg000:00407234 push [ebp+hDC] ; HDC
seg000:00407237 call SelectObject
seg000:0040723C mov esi, eax
seg000:0040723E push 25h
//DT_SINGLELINE+DT_VCENTER+DT_CENTER
seg000:00407240 push edi
seg000:00407241 push 0FFFFFFFFh
seg000:00407243 lea eax, [ebp+String]
seg000:00407249 push eax
seg000:0040724A push [ebp+hDC]
seg000:0040724D call DrawTextA_0
seg000:00407252 push esi ; HGDIOBJ
seg000:00407253 push [ebp+hDC] ; HDC
seg000:00407256 call SelectObject
seg000:0040725B
seg000:0040725B loc_40725B: ; CODE XREF: sub_4070D9+123
seg000:0040725B mov [ebp+var_18], 1
seg000:00407262 lea edx, [ebp+var_24]
seg000:00407265 push edx
seg000:00407266 call sub_406CA5
seg000:0040726B pop edi
seg000:0040726C pop esi
seg000:0040726D pop ebx
seg000:0040726E mov esp, ebp
seg000:00407270 pop ebp
seg000:00407271 retn 4
seg000:00407271 sub_4070D9 endp
通过查找引用,可以知道arg_0是PWindowProperty类型的。
Const ARGBs:Array[0..2] of Array[0..3] of AlphaRGB= ( ((ARGB:$A5B2B5),(ARGB:$CED7D6),(ARGB:$CED7D6),(ARGB:$DEEFF7)), ((ARGB:$CEF3FF),(ARGB:$63CBFF),(ARGB:$63CBFF),(ARGB:$31B2FF)), ((ARGB:$FAE3BA),(ARGB:$CCA372),(ARGB:$BC9362),(ARGB:$BE9463)) ) ; GradientARGBs:Array[0..3] of AlphaRGB= ((ARGB:$DEE3E7),(ARGB:$E7E7E7),(ARGB:$DEE3E7),(ARGB:$FFDEE3E7)); Procedure sub_4070D9(wp:PWindowProperty); Var title:Array[0..256] of Char; r:Rect; DCInfo:WindowsDCInfo; Brush:HBRUSH; color:COLORREF; clrindex:Byte; fnt:HFONT; Begin DCInfo.hWindow:=wp^.CurrentWindow; DCInfo.unknown:=0; DCInfo.hBitmap:=0; sub_406C06(DCInfo); GetWindowRect(wp^.CurrentWindow,r); r.right:=r.right-r.left; r.bottom:=r.bottom-r.top; r.top:=0; r.left:=0; If wp^.Preserve2 AND 1<>0 Then Begin color:=GetSysColor(COLOR_3DFACE)-$202020; End Else Begin color:=$733C00; End; Brush:=CreateSolidBrush(color); FrameRect(DCInfo.CompDC,r,Brush); DeleteObject(Brush); InflateRect(r,-1,-1); If wp^.Preserve2 AND 1<>0 Then Begin Brush:=CreateSolidBrush($EAF4F5); FillRect(DCInfo.CompDC,r,Brush); DeleteObject(Brush); End Else Begin If (wp^.Preserve2 AND 2=0) AND (wp^.Preserve2 AND 4=0) Then Begin clrindex:=2; End Else Begin clrindex:=0; End; sub_406F99(DCInfo.CompDC,r,ARGBs[clrindex]); End; If wp^.Preserve2 AND 2<>0 Then Begin DoGradientFill(DCInfo.CompDC,r,GradientARGBs); End; If wp^.Preserve2 AND 8<>0 Then Begin InflateRect(r,-1,-1); DrawFocusRect(DCInfo.CompDC,r); End; If GetWindowText(wp^.CurrentWindow,@title,$100)<>0 Then Begin If wp^.Preserve2 AND 2<>0 Then Begin OffsetRect(r,1,1); End; If wp^.Preserve2 AND 1<>0 Then Begin clrindex:=94A2A5h End Else Begin clrindex:=0; End; SetTextColor(DCInfo.CompDC,clrindex); fnt:=SelectObject(DCInfo.CompDC,SendMessage(wp^.CurrentWindow,WM_GETFONT,0,0)); DrawTextA(DCInfo.CompDC,@title,-1,r); SelectObject(DCInfo.CompDC,fnt); End; DCInfo.unknown:=1; sub_406CA5(DCInfo); End;
不过,wp^.Preserve2到底是什么玩意,确实值得分析。
