欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

答复

答复

对[FCG]KeyGen2.0按钮特效的分析4
    粗略看了一下sub_406D7D,发现其中有很多对程序里其它函数的调用。所以这部分延后分析。
    sub_406D7D调用了以下函数:sub_406B69、sub_406974、sub_4070D9、sub_407274,其中sub_406B69已经分析。
seg000:00406974 sub_406974      proc near               ; CODE XREF: sub_406D7D+53
seg000:00406974                                         ; sub_406D7D+80 ...
seg000:00406974
seg000:00406974 arg_4           = dword ptr  0Ch
seg000:00406974 arg_8           = dword ptr  10h
seg000:00406974
seg000:00406974                 push    ebp
seg000:00406975                 mov     ebp, esp
seg000:00406977                 mov     eax, [ebp+arg_4]
seg000:0040697A                 cmp     [ebp+arg_8], 0
seg000:0040697E                 jnz     short loc_406982
seg000:00406980                 not     eax
seg000:00406982
seg000:00406982 loc_406982:                             ; CODE XREF: sub_406974+A
seg000:00406982                 pop     ebp
seg000:00406983                 retn
seg000:00406983 sub_406974      endp
    逻辑非常简单:如果参数3为0则返回参数2的反值,否则直接返回参数2。从堆栈看,有参数1,只是被忽略了。

代码:
    Function sub_406974(param1:LongWord;param2:LongWord;param3:LongWord)

    Begin

      If param3=0 Then

        Result:=param2 XOR $FFFFFFFF

      Else

        Result:=param2;

    End;

    sub_4070D9调用了sub_406C06、sub_406F99、sub_406CA5三个函数。
seg000:00406C06 sub_406C06      proc near               ; CODE XREF: sub_4070D9+25
seg000:00406C06
seg000:00406C06 Rect            = tagRECT ptr -10h
seg000:00406C06 arg_0           = dword ptr  8
seg000:00406C06
seg000:00406C06                 push    ebp
seg000:00406C07                 mov     ebp, esp
seg000:00406C09                 add     esp, 0FFFFFFF0h
//分配临时变量
seg000:00406C0C                 push    ebx
seg000:00406C0D                 mov     ebx, [ebp+arg_0]
//ebx=arg0
seg000:00406C10                 lea     eax, [ebp+Rect]
seg000:00406C13                 push    eax             ; lpRect
seg000:00406C14                 push    dword ptr [ebx] ; hWnd
//从这里可以看出,arg0实际是指针,指向的结构体开始部分为窗口句柄
seg000:00406C16                 call    GetWindowRect
seg000:00406C1B                 push    dword ptr [ebx] ; hWnd
seg000:00406C1D                 call    GetWindowDC
seg000:00406C22                 mov     [ebx+4], eax
//将对应的DC保存到结构体的[4]
seg000:00406C25                 push    dword ptr [ebx+4] ; HDC
seg000:00406C28                 call    CreateCompatibleDC
seg000:00406C2D                 mov     [ebx+8], eax
//memdc
seg000:00406C30                 push    1               ; int
seg000:00406C32                 push    dword ptr [ebx+8] ; HDC
seg000:00406C35                 call    SetBkMode
seg000:00406C3A                 cmp     dword ptr [ebx+10h], 0
//如果结构体的[10h]是0
seg000:00406C3E                 jz      short loc_406C4D
//非0就直接选择对象
seg000:00406C40                 push    dword ptr [ebx+10h] ; HGDIOBJ
seg000:00406C43                 push    dword ptr [ebx+8] ; HDC
seg000:00406C46                 call    SelectObject
seg000:00406C4B                 jmp     short loc_406C6F
seg000:00406C4D
seg000:00406C4D loc_406C4D:                             ; CODE XREF: sub_406C06+38
seg000:00406C4D                 mov     edx, [ebp+Rect.bottom]
seg000:00406C50                 sub     edx, [ebp+Rect.top]
seg000:00406C53                 push    edx             ; int
seg000:00406C54                 mov     ecx, [ebp+Rect.right]
seg000:00406C57                 sub     ecx, [ebp+Rect.left]
seg000:00406C5A                 push    ecx             ; int
seg000:00406C5B                 push    dword ptr [ebx+4] ; HDC
seg000:00406C5E                 call    CreateCompatibleBitmap
seg000:00406C63                 push    eax             ; HGDIOBJ
seg000:00406C64                 push    dword ptr [ebx+8] ; HDC
seg000:00406C67                 call    SelectObject
seg000:00406C6C                 mov     [ebx+10h], eax
//看来[10h]是bitmap的句柄
seg000:00406C6F
seg000:00406C6F loc_406C6F:                             ; CODE XREF: sub_406C06+45
seg000:00406C6F                 cmp     dword ptr [ebx+0Ch], 1
seg000:00406C73                 jnz     short loc_406C9B
//[0ch]是什么,从下文看不出
seg000:00406C75                 push    0CC0020h        ; DWORD
//SRCCOPY
seg000:00406C7A                 push    0               ; int
seg000:00406C7C                 push    0               ; int
seg000:00406C7E                 push    dword ptr [ebx+4] ; HDC
seg000:00406C81                 mov     eax, [ebp+Rect.bottom]
seg000:00406C84                 sub     eax, [ebp+Rect.top]
seg000:00406C87                 push    eax             ; int
seg000:00406C88                 mov     edx, [ebp+Rect.right]
seg000:00406C8B                 sub     edx, [ebp+Rect.left]
seg000:00406C8E                 push    edx             ; int
seg000:00406C8F                 push    0               ; int
seg000:00406C91                 push    0               ; int
seg000:00406C93                 push    dword ptr [ebx+8] ; HDC
seg000:00406C96                 call    BitBlt
//保存原始DC?
seg000:00406C9B
seg000:00406C9B loc_406C9B:                             ; CODE XREF: sub_406C06+6D
seg000:00406C9B                 mov     eax, [ebx+8]
//返回MEM DC的句柄
seg000:00406C9E                 pop     ebx
seg000:00406C9F                 mov     esp, ebp
seg000:00406CA1                 pop     ebp
seg000:00406CA2                 retn    4
seg000:00406CA2 sub_406C06      endp
代码:
Type

  WindowsDCInfo=Record

    hWindow:HWND;

    WinDC:HDC;

    CompDC:HDC;

    unknown:LongWord;

    hBitmap:HBITMAP;

  End;

  PWindowsDCInfo=^WindowsDCInfo;

Function sub_406C06(Var DCInfo:WindowsDCInfo):HDC;

Var

  Rect:TRect;

Begin

  GetWindowRect(DCInfo.hWindow,Rect);

  DCInfo.WinDC:=GetWindowDC(DCInfo.hWindow);

  DCInfo.CompDC:=CreateCompatibleDC(DCInfo.WinDC);

  SetBkMode(DCInfo.CompDC,TRANSPARENT);

  

  If DCInfo.hBitmap<>0 Then

    Begin

      SelectObject(DCInfo.CompDC,DCInfo.hBitmap);

    End

  Else

    Begin

      DCInfo.hBitmap:=CreateCompatibleBitmap(DCInfo.WinDC,Rect.right-Rect.left,Rect.bottom-Rect.top);

      SelectObject(DCInfo.CompDC,DCInfo.hBitmap);

    End;

    

  If DCInfo.unknown=1 Then

    Begin

      BitBlt(DCInfo.CompDC,0,0,Rect.right-Rect.left,Rect.bottom-Rect.top,DCInfo.WinDC,0,0,SRCCOPY);

    End;

    

  Result:=DCInfo.CompDC;

End;

    显然,某些东西依然未知。 
    看起来,sub_406F99就是生成渐变的核心过程。各位打起精神来! 首先,从GradientFill的两个call得到,var_48处是一个Arrayp[0..3] of TRIVERTEX的结构数组。var_54和var_8分别是GRADIENT_TRIANGLE和GRADIENT_RECT。但d5里对于TRIVERTEX的定义似乎有问题:COLOR16是8位而不是16位。最好的办法是自己重新写定义。
seg000:00406F99 ; int __stdcall sub_406F99(HDC,int,int)
seg000:00406F99 sub_406F99      proc near               ; CODE XREF: sub_4070D9+DC
seg000:00406F99                                         ; sub_4070D9+F0
seg000:00406F99
seg000:00406F99 var_54          = dword ptr -54h
seg000:00406F99 var_50          = dword ptr -50h
seg000:00406F99 var_4C          = dword ptr -4Ch
seg000:00406F99 var_48          = dword ptr -48h
seg000:00406F99 var_8           = dword ptr -8
seg000:00406F99 var_4           = dword ptr -4
seg000:00406F99 arg_0           = dword ptr  8
seg000:00406F99 arg_4           = dword ptr  0Ch
seg000:00406F99 arg_8           = dword ptr  10h
seg000:00406F99
seg000:00406F99                 push    ebp
seg000:00406F9A                 mov     ebp, esp
seg000:00406F9C                 add     esp, 0FFFFFFACh
//分配局部堆栈变量
seg000:00406F9F                 push    ebx
seg000:00406FA0                 push    esi
seg000:00406FA1                 push    edi
seg000:00406FA2                 mov     eax, [ebp+arg_8]
//eax=arg_8
seg000:00406FA5                 mov     edx, [ebp+arg_4]
//edx=arg_4
seg000:00406FA8                 lea     esi, [ebp+var_48]
seg000:00406FAB                 xor     ebx, ebx
//ebx=0
seg000:00406FAD
seg000:00406FAD loc_406FAD:                             ; CODE XREF: sub_406F99+70
seg000:00406FAD                 xor     ecx, ecx
seg000:00406FAF                 mov     cl, [eax+ebx*4]
//arg_8应该是指针
seg000:00406FB2                 shl     ecx, 8
//ecx=((eax+ebx*4)^) shl 8
seg000:00406FB5                 mov     edi, ebx
seg000:00406FB7                 shl     edi, 4
seg000:00406FBA                 mov     [esi+edi+8], cx
//注意:TRIVERTEX长度为10h=4h shl 4,所以这里应该写成
//var_48[ebx].Red=ecx and $FFFF
seg000:00406FBF                 movzx   ecx, word ptr [eax+ebx*4]
seg000:00406FC3                 sar     ecx, 8
seg000:00406FC6                 and     ecx, 0FFh
seg000:00406FCC                 shl     ecx, 8
//ecx=(((arg_8+ebx*4)^ sar 8)and $ff) shl 8
seg000:00406FCF                 mov     edi, ebx
seg000:00406FD1                 shl     edi, 4
seg000:00406FD4                 mov     [esi+edi+0Ah], cx
//var_48[ebx].Green=ecx and $FFFF
seg000:00406FD9                 mov     ecx, [eax+ebx*4]
seg000:00406FDC                 shr     ecx, 10h
seg000:00406FDF                 and     ecx, 0FFh
seg000:00406FE5                 shl     ecx, 8
seg000:00406FE8                 mov     edi, ebx
seg000:00406FEA                 shl     edi, 4
seg000:00406FED                 mov     [esi+edi+0Ch], cx
//var_48[ebx].Blue=(((arg_8+ebx*4)^ shr $10)and $ff) shl 8
seg000:00406FF2                 mov     ecx, [eax+ebx*4]
seg000:00406FF5                 shr     ecx, 18h
seg000:00406FF8                 shl     ecx, 8
seg000:00406FFB                 mov     edi, ebx
seg000:00406FFD                 shl     edi, 4
seg000:00407000                 mov     [esi+edi+0Eh], cx
//var_48[ebx].Alpha=(((arg_8^+ebx*4) shr $18) shl 8) and $ffff
seg000:00407005                 inc     ebx
seg000:00407006                 cmp     ebx, 4
seg000:00407009                 jl      short loc_406FAD
//loc_406FAD到此为一个循环
//for ebx:=0 to 3 do ....
//综合一下,arg_8的结构应该是Array[0..3] of DWORD,元素的结构为TColorRef,但是最高8位为Alpha值
seg000:0040700B                 mov     ecx, [edx]
seg000:0040700D                 mov     [esi], ecx
//看来arg_4也是指针
//var48[0].x=arg_4^
seg000:0040700F                 mov     ecx, [edx+4]
seg000:00407012                 mov     [esi+4], ecx
//var48[0].y=arg_4^[4]
seg000:00407015                 mov     ecx, [edx+8]
seg000:00407018                 lea     ebx, [esi+10h]
seg000:0040701B                 mov     [ebx], ecx
//var48[1].x=arg_4^[8]
seg000:0040701D                 mov     ecx, [edx+4]
seg000:00407020                 lea     ebx, [esi+10h]
seg000:00407023                 mov     [ebx+4], ecx
//var48[1].y=arg_4^[4]
seg000:00407026                 mov     ecx, [edx]
seg000:00407028                 lea     ebx, [esi+20h]
seg000:0040702B                 mov     [ebx], ecx
//var48[2].x=arg_4^
seg000:0040702D                 mov     ecx, [edx+0Ch]
seg000:00407030                 lea     ebx, [esi+20h]
seg000:00407033                 mov     [ebx+4], ecx
//var48[2].y=arg_4^[$c]
seg000:00407036                 mov     ecx, [edx+8]
seg000:00407039                 lea     ebx, [esi+30h]
seg000:0040703C                 mov     [ebx], ecx
//var48[3].x=arg_4^[$8]
seg000:0040703E                 mov     edx, [edx+0Ch]
seg000:00407041                 lea     ecx, [esi+30h]
seg000:00407044                 mov     [ecx+4], edx
//var48[3].y=arg_4^[$c]
//看来arg_4指向的应该是rect结构
seg000:00407047                 mov     edx, [eax]
seg000:00407049                 cmp     edx, [eax+8]
seg000:0040704C                 jnz     short loc_407054
//if arg_8^<>arg_8^[8] then goto loc_407054
seg000:0040704E                 mov     ecx, [eax+4]
seg000:00407051                 cmp     ecx, [eax+0Ch]
//无实际用途?
seg000:00407054
seg000:00407054 loc_407054:                             ; CODE XREF: sub_406F99+B3
seg000:00407054                 mov     edx, [eax]
seg000:00407056                 cmp     edx, [eax+4]
seg000:00407059                 jnz     short loc_40706A
//if arg_8^<>arg_8^[4] then goto loc_40706A
seg000:0040705B                 mov     ecx, [eax+8]
seg000:0040705E                 cmp     ecx, [eax+0Ch]
seg000:00407061                 jnz     short loc_40706A
//if arg_8^[8]<>arg_8^[$c] then goto loc_40706A
seg000:00407063                 mov     ebx, 1
//ebx=GRADIENT_FILL_RECT_V
seg000:00407068                 jmp     short loc_40706F
seg000:0040706A
seg000:0040706A loc_40706A:                             ; CODE XREF: sub_406F99+C0
seg000:0040706A                                         ; sub_406F99+C8
seg000:0040706A                 mov     ebx, 2
//ebx=GRADIENT_FILL_TRIANGLE
seg000:0040706F
seg000:0040706F loc_40706F:                             ; CODE XREF: sub_406F99+CF
seg000:0040706F                 cmp     ebx, 2
seg000:00407072                 jnz     short loc_407089
//if ebx<>GRADIENT_FILL_TRIANGLE then goto loc_407089
seg000:00407074                 xor     eax, eax
seg000:00407076                 mov     [ebp+var_54], eax
seg000:00407079                 mov     [ebp+var_50], 1
seg000:00407080                 mov     [ebp+var_4C], 2
//var_54.Vertex1=0
//var_54.Vertex2=1
//var_54.Vertex3=2
seg000:00407087                 jmp     short loc_407095
seg000:00407089
seg000:00407089 loc_407089:                             ; CODE XREF: sub_406F99+D9
seg000:00407089                 xor     edx, edx
seg000:0040708B                 mov     [ebp+var_8], edx
seg000:0040708E                 mov     [ebp+var_4], 3
//var_8.UpperLeft=0
//var_8.LowerRight=3
seg000:00407095
seg000:00407095 loc_407095:                             ; CODE XREF: sub_406F99+EE
seg000:00407095                 push    ebx             ; ULONG
seg000:00407096                 push    1               ; ULONG
seg000:00407098                 cmp     ebx, 2
seg000:0040709B                 jnz     short loc_4070A2
seg000:0040709D                 lea     ecx, [ebp+var_54]
seg000:004070A0                 jmp     short loc_4070A5
seg000:004070A2
seg000:004070A2 loc_4070A2:                             ; CODE XREF: sub_406F99+102
seg000:004070A2                 lea     ecx, [ebp+var_8]
seg000:004070A5
seg000:004070A5 loc_4070A5:                             ; CODE XREF: sub_406F99+107
seg000:004070A5                 push    ecx             ; PVOID
seg000:004070A6                 push    4               ; ULONG
seg000:004070A8                 push    esi             ; PTRIVERTEX
seg000:004070A9                 push    [ebp+arg_0]     ; HDC
seg000:004070AC                 call    GradientFill
//注意0040709B的判断
seg000:004070B1                 cmp     ebx, 2
seg000:004070B4                 jnz     short loc_4070D0
//如果ebx=GRADIENT_FILL_TRIANGLE,那么继续
seg000:004070B6                 mov     [ebp+var_54], 3
//var_54.Vertex1=3
seg000:004070BD                 push    2               ; ULONG
//GRADIENT_FILL_TRIANGLE
seg000:004070BF                 push    1               ; ULONG
seg000:004070C1                 lea     eax, [ebp+var_54]
seg000:004070C4                 push    eax             ; PVOID
seg000:004070C5                 push    4               ; ULONG
seg000:004070C7                 push    esi             ; PTRIVERTEX
seg000:004070C8                 push    [ebp+arg_0]     ; HDC
seg000:004070CB                 call    GradientFill
seg000:004070D0
seg000:004070D0 loc_4070D0:                             ; CODE XREF: sub_406F99+11B
seg000:004070D0                 pop     edi
seg000:004070D1                 pop     esi
seg000:004070D2                 pop     ebx
seg000:004070D3                 mov     esp, ebp
seg000:004070D5                 pop     ebp
seg000:004070D6                 retn    0Ch
seg000:004070D6 sub_406F99      endp
    从调用代码看,这段代码没有返回值。下面的代码做了一点整理。
代码:
    

Type

  COLOR16 = Word;

  PTriVertex = ^TTriVertex;

  _TRIVERTEX = Packed Record

    x: Longint;

    y: Longint;

    Red: COLOR16;

    Green: COLOR16;

    Blue: COLOR16;

    Alpha: COLOR16;

  End;

  TTriVertex = _TRIVERTEX;

  TRIVERTEX = _TRIVERTEX;

  

  AlphaRGB=Packed Record

    Case Byte Of

    1:(

    Alpha:Byte;

    Blue:Byte;

    Green:Byte;

    Red:Byte);

    2:(

    ARGB:LongWord);

  End;

Procedure DoGradientFill(WinDC:HDC;DCRect:PRect;AlphaRGBArray:Array[0..3] of AlphaRGB);

Var

  GT:GRADIENT_TRIANGLE;

  TVs:Array[0..3] of TRIVERTEX;

  GR:GRADIENT_RECT;

  i:LongWord;

Begin

  For i:=0 To 3 Do

    Begin

      TVs[i].Red:=AlphaRGBArray[i].Red;

      TVs[i].Green:=AlphaRGBArray[i].Green;

      TVs[i].Blue:=AlphaRGBArray[i].Blue;

      TVs[i].Alpha:=AlphaRGBArray[i].Alpha;

    End;

  TVs[0].x:=DCRect^.Left;

  TVs[0].y:=DCRect^.Top;

  TVs[1].x:=DCRect^.Right;

  TVs[1].y:=DCRect^.Top;

  TVs[2].x:=DCRect^.Left;

  TVs[2].y:=DCRect^.Bottom;

  TVs[3].x:=DCRect^.Right;

  TVs[3].y:=DCRect^.Bottom;

  

  If (DCRect^.Left=DCRect^.Top) AND (DCRect^.Right=DCRect^.Bottom) Then

    Begin

      GR.UpperLeft:=0;

      GR.LowerRight:=3;

      GradientFill(WinDC,@TVs,4,@GR,1,GRADIENT_FILL_RECT_V);

    End

  Else

    Begin

      GT.Vertex1:=0;

      GT.Vertex2:=1;

      GT.Vertex3:=2;

      GradientFill(WinDC,@TVs,4,@GT,1,GRADIENT_FILL_TRIANGLE);

      GT.Vertex1:=3;

      GradientFill(WinDC,@TVs,4,@GT,1,GRADIENT_FILL_TRIANGLE);

    End;

End;

    小结:保持清醒的头脑是非常重要的。我曾经算错mov的地址,后来从头看才发现错误所在。
    OK,休息。

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功