msimg32.dll劫持失败原因分析

文章目录
  1. 1. 问题描述
  2. 2. 问题分析调试
    1. 2.1. 问题1
  3. 3. 问题2
  4. 4. 总结
  5. 5. 参考文献

问题描述

前一段事件做一个题的时候,需要修改主程序执行逻辑,当时想想应该很简单,直接做dll劫持然后在该DllMain中去修改主程序Exe的执行逻辑(因为之前看到飘云阁的 Visual Assist X劫持用的msimg32)。很顺利的在调试系统(win xp)做完了,达到了预期目的。但是拿到win7和win10上运行顿时就不行了。
主要问题有两个:

  • win7上直接不加载劫持dll,msimg32.dll了
  • win10上会加载msimg32.dll,但是加载时间靠后,在主程序逻辑执行后才被加载,这会修改逻辑也没用了

当时时间紧急,也比较慌。没有分析,改了方案直接修改主程序二进制,文件补丁方式做的

问题分析调试

问题1


主程序dll依赖情况

首先depends看下主程序dll依赖情况,发现确实有msimg32.dll啊。怎么会出现win7不加载呢?好像前面有个沙漏,F1查看depends帮助发现这个沙漏标志msimg32.dll是延迟加载dll(延迟加载的dll是在该dll中的函数被调用的时候才被加载,延迟加载提高的程序的启动速度)。那为什么winxp会加载呢?

winxp加载msimg32.dll堆栈情况

上神器procmon,发现是在imm32.dll中加载了msimg32.dll,搜索imm32.dll发现是和输入法相关。对比两个系统发现winxp调试系统安装了qq拼音输入法而win7上没有,应该qq拼音的原因。将xp的qq输入法卸载,果然xp系统也不加载了。但是具体什么原因还不知道,直接上调试器,但开始不知道怎么下断点,就直接将msimg32.dll的入口点修改二进制为0xcc,直接断下(其实可以直接对bu ntdll!LdrLoadDll “dU /c 50 poi(@ebp+8)”
,开始下的LoadLibaryExW以为加载dll都会通过这个函数),堆栈情况如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
0012e3cc 7c93c4da 762f110c 762f0000 00000001 MSIMG32!DllInitialize
0012e4d4 7c936351 00000000 c0150008 00000000 ntdll!LdrFindResourceDirectory_U+0x28d
0012e780 7c9364b3 00000000 00148818 0012ea74 ntdll!RtlValidateUnicodeString+0x507
0012ea28 7c801bbd 00148818 0012ea74 0012ea54 ntdll!LdrLoadDll+0x110
0012ea90 7c80aeec 0012eac4 00000000 00000000 kernel32!LoadLibraryExW+0xc8
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\IMM32.DLL -
0012eaa4 763071f4 0012eac4 00000000 00147790 kernel32!LoadLibraryW+0x11
0012ecd0 76307680 0012ed08 00147790 001464e0 IMM32!ImmNotifyIME+0x21c
0012ee64 763077bb e0200804 00000000 0012ee84 IMM32!ImmNotifyIME+0x6a8
0012ee74 77d6b570 e0200804 001464e0 0012f0d4 IMM32!ImmLoadIME+0x4c
0012ee84 77d6be00 001464e0 00647ac8 00000287 USER32!IMPSetIMEA+0x6c
0012f0d4 77d6c8cf 001464e0 00000287 00000021 USER32!IMPSetIMEA+0x8fc
0012f0f8 77d6c952 00010b7c 00000287 00000021 USER32!IMPSetIMEA+0x13cb
0012f114 77d18734 00010b7c 00000287 00000021 USER32!IMPSetIMEA+0x144e
0012f140 77d18816 77d6c930 00010b7c 00000287 USER32!GetDC+0x6d
0012f1a8 77d2a013 00000000 77d6c930 00010b7c USER32!GetDC+0x14f
0012f1d8 77d2a998 77d6c930 00010b7c 00000287 USER32!IsWindowUnicode+0xa1
*** WARNING: Unable to verify checksum for image00400000
*** ERROR: Module load completed but symbols could not be loaded for image00400000
0012f1f8 0040d08f 77d6c930 00010b7c 00000287 USER32!CallWindowProcA+0x1b
0012f26c 77d18734 00010b7c 00000287 00000021 image00400000+0xd08f
0012f298 77d18816 0040cf74 00010b7c 00000287 USER32!GetDC+0x6d
0012f300 77d28ea0 00000000 0040cf74 00010b7c USER32!GetDC+0x14f
0012f354 77d28eec 00647ac8 00000287 00000021 USER32!DefWindowProcW+0x180
0012f37c 7c92e453 0012f38c 00000018 00647ac8 USER32!DefWindowProcW+0x1cc
0012f844 77d26423 80050101 00008002 0012f8a8 ntdll!KiUserCallbackDispatcher+0x13
0012f91c 77d2683e 00400000 00008002 00000110 USER32!IsDlgButtonChecked+0x1629
0012f940 77d39b43 00400000 00420988 00000000 USER32!CreateDialogIndirectParamAorW+0x33
0012f960 0040c465 00400000 00420988 00000000 USER32!CreateDialogIndirectParamA+0x1b
0012f9c8 0040c68e 00420988 00000000 00400000 image00400000+0xc465
0012fa0c 004010e4 0041c5d0 ffffffff 00414518 image00400000+0xc68e
0012ffc0 7c817067 00bcf6ee 00bcf774 7ffd9000 image00400000+0x10e4
0012fff0 00000000 0040283e 00000000 78746341 kernel32!RegisterWaitForInputIdle+0x49
0:000> du 0012eac4
0012eac4 "C:\WINDOWS\system32\QQPINYIN.IME"
0012eb04 ""


发现在加载QQPINYIN.IME的时候,在解决QQPINYIN.IME依赖dll的时候加载了msimg32.dll。

QQPINYIN.ime的DLL依赖项

问题2

好了,问题1解决了,该问题2了。win10上同样装的qq输入法,但是输入法劫持dll的加载时机却靠后了,这是怎么回事呢?
在procmon观察,在win10系统QQpinyin.ime是被QQPinyinTSF.dll这个dll加载的,而在winxp上是imm32.dll。上调试器观察下有什么不同
winxp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
0012eac4  "C:\WINDOWS\system32\QQPINYIN.IME"
00 0012eaa4 763071f4 kernel32!LoadLibraryW+0x5
01 0012ecd0 76307680 IMM32!ImmNotifyIME+0x21c
02 0012ee64 763077bb IMM32!ImmNotifyIME+0x6a8
03 0012ee74 77d6b570 IMM32!ImmLoadIME+0x4c
04 0012ee84 77d6be00 USER32!IMPSetIMEA+0x6c
05 0012f0d4 77d6c8cf USER32!IMPSetIMEA+0x8fc
06 0012f0f8 77d6c952 USER32!IMPSetIMEA+0x13cb
07 0012f114 77d18734 USER32!IMPSetIMEA+0x144e
08 0012f140 77d18816 USER32!GetDC+0x6d
09 0012f1a8 77d2a013 USER32!GetDC+0x14f
0a 0012f1d8 77d2a998 USER32!IsWindowUnicode+0xa1
0b 0012f1f8 0040d08f USER32!CallWindowProcA+0x1b
0c 0012f26c 77d18734 image00400000+0xd08f
0d 0012f298 77d18816 USER32!GetDC+0x6d
0e 0012f300 77d28ea0 USER32!GetDC+0x14f
0f 0012f354 77d28eec USER32!DefWindowProcW+0x180
10 0012f37c 7c92e453 USER32!DefWindowProcW+0x1cc
11 0012f844 77d26423 ntdll!KiUserCallbackDispatcher+0x13
12 0012f91c 77d2683e USER32!IsDlgButtonChecked+0x1629
13 0012f940 77d39b43 USER32!CreateDialogIndirectParamAorW+0x33
14 0012f960 0040c465 USER32!CreateDialogIndirectParamA+0x1b
15 0012f9c8 0040c68e image00400000+0xc465
16 0012fa0c 004010e4 image00400000+0xc68e
17 0012ffc0 7c817067 image00400000+0x10e4
18 0012fff0 00000000 kernel32!RegisterWaitForInputIdle+0x49

win10

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
0019d848  "C:\WINDOWS\SysWow64\IME\QQPinyinTSF\QQPinyinTSF.dll"
00 0019d794 752ac012 KERNELBASE!LoadLibraryExW+0x5
01 0019d7b8 752abf8a combase!LoadLibraryWithLogging+0x1b
02 0019d7e4 752ac136 combase!CClassCache::CDllPathEntry::LoadDll+0x50
03 0019d824 752ad6f7 combase!CClassCache::CDllPathEntry::Create+0x3c
04 0019da74 752f98ce combase!CClassCache::CClassEntry::CreateDllClassEntry+0xe3
05 0019dda4 752accb2 combase!CClassCache::GetClassObjectActivator+0x82e
06 0019ddd8 752ac898 combase!CClassCache::GetClassObject+0x30
07 0019de48 752b6dfa combase!CServerContextActivator::CreateInstance+0x128
08 0019de94 752acef2 combase!ActivationPropertiesIn::DelegateCreateInstance+0xba
09 0019deec 752b1575 combase!CApartmentActivator::CreateInstance+0xa2
0a 0019df1c 752b1640 combase!CProcessActivator::CCICallback+0x65
0b 0019df40 752b16d7 combase!CProcessActivator::AttemptActivation+0x40
0c 0019df80 752b18f7 combase!CProcessActivator::ActivateByContext+0x77
0d 0019dfb0 752b6ddb combase!CProcessActivator::CreateInstance+0x67
0e 0019dffc 752b2e7d combase!ActivationPropertiesIn::DelegateCreateInstance+0x9b
0f 0019e260 752b6de2 combase!CClientContextActivator::CreateInstance+0xfd
10 0019e2ac 752f77a0 combase!ActivationPropertiesIn::DelegateCreateInstance+0xa2
11 0019ec18 752f6ba2 combase!ICoCreateInstanceEx+0xae0
12 0019ecc8 752f8209 combase!CComActivator::DoCreateInstance+0x162
13 0019ed08 7510dece combase!CoCreateInstance+0xa9
14 0019ee44 7510e28f MSCTF!CThreadInputMgr::_CreateTip+0x1be
15 0019ee84 7510c458 MSCTF!CThreadInputMgr::ActivateInputProfile+0x10f
16 0019efb0 7510c85d MSCTF!CThreadInputMgr::OnActiveProfileChange+0x668
17 0019f1e0 7511e12f MSCTF!CThreadInputMgr::OnInputFocusEvent+0x2cd
18 0019f8a0 743a9733 MSCTF!WinEventProc+0x5bf
19 0019f8e8 777608c6 USER32!__ClientCallWinEventProc+0x43
1a 0019f920 775d24ec ntdll!KiUserCallbackDispatcher+0x36
1b 0019f924 743b24d3 win32u!NtUserGetMessage+0xc
1c 0019f950 0040bc09 USER32!GetMessageA+0x53
WARNING: Stack unwind information not available. Following frames may be wrong.
1d 0019f96c 0040eff5 image00400000+0xbc09
1e 0019f9dc 00000000 image00400000+0xeff5

00670ab0 "C:\WINDOWS\system32\IME\QQPinyinTSF\QQPinyin.ime"
00 0019e974 7578c711 KERNELBASE!LoadLibraryExW+0x5
01 0019e988 568cb24f KERNELBASE!LoadLibraryW+0x11
WARNING: Stack unwind information not available. Following frames may be wrong.
02 0019ecf4 568cd764 QQPinyinTSF!DllGetClassObject+0x24cf
03 0019ed18 568cb8da QQPinyinTSF!DllGetClassObject+0x49e4
04 0019eda8 750f4939 QQPinyinTSF!DllGetClassObject+0x2b5a
05 0019eddc 7510dc53 MSCTF!CTip::Activate+0x63
06 0019ee48 7510e2d9 MSCTF!CThreadInputMgr::_ActivateTip+0x9f
07 0019ee84 7510c458 MSCTF!CThreadInputMgr::ActivateInputProfile+0x159
08 0019efb0 7510c85d MSCTF!CThreadInputMgr::OnActiveProfileChange+0x668
09 0019f1e0 7511e12f MSCTF!CThreadInputMgr::OnInputFocusEvent+0x2cd
0a 0019f8a0 743a9733 MSCTF!WinEventProc+0x5bf
0b 0019f8e8 777608c6 USER32!__ClientCallWinEventProc+0x43
0c 0019f920 775d24ec ntdll!KiUserCallbackDispatcher+0x36
0d 0019f924 743b24d3 win32u!NtUserGetMessage+0xc
0e 0019f950 0040bc09 USER32!GetMessageA+0x53
0f 0019f96c 0040eff5 image00400000+0xbc09
10 0019f9dc 00000000 image00400000+0xeff5

总结一下QQpinyin.ime在winxp和win10上的不同调用序列:
winxp:kernel32!RegisterWaitForInputIdle———>user32!CreateDialogIndirectParamA———->USER32!IMPSetIMEA+0x13cb———>IMM32!ImmNotifyIME+0x21c
win10:USER32!GetMessageA+0x53————>MSCTF!CThreadInputMgr::_CreateTip+0x1be——->combase!CClassCache::CDllPathEntry::LoadDll+0x50 ——–>MSCTF!CTip::Activate+0x63———->QQPinyinTSF!DllGetClassObject+0x24cf

基本描述了问题(在xp上在exe主函数未执行前QQpinyin.ime就已经被加载了,在win10是在exez主函数执行完成后开始获取消息的时候加载的ime),但是没有解释为什么会这样

google搜索一下发现了在xp与win10上输入法的框架的不同:

1
2
3
4
5
6
7
8
Windows提供了两套输入法框架: Windows XP及之前,是IMM (Input Method Manager),
基于纯函数API的。目前市面上非微软中文输入法基本上都是只实现IMM框架。Windows XP开
始及以后,Windows提供新的输入框架TSF,是基于COM的实际上,到了WindowsVista,Windows7,
所有的应用程序和各种输入控件都是优先使用TSF的实现。但之所以Windows Vista,Windows 7
用户还能使用各种基于IMM的输入法,是因为Windows提供了一个组件来将所有TSF的请求转为IMM的API。
(PunCha:难道Win8开始就不提供了吗?!很有可能,因为Win8下很多Imm的函数
都不能使用了)按照微软的说法,TSF会最终取代IMM框架。而微软拼音基于兼容,
功能和性能方面的原因,将这两个框架都实现了。

总结

总结一下就是,由于使用QQ输入法而引入了Dll劫持漏洞但是由于输入法框架的不同导致劫持dll的加载时机的不同。

参考文献

Visual Assist X 劫持破解 Patch With Key (通杀1041~2118) 解决变灰问题
动态链接库的静态链接导致程序的DLL劫持漏洞-借助QQ程序xGraphic32.dll描述
TSF(Text Service Framework)简介
逗比的输入法实现(一):基本情况