目的:
在Win7 64位系统编写驱动获取目标进程的模块地址
操作步骤:
1.打开目标进程
2.附加到目标进程
3.根据PsGetProcessWow64Process获取目标进程版本
3.根据不同的位数遍历相应的进程链表结构LDR寻找目标模块,匹配成功则返回模块地址
注意事项
在64位很多宏默认为64位需要进行调整修改为特定长度,这样寻找到的LDR等值才能与32位程序适配
实现代码:
代码如下:
头文件“GetModule.h”
#pragma once
#include<ntifs.h>
HANDLE GetObjectModule(HANDLE pid,CHAR* ModuleName);
EXTERN_C PVOID NTAPI PsGetProcessWow64Process(PEPROCESS Process);
typedef PPEB(__stdcall* PFNPsGetProcessPeb)(PEPROCESS pEProcess);typedef struct _PEB32 {UCHAR InheritedAddressSpace;UCHAR ReadImageFileExecOptions;UCHAR BeingDebugged;UCHAR Spare;ULONG Mutant;ULONG ImageBaseAddress;ULONG/*PPEB_LDR_DATA32*/ Ldr;
} PEB32, * PPEB32;typedef struct _PEB64
{UCHAR InheritedAddressSpace; //0x0UCHAR ReadImageFileExecOptions; //0x1UCHAR BeingDebugged; //0x2union{UCHAR BitField; //0x3struct{UCHAR ImageUsesLargePages : 1; //0x3UCHAR IsProtectedProcess : 1; //0x3UCHAR IsLegacyProcess : 1; //0x3UCHAR IsImageDynamicallyRelocated : 1; //0x3UCHAR SkipPatchingUser32Forwarders : 1; //0x3UCHAR SpareBits : 3; //0x3};};ULONGLONG Mutant; //0x8ULONGLONG ImageBaseAddress; //0x10ULONGLONG Ldr; //0x18
}PEB64, * PPEB64;//0x58 bytes (sizeof)
typedef struct _PEB_LDR_DATA64
{ULONG Length; //0x0UCHAR Initialized; //0x4VOID* SsHandle; //0x8struct _LIST_ENTRY InLoadOrderModuleList; //0x10struct _LIST_ENTRY InMemoryOrderModuleList; //0x20struct _LIST_ENTRY InInitializationOrderModuleList; //0x30VOID* EntryInProgress; //0x40UCHAR ShutdownInProgress; //0x48VOID* ShutdownThreadId; //0x50
}PEB_LDR_DATA64,*PPEB_LDR_DATA64;typedef struct _PEB_LDR_DATA32
{ULONG Length; //0x0UCHAR Initialized; //0x4ULONG SsHandle; //0x8LIST_ENTRY32 InLoadOrderModuleList; //0xcLIST_ENTRY32 InMemoryOrderModuleList; //0x14LIST_ENTRY32 InInitializationOrderModuleList; //0x1cULONG EntryInProgress; //0x24UCHAR ShutdownInProgress; //0x28ULONG ShutdownThreadId; //0x2c
}PEB_LDR_DATA32,*PPEB_LDR_DATA32;//0x78 bytes (sizeof)
typedef struct _LDR_DATA_TABLE_ENTRY32
{LIST_ENTRY32 InLoadOrderLinks; //0x0LIST_ENTRY32 InMemoryOrderLinks; //0x8LIST_ENTRY32 InInitializationOrderLinks; //0x10ULONG DllBase; //0x18ULONG EntryPoint; //0x1cULONG SizeOfImage; //0x20UNICODE_STRING32 FullDllName; //0x24UNICODE_STRING32 BaseDllName; //0x2cULONG Flags; //0x34USHORT LoadCount; //0x38USHORT TlsIndex; //0x3a
}LDR_DATA_TABLE_ENTRY32,* PLDR_DATA_TABLE_ENTRY32;//0xe0 bytes (sizeof)
typedef struct _LDR_DATA_TABLE_ENTRY64
{struct _LIST_ENTRY InLoadOrderLinks; //0x0struct _LIST_ENTRY InMemoryOrderLinks; //0x10struct _LIST_ENTRY InInitializationOrderLinks; //0x20VOID* DllBase; //0x30VOID* EntryPoint; //0x38LONGLONG SizeOfImage; //0x40struct _UNICODE_STRING FullDllName; //0x48struct _UNICODE_STRING BaseDllName; //0x58
}LDR_DATA_TABLE_ENTRY64, * PLDR_DATA_TABLE_ENTRY64;
实现函数文件function.c
#include<ntifs.h>
#include<ntstrsafe.h>
#include"GetModule.h"NTSTATUS ConvertCharToUnicodeString(char* charString, UNICODE_STRING* unicodeString)
{ANSI_STRING ansiString = {0};RtlInitAnsiString(&ansiString, charString);return RtlAnsiStringToUnicodeString(unicodeString, &ansiString, TRUE);
}/*
功能:获取目标进程的模块的DllBase
参数一:目标进程的PID
参数二:需要寻找的模块名称
返回:寻找到的模块DllBase
*/
HANDLE GetObjectModule(HANDLE pid, CHAR* ModuleName)
{PEPROCESS Process = 0;PLDR_DATA_TABLE_ENTRY32 pBase32, pNext32;PLDR_DATA_TABLE_ENTRY64 pBase64, pNext64;UNICODE_STRING CompareModuleName = {0};BOOLEAN FindIs = FALSE;HANDLE return_handle = 0;UNICODE_STRING uniFunctionName;ConvertCharToUnicodeString(ModuleName,&CompareModuleName);PFNPsGetProcessPeb PsGetProcessPeb = NULL;NTSTATUS is = PsLookupProcessByProcessId(pid, &Process);if (!NT_SUCCESS(is)){return 0;}KAPC_STATE stack = { 0 };KeStackAttachProcess(Process, &stack);PPEB32 peb32 = PsGetProcessWow64Process(Process);if (peb32 == NULL) //如果为64位进程{RtlInitUnicodeString(&uniFunctionName, L"PsGetProcessPeb");PsGetProcessPeb = (PFNPsGetProcessPeb)MmGetSystemRoutineAddress(&uniFunctionName);PPEB64 peb64 = PsGetProcessPeb(Process);PPEB_LDR_DATA64 peb64ldr = (PPEB_LDR_DATA64)peb64->Ldr;pBase64 = (PLDR_DATA_TABLE_ENTRY64)(peb64ldr->InLoadOrderModuleList.Flink);pNext64 = pBase64;do{UNICODE_STRING UnicodeString = { 0 };RtlUnicodeStringInit(&UnicodeString, pNext64->BaseDllName.Buffer);if (!RtlCompareUnicodeString(&UnicodeString, &CompareModuleName, TRUE)){FindIs = TRUE;return_handle = pNext64->DllBase;break;}else{pNext64 = pNext64->InLoadOrderLinks.Flink;}} while (pNext64 != pBase64);KeUnstackDetachProcess(&stack);ObDereferenceObject(Process);RtlFreeUnicodeString(&CompareModuleName);}else //如果为32位进程{PPEB_LDR_DATA32 peb32ldr = (PPEB_LDR_DATA32)peb32->Ldr;pBase32 = (PLDR_DATA_TABLE_ENTRY32)(peb32ldr->InLoadOrderModuleList.Flink);pNext32 = pBase32;do{UNICODE_STRING UnicodeString = { 0 };RtlUnicodeStringInit(&UnicodeString, (PWCH)pNext32->BaseDllName.Buffer);if (!RtlCompareUnicodeString(&UnicodeString, &CompareModuleName, TRUE)){FindIs = TRUE;return_handle = pNext32->DllBase;break;}else{pNext32 = pNext32->InLoadOrderLinks.Flink;}} while (pNext32 != pBase32);KeUnstackDetachProcess(&stack);ObDereferenceObject(Process);RtlFreeUnicodeString(&CompareModuleName);}if (FindIs == TRUE){return return_handle;}return 0;
}
驱动主文件main.c
#include<ntifs.h>
#include"GetModule.h"VOID DriverUnload(_In_ struct _DRIVER_OBJECT* DriverObject)
{DbgPrint("--------------DRIVER_UNLOAD-----------------");
}NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
{HANDLE address;DbgBreakPoint();address = GetObjectModule(1140,"ntdll.dll");pDriverObject->DriverUnload = DriverUnload;return STATUS_SUCCESS;
}