都快过年了,还受这个折腾……
这个动态库最早用于为公司开发的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空间