如何从 PEPROCESS 读取驱动程序中的导入地址 Table?
How to read Import Address Table, in a driver, from a PEPROCESS?
我正在编写驱动程序以创建 Antivirus。但是,我卡在从进程中读取导入地址 table。
我有一个 CreateProcessNotify:
VOID CreateProcNotify(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create)
{
UNREFERENCED_PARAMETER(ParentId);
UNREFERENCED_PARAMETER(Create);
PEPROCESS Process;
KAPC_STATE Apc;
PVOID ModuleBase;
// From PID to PEPROCESS
PsLookupProcessByProcessId(ProcessId, &Process);
// Attach into the target process' memory
KeStackAttachProcess(Process, &Apc);
ModuleBase = GetModuleBase(Process);
PIMAGE_IMPORT_DESCRIPTOR pImportAddressTable = GetIAT(ModuleBase);
DPrint("Imports of [Meias] are: \n");
DPrint("IAT: %x\n", pImportAddressTable);
// Iterate all Modules Imports
while (pImportAddressTable->Name != 0) {
DPrint("{%s}, ", (PCHAR)((ULONG)ModuleBase + (pImportAddressTable->Name)));
pImportAddressTable++;
}
// Unattach ourselves from the target process' memory
KeUnstackDetachProcess(&Apc);
}
同时还具有以下功能:
/*Returns the Base of the Process*/
PVOID GetModuleBase(PEPROCESS Process)
{
PVOID ModuleBase;
__try
{
ModuleBase = PsGetProcessSectionBaseAddress(Process);
}
__except (GetExceptionCode())
{
return 0;
}
return ModuleBase;
}
/*Returns the Import Address Table*/
PIMAGE_IMPORT_DESCRIPTOR GetIAT(PVOID ModuleBase)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)ModuleBase;
PIMAGE_NT_HEADERS32 pNtHeader32 = NULL;
PIMAGE_NT_HEADERS64 pNtHeader64 = NULL;
PIMAGE_IMPORT_DESCRIPTOR pIAT = NULL;
if (ModuleBase == 0)
return NULL;
DPrint("ModuleBase: 0x%x\n", pDosHeader);
// If the magic value isn't MZ then isn't a valid PE
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
return NULL;
pNtHeader32 = (PIMAGE_NT_HEADERS32)((PUCHAR)ModuleBase + pDosHeader->e_lfanew);
pNtHeader64 = (PIMAGE_NT_HEADERS64)((PUCHAR)ModuleBase + pDosHeader->e_lfanew);
// If the image doesn't have a DOS
if ((INT)pNtHeader32 != IMAGE_NT_SIGNATURE)
return NULL;
// Check if is 32 bit
if (pNtHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
pIAT = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)ModuleBase + pNtHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
}
// Check if is 64 bit
else if (pNtHeader64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
pIAT = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)ModuleBase + pNtHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
}
return pIAT;
}
使用 WinDBG 调试时:
使用 !analyze -v:
异常:
代码:
我在 this
的帮助下实现了 GetIAT
如您所见,问题是它没有正确获取 IAT,但我不知道为什么...
提前致谢。
问题是因为我正在使用
if ((INT)pNtHeader32 != IMAGE_NT_SIGNATURE)
return NULL;
什么时候我应该检查它的签名:
if ((INT)pNtHeader32->Signature != IMAGE_NT_SIGNATURE)
return NULL;
完成。
IAT函数的代码不可靠。如果 Import Table Address 为 0,这将是 BSOD.
的原因
比如这个project(分析依赖关系;remake旧的遗留软件depends.exe ) 导入 Table 地址 为 0.
为了避免蓝屏死机你需要添加一个检查,像这样:
...
// Check if is 32 bit
if (pNtHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
if (pNtHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)
return NULL;
pIAT = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)ModuleBase
+ pNtHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
}
// Check if is 64 bit
else if (pNtHeader64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
if (pNtHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)
return NULL;
pIAT = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)ModuleBase + pNtHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
}
...
我正在编写驱动程序以创建 Antivirus。但是,我卡在从进程中读取导入地址 table。
我有一个 CreateProcessNotify:
VOID CreateProcNotify(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create)
{
UNREFERENCED_PARAMETER(ParentId);
UNREFERENCED_PARAMETER(Create);
PEPROCESS Process;
KAPC_STATE Apc;
PVOID ModuleBase;
// From PID to PEPROCESS
PsLookupProcessByProcessId(ProcessId, &Process);
// Attach into the target process' memory
KeStackAttachProcess(Process, &Apc);
ModuleBase = GetModuleBase(Process);
PIMAGE_IMPORT_DESCRIPTOR pImportAddressTable = GetIAT(ModuleBase);
DPrint("Imports of [Meias] are: \n");
DPrint("IAT: %x\n", pImportAddressTable);
// Iterate all Modules Imports
while (pImportAddressTable->Name != 0) {
DPrint("{%s}, ", (PCHAR)((ULONG)ModuleBase + (pImportAddressTable->Name)));
pImportAddressTable++;
}
// Unattach ourselves from the target process' memory
KeUnstackDetachProcess(&Apc);
}
同时还具有以下功能:
/*Returns the Base of the Process*/
PVOID GetModuleBase(PEPROCESS Process)
{
PVOID ModuleBase;
__try
{
ModuleBase = PsGetProcessSectionBaseAddress(Process);
}
__except (GetExceptionCode())
{
return 0;
}
return ModuleBase;
}
/*Returns the Import Address Table*/
PIMAGE_IMPORT_DESCRIPTOR GetIAT(PVOID ModuleBase)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)ModuleBase;
PIMAGE_NT_HEADERS32 pNtHeader32 = NULL;
PIMAGE_NT_HEADERS64 pNtHeader64 = NULL;
PIMAGE_IMPORT_DESCRIPTOR pIAT = NULL;
if (ModuleBase == 0)
return NULL;
DPrint("ModuleBase: 0x%x\n", pDosHeader);
// If the magic value isn't MZ then isn't a valid PE
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
return NULL;
pNtHeader32 = (PIMAGE_NT_HEADERS32)((PUCHAR)ModuleBase + pDosHeader->e_lfanew);
pNtHeader64 = (PIMAGE_NT_HEADERS64)((PUCHAR)ModuleBase + pDosHeader->e_lfanew);
// If the image doesn't have a DOS
if ((INT)pNtHeader32 != IMAGE_NT_SIGNATURE)
return NULL;
// Check if is 32 bit
if (pNtHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
pIAT = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)ModuleBase + pNtHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
}
// Check if is 64 bit
else if (pNtHeader64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
pIAT = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)ModuleBase + pNtHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
}
return pIAT;
}
使用 WinDBG 调试时:
使用 !analyze -v:
异常:
代码:
我在 this
的帮助下实现了 GetIAT如您所见,问题是它没有正确获取 IAT,但我不知道为什么...
提前致谢。
问题是因为我正在使用
if ((INT)pNtHeader32 != IMAGE_NT_SIGNATURE)
return NULL;
什么时候我应该检查它的签名:
if ((INT)pNtHeader32->Signature != IMAGE_NT_SIGNATURE)
return NULL;
完成。
IAT函数的代码不可靠。如果 Import Table Address 为 0,这将是 BSOD.
的原因比如这个project(分析依赖关系;remake旧的遗留软件depends.exe ) 导入 Table 地址 为 0.
为了避免蓝屏死机你需要添加一个检查,像这样:
...
// Check if is 32 bit
if (pNtHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
if (pNtHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)
return NULL;
pIAT = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)ModuleBase
+ pNtHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
}
// Check if is 64 bit
else if (pNtHeader64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
if (pNtHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)
return NULL;
pIAT = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)ModuleBase + pNtHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
}
...