cve-2017-8464(震网三代)
漏洞简介
Windows系统在解析快捷方式时存在远程执行任意代码的高危漏洞,黑客可以通过U盘、网络共享等途径触发漏洞,完全控制用户系统,安全风险高危。该漏洞的原理同2010年据称美国和以色列入侵并破坏伊朗核设施的震网行动中所使用的震网病毒(Stuxnet)非常相似,所以也被一些人称为“震网三代”。
测试环境
漏洞机:win 7 sp 1 x86
本机:win10
漏洞影响范围
Microsoft Windows 10 Version 1607 for 32-bit Systems
Microsoft Windows 10 Version 1607 for x64-based Systems
Microsoft Windows 10 for 32-bit Systems
Microsoft Windows 10 for x64-based Systems
Microsoft Windows 10 version 1511 for 32-bit Systems
Microsoft Windows 10 version 1511 for x64-based Systems
Microsoft Windows 10 version 1703 for 32-bit Systems
Microsoft Windows 10 version 1703 for x64-based Systems
Microsoft Windows 7 for 32-bit Systems SP1
Microsoft Windows 7 for x64-based Systems SP1
Microsoft Windows 8.1 for 32-bit Systems
Microsoft Windows 8.1 for x64-based Systems
Microsoft Windows RT 8.1
服务器系统
Microsoft Windows Server 2008 R2 for Itanium-based Systems SP1
Microsoft Windows Server 2008 R2 for x64-based Systems SP1
Microsoft Windows Server 2008 for 32-bit Systems SP2
Microsoft Windows Server 2008 for Itanium-based Systems SP2
Microsoft Windows Server 2008 for x64-based Systems SP2
Microsoft Windows Server 2012
Microsoft Windows Server 2012 R2
Microsoft Windows Server 2016
lnk文件格式分析
lnk文件通用结构
lnk file header、Shell Item Id List、File location info、Description string、Relative path string、Working directory string、Command line string、Icon filename string、Extra stuff。除了第一个和最后一个,其他都不是必须存在的,但如果存在就必须按照上面的排列顺序。
lnk file header
Offset Size Type Description
0x00 1 dword 总是为0000004CH,相当于字符"L",用于标识是否是个有效的.lnk文件。
0x04 16 bytes GUID,标识.lnk的唯一标识符,不排除以后MS对该字段有所修改。
0x14 1 dword *重要,Flags用来标识.lnk文件中有哪些可选属性,也就是哪些节是可选的。
0x18 1 dword 目标文件属性(是否只读、隐藏、系统文件、加密、临时...)
0x1c 1 qword 文件创建时间
0x24 1 qword 文件修改时间
0x2c 1 qword 文件最后一次访问时间
0x34 1 dword 目标文件长度
0x38 1 dword 自定义图标个数
0x3c 1 dword 目标文件执行时窗口显示方式(1-正常显示,2-最小化,3-最大化)
0x40 1 dword 热键
0x44 2 dword 该字段未知,常为0
偏移0x14处的值含义:
bit 该bit置1
0 包含shell item id list节,通过修改文件过滤掉该节,不影响.lnk执行目标文件,但影响其它功能。
1 指向文件或文件夹,如果此位为0表示指向其他。
2 存在描述字符串
3 存在相对路径
4 存在工作路径
5 存在命令行参数
6 存在自定义图标 *--> 该位置一般用于病毒判断是否感染目标文件的标志.
Shell Item Id List
是个可选结构,由文件头中offset 0x14位置处的值来决定,0 bit值为1时,表示该lnk文件包含该结构。
如果存在该结构,偏移0x4c的位置的一个unsigned short int是Shell Item Id List结构的大小标识,后面紧跟一个SHITEMID结构,该结构体定义如下
typedef struct _SHITEMID
{
unsigned short int cb;
unsigned char abID[0];
}SHITEMID,*LPSHITEMID;
cb标识一项SHITEMID结构大小,abID是可变结构,存储数据具体数据,里面的含义有些未知,但第0项里面的数据是不能修改的,否则.lnk文件无法运行。
Shell Item Id List 结构
size (该节总长度): 该项如果修改,会导致.lnk无法运行,如果含有命令参数,也会混乱。
SHITEMID[0]: 该项所有值均固定,unsigned char data[22] = { 0x14, 0x00, 0x1F,0x50, 0xE0, 0x4F, 0xD0, 0x20, 0xEA, 0x3A, 0x69, 0x10, 0xA2, 0xD8, 0x08, 0x00,0x2B, 0x30, 0x30, 0x9D}
SHITEMID[1]: 该项cb的值一般固定为0x2f(也可能是别的值),不可修改。abID的值为指向目标程序所在盘符的字符串,如”C:”,该段空间数据可以任意修改。
……………
File location info
Offset Size Type Description
0x00 1dword 该节总长度,该值的修改,会影响.lnk文件执行或命令参数混乱失效。
0x04 1dword 固定为0x1c,指明为该节长度,该值可任意修改。
0x08 1dword flags标志,指示文件在哪些卷有效,例如是本地卷标还是网络卷标。
0x0c 1dword 固定为0x1c,本地卷信息表偏移。
0x10 1dword 指明目标文件路径相对本节头部的偏移,但.lnk文件执行目标程序并不依赖于该值指向的路径是否正确。
0x14 1dword 网络卷信息表偏移,如果flags标记含有网络卷的话,否则为0.
0x18 1dword 剩余偏移路径,一般都指向本节的末尾,也就是节总长度减1的值,当该值指向的位置为0时(大多数情况下都是0),该值可任意修改。
flags 具体含义:
如果目标文件是本地文件,那么文件名称 = 本地路径信息+剩余偏移路径
如果目标文件是网络文件,那么文件名称 = 网络卷中共享名称+剩余偏移路径
接着File location info节的数据是,本地卷信息表,及网络卷信息表。
本地卷信息表结构如下:
Offset Size Type Description
0x00 1dword 本地卷信息表的长度,该值可任意修改。
0x04 1dword 卷类型(网络盘,软盘,硬盘,可移动...后面有说明),该值可以任意修改。
0x08 1dword 标识卷序列号,2byte一组,该值可任意修改。
0x0c 1dword 卷名称的偏移,固定为0x10,该值可以任意修改。
0x10 可变长度 卷名称,其大小由该表总长度决定。
网络卷信息表结构如下:
Offset Size Type Description
0x00 1dword 网络卷信息表的长度,该值可任意修改。
0x04 1dword 固定为0x2
0x08 1dword 固定为0x14
0x0c 1dword 固定为0
0x10 可变长度 固定为0x20000
0x10 可变长度 网络共享名
Description string
一般指描述字符节,是个可选结构,由文件头中offset 0x14位置处的值来决定,2 bit值为1时,表示该lnk文件包含该结构。该节开始是个unsigned short int表示该节的长度,不包含这2byte,由于该字符串的描述字符为unicode字符,所以取得该值后还得乘以2.该字符也就是右键查看快捷方式信息中的“起始位置(S)”中的那个描述,该值修改不影响.lnk文件执行。
Relative path string
一般指相对路径节,是个可选结构,由文件头中offset 0x14位置处的值来决定,3 bit值为1时,表示该lnk文件包含该结构。该节结构同上。
Working directory string
一般指工作路径节,是个可选结构,由文件头中offset 0x14位置处的值来决定,4 bit值为1时,表示该lnk文件包含该结构。该节结构同上。
Command line string
一般指命令行节,是个可选结构,由文件头中offset 0x14位置处的值来决定,5 bit值为1时,表示该lnk文件包含该结构。该节结构同上。
Icon filename string
一般指自定义图标节,是个可选结构,由文件头中offset 0x14位置处的值来决定,6 bit值为1时,表示该lnk文件包含该结构。该节结构同上。
Extra stuff
里面的数据具体含义未知,有些里面会包含一些本机机器名称。
漏洞分析
编写poc脚本,放在桌面,然后再写一个dll文件,放在C盘根目录。 poc脚本:
dll文件:
#include<Windows.h>
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
if(dwReason == DLL_PROCESS_ATTACH)
MessageBox(0, TEXT("Called me!"), TEXT("Cap"), 0);
return TRUE;
}
然后返回桌面刷新一下,就会有弹窗出现。
因为不知道是什么触发漏洞的,看了些文章,认为是explorer.exe解析luk文件出现问题,所以这里要用双机调试。加载完后在windbg里运行如下:
nt!RtlpBreakWithStatusInstruction:
83ec8110 cc int 3
kd> !sym noisy;.reload /user *
noisy mode - symbol prompts on
Press ctrl-c (cdb, kd, ntsd) or ctrl-break (windbg) to abort symbol loads that
take too long.
Run !sym noisy before .reload to track down problems loading symbols.
SYMSRV: BYINDEX: 0x2
f:windows kitsmylocalsymbols*http://msdl.microsoft.com/download/symbols
ntdll.dll
4CE7B96E13c000
SYMSRV: UNC: f:windows kitsmylocalsymbolsntdll.dll4CE7B96E13c000ntdll.dll - path not found
SYMSRV: UNC: f:windows kitsmylocalsymbolsntdll.dll4CE7B96E13c000ntdll.dl_ - path not found
SYMSRV: UNC: f:windows kitsmylocalsymbolsntdll.dll4CE7B96E13c000file.ptr - path not found
SYMSRV: HTTPGET: /download/symbols/index2.txt
SYMSRV: HttpQueryInfo: 80190190 - HTTP_STATUS_BAD_REQUEST
SYMSRV: HTTPGET: /download/symbols/ntdll.dll/4CE7B96E13c000/ntdll.dll
SYMSRV: HttpQueryInfo: 801900c8 - HTTP_STATUS_OK
SYMSRV: ntdll.dll from http://msdl.microsoft.com/download/symbols: 1288488 bcopied
SYMSRV: PATH: f:windows kitsmylocalsymbolsntdll.dll4CE7B96E13c000ntdll.dll
SYMSRV: RESULT: 0x00000000
DBGHELP: f:windows kitsmylocalsymbolsntdll.dll4CE7B96E13c000ntdll.dll - OK
DBGENG: Partial symbol load found image f:windows kitsmylocalsymbolsntdll.dll4CE7B96E13c000ntdll.dll.
DBGHELP: f:windows kitsmycodessymbolsntdll.pdb - file not found
DBGHELP: f:windows kitsmycodessymbolsdllntdll.pdb - file not found
DBGHELP: f:windows kitsmycodessymbolssymbolsdllntdll.pdb - file not found
SYMSRV: BYINDEX: 0x3
f:windows kitsmylocalsymbols*http://msdl.microsoft.com/download/symbols
ntdll.pdb
120028FA453F4CD5A6A404EC37396A582
SYMSRV: UNC: f:windows
kitsmylocalsymbolsntdll.pdb120028FA453F4CD5A6A404EC37396A582ntdll.pdb -
path not found
SYMSRV: UNC: f:windows
kitsmylocalsymbolsntdll.pdb120028FA453F4CD5A6A404EC37396A582ntdll.pd_ -
path not found
SYMSRV: UNC: f:windows
kitsmylocalsymbolsntdll.pdb120028FA453F4CD5A6A404EC37396A582file.ptr -
path not found
SYMSRV: HTTPGET:
/download/symbols/ntdll.pdb/120028FA453F4CD5A6A404EC37396A582/ntdll.pdb
SYMSRV: HttpQueryInfo: 801900c8 - HTTP_STATUS_OK
SYMSRV: ntdll.pdb from http://msdl.microsoft.com/download/symbols: 2124800
copied
SYMSRV: PATH: f:windows
kitsmylocalsymbolsntdll.pdb120028FA453F4CD5A6A404EC37396A582ntdll.pdb
SYMSRV: RESULT: 0x00000000
DBGHELP: ntdll - public symbols
f:windows
kitsmylocalsymbolsntdll.pdb120028FA453F4CD5A6A404EC37396A582ntdll.pdb
kd> .reload
Connected to Windows 7 7601 x86 compatible target at (Wed Jul 31 14:33:51.828
2019 (UTC + 8:00)), ptr64 FALSE
DBGHELP: f:windows kitsmycodessymbolsntkrpamp.pdb - file not found
DBGHELP: f:windows kitsmycodessymbolsexentkrpamp.pdb - file not found
DBGHELP: f:windows kitsmycodessymbolssymbolsexentkrpamp.pdb - file not
found
SYMSRV: BYINDEX: 0x4
f:windows kitsmylocalsymbols*http://msdl.microsoft.com/download/symbols
ntkrpamp.pdb
684DA42A30CC450F81C535B4D18944B12
SYMSRV: PATH: f:windows
kitsmylocalsymbolsntkrpamp.pdb684DA42A30CC450F81C535B4D18944B12ntkrpamp.pdb
SYMSRV: RESULT: 0x00000000
DBGHELP: nt - public symbols
f:windows
kitsmylocalsymbolsntkrpamp.pdb684DA42A30CC450F81C535B4D18944B12ntkrpamp.pdb
Loading Kernel Symbols
.......................................
Press ctrl-c (cdb, kd, ntsd) or ctrl-break (windbg) to abort symbol loads that
take too long.
Run !sym noisy before .reload to track down problems loading symbols.
........................
................................................................
............................
Loading User Symbols
...................................................
Loading unloaded module list
......
SYMSRV: BYINDEX: 0x5
f:windows kitsmylocalsymbols*http://msdl.microsoft.com/download/symbols
ntdll.dll
4CE7B96E13c000
SYMSRV: PATH: f:windows
kitsmylocalsymbolsntdll.dll4CE7B96E13c000ntdll.dll
SYMSRV: RESULT: 0x00000000
DBGHELP: f:windows kitsmylocalsymbolsntdll.dll4CE7B96E13c000ntdll.dll
- OK
DBGENG: Partial symbol load found image f:windows
kitsmylocalsymbolsntdll.dll4CE7B96E13c000ntdll.dll.
DBGHELP: f:windows kitsmycodessymbolsntdll.pdb - file not found
DBGHELP: f:windows kitsmycodessymbolsdllntdll.pdb - file not found
DBGHELP: f:windows kitsmycodessymbolssymbolsdllntdll.pdb - file not
found
SYMSRV: BYINDEX: 0x6
f:windows kitsmylocalsymbols*http://msdl.microsoft.com/download/symbols
ntdll.pdb
120028FA453F4CD5A6A404EC37396A582
SYMSRV: PATH: f:windows
kitsmylocalsymbolsntdll.pdb120028FA453F4CD5A6A404EC37396A582ntdll.pdb
SYMSRV: RESULT: 0x00000000
DBGHELP: ntdll - public symbols
f:windows
kitsmylocalsymbolsntdll.pdb120028FA453F4CD5A6A404EC37396A582ntdll.pdb
........
kd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
………………………………
PROCESS 87ab9d40 SessionId: 1 Cid: 09c8 Peb: 7ffd7000 ParentCid: 09a8
DirBase: 3f313440 ObjectTable: 941e92b8 HandleCount: 747.
Image: explorer.exe
………………………………
kd> .process -i -r -p 87ab9d40
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
83ec8110 cc int 3
kd> bp Kernel32!LoadLibraryW "$<C:Users32716Desktop"
SYMSRV: BYINDEX: 0x7
f:windows kitsmylocalsymbols*http://msdl.microsoft.com/download/symbols
kernel32.dll
4CE7B8EFd4000
SYMSRV: UNC: f:windows kitsmylocalsymbolskernel32.dll4CE7B8EFd4000kernel32.dll - path not found
SYMSRV: UNC: f:windows kitsmylocalsymbolskernel32.dll4CE7B8EFd4000kernel32.dl_ - path not found
SYMSRV: UNC: f:windows kitsmylocalsymbolskernel32.dll4CE7B8EFd4000file.ptr - path not found
SYMSRV: HTTPGET: /download/symbols/kernel32.dll/4CE7B8EFd4000/kernel32.dll
SYMSRV: HttpQueryInfo: 801900c8 - HTTP_STATUS_OK
SYMSRV: kernel32.dll from http://msdl.microsoft.com/download/symbols: 857600 bytcopied
SYMSRV: PATH: f:windows kitsmylocalsymbolskernel32.dll4CE7B8EFd4000kernel32.dll
SYMSRV: RESULT: 0x00000000
DBGHELP: f:windows kitsmylocalsymbolskernel32.dll4CE7B8EFd4000kernel32.dll - OK
DBGENG: Partial symbol load found image f:windows kitsmylocalsymbolskernel32.dll4CE7B8EFd4000kernel32.dll.
DBGHELP: f:windows kitsmycodessymbolskernel32.pdb - file not found
DBGHELP: f:windows kitsmycodessymbolsdllkernel32.pdb - file not found
DBGHELP: f:windows kitsmycodessymbolssymbolsdllkernel32.pdb - file not found
SYMSRV: BYINDEX: 0x8
f:windows kitsmylocalsymbols*http://msdl.microsoft.com/download/symbols
kernel32.pdb
D4AC3906D49D487B9F69F9326A7D206A2
SYMSRV: UNC: f:windows kitsmylocalsymbolskernel32.pdbD4AC3906D49D487B9F69F9326A7D206A2kernel32.pdb - path not found
SYMSRV: UNC: f:windows kitsmylocalsymbolskernel32.pdbD4AC3906D49D487B9F69F9326A7D206A2kernel32.pd_ - path not found
SYMSRV: UNC: f:windows kitsmylocalsymbolskernel32.pdbD4AC3906D49D487B9F69F9326A7D206A2file.ptr - path not found
SYMSRV: HTTPGET: /download/symbols/kernel32.pdb/D4AC3906D49D487B9F69F9326A7D206A2/kernel32.pdb
SYMSRV: HttpQueryInfo: 801900c8 - HTTP_STATUS_OK
SYMSRV: kernel32.pdb from http://msdl.microsoft.com/download/symbols: 2698240 copied
SYMSRV: PATH: f:windows kitsmylocalsymbolskernel32.pdbD4AC3906D49D487B9F69F9326A7D206A2kernel32.pdb
SYMSRV: RESULT: 0x00000000
DBGHELP: kernel32 - public symbols
f:windows kitsmylocalsymbolskernel32.pdbD4AC3906D49D487B9F69F9326A7D206A2kernel32.pdb
kd> bl
0 e Disable Clear 77403c01 0001 (0001) kernel32!LoadLibraryW "$<C:Users32716Desktop"
kd> g
SYMSRV: BYINDEX: 0x9
f:windows kitsmylocalsymbols*http://msdl.microsoft.com/download/symbols
SHELL32.dll
4CE7B9DEc4a000
SYMSRV: UNC: f:windows kitsmylocalsymbolsSHELL32.dll4CE7B9DEc4a000SHELL32.dll - path not found
SYMSRV: UNC: f:windows kitsmylocalsymbolsSHELL32.dll4CE7B9DEc4a000SHELL32.dl_ - path not found
SYMSRV: UNC: f:windows kitsmylocalsymbolsSHELL32.dll4CE7B9DEc4a000file.ptr - path not found
SYMSRV: HTTPGET: /download/symbols/SHELL32.dll/4CE7B9DEc4a000/SHELL32.dll
SYMSRV: HttpQueryInfo: 801900c8 - HTTP_STATUS_OK
SYMSRV: SHELL32.dll from http://msdl.microsoft.cocopied
SYMSRV: PATH: f:windows kitsmylocalsymbolsSHELL32.dll4CE7B9DEc4a000SHELL32.dll
SYMSRV: RESULT: 0x00000000
DBGHELP: f:windows kitsmylocalsymbolsSHELL32.dll4CE7B9DEc4a000SHELL32.dll - OK
DBGENG: Partial symbol load found image f:windows kitsmylocalsymbolsSHELL32.dll4CE7B9DEc4a000SHELL32.dll.
DBGHELP: f:windows kitsmycodessymbolsshell32.pdb - file not found
DBGHELP: f:windows kitsmycodessymbolsdllshell32.pdb - file not found
DBGHELP: f:windows kitsmycodessymbolssymbolsdllshell32.pdb - file not found
SYMSRV: BYINDEX: 0xA
f:windows kitsmylocalsymbols*http://msdl.microsoft.com/download/symbols
shell32.pdb
4555A5FB02FA4E49B65A25616CD97A6B2
SYMSRV: UNC: f:windows
kitsmylocalsymbolsshell32.pdb4555A5FB02FA4E49B65A25616CD97A6B2shell32.pdb - path not found
SYMSRV: UNC: f:windows
kitsmylocalsymbolsshell32.pdb4555A5FB02FA4E49B65A25616CD97A6B2shell32.pd_ - path not found
SYMSRV: UNC: f:windows
kitsmylocalsymbolsshell32.pdb4555A5FB02FA4E49B65A25616CD97A6B2file.ptr - path not found
SYMSRV: HTTPGET:
/download/symbols/shell32.pdb/4555A5FB02FA4E49B65A25616CD97A6B2/shell32.pdb
SYMSRV: HttpQueryInfo: 801900c8 - HTTP_STATUS_OK
SYMSRV: shell32.pdb from http://msdl.microsoft.ccopied
SYMSRV: PATH: f:windows kitsmylocalsymbolsshell32.pdb4555A5FB02FA4E49B65A25616CD97A6B2shell32.pdb
SYMSRV: RESULT: 0x00000000
DBGHELP: SHELL32 - public symbols
f:windows kitsmylocalsymbolsshell32.pdb4555A5FB02FA4E49B65A25616CD97A6B2shell32.pdb
Command file execution failed, Win32 error 0n5
"拒绝访问。"
kernel32!LoadLibraryW:
001b:77403c01 8bff mov edi,edi
kd> k
ChildEBP RetAddr
00 0429b7e4 75f873ed kernel32!LoadLibraryW
01 0429ba40 761a259f SHELL32!CPL_LoadCPLModule+0x169
02 0429c0e4 761a26e6 SHELL32!CControlPanelFolder::_GetPidlFromAppletId+0x19c
03 0429c110 75f37b0b SHELL32!CControlPanelFolder::ParseDisplayName+0x49
04 0429c194 75f3f21f SHELL32!CRegFolder::ParseDisplayName+0x93
05 0429c208 75f4083d SHELL32!ReparseRelativeIDList+0x137
06 0429c24c 75f40885 SHELL32!TranslateAliasWithEvent+0xa6
07 0429c264 75f0e916 SHELL32!TranslateAlias+0x15
08 0429c290 75f0e6ab SHELL32!CShellLink::_DecodeSpecialFolder+0xf9
09 0429d554 760580b5 SHELL32!CShellLink::_LoadFromStream+0x39f kd> lm v m shell32
Browse full module list
start end module name
76760000 773aa000 SHELL32 (pdb symbols) f:windows kitsmylocalsymbolsshell32.pdb4555A5FB02FA4E49B65A25616CD97A6B2shell32.pdb
Loaded symbol image file: SHELL32.dll
Mapped memory image file: f:windows kitsmylocalsymbolsSHELL32.dll4CE7B9DEc4a000SHELL32.dll
Image path: C:Windowssystem32SHELL32.dll
Image name: SHELL32.dll
Browse all global symbols functions data
Timestamp: Sat Nov 20 20:06:54 2010 (4CE7B9DE)
CheckSum: 00C531DC
ImageSize: 00C4A000
Translations: 0000.04b0 0000.04e4 0409.04b0 0409.04e4
Information from resource tables:
可以通过栈回溯看到大部分的函数都是shell32.dll调用的,那么就找到dll的位置,用ida加载。从加载lnk文件的位置开始,找到CShellLink::_LoadFromStream函数,F5看伪代码。
a2就是指向lnk文件的指针,这里先是读取了lnk文件的前4个字节到v20,然后判断是否为0x4C。其实就是判断这个文件是不是lnk文件。如果是lnk文件,则再读取4个字节后面0x48个字节的内容,存在v3+0xF4的位置,再比较4个字节后的0x10个字节的字符是否为指定字符。可以看到poc均是满足这些条件的。
v19 = v4->Read(a2, &v20, 4, (ULONG *)&v21);
if ( v20 != 0x4C
|| (v19 = a2->lpVtbl->Read(a2, (char *)v3 + 0xF4, 0x48, (ULONG *)&v21), v19 < 0)
|| v21 != 0x48
|| memcmp((char *)v3 + 0xF4, &CLSID_ShellLink, 0x10u) )
{
LABEL_72:
v19 = -2147467259;
goto LABEL_44;
}
然后是这一段,注意v3是dword所以后面要*4,也就是说v5=v3+0x12C-1的位置,而v3是从0xF4开始读取了0x48个字节的字符,所以这里其实是lnk文件格式偏移的第0x3C位,可以通过poc知道v3+0x12C为0,所以这里v5为-1。跳过下面的if。
v5 = *((_DWORD *)v3 + 0x4B) - 1;
*((_DWORD *)v3 + 0x3C) = 0x4C;
if ( v5 )
{
v18 = v5 - 2;
if ( v18 )
{
if ( v18 != 4 )
*((_DWORD *)v3 + 75) = 1;
}
}
这里的v3+0x104的位置是lnk+0x14的位置,也就是前面lnk文件格式介绍的Flags标识位。Poc里面是1所以v6=0。会进入CShellLink::_LoadIDList函数。这个函数从名字上就可以猜测是加载IDList位置的。动态调试可以看到读取了lnk后面的SHITEMID[]。同时还可以看到这里有我们编译的poc的地址,也就是c:a.dll
然后后面就是读取最后的Extra stuff段,放在v3+228的位置。
v19 = SHReadDataBlockList(a2, (char *)v3 + 228);
if ( v19 >= 0 )
{
if ( !*((_DWORD *)v3 + 47) )
{
if ( *((_DWORD *)v3 + 65) & 0x2000000 )
{
if ( CShellLink::_GetExpandedPath(v3, &pszPath, 0x104u) )
CShellLink::_SetSimplePIDL(v3, &pszPath);
}
else
{
v16 = SHFindDataBlock(*((_DWORD *)v3 + 57), -1610612724);
if ( v16 )
{
ppbc.lpVtbl = (IBindCtxVtbl *)1;
v19 = SHILClone((void *)(v16 + 8), (int)v3 + 188);
}
}
}
这里看到了CShellLink::_DecodeSpecialFolder函数,从前面的崩溃函数位置的栈回溯可以看到有这个函数,所以需要注意一下,v3+47*4其实就是判断前面读取的IDlist是否存在,poc中是存在的所以会进入CShellLink::_DecodeSpecialFolder。
if ( *((_DWORD *)v3 + 65) & 0x1000 )
{
CShellLink::_UpdateIconFromExpIconSz(v3);
v17 = *((_DWORD *)v3 + 54);
if ( v17 && SHExpandEnvironmentStringsW(v17, &pszPath, 260) )
CShellLink::_SetPIDLPath(0, &pszPath, 0);
}
else if ( *((_DWORD *)v3 + 47) )
{
CShellLink::_DecodeSpecialFolder(v3);
}
在CShellLink::_DecodeSpecialFolder函数里面现实寻找加载lnk偏移57*4的位置是否有0xA000000B,从poc中可以看到没有,v2=0,进入else。然后又寻找0xA0000005,可以发现poc里存在这个值,v16为“0xA0000005”的地址。后面这句v20 = (LPITEMIDLIST)SHCloneSpecialIDList(0, *(_DWORD *)(v16 + 8), 0);是
v20 = 0;
v1 = this;
v2 = SHFindDataBlock(*((_DWORD *)this + 57), 0xA000000B);
v3 = v2;
if ( v2 )
{
if ( !CShellLink::_ShouldDecodeSpecialFolder(v1, (const struct _GUID *)(v2 + 8)) )
goto LABEL_19;
v4 = 0x4000;
if ( *((_DWORD *)v1 + 65) & 0x400000 )
v4 = 20480;
v5 = SHGetKnownFolderIDList(v3 + 8, v4, 0, &v20);
v6 = *(_DWORD *)(v3 + 24);
}
else
{
v16 = SHFindDataBlock(*((_DWORD *)v1 + 57), 0xA0000005);
v17 = v16;
if ( !v16 )
goto LABEL_19;
v20 = (LPITEMIDLIST)SHCloneSpecialIDList(0, *(_DWORD *)(v16 + 8), 0);
v6 = *(_DWORD *)(v17 + 12);
v5 = v20 != 0 ? 0 : 0x8007000E;
}
寻找0xA0000005,可以发现poc里存在这个值,返回值为“0xA0000005”的地址
kd> p
SHELL32!CShellLink::_DecodeSpecialFolder+0x6f:
75f0f401 68050000a0 push 0A0000005h
kd> p
SHELL32!CShellLink::_DecodeSpecialFolder+0x74:
75f0f406 ffb6e4000000 push dword ptr [esi+0E4h]
kd> p
SHELL32!CShellLink::_DecodeSpecialFolder+0x7a:
75f0f40c ffd3 call ebx
kd> p
SHELL32!CShellLink::_DecodeSpecialFolder+0x7c:
75f0f40e 8bf8 mov edi,eax
kd> r
eax=03ec8df0 ebx=758e1e1e ecx=00000010 edx=a0000005 esi=03eaf340 edi=00000000
eip=75f0f40e esp=021cc078 ebp=021cc090 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
SHELL32!CShellLink::_DecodeSpecialFolder+0x7c:
75f0f40e 8bf8 mov edi,eax
kd> db 03ec8df0
03ec8df0 10 00 00 00 05 00 00 a0-03 00 00 00 28 00 00 00 ............(...
03ec8e00 00 00 00 00 70 18 ea 07-a7 66 a7 6d 72 00 00 80 ....p....f.mr...
03ec8e10 8a 01 f5 75 00 00 00 00-00 00 00 00 00 00 00 00 ...u............
03ec8e20 00 00 00 00 00 00 61 00-a3 66 a7 6d 5c 00 00 8c ......a..f.m...
03ec8e30 02 00 00 00 f0 17 df 07-02 00 00 00 08 00 00 00 ................
03ec8e40 02 00 00 00 00 00 45 00-af 66 a7 6d 45 00 00 8c ......E..f.mE...
03ec8e50 e0 bc f5 75 01 00 00 00-d2 00 01 00 58 0a 00 00 ...u........X...
03ec8e60 00 52 97 02 00 00 72 00-ab 66 a7 6d 39 00 00 80 .R....r..f.m9...
后面调用SHCloneSpecialIDList函数,第二个参数是前面寻到的指针的后一位,poc中是3。
官方文档中对这个函数的解释是这样的,返回值是指向Control Panel的ITEMIDList结构的指针。
PIDLIST_ABSOLUTE SHCloneSpecialIDList(
HWND hwnd,
int csidl,
BOOL fCreate
);
Returns a pointer to the ITEMIDLIST structure of a special folder specified by csidl. The function creates the folder if fCreate is TRUE.
这个是动态调试的结果,返回值eax就是ITEMIDList结构指针。
kd> p
SHELL32!CShellLink::_DecodeSpecialFolder+0x86:
76079b56 6a00 push 0
kd> p
SHELL32!CShellLink::_DecodeSpecialFolder+0x88:
76079b58 ff7708 push dword ptr [edi+8]
kd> p
SHELL32!CShellLink::_DecodeSpecialFolder+0x8b:
76079b5b 6a00 push 0
kd> p
SHELL32!CShellLink::_DecodeSpecialFolder+0x8d:
76079b5d e86309e5ff call SHELL32!SHCloneSpecialIDList (75eca4c5)
kd> p
SHELL32!CShellLink::_DecodeSpecialFolder+0x92:
76079b62 8945f8 mov dword ptr [ebp-8],eax
kd> r
eax=07e06708 ebx=758e1e1e ecx=62016717 edx=00000002 esi=03eaf340 edi=03ec8df0
eip=76079b62 esp=021cc078 ebp=021cc090 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
SHELL32!CShellLink::_DecodeSpecialFolder+0x92:
76079b62 8945f8 mov dword ptr [ebp-8],eax ss:0023:021cc088=00000000
kd> db eax
07e06708 14 00 1f 70 68 06 ee 26-0a a0 d7 44 93 71 be b0 ...ph..&...D.q..
07e06718 64 c9 86 83 0c 00 01 00-84 21 de 39 00 00 00 00 d........!.9....
07e06728 00 00 00 00 0a 00 00 00-00 4a 37 6d 00 00 00 8e .........J7m....
07e06738 20 00 00 00 1a 00 ee bb-fe 23 00 00 10 00 2f 92 ........#..../.
07e06748 1e 49 43 56 f4 4a a7 eb-4e 7a 13 8d 81 74 00 00 .ICV.J..Nz...t..
07e06758 00 00 33 00 32 00 00 00-0a 4a 37 6d 00 00 00 8e ..3.2....J7m....
07e06768 87 65 f6 4e 1a 5c 2a 67-07 59 fd 4e 02 30 f7 8b .e.N.*g.Y.N.0..
07e06778 55 53 fb 51 e5 4e be 8b-6e 7f 07 59 fd 4e 02 30 US.Q.N..n..Y.N.0
kd> dd edi+8
03ec8df8 00000003 00000028 00000000 07ea1870
03ec8e08 6da766a7 80000072 75f5018a 00000000
03ec8e18 00000000 00000000 00000000 00610000
03ec8e28 6da766a3 8c00005c 00000002 07df17f0
03ec8e38 00000002 00000008 00000002 00450000
03ec8e48 6da766af 8c000045 75f5bce0 00000001
03ec8e58 000100d2 00000a58 02975200 00720000
03ec8e68 6da766ab 80000039 000000ba 029d9850
继续照着栈回溯走,下一个函数是TranslateAlias,传入的第一个参数是ItemID[],第二个参数是ILCloneUpTo函数的返回值,查到资料,ILCloneUpTo函数返回值为“Returns a pointer to a copy of the ITEMIDLIST structure pointed to by pidl”,其实就是一片复制的区域,第三个参数是ITEMIDList结构指针。
v11 = ILCloneUpTo(v7, v8);
pidla = (ITEMIDLIST *)v11;
if ( v11 )
{
v12 = (ITEMIDLIST *)TranslateAlias(*((void **)v1 + 47), v11, (int)v20);
if ( v12 )
{
v13 = (ITEMIDLIST *)ILClone(*((void **)v1 + 47));
v14 = (int)v1 + 192;
v15 = CShellLink::_SetPIDLPath(v12, 0, 2) >= 0;
*(_DWORD *)(v14 + 164) = v15;
…………
动态调试查看ILCloneUpTo返回值,复制的是前两个ItemID,没有复制dll的链接地址。
kd> p
SHELL32!CShellLink::_DecodeSpecialFolder+0xdc:
75f0e8f9 53 push ebx
kd> p
SHELL32!CShellLink::_DecodeSpecialFolder+0xdd:
75f0e8fa 57 push edi
kd> p
SHELL32!CShellLink::_DecodeSpecialFolder+0xde:
75f0e8fb e88de00200 call SHELL32!ILCloneUpTo (75f3c98d)
kd> r
eax=00000000 ebx=02a18e30 ecx=00000028 edx=00000002 esi=03eaf340 edi=02a18e08
eip=75f0e8fb esp=021cc070 ebp=021cc090 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
SHELL32!CShellLink::_DecodeSpecialFolder+0xde:
75f0e8fb e88de00200 call SHELL32!ILCloneUpTo (75f3c98d)
kd> db ebx
02a18e30 44 00 00 00 00 00 00 00-00 00 00 00 00 6a 00 00 D............j..
02a18e40 00 00 00 00 00 00 00 00-43 00 3a 00 5c 00 61 00 ........C.:..a.
02a18e50 2e 00 64 00 6c 00 6c 00-00 00 00 00 00 00 00 00 ..d.l.l.........
02a18e60 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
02a18e70 00 00 00 00 00 00 00 00-81 88 f9 6c 41 00 00 88 ...........lA...
02a18e80 84 f2 b3 75 02 00 00 00-94 cc ba be d3 5c 62 46 ...u.........bF
02a18e90 a1 e0 f3 31 99 49 36 69-a2 67 0f 19 4f 02 d9 40 ...1.I6i.g..O..@
02a18ea0 aa ba 43 9f 5c 80 8f 67-10 00 01 00 00 00 00 00 ..C...g........
kd> db edi
02a18e08 14 00 1f 50 e0 4f d0 20-ea 3a 69 10 a2 d8 08 00 ...P.O. .:i.....
02a18e18 2b 30 30 9d 14 00 2e 80-20 20 ec 21 ea 3a 69 10 +00..... .!.:i.
02a18e28 a2 dd 08 00 2b 30 30 9d-44 00 00 00 00 00 00 00 ....+00.D.......
02a18e38 00 00 00 00 00 6a 00 00-00 00 00 00 00 00 00 00 .....j..........
02a18e48 43 00 3a 00 5c 00 61 00-2e 00 64 00 6c 00 6c 00 C.:..a...d.l.l.
02a18e58 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
02a18e68 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
02a18e78 81 88 f9 6c 41 00 00 88-84 f2 b3 75 02 00 00 00 ...lA......u....
kd> p
SHELL32!CShellLink::_DecodeSpecialFolder+0xe3:
75f0e900 8945f4 mov dword ptr [ebp-0Ch],eax
kd> r
eax=07ed7510 ebx=02a18e30 ecx=62016717 edx=00000000 esi=03eaf340 edi=02a18e08
eip=75f0e900 esp=021cc078 ebp=021cc090 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
SHELL32!CShellLink::_DecodeSpecialFolder+0xe3:
75f0e900 8945f4 mov dword ptr [ebp-0Ch],eax ss:0023:021cc084=02a18e30
kd> db eax
07ed7510 14 00 1f 50 e0 4f d0 20-ea 3a 69 10 a2 d8 08 00 ...P.O. .:i.....
07ed7520 2b 30 30 9d 14 00 2e 80-20 20 ec 21 ea 3a 69 10 +00..... .!.:i.
07ed7530 a2 dd 08 00 2b 30 30 9d-00 00 01 00 00 00 00 00 ....+00.........
07ed7540 be 78 2d 69 c0 87 00 80-9f 01 00 60 00 00 00 00 .x-i.......`....
07ed7550 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
07ed7560 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
07ed7570 00 00 00 00 00 00 00 00-b9 78 2d 69 64 00 00 80 .........x-id...
07ed7580 91 01 1f 50 e0 4f d0 20-ea 3a 69 10 a2 d8 08 00 ...P.O. .:i.....
TranslateAlias函数就一句话,进入TranslateAliasWithEvent函数。
int __stdcall TranslateAlias(void *a1, int a2, int a3)
{
return TranslateAliasWithEvent(0, a1, a2, a3);
}
TranslateAliasWithEvent函数比较短,ILIsEqual function函数测试是否两个ITEMIDLIST结构在二进制比较中是相等的。然后进入else if里面SHBindToObject函数 是Retrieves and binds to a specified object by using the Shell namespace IShellFolder::BindToObject method.是一个绑定相关的函数。ILFindchild函数是确定指定的ITEMIDLIST结构是另一个结构的子结构。返回值是指向子元素的简单值的指针。
int __stdcall TranslateAliasWithEvent(int a1, void *pidl1, int pidl2, int a4)
{
int v4; // eax
int v6; // [esp+10h] [ebp-14h]
int v7; // [esp+14h] [ebp-10h]
LPITEMIDLIST pidl; // [esp+18h] [ebp-Ch]
int v9; // [esp+1Ch] [ebp-8h]
v9 = 0;
if ( pidl1 )
{
if ( ILIsEqual((LPCITEMIDLIST)pidl1, (LPCITEMIDLIST)pidl2) )
{
if ( !a1 || a1 & 0x3000 )
SHILClone((void *)a4, (int)&v9);
}
else if ( SHBindToObject(0, pidl2, 0, &_GUID_000214e6_0000_0000_c000_000000000046, &v6) >= 0 )
{
if ( SHBindToObject(0, a4, 0, &_GUID_000214e6_0000_0000_c000_000000000046, &v7) >= 0 )
{
v4 = ILFindChild(pidl2, pidl1);
if ( v4 && ReparseRelativeIDList(v6, v4, &GUID_NULL, v7, 1, &pidl) >= 0 )
{
SHILCombine((void *)a4, pidl, (int)&v9);
ILFree(pidl);
}
(*(void (__stdcall **)(int))(*(_DWORD *)v7 + 8))(v7);
}
(*(void (__stdcall **)(int))(*(_DWORD *)v6 + 8))(v6);
}
}
return v9;
}
这是ILFindchild函数的演示,可以看到返回值是两个地址不同位置开始的指针,也就是获取dll的路径。
kd> p
SHELL32!TranslateAliasWithEvent+0x86:
75f4081d e844adffff call SHELL32!ILFindChild (75f3b566)
kd> dd esp
0429c220 03f0efe8 02a19330 02a19330 02a12a38
0429c230 02a19358 07e04fc8 07e915a4 03ea2e9c
0429c240 00000028 00000000 6628a55b 0429c264
0429c250 75f40885 00000000 02a19330 03f0efe8
0429c260 07e04fc8 0429c290 75f0e916 02a19330
0429c270 03f0efe8 07e04fc8 00000104 00000000
0429c280 02a12a38 03f0efe8 07e04fc8 6628a587
0429c290 0429d554 75f0e6ab 07f9e4a8 02a12a48
kd> db 03f0efe8
03f0efe8 14 00 1f 50 e0 4f d0 20-ea 3a 69 10 a2 d8 08 00 ...P.O. .:i.....
03f0eff8 2b 30 30 9d 14 00 2e 80-20 20 ec 21 ea 3a 69 10 +00..... .!.:i.
03f0f008 a2 dd 08 00 2b 30 30 9d-00 00 70 00 00 00 00 00 ....+00...p.....
03f0f018 a5 ea a4 6d 00 00 00 8c-38 4f f2 75 30 3a f2 75 ...m....8O.u0:.u
03f0f028 0c 35 f1 75 07 00 00 00-40 25 df 07 30 e0 e5 07 .5.u....@%..0...
03f0f038 68 d3 fe 03 a0 20 fd 03-0b 00 00 00 ff ff ff ff h.... ..........
03f0f048 ff ff ff ff 70 00 00 00-ac ea a4 6d 00 00 00 8c ....p......m....
03f0f058 a8 8a 96 02 00 00 00 00-00 00 00 00 00 00 00 00 ................
kd> db 02a19330
02a19330 14 00 1f 50 e0 4f d0 20-ea 3a 69 10 a2 d8 08 00 ...P.O. .:i.....
02a19340 2b 30 30 9d 14 00 2e 80-20 20 ec 21 ea 3a 69 10 +00..... .!.:i.
02a19350 a2 dd 08 00 2b 30 30 9d-44 00 00 00 00 00 00 00 ....+00.D.......
02a19360 00 00 00 00 00 6a 00 00-00 00 00 00 00 00 00 00 .....j..........
02a19370 43 00 3a 00 5c 00 61 00-2e 00 64 00 6c 00 6c 00 C.:..a...d.l.l.
02a19380 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
02a19390 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
02a193a0 3a 8b f9 6c 68 00 00 80-4c 01 1f 50 e0 4f d0 20 :..lh...L..P.O.
kd> p
SHELL32!TranslateAliasWithEvent+0x8b:
75f40822 85c0 test eax,eax
kd> r
eax=02a19358 ebx=02a19330 ecx=00000e3c edx=00000e3b esi=75f4f9b8 edi=03f0efe8
eip=75f40822 esp=0429c228 ebp=0429c24c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
SHELL32!TranslateAliasWithEvent+0x8b:
75f40822 85c0 test eax,eax
kd> db eax
02a19358 44 00 00 00 00 00 00 00-00 00 00 00 00 6a 00 00 D............j..
02a19368 00 00 00 00 00 00 00 00-43 00 3a 00 5c 00 61 00 ........C.:..a.
02a19378 2e 00 64 00 6c 00 6c 00-00 00 00 00 00 00 00 00 ..d.l.l.........
02a19388 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
02a19398 00 00 00 00 00 00 00 00-3a 8b f9 6c 68 00 00 80 ........:..lh...
02a193a8 4c 01 1f 50 e0 4f d0 20-ea 3a 69 10 a2 d8 08 00 L..P.O. .:i.....
02a193b8 2b 30 30 9d 14 00 2e 80-20 20 ec 21 ea 3a 69 10 +00..... .!.:i.
02a193c8 a2 dd 08 00 2b 30 30 9d-00 00 00 00 00 00 00 00 ....+00.........
接着就是下一个函数ReparseRelativeIDList,它的六个参数是
kd> p
SHELL32!TranslateAliasWithEvent+0xa1:
75f40838 e8e7e8ffff call SHELL32!ReparseRelativeIDList (75f3f124)
kd> dd esp l6
0429c210 07e915a4 02a19358 75f5a7f0 03ea2e9c
0429c220 00000001 0429c240
kd> db 07e915a4
07e915a4 10 fe f4 75 c4 fc f4 75-2c 02 f5 75 b4 9f f4 75 ...u...u,..u...u
07e915b4 d4 fc f4 75 d8 9f f4 75-58 a0 f4 75 a4 9f f4 75 ...u...uX..u...u
07e915c4 ec 9f f4 75 48 a0 f4 75-94 9f f4 75 00 a0 f4 75 ...uH..u...u...u
07e915d4 c4 9f f4 75 50 44 39 38-00 00 00 00 00 00 00 00 ...uPD98........
07e915e4 78 46 e0 07 00 00 00 00-00 00 00 00 00 00 00 00 xF..............
07e915f4 88 46 e0 07 00 00 00 00-00 00 00 00 00 00 00 00 .F..............
07e91604 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
07e91614 00 00 00 00 00 00 00 00-03 00 00 00 f0 87 f1 75 ...............u
kd> db 02a19358
02a19358 44 00 00 00 00 00 00 00-00 00 00 00 00 6a 00 00 D............j..
02a19368 00 00 00 00 00 00 00 00-43 00 3a 00 5c 00 61 00 ........C.:..a.
02a19378 2e 00 64 00 6c 00 6c 00-00 00 00 00 00 00 00 00 ..d.l.l.........
02a19388 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
02a19398 00 00 00 00 00 00 00 00-3a 8b f9 6c 68 00 00 80 ........:..lh...
02a193a8 4c 01 1f 50 e0 4f d0 20-ea 3a 69 10 a2 d8 08 00 L..P.O. .:i.....
02a193b8 2b 30 30 9d 14 00 2e 80-20 20 ec 21 ea 3a 69 10 +00..... .!.:i.
02a193c8 a2 dd 08 00 2b 30 30 9d-00 00 00 00 00 00 00 00 ....+00.........
kd> db 75f5a7f0
75f5a7f0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
75f5a800 ef 40 5a 7c fb a0 fc 4b-87 4a c0 f2 e0 b9 fa 8e .@Z|...K.J......
75f5a810 90 90 90 90 90 8b ff 55-8b ec 83 7d 0c 00 0f 87 .......U...}....
75f5a820 6d 61 10 00 8b 45 08 72-09 83 f8 ff 0f 87 5f 61 ma...E.r......_a
75f5a830 10 00 8b 4d 10 89 01 33-c0 5d c2 0c 00 90 90 90 ...M...3.]......
75f5a840 90 90 8b ff 55 8b ec ff-75 10 8b 45 0c 83 e0 40 ....U...u..E...@
75f5a850 50 ff 15 34 13 eb 75 8b-4d 14 89 01 f7 d8 1b c0 P..4..u.M.......
75f5a860 25 f2 ff f8 7f 05 0e 00-07 80 5d c2 10 00 90 90 %.........].....
kd> db 03ea2e9c
03ea2e9c 10 fe f4 75 c4 fc f4 75-2c 02 f5 75 b4 9f f4 75 ...u...u,..u...u
03ea2eac d4 fc f4 75 d8 9f f4 75-58 a0 f4 75 a4 9f f4 75 ...u...uX..u...u
03ea2ebc ec 9f f4 75 48 a0 f4 75-94 9f f4 75 00 a0 f4 75 ...uH..u...u...u
03ea2ecc c4 9f f4 75 50 44 39 38-00 00 00 00 00 00 00 00 ...uPD98........
03ea2edc 78 40 e0 07 00 00 00 00-00 00 00 00 00 00 00 00 x@..............
03ea2eec 88 40 e0 07 00 00 00 00-00 00 00 00 00 00 00 00 .@..............
03ea2efc 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
03ea2f0c 00 00 00 00 00 00 00 00-03 00 00 00 f0 87 f1 75 ...............u
kd> db 0429c240
0429c240 28 00 00 00 00 00 00 00-5b a5 28 66 64 c2 29 04 (.......[.(fd.).
0429c250 85 08 f4 75 00 00 00 00-30 93 a1 02 e8 ef f0 03 ...u....0.......
0429c260 c8 4f e0 07 90 c2 29 04-16 e9 f0 75 30 93 a1 02 .O....)....u0...
0429c270 e8 ef f0 03 c8 4f e0 07-04 01 00 00 00 00 00 00 .....O..........
0429c280 38 2a a1 02 e8 ef f0 03-c8 4f e0 07 87 a5 28 66 8*.......O....(f
0429c290 54 d5 29 04 ab e6 f0 75-a8 e4 f9 07 48 2a a1 02 T.)....u....H*..
0429c2a0 00 00 00 00 a8 e4 f9 07-00 00 00 00 4c 00 00 00 ............L...
0429c2b0 48 00 00 00 00 00 00 00-24 00 00 00 c8 c2 29 04 H.......$.....).
这里的pv是前面ILFindchild函数的返回值,就是dll的路径所以这里会到else里面去。然后后面的SHILCloneFirst没有查到函数作用,但动态调试出来返回值是0。往下的GetParsingBindCtx函数也没有查到,但返回值还是0。
if ( ILIsEmpty((const struct _ITEMIDLIST_RELATIVE *)pv) )
{
LABEL_21:
if ( v6 >= 0 )
{
if ( !*(_DWORD *)v15 )
v6 = -2147467259;
goto LABEL_24;
}
}
else
{
while ( v6 >= 0 )
{
v6 = SHILCloneFirst(Src, (int)&v14);
if ( v6 >= 0 )
{
v6 = DisplayNameOfAsString((int)v18, (int)v14, 0x8001, &pv);
if ( v6 >= 0 )
{
v6 = GetParsingBindCtx(
(struct IShellFolder2 *)v18,
(const struct _ITEMID_CHILD *)v14,
a5,
(struct IBindCtx **)&v16);
if ( v6 >= 0 )
{
if ( ILIsChild((const struct _ITEMIDLIST_RELATIVE *)Src)
&& memcmp(&GUID_NULL, &v21, 0x10u)
&& SHCreateGUIDBindCtx((int)v16, (int)L"KnownFolderID", v11, &ppbc) >= 0 )
{
IUnknown_Set(&v16, (IUnknown *)ppbc);
ppbc->lpVtbl->Release(ppbc);
}
v6 = ((int (__stdcall *)(IUnknown *, _DWORD, IUnknown *, LPVOID, _DWORD, LPITEMIDLIST *, _DWORD))ppunk->lpVtbl[1].QueryInterface)(
ppunk,
0,
v16,
pv,
0,
&pidl,
0);
继续跟着栈回溯找函数,下一个应该是CRegFolder::ParseDisplayName函数,但在这个ReparseRelativeIDList函数里面并没有找到CRegFolder::ParseDisplayName函数,于是怀疑是不是ida没有解析出来,利用动态调试,根据栈回溯调用的位置SHELL32!ReparseRelativeIDList+0x134找到ReparseRelativeIDList函数。找到ReparseRelativeIDList函数及其个参数。
kd> p
SHELL32!ReparseRelativeIDList+0x134:
75f3f21c ff510c call dword ptr [ecx+0Ch]
kd> dd esp l7
0429c19c 03ea2e9c 00000000 03e94448 03efb990
0429c1ac 00000000 0429c1ec 00000000
kd> db 03ea2e9c
03ea2e9c 10 fe f4 75 c4 fc f4 75-2c 02 f5 75 b4 9f f4 75 ...u...u,..u...u
03ea2eac d4 fc f4 75 d8 9f f4 75-58 a0 f4 75 a4 9f f4 75 ...u...uX..u...u
03ea2ebc ec 9f f4 75 48 a0 f4 75-94 9f f4 75 00 a0 f4 75 ...uH..u...u...u
03ea2ecc c4 9f f4 75 50 44 39 38-00 00 00 00 00 00 00 00 ...uPD98........
03ea2edc 78 40 e0 07 00 00 00 00-00 00 00 00 00 00 00 00 x@..............
03ea2eec 88 40 e0 07 00 00 00 00-00 00 00 00 00 00 00 00 .@..............
03ea2efc 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
03ea2f0c 00 00 00 00 00 00 00 00-03 00 00 00 f0 87 f1 75 ...............u
kd> db 03e94448
03e94448 88 62 fb 76 01 00 00 00-10 00 00 00 00 00 00 00 .b.v............
03e94458 00 10 00 00 00 00 00 00-00 00 00 00 15 00 00 00 ................
03e94468 04 08 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
03e94478 88 50 e0 07 2b 30 30 9d-ae d3 ec 6c 00 00 00 80 .P..+00....l....
03e94488 6a 00 fb 76 00 00 00 00-24 00 00 00 00 00 00 00 j..v....$.......
03e94498 02 00 00 00 00 00 00 00-00 00 00 00 15 00 00 00 ................
03e944a8 04 08 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
03e944b8 e8 50 e0 07 6c 00 00 00-a6 d3 ec 6c 00 00 00 8c .P..l......l....
kd> db 03efb990
03efb990 7b 00 42 00 39 00 43 00-41 00 42 00 35 00 32 00 {.B.9.C.A.B.5.2.
03efb9a0 39 00 2d 00 35 00 43 00-37 00 43 00 2d 00 34 00 9.-.5.C.7.C.-.4.
03efb9b0 42 00 35 00 41 00 2d 00-38 00 31 00 34 00 45 00 B.5.A.-.8.1.4.E.
03efb9c0 2d 00 32 00 46 00 35 00-32 00 35 00 31 00 38 00 -.2.F.5.2.5.1.8.
03efb9d0 45 00 36 00 45 00 46 00-46 00 7d 00 00 00 00 00 E.6.E.F.F.}.....
03efb9e0 1a 03 a7 6d 3d 95 00 88-30 f1 25 b7 ef 47 1a 10 ...m=...0.%..G..
03efb9f0 a5 f1 02 60 8c 9e eb ac-0e 00 00 00 a6 6a 63 28 ...`.........jc(
03efba00 3d 95 d2 11 b5 d6 00 c0-4f d9 18 d0 0b 00 00 00 =.......O.......
kd> db 0429c1ec
0429c1ec 04 c2 29 04 58 93 a1 02-00 00 00 00 00 00 00 00 ..).X...........
0429c1fc 00 00 00 00 00 00 00 00-1f a5 28 66 4c c2 29 04 ..........(fL.).
0429c20c 3d 08 f4 75 a4 15 e9 07-58 93 a1 02 f0 a7 f5 75 =..u....X......u
0429c21c 9c 2e ea 03 01 00 00 00-40 c2 29 04 30 93 a1 02 ........@.).0...
0429c22c 38 2a a1 02 58 93 a1 02-c8 4f e0 07 a4 15 e9 07 8*..X....O......
0429c23c 9c 2e ea 03 00 00 00 00-00 00 00 00 5b a5 28 66 ............[.(f
0429c24c 64 c2 29 04 85 08 f4 75-00 00 00 00 30 93 a1 02 d.)....u....0...
0429c25c e8 ef f0 03 c8 4f e0 07-90 c2 29 04 16 e9 f0 75 .....O....)....u
kd> t
SHELL32!CRegFolder::ParseDisplayName:
75f37a98 8bff mov edi,edi
进入CRegFolder::ParseDisplayName函数,a6是第六个参数,a4是第四个参数,从上面可以看出不符合if条件所以到else,这又是一个没有解析出来的函数,但通过动态调试,发现它就是需要找的下一个CControlPanelFolder::ParseDisplayName
v10 = 0x80070057;
if ( a6 )
{
*a6 = 0;
if ( a4 )
{
if ( *a4 && *a4 == 58 && a4[1] == 58 )
{
v10 = CRegFolder::_ParseItemName((CRegFolder *)((char *)this - 20), a4, a2, a3, a6, a7);
}
else
{
v11 = (*(int (__stdcall **)(_DWORD, HWND, struct IBindCtx *, unsigned __int16 *, unsigned int *, struct _ITEMIDLIST_RELATIVE **, unsigned int *))(**((_DWORD **)this + 16) + 12))(
*((_DWORD *)this + 16),
a2,
a3,
a4,
a5,
a6,
a7);
v10 = v11;
CControlPanelFolder::ParseDisplayName函数除了第一个参数和前面不一样,后面六个参数和前面的都一样。
kd> p
SHELL32!CRegFolder::ParseDisplayName+0x90:
75f37b08 ff570c call dword ptr [edi+0Ch]
kd> r
eax=07e04078 ebx=03ea2e9c ecx=0429c1ec edx=00000000 esi=03efb990 edi=75f50320
eip=75f37b08 esp=0429c118 ebp=0429c194 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
SHELL32!CRegFolder::ParseDisplayName+0x90:
75f37b08 ff570c call dword ptr [edi+0Ch] ds:0023:75f5032c={SHELL32!CControlPanelFolder::ParseDisplayName (761a269d)}
kd> dd esp l7
0429c118 07e04078 00000000 03e94448 03efb990
0429c128 00000000 0429c1ec 00000000
kd> db 07e04078
07e04078 20 03 f5 75 64 00 f5 75-e4 fc f4 75 f8 6d f5 75 ..ud..u...u.m.u
07e04088 e8 48 f1 75 18 40 f5 75-f4 71 f1 75 9c 39 f2 75 .H.u.@.u.q.u.9.u
07e04098 8c 84 f1 75 88 6e e0 07-8c 2e ea 03 00 00 00 00 ...u.n..........
07e040a8 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
07e040b8 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
07e040c8 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
07e040d8 00 00 00 00 87 00 00 00-9a 4e 37 6d 00 00 00 8c .........N7m....
07e040e8 74 f8 f4 75 18 18 f5 75-01 00 00 00 ec 40 e0 07 t..u...u.....@..
kd> t
SHELL32!CControlPanelFolder::ParseDisplayName:
761a269d 8bff mov edi,edi
这个函数没什么分析的,因为下一个目标函数就很近CControlPanelFolder::_GetPidlFromAppletId
int __stdcall CControlPanelFolder::ParseDisplayName(CControlPanelFolder *this, HWND a2, struct IBindCtx *a3, unsigned __int16 *a4, unsigned int *a5, struct _ITEMIDLIST_RELATIVE **a6, unsigned int *a7)
{
int result; // eax
int v8; // eax
int v9; // [esp+10h] [ebp-Ch]
struct _ITEMID_CHILD *v10; // [esp+14h] [ebp-8h]
result = 0x80070057;
if ( a6 )
{
*a6 = 0;
if ( a4 )
{
result = GetPidlFromCanonicalName(a4, a6);
if ( result >= 0
|| (result = CControlPanelFolder::_GetPidlFromAppletId((CControlPanelFolder *)((char *)this - 16), a4, a6),
result >= 0) )
{
if ( *a6 )
{
v8 = *(_DWORD *)this;
v10 = *a6;
v9 = 0x1000000;
result = (*(int (__stdcall **)(CControlPanelFolder *, signed int, struct _ITEMID_CHILD **, int *))(v8 + 36))(
this,
1,
&v10,
&v9);
if ( result >= 0 )
{
if ( a7 )
{
if ( *a7 )
result = (*(int (__stdcall **)(CControlPanelFolder *, signed int, struct _ITEMID_CHILD **, unsigned int *))(*(_DWORD *)this + 36))(
this,
1,
&v10,
a7);
}
}
}
}
}
}
return result;
}
动态调试出来这里有个问题就是,ida里面显示的是这个函数有三个参数,但实际调试出来却只有两个参数,我怀疑是不是ida把ecx的值也当作了参数,看ecx的值确实和ida的第一个参数显示是一样的。
kd> p
SHELL32!CControlPanelFolder::ParseDisplayName+0x3f:
761a26dc 57 push edi
kd> p
SHELL32!CControlPanelFolder::ParseDisplayName+0x40:
761a26dd 53 push ebx
kd> p
SHELL32!CControlPanelFolder::ParseDisplayName+0x41:
761a26de 8d4ef0 lea ecx,[esi-10h]
kd> p
SHELL32!CControlPanelFolder::ParseDisplayName+0x44:
761a26e1 e81dfdffff call SHELL32!CControlPanelFolder::_GetPidlFromAppletId
(761a2403)
kd> dd esp
0429c0ec 03efb990 0429c1ec 75f50320 03efb990
0429c0fc 03ea2e9c 00000000 0429c11c 76fb6ff7
0429c10c 6628a607 0429c194 75f37b0b 07e04078
0429c11c 00000000 03e94448 03efb990 00000000
0429c12c 0429c1ec 00000000 00000000 75f5a7f4
0429c13c 00000000 03efb990 00000000 0429c1ec
0429c14c 75f5a800 00000000 75f182a8 00000000
0429c15c 03e94448 000000db 00000000 00000000
kd> dd esp l2
0429c0ec 03efb990 0429c1ec
kd> db 03efb990
03efb990 7b 00 42 00 39 00 43 00-41 00 42 00 35 00 32 00 {.B.9.C.A.B.5.2.
03efb9a0 39 00 2d 00 35 00 43 00-37 00 43 00 2d 00 34 00 9.-.5.C.7.C.-.4.
03efb9b0 42 00 35 00 41 00 2d 00-38 00 31 00 34 00 45 00 B.5.A.-.8.1.4.E.
03efb9c0 2d 00 32 00 46 00 35 00-32 00 35 00 31 00 38 00 -.2.F.5.2.5.1.8.
03efb9d0 45 00 36 00 45 00 46 00-46 00 7d 00 00 00 00 00 E.6.E.F.F.}.....
03efb9e0 1a 03 a7 6d 3d 95 00 88-30 f1 25 b7 ef 47 1a 10 ...m=...0.%..G..
03efb9f0 a5 f1 02 60 8c 9e eb ac-0e 00 00 00 a6 6a 63 28 ...`.........jc(
03efba00 3d 95 d2 11 b5 d6 00 c0-4f d9 18 d0 0b 00 00 00 =.......O.......
kd> db 0429c1ec
0429c1ec 00 00 00 00 58 93 a1 02-00 00 00 00 00 00 00 00 ....X...........
0429c1fc 00 00 00 00 00 00 00 00-1f a5 28 66 4c c2 29 04 ..........(fL.).
0429c20c 3d 08 f4 75 a4 15 e9 07-58 93 a1 02 f0 a7 f5 75 =..u....X......u
0429c21c 9c 2e ea 03 01 00 00 00-40 c2 29 04 30 93 a1 02 ........@.).0...
0429c22c 38 2a a1 02 58 93 a1 02-c8 4f e0 07 a4 15 e9 07 8*..X....O......
0429c23c 9c 2e ea 03 00 00 00 00-00 00 00 00 5b a5 28 66 ............[.(f
0429c24c 64 c2 29 04 85 08 f4 75-00 00 00 00 30 93 a1 02 d.)....u....0...
0429c25c e8 ef f0 03 c8 4f e0 07-90 c2 29 04 16 e9 f0 75 .....O....)....u
kd> db ecx
07e04068 74 f8 f4 75 18 18 f5 75-02 00 00 00 6c 40 e0 07 t..u...u....l@..
07e04078 20 03 f5 75 64 00 f5 75-e4 fc f4 75 f8 6d f5 75 ..ud..u...u.m.u
07e04088 e8 48 f1 75 18 40 f5 75-f4 71 f1 75 9c 39 f2 75 .H.u.@.u.q.u.9.u
07e04098 8c 84 f1 75 88 6e e0 07-8c 2e ea 03 00 00 00 00 ...u.n..........
07e040a8 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
07e040b8 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
07e040c8 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
07e040d8 00 00 00 00 87 00 00 00-9a 4e 37 6d 00 00 00 8c .........N7m....
CControlPanelFolder::_GetPidlFromAppletId函数如下,先是遇到一个PSGetNameFromPropertyKey函数,这个函数是Retrieves the canonical name of the property, given its PROPERTYKEY.(检索属性的规范名称)
HRESULT __thiscall CControlPanelFolder::_GetPidlFromAppletId(CControlPanelFolder *this, const unsigned __int16 *a2, struct _ITEMID_CHILD **a3)
{
char v3; // ST37_1
char v4; // bl
LPWSTR v5; // eax
int v6; // ebx
struct CPLMODULE *v7; // edi
struct _DSA *v8; // eax
PVOID v9; // eax
CControlPanelFolder *v11; // [esp+8h] [ebp-680h]
HRESULT v12; // [esp+Ch] [ebp-67Ch]
char v13; // [esp+13h] [ebp-675h]
LPVOID pv; // [esp+14h] [ebp-674h]
HKEY phkResult; // [esp+18h] [ebp-670h]
char v16; // [esp+1Ch] [ebp-66Ch]
WCHAR SubKey; // [esp+224h] [ebp-464h]
WCHAR Start; // [esp+42Ch] [ebp-25Ch]
char v19; // [esp+634h] [ebp-54h]
v11 = this;
v12 = PSGetNameFromPropertyKey(&PKEY_Software_AppId, (PWSTR *)&pv);
if ( v12 >= 0 )
{
v12 = StringCchPrintfW(
&SubKey,
0x104u,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Extended Properties\\%s",
pv);
if ( v12 >= 0 )
{
if ( (v12 = -2147467259, !RegOpenKeyExW(HKEY_LOCAL_MACHINE, &SubKey, 0, 1u, &phkResult))
&& (v3 = CControlPanelFolder::_FindMatchingAppletId(phkResult, (int)a2, &Start, 260), RegCloseKey(phkResult), v3)
|| !RegOpenKeyExW(HKEY_CURRENT_USER, &SubKey, 0, 1u, &phkResult)
&& (v4 = CControlPanelFolder::_FindMatchingAppletId(phkResult, (int)a2, &Start, 260), RegCloseKey(phkResult), v4)
|| (v12 = CControlPanelFolder::_GetAppletPathForTemporaryAppId(a2, &Start, 0x104u), v12 >= 0) )
{
v5 = StrChrW(&Start, 0x2Cu);
v6 = 0;
if ( v5 )
*v5 = 0;
if ( SHExpandEnvironmentStringsW(&Start, &v16, 260) )
{
v7 = CPL_LoadCPLModule((const unsigned __int16 *)&v16, 0);
慢慢动态调试往下走,这里要注意CControlPanelFolder::_GetAppletPathForTemporaryAppId这个函数,因为它的第二个参数,在后面我们想要寻找的下一个函数有过交际。可以看到再运行完这个函数之后,它的第二个参数变成了dll的地址。
kd> p
SHELL32!CControlPanelFolder::_GetPidlFromAppletId+0x145:
761a2548 e846feffff call
SHELL32!CControlPanelFolder::_GetAppletPathForTemporaryAppId (761a2393)
kd> dd esp l3
0429ba44 03efb990 0429be88 00000104
kd> db 03efb990
03efb990 7b 00 42 00 39 00 43 00-41 00 42 00 35 00 32 00 {.B.9.C.A.B.5.2.
03efb9a0 39 00 2d 00 35 00 43 00-37 00 43 00 2d 00 34 00 9.-.5.C.7.C.-.4.
03efb9b0 42 00 35 00 41 00 2d 00-38 00 31 00 34 00 45 00 B.5.A.-.8.1.4.E.
03efb9c0 2d 00 32 00 46 00 35 00-32 00 35 00 31 00 38 00 -.2.F.5.2.5.1.8.
03efb9d0 45 00 36 00 45 00 46 00-46 00 7d 00 00 00 00 00 E.6.E.F.F.}.....
03efb9e0 1a 03 a7 6d 3d 95 00 88-30 f1 25 b7 ef 47 1a 10 ...m=...0.%..G..
03efb9f0 a5 f1 02 60 8c 9e eb ac-0e 00 00 00 a6 6a 63 28 ...`.........jc(
03efba00 3d 95 d2 11 b5 d6 00 c0-4f d9 18 d0 0b 00 00 00 =.......O.......
kd> db 0429be88
0429be88 ac be 29 04 45 70 fb 76-0e 00 00 00 b0 fc f2 75 ..).Ep.v.......u
0429be98 22 00 00 00 d0 be 29 04-8c 9d 97 02 88 50 e0 07 ".....)......P..
0429bea8 0e 00 00 00 c4 be 29 04-f7 6f fb 76 b0 fc f2 75 ......)..o.v...u
0429beb8 22 00 00 00 e7 2f 43 77-71 43 63 73 00 00 00 00 "..../CwqCcs....
0429bec8 b4 01 55 00 00 00 55 00-88 9d 97 02 10 f6 f4 75 ..U...U........u
0429bed8 53 00 6f 00 66 00 74 00-77 00 61 00 72 00 65 00 S.o.f.t.w.a.r.e.
0429bee8 5c 00 4d 00 69 00 63 00-72 00 6f 00 73 00 6f 00 .M.i.c.r.o.s.o.
0429bef8 66 00 74 00 5c 00 57 00-69 00 6e 00 64 00 6f 00 f.t..W.i.n.d.o.
kd> r
eax=0429be88 ebx=7757c189 ecx=07e04068 edx=00000002 esi=00000104 edi=7757cb4f
eip=761a2548 esp=0429ba44 ebp=0429c0e4 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
SHELL32!CControlPanelFolder::_GetPidlFromAppletId+0x145:
761a2548 e846feffff call
SHELL32!CControlPanelFolder::_GetAppletPathForTemporaryAppId (761a2393)
kd> db 0429be88
0429be88 ac be 29 04 45 70 fb 76-0e 00 00 00 b0 fc f2 75 ..).Ep.v.......u
0429be98 22 00 00 00 d0 be 29 04-8c 9d 97 02 88 50 e0 07 ".....)......P..
0429bea8 0e 00 00 00 c4 be 29 04-f7 6f fb 76 b0 fc f2 75 ......)..o.v...u
0429beb8 22 00 00 00 e7 2f 43 77-71 43 63 73 00 00 00 00 "..../CwqCcs....
0429bec8 b4 01 55 00 00 00 55 00-88 9d 97 02 10 f6 f4 75 ..U...U........u
0429bed8 53 00 6f 00 66 00 74 00-77 00 61 00 72 00 65 00 S.o.f.t.w.a.r.e.
0429bee8 5c 00 4d 00 69 00 63 00-72 00 6f 00 73 00 6f 00 .M.i.c.r.o.s.o.
0429bef8 66 00 74 00 5c 00 57 00-69 00 6e 00 64 00 6f 00 f.t..W.i.n.d.o.
kd> p
SHELL32!CControlPanelFolder::_GetPidlFromAppletId+0x14a:
761a254d 898584f9ffff mov dword ptr [ebp-67Ch],eax
kd> r
eax=00000000 ebx=7757c189 ecx=00000011 edx=7627c73c esi=00000104 edi=7757cb4f
eip=761a254d esp=0429ba50 ebp=0429c0e4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
SHELL32!CControlPanelFolder::_GetPidlFromAppletId+0x14a:
761a254d 898584f9ffff mov dword ptr [ebp-67Ch],eax ss:0023:0429ba68=80004005
kd> db 0429be88
0429be88 43 00 3a 00 5c 00 61 00-2e 00 64 00 6c 00 6c 00 C.:..a...d.l.l.
0429be98 2c 00 43 00 3a 00 5c 00-61 00 2e 00 64 00 6c 00 ,.C.:..a...d.l.
0429bea8 6c 00 00 00 c4 be 29 04-f7 6f fb 76 b0 fc f2 75 l.....)..o.v...u
0429beb8 22 00 00 00 e7 2f 43 77-71 43 63 73 00 00 00 00 "..../CwqCcs....
0429bec8 b4 01 55 00 00 00 55 00-88 9d 97 02 10 f6 f4 75 ..U...U........u
0429bed8 53 00 6f 00 66 00 74 00-77 00 61 00 72 00 65 00 S.o.f.t.w.a.r.e.
0429bee8 5c 00 4d 00 69 00 63 00-72 00 6f 00 73 00 6f 00 .M.i.c.r.o.s.o.
0429bef8 66 00 74 00 5c 00 57 00-69 00 6e 00 64 00 6f 00 f.t..W.i.n.d.o.
进入CControlPanelFolder::_GetAppletPathForTemporaryAppId函数看看AcquireSRWLockShared函数的功能是Acquires a slim reader/writer (SRW) lock in shared mode.也就是获得CControlPanelFolder::s_srwTemporaryAppIdLock的读写锁。然后再判断CControlPanelFolder::s_srwTemporaryAppIdLock是否有值。后面的 DSA_GetItemPtr函数功能是Gets a pointer to an element from a dynamic structure array (DSA).获取动态dsa中元素的指针。
signed int __stdcall CControlPanelFolder::_GetAppletPathForTemporaryAppId(const unsigned __int16 *a2, unsigned __int16 *a3, unsigned int a4)
{
signed int v4; // ebx
int v5; // eax
const unsigned __int16 *v6; // eax
v4 = 0x80004005;
AcquireSRWLockShared(&CControlPanelFolder::s_srwTemporaryAppIdLock);
if ( CControlPanelFolder::s_dsaTemporaryAppId )
{
v5 = CDSA_Base<CMCMatch>::Search(0, 0, CControlPanelFolder::s_DSAFindAppId, a2, 0);
if ( v5 >= 0 )
{
v6 = (const unsigned __int16 *)DSA_GetItemPtr(CControlPanelFolder::s_dsaTemporaryAppId, v5);
if ( v6 )
v4 = StringCchCopyW(a3, a4, v6);
}
}
ReleaseSRWLockShared(&CControlPanelFolder::s_srwTemporaryAppIdLock);
return v4;
}
运行DSA_GetItemPtr函数之后的结果,返回值就是dll的路径。之后就是用StringCchCopyW函数将值传给a3。
kd> p
SHELL32!CControlPanelFolder::_GetAppletPathForTemporaryAppId+0x44:
761a23d7 ff15f498f675 call dword ptr [SHELL32!_imp__DSA_GetItemPtr (75f698f4)]
kd> dd esp l2
0429c930 029caad0 00000000
kd> db 029caad0
029caad0 01 00 00 00 00 af 9d 02-04 00 00 00 60 04 00 00 ............`...
029caae0 04 00 00 00 00 00 00 00-83 a2 f9 6c 00 00 00 80 ...........l....
029caaf0 06 00 00 00 98 ee f1 03-04 00 00 00 08 00 00 00 ................
029cab00 04 00 00 00 00 00 00 00-bf a2 f9 6c 00 00 00 80 ...........l....
029cab10 32 00 00 00 f4 bb 5e 00-08 bc 5e 00 00 00 00 00 2.....^...^.....
029cab20 00 00 00 00 00 00 72 00-bb a2 f9 6c 00 00 00 8c ......r....l....
029cab30 2d 4e 87 65 28 00 80 7b-53 4f 0c ff 2d 4e fd 56 -N.e(..{SO..-N.V
029cab40 29 00 00 00 e8 06 9c 02-b7 a2 f9 6c 00 00 00 8e )..........l....
kd> p
SHELL32!CControlPanelFolder::_GetAppletPathForTemporaryAppId+0x4a:
761a23dd 85c0 test eax,eax
kd> r
eax=029daf00 ebx=80004005 ecx=029caad0 edx=00000000 esi=7627c73c edi=7757cb4f
eip=761a23dd esp=0429c938 ebp=0429c940 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
SHELL32!CControlPanelFolder::_GetAppletPathForTemporaryAppId+0x4a:
761a23dd 85c0 test eax,eax
kd> db eax
029daf00 43 00 3a 00 5c 00 61 00-2e 00 64 00 6c 00 6c 00 C.:..a...d.l.l.
029daf10 2c 00 43 00 3a 00 5c 00-61 00 2e 00 64 00 6c 00 ,.C.:..a...d.l.
029daf20 6c 00 00 00 34 00 00 c0-50 bd e4 03 97 3c 43 77 l...4...P....<Cw
029daf30 9c 3c 43 77 65 41 ae 74-34 00 00 c0 04 be e4 03 .<CweA.t4.......
029daf40 28 c1 e4 03 28 bd e4 03-00 00 00 00 c4 bd e4 03 (...(...........
029daf50 ed e0 3f 77 35 e0 09 00-fe ff ff ff 9c 3c 43 77 ..?w5........<Cw
029daf60 2e c1 57 77 5e c1 57 77-04 96 c4 61 8c be e4 03 ..Ww^.Ww...a....
029daf70 00 00 00 00 00 00 00 00-74 47 f7 73 00 00 00 00 ........tG.s....
往后面走来到最后一个CPL_LoadCPLModule函数,它的两个参数,第一个参数就是dll文件路径。
kd> p
SHELL32!CControlPanelFolder::_GetPidlFromAppletId+0x197:
761a259a e83c4ddeff call SHELL32!CPL_LoadCPLModule (75f872db)
kd> dd esp l2
0429ba48 0429ba78 00000000
kd> db 0429ba78
0429ba78 43 00 3a 00 5c 00 61 00-2e 00 64 00 6c 00 6c 00 C.:..a...d.l.l.
0429ba88 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0429ba98 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0429baa8 e7 2f 43 77 05 47 63 73-2a 00 00 00 bc 01 55 00 ./Cw.Gcs*.....U.
0429bab8 00 00 55 00 00 00 00 00-00 00 00 00 34 00 1e 00 ..U.........4...
0429bac8 dd 04 00 00 65 47 63 73-0f 00 00 00 64 02 55 00 ....eGcs....d.U.
0429bad8 00 00 55 00 35 00 56 00-dd 04 00 00 0f 00 da 02 ..U.5.V.........
0429bae8 4a 16 00 00 58 6a 55 00-00 00 55 00 2a 00 00 00 J...XjU...U.*...
最后在这里加载运行dll
kd> p
SHELL32!CPL_LoadCPLModule+0x15d:
75f873e1 ffb5ecfdffff push dword ptr [ebp-214h]
kd> p
SHELL32!CPL_LoadCPLModule+0x163:
75f873e7 ff154c22eb75 call dword ptr [SHELL32!_imp__LoadLibraryW (75eb224c)]
kd> dd esp l1
0429b7ec 0429ba78
kd> db 0429ba78
0429ba78 43 00 3a 00 5c 00 61 00-2e 00 64 00 6c 00 6c 00 C.:..a...d.l.l.
0429ba88 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0429ba98 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0429baa8 e7 2f 43 77 05 47 63 73-2a 00 00 00 bc 01 55 00 ./Cw.Gcs*.....U.
0429bab8 00 00 55 00 00 00 00 00-00 00 00 00 34 00 1e 00 ..U.........4...
0429bac8 dd 04 00 00 65 47 63 73-0f 00 00 00 64 02 55 00 ....eGcs....d.U.
0429bad8 00 00 55 00 35 00 56 00-dd 04 00 00 0f 00 da 02 ..U.5.V.........
0429bae8 4a 16 00 00 58 6a 55 00-00 00 55 00 2a 00 00 00 J...XjU...U.*...
补丁比较
在CControlPanelFolder::_GetPidlFromAppletId函数这里加了一个校验,用_IsRegisteredCPLApplet对DLL路径进行校验
if ( SHExpandEnvironmentStringsW(&Start, &v17, 260) )
{
if ( CControlPanelFolder::_IsRegisteredCPLApplet(v11, &v17) ) // --- 增加了一个校验
{
v12 = 0;
v7 = CPL_LoadCPLModule(&v17, 0);
if ( v7 )
{
v13 = 0;
do
{
v8 = (struct _DSA *)*((_DWORD *)v7 + 135);
if ( v6 >= *(_DWORD *)v8 )
break;
v9 = DSA_GetItemPtr(v8, v6);
if ( v9 )
{
v12 = IDControlCreate(
...
}
参考链接
https://blog.csdn.net/Sagittarius_Warrior/article/details/51305046(双机调试)
http://www.vxjump.net/files/security_research/lnk_inf.txt
https://bbs.pediy.com/thread-248701.htm