基本上,我有一个用户模式程序调用kernel32.CreateProcessA(),它在内部调用kernel32.CreateProcessInternalW()。在这个函数中,我对ntdll.NtCreateSection()中发生的事情感兴趣,它试图在虚拟内存中映射可执行文件。进入此函数后,程序会快速将内核调用设置为EAX = 0x32并执行SYSENTER指令。
显然,我无法在用户模式调试器中看到调用门之外的内容。我有一点调试内核模式驱动程序的经验,所以我在VMWare窗口中加载了一个XP SP3副本,并使用VirtualKD将管道连接到WinDbg(我碰巧在IDA中运行)。连接内核调试器后,我将用户模式EXE程序和PDB复制到虚拟机上,但我对如何在用户模式程序中正确设置初始断点感到茫然。我不想拦截对等效ntdll.ZwCreateSection()的所有调用,我认为这些调用位于调用门的另一侧。理想情况下,我现在想要使用内核调试器进入用户模式代码并逐步调用该调用门,但我不知道最初的步骤是什么。
我已经完成了一些谷歌搜索,并且通过设置" ntsd -d"
中的价值HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\myprocess.exe
当我启动进程时,这会导致内核调试器中断,但我似乎无法在.breakin命令之后设置任何断点我需要向IDA发出以进入WinDbg提示符。我一直关注这个guide,我在那里找到我的流程!process然后切换到上下文,然后重新加载符号,但是我在设置过程中的断点或者超过初始值时遇到了问题断点由" ntsd -d"设置。在收到无法解析断点并添加延迟断点的消息后,我似乎无法推进"进入"没有清除断点的过程,如果这是有道理的。这是我在初次突破时看起来所处的堆栈:
ChildEBP RetAddr
b2b55ccc 8060e302 nt!RtlpBreakWithStatusInstruction
b2b55d44 8053d638 nt!NtSystemDebugControl+0x128
b2b55d44 7c90e4f4 nt!KiFastCallEntry+0xf8
0007b270 7c90de3c ntdll!KiFastSystemCallRet
0007b274 6d5f5ca6 ntdll!ZwSystemDebugControl+0xc
0007bd48 6d5f6102 dbgeng!DotCommand+0xd0d
0007de8c 6d5f7077 dbgeng!ProcessCommands+0x318
0007dec4 6d5bec6c dbgeng!ProcessCommandsAndCatch+0x1a
0007eedc 6d5bed4d dbgeng!Execute+0x113
0007ef0c 010052ce dbgeng!DebugClient::Execute+0x63
0007ff3c 010069fb ntsd!MainLoop+0x1ec
0007ff44 01006b31 ntsd!main+0x10e
0007ffc0 7c817067 ntsd!mainCRTStartup+0x125
0007fff0 00000000 kernel32!BaseProcessStart+0x23
说实话,我不确定我的PDB是否正在加载,但我怀疑它可能不是我的直接问题;我的模块窗格仅显示内核驱动程序模块,而不是用户模式模块。当我过去进行驱动程序调试时,我可以在此窗格中看到我的驱动程序映像以及符号是否已加载,因此我不确定用户模式映像会发生什么。 没有图像,我真的不希望调试器解决任何断点。
我意识到我可能会完全错误地解决这个问题但是我没有运气搜索如何进行用户模式/内核模式混合调试。有没有人可以指出我正确的方向,所以我可以从特定的用户模式进程进入这个内核模式功能?或者,至少设置一个合适的内核模式断点,以便仅在我的特定用户模式进程中触发它?
更新的: 我在调试的操作系统上的用户模式调试器中加载了我的模块(恰好名为runlist.exe)(我碰巧使用了OllyDbg)。一旦我在用户模式断点处暂停了SYSENTER的几条指令,我就使用内核调试器暂停了操作系统。然后我设置了流程上下文。 WinDbg命令窗口内容如下:
WINDBG>!process 0 0 runlist.exe
PROCESS 820645a8 SessionId: 0 Cid: 01b4 Peb: 7ffd7000 ParentCid: 02b0
DirBase: 089c02e0 ObjectTable: e1671bb0 HandleCount: 8.
Image: runlist.exe
WINDBG>.process /i /r /p 820645a8
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.
WINDBG>g
This command cannot be passed to the WinDbg plugin directly, please use IDA Debugger menu to achieve the same result.
Break instruction exception - code 80000003 (first chance)
WINDBG>.reload /user
Loading User Symbols
....
Caching 'Modules'... ok
WINDBG>lmu
start end module name
00400000 00405000 runlist C (no symbols)
7c340000 7c396000 MSVCR71 (private pdb symbols) g:\symcache\msvcr71.pdb\630C79175C1942C099C9BC4ED019C6092\msvcr71.pdb
7c800000 7c8f6000 kernel32 (pdb symbols) e:\windows\symbols\dll\kernel32.pdb
7c900000 7c9af000 ntdll (pdb symbols) e:\windows\symbols\dll\ntdll.pdb
WINDBG>bp 0x7c90d16a
WINDBG>bl
0 e 7c90d16a 0001 (0001) ntdll!ZwCreateSection+0xa
虽然我无法获得我的流程&#39;要加载的符号&#34; .reload&#34; (PDB在同一目录中 - 可能需要将其复制到我的符号dir),我关心的断点无论如何都在ntdll中,所以我将它设置在调试器识别为ntdll.ZwCreateSection()内的地址0x7C90D16A上。奇怪的是,在用户模式代码中,这个地址解析为ntdll.NtCreateSection(),但无论哪种方式,断点只有2条指令来自我的用户模式中断。当我恢复机器时,我的意图是&#34;运行&#34;用户模式调试过程,这将触发内核模式断点2指令。内核断点从未被击中,应用程序恢复了这一点。但是我可以在ntdll上设置一个断点!ZwCreateSection()但是当恢复操作系统时,断点会被其他进程反复命中,导致我无法返回到用户模式调试器,所以我可以&#34;运行&#34;它只在我自己的过程中到达那个位置。
更新 合并@conio提供的提示,以下步骤适用于我:
1&GT;在附加内核调试器和引导目标OS之后,暂停操作系统并应用一些配置选项:
!gflag +ksl //allow sxe to report user-mode module load events under kernel debugger
sxe ld myproc.exe //cause kernel debugger break upon process load
.sympath+ <path> //path to HOST machine's user-mode app's symbols
2 - ;运行调试器以恢复目标操作系统
3&GT;在目标上,运行我们想要调试的EXE
4&GT;内核调试器应该中断;现在输入以下命令切换到usermode上下文:
!process 0 0 myproc.exe //get address of EProcess structure (first number on 1st line after "PROCESS")
.process /i /r /p <eprocess*> //set kernel debugger to process context
g //continue execution to allow the context switch; debugger will break after switch complete
.reload /user //reload user symbols
lmu //ensure you have symbols although not really necessary in my particular case
5个既然我已经知道在ntdll.NtCreateSection()的用户模式端发生了什么,我就继续为该函数的内核模式端设置断点,但指定我希望断点仅在上下文中发生我的过程这样,断点不会在OS范围内触发:
bu /p <eprocess*> nt!NtCreateSection //set breakpoint in kernel side of function
g //run to break
6个如果一切按计划进行,断点将在NtCreateSection()的内核模式端唤醒调试器。我感谢所有的回复和提示!
答案 0 :(得分:8)
有两种方法可以将用户模式调试与内核模式调试结合起来,让您感到困惑和混淆。
您尝试的方法是使用内核模式调试器来调试内核模式代码,使用用户模式调试器(ntsd
)来调试用户模式代码,并控制用户模式调试器运行在内核调试器的目标机器上。这就是-d
ntsd
标志的作用。此方法在Controlling the User-Mode Debugger from the Kernel Debugger页面及其MSDN上的子页面中进行了描述。
这样做(或多或少)是将ntsd
输入和输出重定向到内核调试器。模块窗格 - 作为WinDbg中的其余窗口 - 属于内核调试器。您与用户模式调试器的唯一交互是通过内核调试器创建的隧道,您只能通过命令窗口访问它。这在-d
标志的文档中有记录:
<强> -d 强>
将此调试器的控制权传递给内核调试器。如果您正在调试CSRSS,则此控件重定向始终处于活动状态,即使未指定 -d 也是如此。 (在远程调试期间不能使用此选项 - 请改用 -ddefer 。)有关详细信息,请参阅从内核调试器控制用户模式调试器。此选项不能与 -ddefer 选项或 -noio 选项一起使用。
注意如果您使用WinDbg作为内核调试程序,则WinDbg的许多常见功能在此方案中不可用。例如,您无法使用“本地”窗口,“反汇编”窗口或“调用堆栈”窗口,也无法单步执行源代码。这是因为WinDbg仅作为目标计算机上运行的调试器(NTSD或CDB)的查看器。
第二种方法是使用内核调试器来调试内核模式代码和用户模式代码。没有用户模式调试器。没有ntsd
。你说你已经按照指南,但实际上你没有。如果有,则不会有任何ntsd
。
我建议您使用此方法启动,并且只有在您发现需要时才使用用户模式调试器(例如,因为您想使用用户模式扩展)。
为了使内核调试器能够很好地与用户模式模块配合使用,您必须启用Enable loading of kernel debugger symbols GlobalFlag。使用!gflag +ksl
来执行此操作。
执行此操作后,使用sxe ld:runlist
中断流程的加载,设置断点(可能使用/p
选项)并调试您想要的任何内容。
只需这样做而不是所有ntsd
混乱。
答案 1 :(得分:3)
使用ntsd -d并使用kd连接从目标开始调试executabke你可以使用kd作为用户模式调试器以及内核调试器多次读取文档不是很容易做到这一点但是经过几次试验你应该了解一下.breakin等等。
How to break on the entry point of a program when debug in kernel mode with windbg?
已修改为添加使用ntsd -d
的演示设置
1 ) a vm running winxp sp3 and windbg version 6.12 installed in it
2 ) _NT_SYMBOL_PATH in vm is set to z:\
3 ) z:\ is a mapped network drive that points to e:\symbols in host
4 ) host running win 7 sp2
5 ) host windbg 10.0010586
在ntsd下的vm中启动应用程序并将其重定向到kd
在vm中打开一个命令提示符,导航到windbg安装目录并发出ntsd -s -d calc
-s is to disable lazy symbol loading
0:000> version
version
Windows XP Version 2600 (Service Pack 3) UP Free x86 compatible
Product: WinNt, suite: SingleUserTS
kernel32.dll version: 5.1.2600.5512 (xpsp.080413-2111)
Machine Name:
Debug session time: Thu Mar 16 16:44:29.222 2017
System Uptime: 0 days 0:10:12.941
Process Uptime: 0 days 0:01:40.980
Kernel time: 0 days 0:00:01.632
User time: 0 days 0:00:00.040
Live user mode: <Local>
Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
Copyright (c) Microsoft Corporation. All rights reserved.
command line: 'ntsd -s -d calc' Debugger Process 0xA8
dbgeng: image 6.12.0002.633, built Tue Feb 02 01:38:31 2010
[path C:\Documents and Settings\admin\Desktop\Debugging Tools for Windows (x86)\dbgeng.dll]
SystemBreakPoint上的 windbg中断,Debug提示符为Input:\&gt;
lm显示符号是从z:\
CommandLine: calc
Symbol search path is: z:\
Executable search path is:
ModLoad: 01000000 0101f000 calc.exe
xxxxx
ntdll!DbgBreakPoint:
7c90120e cc int 3
0:000> lm
lm
start end module name
01000000 0101f000 calc (pdb symbols) z:\calc.pdb\3B7D84101\calc.pdb
77c10000 77c68000 msvcrt (export symbols) C:\WINDOWS\system32\msvcrt.dll
执行至AddressOfEntryPoint
0:000> g @$exentry
g @$exentry
calc!WinMainCRTStartup:
01012475 6a70 push 70h
立即在用户模式及其内核模式下设置断点
0:000> bp ntdll!ZwCreateSection <--- user mode bp notice prompt 0:000
bp ntdll!ZwCreateSection
0:000> .breakin <<---- transferring to kd mode
.breakin
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
804e3592 cc int 3
kd> !process 0 0 calc.exe <<----- looking for our process of interest
Failed to get VAD root
PROCESS ffae2020 SessionId: 0 Cid: 0410 Peb: 7ffde000 ParentCid: 00a8
DirBase: 04d87000 ObjectTable: e1bd5238 HandleCount: 26.
Image: calc.exe
kd> bp /p ffae2020 nt!NtCreateSection << setting a kernel mode bp
on counterpart that matches with our process of interest notice prompt kd>
kd> g <<<---- return to user mode after setting a breakpoint
0:000> g <<<<<--------- executing in user mode
g
现在,calc进程正在vm中的usermode中运行 单击help about(这将触发一个Loadlib并且需要一个Section,因此我们将在内核调试器中打破我们的用户模式bp)
Breakpoint 0 hit
eax=00000000 ebx=00000000 ecx=00000001 edx=ffffffff esi=0007f368 edi=00000000
eip=7c90d160 esp=0007f22c ebp=0007f2a8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!NtCreateSection:
7c90d160 b832000000 mov eax,32h
现在我们可以快速追踪使用t跟踪而不是p或g或任何其他执行命令
0:000> t
t
eax=00000032 ebx=00000000 ecx=00000001 edx=ffffffff esi=0007f368 edi=00000000
eip=7c90d165 esp=0007f22c ebp=0007f2a8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!ZwCreateSection+0x5:
7c90d165 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300)
0:000>
eax=00000032 ebx=00000000 ecx=00000001 edx=7ffe0300 esi=0007f368 edi=00000000
eip=7c90d16a esp=0007f22c ebp=0007f2a8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!ZwCreateSection+0xa:
7c90d16a ff12 call dword ptr [edx] ds:0023:7ffe0300={ntdll!KiFastSystemCall (7c90e4f0)}
0:000>
eax=00000032 ebx=00000000 ecx=00000001 edx=7ffe0300 esi=0007f368 edi=00000000
eip=7c90e4f0 esp=0007f228 ebp=0007f2a8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!KiFastSystemCall:
7c90e4f0 8bd4 mov edx,esp
0:000>
eax=00000032 ebx=00000000 ecx=00000001 edx=0007f228 esi=0007f368 edi=00000000
eip=7c90e4f2 esp=0007f228 ebp=0007f2a8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!KiFastSystemCall+0x2:
7c90e4f2 0f34 sysenter
0:000>
Breakpoint 1 hit
nt!NtCreateSection:
805652b3 6a2c push 2Ch
在内核.reload的bp中,看到堆栈跟踪
第二个堆栈跟踪与第一个相同但具有更正的符号 Shell32.dll(vm没有互联网访问权限,因此第一次失败 所以我拖动从vm中删除了特定的dll并使用windbg -z shell32.dll和.reload从主机获取其sumbols(因为主机中的downstore是在vm中的网络映射,第二个跟踪正确加载pdb并提供正确的堆栈跟踪而没有警告
kd> kb
# ChildEBP RetAddr Args to Child
00 f8bb1d40 804de7ec 0007f368 0000000f 00000000 nt!NtCreateSection
01 f8bb1d40 7c90e4f4 0007f368 0000000f 00000000 nt!KiFastCallEntry+0xf8
02 0007f224 7c90d16c 7c91c993 0007f368 0000000f ntdll!KiFastSystemCallRet
03 0007f228 7c91c993 0007f368 0000000f 00000000 ntdll!NtCreateSection+0xc
04 0007f2a8 7c91c64a 0007f340 00000790 0007f300 ntdll!LdrpCreateDllSection+0x92
05 0007f388 7c91624a 000add00 0007f414 0007f93c ntdll!LdrpMapDll+0x28f
06 0007f648 7c9164b3 00000000 000add00 0007f93c ntdll!LdrpLoadDll+0x1e9
07 0007f8f0 7c801bbd 000add00 0007f93c 0007f91c ntdll!LdrLoadDll+0x230
08 0007f958 7c801d72 7ffddc00 00000000 00000000 kernel32!LoadLibraryExW+0x18e
09 0007f96c 7ca625a3 7ca625ac 00000000 00000000 kernel32!LoadLibraryExA+0x1f
WARNING: Stack unwind information not available. Following frames may be wrong.
0a 0007f990 010057b8 000700ac 000a7c84 00000000 SHELL32!SHCreateQueryCancelAutoPlayMoniker+0x2062d
0b 0007fbc4 010041ac 0000012e 00000111 01006118 calc!MenuFunctions+0x15d
0c 0007fcb4 01004329 0000012e 00000111 01006118 calc!RealProcessCommands+0x1b61
0d 0007fcdc 01006521 0000012e 0007fd6c 01006118 calc!ProcessCommands+0x2d
0e 0007fd04 7e418734 000700ac 00000111 0000012e calc!CalcWndProc+0x409
0f 0007fd30 7e418816 01006118 000700ac 00000111 USER32!InternalCallWinProc+0x28
10 0007fd98 7e4189cd 00000000 01006118 000700ac USER32!UserCallWinProcCheckWow+0x150
11 0007fdf8 7e418a10 0007fee8 00000000 0007ff1c USER32!DispatchMessageWorker+0x306
12 0007fe08 010021a7 0007fee8 7c80b731 000a1ee4 USER32!DispatchMessageW+0xf
13 0007ff1c 010125e9 000a7738 00000055 000a7738 calc!WinMain+0x256
14 0007ffc0 7c817067 00000000 00000000 7ffde000 calc!WinMainCRTStartup+0x174
15 0007fff0 00000000 01012475 00000000 78746341 kernel32!BaseProcessStart+0x23
没有警告的STACKtrace
Breakpoint 0 hit
nt!NtCreateSection:
805652b3 6a2c push 2Ch
kd> kb
# ChildEBP RetAddr Args to Child
00 f8aa0d40 804de7ec 0007f368 0000000f 00000000 nt!NtCreateSection
01 f8aa0d40 7c90e4f4 0007f368 0000000f 00000000 nt!KiFastCallEntry+0xf8
02 0007f224 7c90d16c 7c91c993 0007f368 0000000f ntdll!KiFastSystemCallRet
03 0007f228 7c91c993 0007f368 0000000f 00000000 ntdll!NtCreateSection+0xc
04 0007f2a8 7c91c64a 0007f340 00000790 0007f300 ntdll!LdrpCreateDllSection+0x92
05 0007f388 7c91624a 000add00 0007f414 0007f93c ntdll!LdrpMapDll+0x28f
06 0007f648 7c9164b3 00000000 000add00 0007f93c ntdll!LdrpLoadDll+0x1e9
07 0007f8f0 7c801bbd 000add00 0007f93c 0007f91c ntdll!LdrLoadDll+0x230
08 0007f958 7c801d72 7ffdfc00 00000000 00000000 kernel32!LoadLibraryExW+0x18e
09 0007f96c 7ca625a3 7ca625ac 00000000 00000000 kernel32!LoadLibraryExA+0x1f
0a 0007f97c 7ca62e8e 003800dd 000a7c84 00000000 SHELL32!GetXPSP1ResModuleHandle+0x16
0b 0007f990 010057b8 000900ac 000a7c84 00000000 SHELL32!ShellAboutW+0x1f
0c 0007fbc4 010041ac 0000012e 00000111 01006118 calc!MenuFunctions+0x15d
0d 0007fcb4 01004329 0000012e 00000111 01006118 calc!RealProcessCommands+0x1b61
0e 0007fcdc 01006521 0000012e 0007fd6c 01006118 calc!ProcessCommands+0x2d
0f 0007fd04 7e418734 000900ac 00000111 0000012e calc!CalcWndProc+0x409
10 0007fd30 7e418816 01006118 000900ac 00000111 USER32!InternalCallWinProc+0x28
11 0007fd98 7e4189cd 00000000 01006118 000900ac USER32!UserCallWinProcCheckWow+0x150
12 0007fdf8 7e418a10 0007fee8 00000000 0007ff1c USER32!DispatchMessageWorker+0x306
13 0007fe08 010021a7 0007fee8 7c80b731 000a1ee4 USER32!DispatchMessageW+0xf
14 0007ff1c 010125e9 000a7738 00000055 000a7738 calc!WinMain+0x256
15 0007ffc0 7c817067 00000000 00000000 7ffda000 calc!WinMainCRTStartup+0x174
16 0007fff0 00000000 01012475 00000000 78746341 kernel32!BaseProcessStart+0x23
将参数转储到NtCreateSection
kd> dds @esp l8
f8bb1d44 804de7ec nt!KiFastCallEntry+0xf8
f8bb1d48 0007f368
f8bb1d4c 0000000f
f8bb1d50 00000000
f8bb1d54 00000000
f8bb1d58 00000010
f8bb1d5c 01000000 calc!_imp__RegOpenKeyExA <PERF> (calc+0x0)
f8bb1d60 00000790
我们知道第七个参数是HANDLE according to prototype of DDI
NTSTATUS ZwCreateSection(
_Out_ PHANDLE SectionHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PLARGE_INTEGER MaximumSize,
_In_ ULONG SectionPageProtection,
_In_ ULONG AllocationAttributes,
_In_opt_ HANDLE FileHandle
);
kd> !handle 790
Failed to get VAD root
PROCESS ffae2020 SessionId: 0 Cid: 0410 Peb: 7ffde000 ParentCid: 00a8
DirBase: 04d87000 ObjectTable: e1bd5238 HandleCount: 29.
Image: calc.exe
Handle table at e1bd5238 with 29 entries in use
0790: Object: 8124b028 GrantedAccess: 00100020 Entry: e1032f20
Object: 8124b028 Type: (8127b900) File
ObjectHeader: 8124b010 (old version)
HandleCount: 1 PointerCount: 1
Directory Object: 00000000 Name: \WINDOWS\system32\xpsp1res.dll {HarddiskVolume1}
从内核模式返回用户模式并检查新的Section Handle
kd> g
eax=00000000 ebx=00000000 ecx=00000001 edx=ffffffff esi=0007f368 edi=00000000
eip=7c90d16c esp=0007f22c ebp=0007f2a8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!ZwCreateSection+0xc:
7c90d16c c21c00 ret 1Ch
在用户模式下检查HANDLE的返回值
0:000> dd 7f368 l1
dd 7f368 l1
0007f368 0000078c
0:000> !handle 78c
!handle 78c
Handle 78c
Type Section
0:000> !handle 78c f
!handle 78c f
Handle 78c
Type Section
Attributes 0
GrantedAccess 0xf:
None
Query,MapWrite,MapRead,MapExecute
HandleCount 2
PointerCount 3
Name <none>
Object Specific Information
Section base address 0
Section attributes 0x1800000
Section max size 0x2f000
0:000>
如果不满意,我们可以恢复为kd设置进程上下文并在内核模式下检查返回的句柄
kd> !handle 78c f
Failed to get VAD root
PROCESS ffae2020 SessionId: 0 Cid: 0410 Peb: 7ffde000 ParentCid: 00a8
DirBase: 04d87000 ObjectTable: e1bd5238 HandleCount: 30.
Image: calc.exe
Handle table at e1bd5238 with 30 entries in use
078c: Object: e1088f30 GrantedAccess: 0000000f Entry: e1032f18
Object: e1088f30 Type: (8128b900) Section
ObjectHeader: e1088f18 (old version)
HandleCount: 1 PointerCount: 1
现在,如果继续执行,您可以在windbg中看到加载的库dbgprint,在vm中看到about对话框:)
kd> g
0:000> g
g
ModLoad: 10000000 1002f000 C:\WINDOWS\system32\xpsp1res.dll