解决skin++2.1破解版对话框GDI泄漏的问题

        都快过年了,还受这个折腾……
        这个动态库最早用于为公司开发的AOI系统上,为了让系统界面不那么丑,又想偷下懒  。就到网上碰到了它——skin++2.1破解版。当第一次用于系统的界面时,感觉不错,又想下它已经没有服务提供者了(应该不存在版权什么什么的东西了吧),就把它用上了。
       可谁想到这才没几天,它的问题就一堆……除了上次的WM_KEYUP消息被它无端端地Hook掉之后,这次又来了个GDI泄漏问题(界面多弹出几次后就变黑或根本再也弹不出了)——对于此,经过艰苦的调试解决后,还是想给自己一句话——没钱的人别想偷懒啊(要么买去,要么自己写去)  。
       SkinPPWTL.dll动态库在某对话框创建的时候分别为此对话框标题栏创建了一个Bitmap、为客户区创建了一个DC及一个Bitmap三个GDI对象(Bitmap由CreateCompatibleBitmap创建,DC由CreateCompatibleDC创建),但这三个对象在对话框销毁的时候均未被删除!
1.
00D64FDB   .  85C0                      test    eax, eax
00D64FDD   .  74 18                      je      short 00D64FF7
00D64FDF   .  FF73 54                 push    dword ptr [ebx+54]
00D64FE2   .  50                           push    eax
00D64FE3   .  FFD6                      call    esi
00D64FE5   .  FF73 4C                 push    dword ptr [ebx+4C]               ; /hDC
00D64FE8   .  FF15 5881D900     call    dword ptr [<&GDI32.DeleteDC>]    ; \DeleteDC
00D64FEE   .  FF73 50                 push    dword ptr [ebx+50]               ; /hObject
00D64FF1   .  FF15 4C81D900    call    dword ptr [<&GDI32.DeleteObject>>; \DeleteObject
00D64FF7   >  57                          push    edi                              ; /hDC
00D64FF8   .  FF15 4880D900    call    dword ptr [<&GDI32.CreateCompati>; \CreateCompatibleDC
00D64FFE   .  8943 4C                mov     dword ptr [ebx+4C], eax        // 此DC不会被删除
00D65001   .  8B45 E4                 mov     eax, dword ptr [ebp-1C]
00D65004   .  2B45 DC                sub     eax, dword ptr [ebp-24]
00D65007   .  50                          push    eax                              ; /Height
00D65008   .  8B45 E0                 mov     eax, dword ptr [ebp-20]          ; |
00D6500B   .  2B45 D8                sub     eax, dword ptr [ebp-28]          ; |
00D6500E   .  50                          push    eax                              ; |Width
00D6500F   .  57                          push    edi                              ; |hDC
00D65010   .  FF15 4080D900    call    dword ptr [<&GDI32.CreateCompati>; \CreateCompatibleBitmap
00D65016   .  50                          push    eax
00D65017   .  8943 50                 mov     dword ptr [ebx+50], eax         // 此Bitmap也不会被删除
00D6501A   .  FF73 4C                push    dword ptr [ebx+4C]
00D6501D   .  FFD6                     call    esi
 
2.
00D6A24A   .  50                           push    eax                              ; /Height
00D6A24B   .  51                           push    ecx                              ; |Width
00D6A24C   .  FF75 08                 push    dword ptr [ebp+8]                ; |hDC
00D6A24F   .  FF15 4080D900     call    dword ptr [<&GDI32.CreateCompati>; \CreateCompatibleBitmap
00D6A255   .  8903                       mov     dword ptr [ebx], eax       // 此处Bitmap也不会删除,调试后发现[ebx]与上面的[ebx+170]一致
00D6A257   .  FF75 08                  push    dword ptr [ebp+8]                ; /hDC
00D6A25A   .  C745 FC 01000>    mov     dword ptr [ebp-4], 1             ; |
00D6A261   .  FF15 4880D900     call    dword ptr [<&GDI32.CreateCompati>; \CreateCompatibleDC
00D6A267   .  FF37                      push    dword ptr [edi]                  ; /hObject
00D6A269   .  8B3D 5481D900    mov     edi, dword ptr [<&GDI32.SelectOb>; |p[飞_n飞
00D6A26F   .  8945 0C                mov     dword ptr [ebp+C], eax           ; |
 
       解决方法:
      新建一小段代码,响应WM_DESTROY消息后删除以上GDI对象:
1.  增加WM_DESTROY处理函数
00D97540  /$  60                        pushad                       // 现场保护
00D97541  |.  8BEC                    mov     ebp, esp
00D97543  |.  83EC 7F               sub     esp, 7F
00D97546  |.  6A 00                    push    0
00D97548  |.  68 32373730         push    30373732
00D9754D  |.  68 00002333        push    33230000         // 建立对话框类名"#32770"
00D97552  |.  8BC5                     mov     eax, ebp
00D97554  |.  83E8 7F                 sub     eax, 7F
00D97557  |.  6A 7F                     push    7F                               ; /Count = 7F (127.)
00D97559  |.  50                           push    eax                              ; |Buffer
00D9755A  |.  8BD9                      mov     ebx, ecx                         ; |
00D9755C  |.  FF73 04                 push    dword ptr [ebx+4]                ; |hWnd
00D9755F  |.  E8 3A9EFFFF        call    <jmp.&USER32.GetClassNameA>      ; \GetClassNameA
00D97564  |.  8BC5                      mov     eax, ebp
00D97566  |.  83E8 7F                 sub     eax, 7F
00D97569  |.  50                           push    eax                              ; /String2
00D9756A  |.  83E8 0A                 sub     eax, 0A                          ; |
00D9756D  |.  50                          push    eax                              ; |String1
00D9756E  |.  E8 8B9BFFFF       call    <jmp.&KERNEL32.lstrcmpA>         ; \lstrcmpA
00D97573  |.  83F8 00                 cmp     eax, 0
00D97576  |.  75 27                      jnz     short 00D9759F         // 仅处理对话窗口的WM_DESTORY消息
00D97578  |.  8B43 4C                 mov     eax, dword ptr [ebx+4C]
00D9757B  |.  FF73 54                 push    dword ptr [ebx+54]               ; /hObject
00D9757E  |.  50                           push    eax                              ; |hDC
00D9757F  |.  E8 469FFFFF        call    <jmp.&GDI32.SelectObject>        ; \SelectObject     
00D97584  |.  FF73 4C                 push    dword ptr [ebx+4C]               ; /hDC
00D97587  |.  E8 2C9FFFFF        call    <jmp.&GDI32.DeleteDC>            ; \DeleteDC
00D9758C  |.  FF73 50                 push    dword ptr [ebx+50]               ; /hObject
00D9758F  |.  E8 1E9FFFFF        call    <jmp.&GDI32.DeleteObject>        ; \DeleteObject
00D97594  |.  FFB3 70010000     push    dword ptr [ebx+170]              ; /hObject
00D9759A  |.  E8 139FFFFF        call    <jmp.&GDI32.DeleteObject>        ; \DeleteObject     // 删除GDI对象
00D9759F  |>  81C4 8B000000    add     esp, 8B
00D975A5  |.  61                           popad          // 恢复寄存器
00D975A6  \.  C3                          retn
 
2. 增加WM_DESTROY判断分支
00D97650   > \83FE 02               cmp     esi, 2                           ;  Switch (cases 0..318)   // 处理WM_DESTROY消息
00D97653   .  75 0A                     jnz      short 00D9765F
00D 97655   .  E8 E6FEFFFF       call    00D97540                         ;  Case 2 of switch 00D97650  // 进入对话框GDI删除子过程
00D9765A   .^ E9 A0B6FCB0       jmp     00D62CB0                   // 处理完成直接跳到3中的default语句
00D9765F   >  83FE 14                cmp     esi, 14                        //  原3中起始于00D62621的部分代码被Copy到此处以为3中的Jmp腾出空间
00D97662   .^ 0F87 B1B0FCFF   ja      00D62719
00D97668   .^ 0F84 9DB0FCFF   je      00D6270B
00D9766E   .^ E9 BDAFFCFF      jmp     00D62630                //
 
3.  修改原代码处
00D62621   . /E9 2A500300   jmp     00D97650                       // 先跳到2代码段以添加一个WM_DESTROY消息判断
00D62626     |90            nop
00D62627     |90            nop
00D62628     |90            nop
00D62629     |90            nop
00D6262A     |90            nop
00D6262B     |90            nop
00D6262C     |90            nop
00D6262D     |90            nop
00D6262E     |90            nop
00D6262F     |90            nop
00D62630   > |83FE 08       cmp     esi, 8                           ;  Cases 0,1,3,4,5,6,7,8,9,A,B,C,D,E,F,10,11,12,13 of switch 00D97650
00D62633   . |0F87 86000000 ja      00D626BF
00D62639   . |74 76         je      short 00D626B1
00D6263B   . |8BFE          mov     edi, esi
00D6263D   . |4F            dec     edi
00D6263E   . |74 66         je      short 00D626A6
00D62640   . |4F            dec     edi
00D62641   . |4F            dec     edi
 
       工作完成。。。..  
 
2012-1-17  QQ空间

你可能感兴趣的:(破解,对话框,skin++,gdI泄漏,界面变黑)