我正在尝试让PE加载器更多地了解Portable Executables。我坚持的是IAT的处理。我无法理解这段代码的作用。
PIMAGE_THUNK_DATA nameRef = (PIMAGE_THUNK_DATA)((DWORD_PTR)dwMapBase + pImportDesc->Characteristics);
PIMAGE_THUNK_DATA symbolRef = (PIMAGE_THUNK_DATA)((DWORD_PTR)dwMapBase + pImportDesc->FirstThunk);
for (; nameRef->u1.AddressOfData; nameRef++, symbolRef++)
{
if (nameRef->u1.AddressOfData & 0x80000000)
{
symbolRef->u1.AddressOfData = (DWORD)GetProcAddress(hMod, MAKEINTRESOURCE(nameRef->u1.AddressOfData));
}
else
{
pImportName = (PIMAGE_IMPORT_BY_NAME)(dwMapBase + nameRef->u1.AddressOfData);
symbolRef->u1.Function = (DWORD)GetProcAddress(hMod, (LPCSTR)pImportName->Name);
}
}
我知道虽然Characteristics
我们确定了授予页面READ, WRITE
或EXECUTE
权限的部分,但这里没有发生任何类似的事情。通过使用一些已经存在的代码,我编写了一个PE加载器,但没有错误,可执行文件没有加载。只是向正确的方向暗示就足够了。感谢。
可在此处找到PS代码https://pastebin.com/0ZEn0i8k
答案 0 :(得分:2)
您放置的那段代码恰好只有一个目标:解析导入表,因此每次调用外部函数都可以使用该导入函数的实际地址。您可以查看此页面以获取更多技术信息:https://msdn.microsoft.com/en-us/library/ms809762.aspx
DWORD特征
有一次,这可能是一组标志。但是,微软改变了它的含义,从不打扰更新WINNT.H。该字段实际上是指针数组的偏移量(RVA)。这些指针中的每一个都指向IMAGE_IMPORT_BY_NAME结构。
因此,您的代码段会将一个指向导入记录数组的指针作为 nameRef 变量。然后,每个导入可以是一种可能的模式:
在两个非零情况下,GetProcAddress都应解析导入(按序号或按名称)到内存中的实际地址。
答案 1 :(得分:-1)
如果您查找IMAGE_IMPORT_DESCRIPTOR
定义,则可以查看Characteristics
与OriginalFirstThunk
共享联盟。所以真正的代码可以写成
PIMAGE_THUNK_DATA nameRef = (PIMAGE_THUNK_DATA)
((DWORD_PTR)dwMapBase + pImportDesc->OriginalFirstThunk);
这将是同样的效果。不过这个
(DWORD)GetProcAddress
不会引起任何问题吗?