目的
在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; //0x0
UCHAR ReadImageFileExecOptions; //0x1
UCHAR BeingDebugged; //0x2
union
{
UCHAR BitField; //0x3
struct
{
UCHAR ImageUsesLargePages : 1; //0x3
UCHAR IsProtectedProcess : 1; //0x3
UCHAR IsLegacyProcess : 1; //0x3
UCHAR IsImageDynamicallyRelocated : 1; //0x3
UCHAR SkipPatchingUser32Forwarders : 1; //0x3
UCHAR SpareBits : 3; //0x3
};
};
ULONGLONG Mutant; //0x8
ULONGLONG ImageBaseAddress; //0x10
ULONGLONG Ldr; //0x18
}PEB64, * PPEB64;
//0x58 bytes (sizeof)
typedef struct _PEB_LDR_DATA64
{
ULONG Length; //0x0
UCHAR Initialized; //0x4
VOID* SsHandle; //0x8
struct _LIST_ENTRY InLoadOrderModuleList; //0x10
struct _LIST_ENTRY InMemoryOrderModuleList; //0x20
struct _LIST_ENTRY InInitializationOrderModuleList; //0x30
VOID* EntryInProgress; //0x40
UCHAR ShutdownInProgress; //0x48
VOID* ShutdownThreadId; //0x50
}PEB_LDR_DATA64,*PPEB_LDR_DATA64;
typedef struct _PEB_LDR_DATA32
{
ULONG Length; //0x0
UCHAR Initialized; //0x4
ULONG SsHandle; //0x8
LIST_ENTRY32 InLoadOrderModuleList; //0xc
LIST_ENTRY32 InMemoryOrderModuleList; //0x14
LIST_ENTRY32 InInitializationOrderModuleList; //0x1c
ULONG EntryInProgress; //0x24
UCHAR ShutdownInProgress; //0x28
ULONG ShutdownThreadId; //0x2c
}PEB_LDR_DATA32,*PPEB_LDR_DATA32;
//0x78 bytes (sizeof)
typedef struct _LDR_DATA_TABLE_ENTRY32
{
LIST_ENTRY32 InLoadOrderLinks; //0x0
LIST_ENTRY32 InMemoryOrderLinks; //0x8
LIST_ENTRY32 InInitializationOrderLinks; //0x10
ULONG DllBase; //0x18
ULONG EntryPoint; //0x1c
ULONG SizeOfImage; //0x20
UNICODE_STRING32 FullDllName; //0x24
UNICODE_STRING32 BaseDllName; //0x2c
ULONG Flags; //0x34
USHORT LoadCount; //0x38
USHORT TlsIndex; //0x3a
}LDR_DATA_TABLE_ENTRY32,* PLDR_DATA_TABLE_ENTRY32;
//0xe0 bytes (sizeof)
typedef struct _LDR_DATA_TABLE_ENTRY64
{
struct _LIST_ENTRY InLoadOrderLinks; //0x0
struct _LIST_ENTRY InMemoryOrderLinks; //0x10
struct _LIST_ENTRY InInitializationOrderLinks; //0x20
VOID* DllBase; //0x30
VOID* EntryPoint; //0x38
LONGLONG SizeOfImage; //0x40
struct _UNICODE_STRING FullDllName; //0x48
struct _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;
}