WinDBG详解进程初始化dll是如何加载的( 二 )

从输出的 VirtualAddress=0x1b1cc 中可以看到,我们 PPEE 截图二中的 DIRECTORY_ENTRY_IMPORT 真实内容是在偏移 0x1b1cc 处,它是一个 combase!_IMAGE_IMPORT_DESCRIPTOR 结构体 , 输出如下:
0:005> dt 0x400000+0x1b1cc combase!_IMAGE_IMPORT_DESCRIPTOR+0x000 Characteristics: 0x1b21c+0x000 OriginalFirstThunk : 0x1b21c+0x004 TimeDateStamp: 0+0x008 ForwarderChain: 0+0x00c Name: 0x1b40c+0x010 FirstThunk: 0x1b000到这里就很关键了,涉及到如下几点信息:

  • 加载的 dll 名字是什么?
可以从 Name 字段提取,参考如下代码:
0:005> da 0x400000+0x1b40c0041b40c"KERNEL32.dll"
  • 加载的 方法名 是什么?
这需要提取 OriginalFirstThunk 字段 , 这里是一个 _IMAGE_IMPORT_BY_NAME类型的指针数组,代码如下:
0:005> dp 0x400000+0x1b21c0041b21c0001b3e8 0001b3fc 0001b954 0001b9420041b22c0001b934 0001b924 0001b912 0001b9060041b23c0001b8fa 0001b8ea 0001b8d6 0001b8ba...0:005> dt 0x400000+0x0001b3e8 combase!_IMAGE_IMPORT_BY_NAME+0x000 Hint: 0x382+0x002 Name: [1]"I"0:005> da 0x400000+0x0001b3e8+0x20041b3ea"IsDebuggerPresent"结合上面的输出 , 我们知道 IsDebuggerPresent() 是属于 KERNEL32.dll 下的,有了这两点信息 , Windows 加载器就可以用 LoadLibraryGetProcAddress 方法将其加载到进程中了,转化为 C 代码大概是这样的 。
typedef BOOL(CALLBACK* DeubbgerFunc)();int main(intargc, char* argv[]){ HMODULE hModule = LoadLibrary(L"KERNEL32.dll"); DeubbgerFunc func = (DeubbgerFunc)GetProcAddress(hModule, "IsDebuggerPresent"); BOOL b= func();}
  • func 函数地址会保存吗?
当然会保存了 , 会放在 _IMAGE_IMPORT_DESCRIPTOR 结构下的 FirstThunk 字段中,这是一个函数地址的指针数组 , 可以用 dds 观察 。
0:005> dt 0x400000+0x1b1cc combase!_IMAGE_IMPORT_DESCRIPTOR+0x000 Characteristics: 0x1b21c+0x000 OriginalFirstThunk : 0x1b21c+0x004 TimeDateStamp: 0+0x008 ForwarderChain: 0+0x00c Name: 0x1b40c+0x010 FirstThunk: 0x1b0000:005> dds 0x400000+0x1b0000041b000753c20d0 KERNEL32!IsDebuggerPresentStub0041b004753c16c0 KERNEL32!LoadLibraryWStub0041b008753c2e80 KERNEL32!GetCurrentProcess0041b00c753bf550 KERNEL32!GetProcAddressStub0041b05c753b9910 KERNEL32!TerminateProcessStub...还有一点要注意,如果你在代码中使用 IsDebuggerPresent() 方法的话,它会从 0041b000 位置上取函数地址,参考如下汇编代码:
WinDBG详解进程初始化dll是如何加载的

文章插图
三:总结对初学者来说 , 搞懂这些还是有一定困难的 , 我在网上找了一份很好的参考图,大家可以对照着这张图理解,在此感谢作者 。
WinDBG详解进程初始化dll是如何加载的

文章插图
  • INT 是 Windows 需要加载的函数名列表 。
  • IAT 是存放 GetProcAddress 返回函数地址的列表 。

推荐阅读