-
-
[原创]发个修复软件下拉框列表及托盘区图标不能显示Bug的修复心得
-
发表于: 2008-6-13 14:49 8806
-
软件名称:Mobiola Web Camera for S60 3rd V3.0 build 11
功 用:把S60 3rd手机转换成PC摄像头软件,同时支持USB/蓝牙/WiFi连接。
已知Bug:WinXPSP2下正常但Win2KSP4系统下Combobox不能全部显示及托盘区小图标不能显示
使用工具:ODICE1.1,eXeScope1.65,Resource Hacker3.4,Hiew7.2
Cracked By [email]WksWlj999@sohu.com[/email]
2008/06/08
**********************************************************************************************
5.20版Armadillo加壳,保护选项如下:
!- Protected Armadillo
Protection system (Professional)
!- <Protection Options>
Debug-Blocker
CopyMem-II
Enable Import Table Elimination
Enable Strategic Code Splicing
Enable Nanomites Processing
Enable Memory-Patching Protections
!- <Backup Key Options>
Variable Backup Keys
!- <Compression Options>
Better/Slower Compression
-----------------------------------------------------------
脱壳修复IAT,手工修复CC,破解优化过程略去...
-----------------------------------------------------------
破解后发现WinXPSP2下运行正常,而在Win2KSP4下运行时有两个Bug:
(1)端口号及相机选择ComboBox下拉框无法显示完全;
(2)托盘区小图标无法显示。如下图:
------------------------------------------------------------------------------------------------------
修正原版存在的Win2K下Combobox不能全部显示的Bug:
------------------------------------------------------------------------------------------------------
需要修改两处ComboBox的显示错误,错误原因在于ComboBox控件的初始化高度太小,Win2K下系统不能自动调整高度导致的。
而WinXP下系统会自动调整,所以WinXP下显示正常。
第一处端口ComboBox初始化:
0040E4D6 |. 8D4C24 3C LEA ECX,DWORD PTR SS:[ESP+3C]
0040E4DA |. 897C24 3C MOV DWORD PTR SS:[ESP+3C],EDI
0040E4DE |. C74424 44 390000>MOV DWORD PTR SS:[ESP+44],39 //宽度
0040E4E6 |. 897C24 40 MOV DWORD PTR SS:[ESP+40],EDI
0040E4EA |. C74424 48 140000>MOV DWORD PTR SS:[ESP+48],14 //14就是初始高度;Height of COMX
0040E4F2 |. 8908 MOV DWORD PTR DS:[EAX],ECX
0040E4F4 |. 8B56 04 MOV EDX,DWORD PTR DS:[ESI+4]
0040E4F7 |. 8D9E 88010000 LEA EBX,DWORD PTR DS:[ESI+188]
0040E4FD |. 52 PUSH EDX
0040E4FE |. 8BCB MOV ECX,EBX
0040E500 |. E8 5BF7FFFF CALL webcam.0040DC60 ; Init COMX Combobox
第二处分辨率ComboBox初始化:
00422885 . 895C24 28 MOV DWORD PTR SS:[ESP+28],EBX
00422889 . 896C24 30 MOV DWORD PTR SS:[ESP+30],EBP
0042288D . C74424 2C 7A0000>MOV DWORD PTR SS:[ESP+2C],7A //宽度
00422895 . C74424 34 8E0000>MOV DWORD PTR SS:[ESP+34],8E //8E减去上面的7A就是初始高度,Height of Combobox Resolution
0042289D . 8908 MOV DWORD PTR DS:[EAX],ECX
0042289F . 8B56 04 MOV EDX,DWORD PTR DS:[ESI+4]
004228A2 . 8DBE 04020000 LEA EDI,DWORD PTR DS:[ESI+204]
004228A8 . 52 PUSH EDX
004228A9 . 8BCF MOV ECX,EDI
004228AB . E8 A04F0000 CALL webcam.00427850
虽然可以直接修改初始化高度值和ComboBox的样式值来正常显示,但是显示效果会与这个软件的XP显示样式不协调。
且有时出现滚动条与选择元素不同步的现象,采用如下方法修复,可保证在不破坏其XP显示样式的情况下在2K下正常显示:
在ComboBox填充完毕后,获取填充元素个数和句柄,用SendMessage函数,发送消息CB_GETCOUNT,获取元素个数,
发送消息CB_GETITEMHEIGHT,获取元素高度,然后[高度]乘以[元素个数+1],获得总高度,确保全部元素都能显示,
再用SetWindowPlacement函数重新设置ComboBox窗口的高度即可。具体实现方法如下:
已知条件:
[00492458] GetMoudleHandleA函数地址
[00492440] GetProcAddress函数地址
[004921A8] SendMessageW函数地址
00489934 "USER32.dll"字串
(1)找空白处写入初始化数据:
00489950 写入字串"SetWindowPlacement"
00489970 写入字串"GetWindowPlacement"
00489990开始 用于保存WINDOWPLACEMENT结构
00489990写入双字"2C 00 00 00"// 结构长度2Ch字节
[004899B0]-〉top
[004899B8]-〉bottom
004899C0 dword用于保存ComboBox的句柄
004899C4 dword用于保存ComboBox的ItemCount个数
修改后如下:
00489930 00 00 00 00 55 53 45 52 33 32 2E 64 6C 6C 00 00 ....USER32.dll..
00489940 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00489950 53 65 74 57 69 6E 64 6F 77 50 6C 61 63 65 6D 65 SetWindowPlaceme
00489960 6E 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 nt..............
00489970 47 65 74 57 69 6E 64 6F 77 50 6C 61 63 65 6D 65 GetWindowPlaceme
00489980 6E 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 nt..............
00489990 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ,............... // WINDOWPLACEMENT结构
004899A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
004899B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
004899C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
(2)第一处修改:
在0042C981处,端口ComboBox填充完毕,此时[ESI+84]-〉ComboBox的句柄
0042C981 |. 33FF XOR EDI,EDI
0042C983 |> 8B4C24 14 MOV ECX,DWORD PTR SS:[ESP+14]
0042C987 |. 8B96 84000000 MOV EDX,DWORD PTR DS:[ESI+84]
改为:
0042C981 - E9 7AC90500 JMP webcam.00489300 //跳至补丁1处
0042C986 90 NOP
0042C987 8B96 84000000 MOV EDX,DWORD PTR DS:[ESI+84]
空白00489300处写入补丁1代码:
00489300 8B86 84000000 MOV EAX,DWORD PTR DS:[ESI+84] ; hwnd
00489306 E8 E0030000 CALL webcam.004896EB //重新设置ComboBox控件高度
0048930B 33FF XOR EDI,EDI
0048930D 8B4C24 14 MOV ECX,DWORD PTR SS:[ESP+14]
00489311 - E9 7136FAFF JMP webcam.0042C987
(3)第二处修改:
在0042AD14处,分辨率ComboBox填充完毕,此时[ESI+8C4]-〉ComboBox的句柄
0042AD14 |. 8B86 C4080000 MOV EAX,DWORD PTR DS:[ESI+8C4]
0042AD1A |. 6A 01 PUSH 1 ; /Erase = TRUE
0042AD1C |. 6A 00 PUSH 0 ; |pRect = NULL
0042AD1E |. 50 PUSH EAX ; |hWnd
0042AD1F |. FF15 90214900 CALL DWORD PTR DS:[<&user32.InvalidateRect>] ; \InvalidateRect
改为:
0042AD14 - E9 E7E60500 JMP webcam.00489400 //跳至补丁2处
0042AD19 90 NOP
0042AD1A |. 6A 01 PUSH 1 ; /Erase = TRUE
0042AD1C |. 6A 00 PUSH 0 ; |pRect = NULL
0042AD1E |. 50 PUSH EAX ; |hWnd
0042AD1F |. FF15 90214900 CALL DWORD PTR DS:[<&user32.InvalidateRect>] ; \InvalidateRect
空白00489400处写入补丁2代码:
00489400 8B86 C4080000 MOV EAX,DWORD PTR DS:[ESI+8C4] ; hwnd
00489406 E8 E0020000 CALL webcam.004896EB //重新设置ComboBox控件高度
0048940B 8B86 C4080000 MOV EAX,DWORD PTR DS:[ESI+8C4]
00489411 - E9 0419FAFF JMP webcam.0042AD1A
(4)空白004896EB处写入重新设置ComboBox控件高度补丁代码:
注意!别忘了用Lord-PE把其所在区段属性修改为可写,因为补丁代码要向其中动态写入数据。
004896EB 60 PUSHAD
004896EC 9C PUSHFD
004896ED A3 C0994800 MOV DWORD PTR DS:[4899C0],EAX ; save handle
004896F2 6A 00 PUSH 0
004896F4 6A 00 PUSH 0
004896F6 68 46010000 PUSH 146 ; CB_GETCOUNT
004896FB FF35 C0994800 PUSH DWORD PTR DS:[4899C0] ; handle
00489701 FF15 A8214900 CALL DWORD PTR DS:[<&user32.SendMessageW>] ; USER32.SendMessageW
00489707 40 INC EAX ; ItemCount+1
00489708 A3 C4994800 MOV DWORD PTR DS:[4899C4],EAX ; save ItemCount+1
0048970D 68 34994800 PUSH webcam.00489934 ; ASCII "USER32.dll"
00489712 FF15 58244900 CALL DWORD PTR DS:[<&kernel32.GetModuleHandleA>] ; KERNEL32.GetModuleHandleA
00489718 68 70994800 PUSH webcam.00489970 ; ASCII "GetWindowPlacement"
0048971D 50 PUSH EAX
0048971E FF15 40244900 CALL DWORD PTR DS:[<&kernel32.GetProcAddress>] ; KERNEL32.GetProcAddress
00489724 68 90994800 PUSH webcam.00489990
00489729 FF35 C0994800 PUSH DWORD PTR DS:[4899C0]
0048972F FFD0 CALL EAX ; call GetWindowPlacement
00489731 6A 00 PUSH 0
00489733 6A FF PUSH -1
00489735 68 54010000 PUSH 154 ; CB_GETITEMHEIGHT
0048973A FF35 C0994800 PUSH DWORD PTR DS:[4899C0] ; handle
00489740 FF15 A8214900 CALL DWORD PTR DS:[<&user32.SendMessageW>] ; USER32.SendMessageW
00489746 8B3D C4994800 MOV EDI,DWORD PTR DS:[4899C4] ; edi<--ItemCount+1
0048974C F7E7 MUL EDI ; eax<--ItemCount+1 * Height
0048974E 0305 B8994800 ADD EAX,DWORD PTR DS:[4899B8]
00489754 A3 B8994800 MOV DWORD PTR DS:[4899B8],EAX
00489759 68 34994800 PUSH webcam.00489934 ; ASCII "USER32.dll"
0048975E FF15 58244900 CALL DWORD PTR DS:[<&kernel32.GetModuleHandleA>] ; KERNEL32.GetModuleHandleA
00489764 68 50994800 PUSH webcam.00489950 ; ASCII "SetWindowPlacement"
00489769 50 PUSH EAX
0048976A FF15 40244900 CALL DWORD PTR DS:[<&kernel32.GetProcAddress>] ; KERNEL32.GetProcAddress
00489770 68 90994800 PUSH webcam.00489990
00489775 FF35 C0994800 PUSH DWORD PTR DS:[4899C0]
0048977B FFD0 CALL EAX ; call SetWindowPlacement
0048977D 9D POPFD
0048977E 61 POPAD
0048977F C3 RETN
修正后效果:
------------------------------------------------------------------------------------------------------
修正原版存在的Win2K下任务栏小图标不能正常显示的Bug:
------------------------------------------------------------------------------------------------------
跟踪调试发现,00415584处,比较程序的不同状态并设置相应的系统托盘区图标:
eax=0表示端口号Invalid 对应图标句柄在[ECX+8A4]
eax=1表示端口号正常,处于未连接状态 对应图标句柄在[ECX+8A0]
eax=2表示端口号处于连接状态 对应图标句柄在[ECX+8A8]
eax=3表示端口号正常,处于连接正在断开状态 对应图标句柄同eax=1
可用LoadIcon函数获取相应图标句柄,并分别替换上面三个地址的图标句柄,以取得正常的显示效果。
00415580 . 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4]
00415584 . 83F8 03 CMP EAX,3 ; Switch (cases 0..3)
00415587 . 77 4F JA SHORT webcam.004155D8
00415589 . FF2485 DC554100 JMP DWORD PTR DS:[EAX*4+4155DC]
00415590 > 8B81 A4080000 MOV EAX,DWORD PTR DS:[ECX+8A4] //图标句柄0 ; Case 0 of switch 00415584
00415596 . 6A 01 PUSH 1 ; /Arg3 = 00000001
00415598 . 68 D4504700 PUSH webcam.004750D4 ; |Arg2 = 004750D4
0041559D . 50 PUSH EAX ; |Arg1
0041559E . 83C1 C4 ADD ECX,-3C ; |
004155A1 . E8 FAF9FFFF CALL webcam.00414FA0 //设置托盘区图标 ; \webcam.00414FA0
004155A6 . C2 0400 RETN 4
004155A9 > 8B81 A8080000 MOV EAX,DWORD PTR DS:[ECX+8A8] //图标句柄2 ; Case 2 of switch 00415584
004155AF . 6A 01 PUSH 1 ; /Arg3 = 00000001
004155B1 . 68 B8504700 PUSH webcam.004750B8 ; |Arg2 = 004750B8
004155B6 . 50 PUSH EAX ; |Arg1
004155B7 . 83C1 C4 ADD ECX,-3C ; |
004155BA . E8 E1F9FFFF CALL webcam.00414FA0 //设置托盘区图标 ; \webcam.00414FA0
004155BF . C2 0400 RETN 4
004155C2 > 8B91 A0080000 MOV EDX,DWORD PTR DS:[ECX+8A0] //图标句柄1,3 ; Cases 1,3 of switch 00415584
004155C8 . 6A 01 PUSH 1 ; /Arg3 = 00000001
004155CA . 68 A4504700 PUSH webcam.004750A4 ; |Arg2 = 004750A4
004155CF . 52 PUSH EDX ; |Arg1
004155D0 . 83C1 C4 ADD ECX,-3C ; |
004155D3 . E8 C8F9FFFF CALL webcam.00414FA0 //设置托盘区图标 ; \webcam.00414FA0
004155D8 > C2 0400 RETN 4 ; Default case of switch 00415584
004155DB 90 NOP
004155DC . 90554100 DD webcam.00415590 ; 分支表 被用于 00415589
004155E0 . C2554100 DD webcam.004155C2
004155E4 . A9554100 DD webcam.004155A9
004155E8 . C2554100 DD webcam.004155C2
已知条件:
[00492458] GetMoudleHandleA函数地址
[00492440] GetProcAddress函数地址
[004923AC] LoadLibraryA函数地址
00489934 "USER32.dll"字串
(1)用Resource Hacker 3.40打开程序自带的effects_dll.dll文件,[注:在exe主程序里添加图标资源后,不能正常运行,所以就选dll文件了]
分别添加16*16 256色图标资源201,202,203号,依次代表三种状态: 连接状态/Invalid/正常。
(2)如下修改00415589处:
00415580 . 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4]
00415584 . 83F8 03 CMP EAX,3 ; Switch (cases 0..3)
00415587 . 77 4F JA SHORT 1webcam.004155D8
00415589 - E9 723F0700 JMP webcam.00489500 //跳至补丁代码处
0041558E 90 NOP
0041558F 90 NOP
00415590 > 8B81 A4080000 MOV EAX,DWORD PTR DS:[ECX+8A4] ; Case 0 of switch 00415584
(3)空白004894E0处写入字符串"effects_dll.dll",004894F0处写入字符串"LoadIconA",00489500处写入补丁代码:
00489500 60 PUSHAD
00489501 9C PUSHFD
00489502 51 PUSH ECX ; save ecx
00489503 68 E0944800 PUSH webcam.004894E0 ; ASCII "effects_dll.dll"
00489508 FF15 AC234900 CALL DWORD PTR DS:[<&kernel32.LoadLibraryA>] ; KERNEL32.LoadLibraryA
0048950E 8BE8 MOV EBP,EAX ; save hInstance of effects_dll.dll
00489510 68 34994800 PUSH webcam.00489934 ; ASCII "USER32.dll"
00489515 FF15 58244900 CALL DWORD PTR DS:[<&kernel32.GetModuleHandleA>] ; KERNEL32.GetModuleHandleA
0048951B 68 F0944800 PUSH webcam.004894F0 ; ASCII "LoadIconA"
00489520 50 PUSH EAX
00489521 FF15 40244900 CALL DWORD PTR DS:[<&kernel32.GetProcAddress>] ; KERNEL32.GetProcAddress
00489527 8BF8 MOV EDI,EAX ; save LoadIconA API address
00489529 5E POP ESI ; load ecx to esi
0048952A 68 C9000000 PUSH 0C9
0048952F 55 PUSH EBP
00489530 FFD7 CALL EDI
00489532 8986 A8080000 MOV DWORD PTR DS:[ESI+8A8],EAX ; 连接状态图标句柄
00489538 68 CA000000 PUSH 0CA
0048953D 55 PUSH EBP
0048953E FFD7 CALL EDI
00489540 8986 A4080000 MOV DWORD PTR DS:[ESI+8A4],EAX ; Invalid状态图标句柄
00489546 68 CB000000 PUSH 0CB
0048954B 55 PUSH EBP
0048954C FFD7 CALL EDI
0048954E 8986 A0080000 MOV DWORD PTR DS:[ESI+8A0],EAX ; 正常状态图标句柄
00489554 9D POPFD
00489555 61 POPAD
00489556 3E:FF2485 DC554100 JMP DWORD PTR DS:[EAX*4+4155DC] ; 恢复原分支跳转
完成后如下所示:
004894E0 65 66 66 65 63 74 73 5F 64 6C 6C 2E 64 6C 6C 00 effects_dll.dll.
004894F0 4C 6F 61 64 49 63 6F 6E 41 00 00 00 00 00 00 00 LoadIconA.......
00489500 60 9C 51 68 E0 94 48 00 FF 15 AC 23 49 00 8B E8 `淨h鄶H.?I.嬭
00489510 68 34 99 48 00 FF 15 58 24 49 00 68 F0 94 48 00 h4橦.X$I.h饠H.
00489520 50 FF 15 40 24 49 00 8B F8 5E 68 C9 00 00 00 55 P@$I.孁^h?..U
00489530 FF D7 89 86 A8 08 00 00 68 CA 00 00 00 55 FF D7 讐啫..h?..U?
00489540 89 86 A4 08 00 00 68 CB 00 00 00 55 FF D7 89 86 墕?..h?..U讐?
00489550 A0 08 00 00 9D 61 3E FF 24 85 DC 55 41 00 00 00 ?..漚>$呠UA...
用16进制编辑器写入修改的数据并保存后运行,ComboBox不能全部显示和托盘区小图标不能显示的Bug都没了!
Bug全部修正后Win2K下效果: