一:背景1.讲故事有朋友咨询个问题,他每次在调试 WinDbg 的时候,进程初始化断点之前都会有一些 dll 加载到进程中,比如下面这样:
Microsoft (R) Windows Debugger Version 10.0.25200.1003 X86Copyright (c) Microsoft Corporation. All rights reserved.CommandLine: D:\net6\ConsoleApp1\Debug\ConsoleApplication3.exe************* Path validation summary **************ResponseTime (ms)LocationDeferredsrv*c:\mysymbols*https://msdl.microsoft.com/download/symbolsSymbol search path is: srv*c:\mysymbols*https://msdl.microsoft.com/download/symbolsExecutable search path is:ModLoad: 00400000 0041f000ConsoleApplication3.exeModLoad: 774b0000 77653000ntdll.dllModLoad: 753a0000 75490000C:\Windows\SysWOW64\KERNEL32.DLLModLoad: 75900000 75b14000C:\Windows\SysWOW64\KERNELBASE.dllModLoad: 79bc0000 79d36000C:\Windows\SysWOW64\ucrtbased.dllModLoad: 79ba0000 79bbe000C:\Windows\SysWOW64\VCRUNTIME140D.dll(44c.4b0c): Break instruction exception - code 80000003 (first chance)eax=00000000 ebx=00000000 ecx=afe00000 edx=00000000 esi=774c1ff4 edi=774c25bceip=77561a42 esp=0019fa20 ebp=0019fa4c iopl=0nv up ei pl zr na pe nccs=0023ss=002bds=002bes=002bfs=0053gs=002befl=00000246ntdll!LdrpDoDebuggerBreak+0x2b:77561a42 ccint3
问是否可以用 WinDbg 解读下内部运作原理,哈哈,其实要了解运作原理,一定要熟知 PE 头,那这篇就安排上 。
二:理解 PE 头结构1. 测试代码为了方便讲述,先上一段测试代码,这里故意加载 combase.dll
是为了提取 PE 中的某些数据结构,代码如下:
#include <iostream>#include <Windows.h>int main(int argc, char* argv[]) { LoadLibrary(L"combase.dll"); getchar();}
其实你仔细想一想也能知道,既然能做到初始化加载,必然在 PE 头上藏了什么东西,这些东西让 Windows 加载器可以顺利加载诸如 ntdll.dll
, KERNEL32.dll
等等,接下来一起观察下 。
2. 可视化观察 PE 头要想可视化观察 PE 头,工具有很多,这里使用 PPEE
工具,截图如下:
![WinDBG详解进程初始化dll是如何加载的](http://shimg.jingyanzongjie.com/230728/032UB643-0.jpg)
文章插图
从图中可以看到,其实初始化加载什么,由可选头中的
DIRECTORY_ENTRY_IMPORT
数据目录项决定,哪这里包含了哪些初始化 dll 呢? 可以选中右边的 DIRECTORY_ENTRY_IMPORT
项即可,如下图所示:![WinDBG详解进程初始化dll是如何加载的](http://shimg.jingyanzongjie.com/230728/032U643J-1.jpg)
文章插图
肯定有朋友说,WinDbg 上显示的是 5 个,你这里才 3 个,还有 2 个为什么没有? 很简单,多余的
ntdll.dll
和 KERNELBASE.dll
必然是依赖项哈 。3. 用 WinDbg 深入探究玩 WinDbg 都喜欢刨根问底,拿可视化 PPEE 肯定忽悠不过去,那好吧,我们用 C 中的结构体去解剖它 。
- DOS Header 节
ntdll!_IMAGE_DOS_HEADER
结构来承载的,可以用 dt 输出,起始点就是我们的 ConsoleApplication3.dll
在进程的首位置,即: 0x400000
。0:000> dt 0x400000 _IMAGE_DOS_HEADERConsoleApplication3!_IMAGE_DOS_HEADER+0x000 e_magic: 0x5a4d+0x002 e_cblp: 0x90+0x004 e_cp: 3...+0x024 e_oemid: 0+0x026 e_oeminfo: 0+0x028 e_res2: [10] 0+0x03c e_lfanew: 0n232
- NT Header 节
_IMAGE_NT_HEADERS
结构来承载的,起始位置的偏移已经保存在上面的 e_lfanew
字段中,即 0n232
。0:000> dt 0x400000+0n232 _IMAGE_NT_HEADERSConsoleApplication3!_IMAGE_NT_HEADERS+0x000 Signature: 0x4550+0x004 FileHeader: _IMAGE_FILE_HEADER+0x018 OptionalHeader: _IMAGE_OPTIONAL_HEADER
- _IMAGE_DATA_DIRECTORY
Data Directorys
数组中的第二项
经验总结扩展阅读
- 80年属猴人2023年每月运势及运程详解
- 无悔华夏8月11日渔樵问答答案详解
- LOL英雄联盟乌迪尔技能重做调整详解
- 四两四钱男命婚姻详解一生 结婚较晚值得依靠
- 叫我大掌柜2022巅峰商会战活动详解攻略
- 百变大侦探罗夫尔斯庄园谜案剧本真相详解
- kubernetes之kubectl与YAML详解1
- 航海王热小队决战活动玩法详解攻略
- jvm双亲委派机制详解
- 网络协议之:redis protocol 详解