获取内核进程DLL基地址 与 获取某进程内部DLL地址


一、驱动编写的基本写法
 
DriverEntry :相当main函数
DriverUnload : 卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
    DbgPrint("已卸载驱动!\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) 
{
DbgPrint("安装驱动成功!\n");
pDriverObject->DriverUnload = DriverUnload;

return STATUS_SUCCESS;
}

  

二、了解内核PEB结构体
Windbg使用命令: dt _PEB [进程EPROCESS]  随便查看一个进程的 EPROCESS  ,图中结构体0x18偏移处有一个Ldr指向了  _PEB_LDR_DATA  
 
点击Ldr 之后查看了 _PEB_LDR_DATA 的结构是这样子的,其中 InLoadOrderModuleList   指向了另一个结构体的地址  _ LDR_DATA_TABLE_ENTRY  这里面就有内核进程DLL的地址
 
下图可以看到双向链表中保存了当前进程的基地址
 
编写代码的思路就有了,获取 PEB->Ldr->InLoadOrderModuleList->Blink
代码中使用了一个微软提供的宏  CONTAINING_RECORD  : 它的功能为已知结构体或类的某一成员、对象中该成员的地址以及这一结构体名或类名,从而得到该对象的基地址。
#include<ntddk.h>
typedef struct _LDR_DATA_TABLE_ENTRY {
    LIST_ENTRY InLoadOrderLinks;
    LIST_ENTRY InMemoryOrderLinks;
    LIST_ENTRY InInitializationOrderLinks;
    PVOID DllBase;
    PVOID EntryPoint;
    ULONG SizeOfImage;
    UNICODE_STRING FullDllName;
    UNICODE_STRING BaseDllName;
    ULONG Flags;
    USHORT LoadCount;
    USHORT TlsIndex;
    union {
        LIST_ENTRY HashLinks;
        struct {
            PVOID SectionPointer;
            ULONG CheckSum;
        };
    };
    union {
        struct {
            ULONG TimeDateStamp;
        };
        struct {
            PVOID LoadedImports;
        };
    };
}LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
    DbgPrint("已卸载驱动!\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
    PLDR_DATA_TABLE_ENTRY pLdr = NULL;
    PLIST_ENTRY pListEntry = NULL;
    PLIST_ENTRY pCurrentListEntry = NULL;
    PLDR_DATA_TABLE_ENTRY pCurrentModule = NULL;
    DbgPrint("安装驱动成功!\n");
    pDriverObject->DriverUnload = DriverUnload;
   // UNICODE_STRING UnicodeString2;
    //RtlInitUnicodeString(&UnicodeString2, L"ntoskrnl.exe");
    pLdr = (PLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;
    pListEntry = pLdr->InLoadOrderLinks.Flink;
    pCurrentListEntry = pListEntry->Flink;
    while (pCurrentListEntry != pListEntry)
    {
        pCurrentModule = CONTAINING_RECORD(pCurrentListEntry, LDR_DATA_TABLE_ENTRY,  InLoadOrderLinks);
        if (pCurrentModule->BaseDllName.Buffer != 0)
        {
            DbgPrint("ModuleName = %wZ ModuleBase = %p \r\n",
                pCurrentModule->BaseDllName,
                pCurrentModule->DllBase);
        }
        pCurrentListEntry = pCurrentListEntry->Flink;
    }
    return STATUS_SUCCESS;
}

  可以看到已经获取到了内核全部模块的基地址

 

 

如果需要获取某个进程的某个DLL的基地址,可以先封装成一个函数 传入eprocess   和需要获取模块的名称,根据函数名判断一下。

NTSTATUS GetModeaddr(PEPROCESS Eprocess, PUNICODE_STRING ModeName)
{

	KAPC_STATE  ks;
	PUNICODE_STRING UnicodeString2;

	DbgPrint("%wZ", ModeName);
	DbgPrint("%wZ", &ModeName);
	RtlInitUnicodeString(&UnicodeString2, ModeName);
	
	PEPROCESS    Eprocess2 = Eprocess;
	if (Eprocess2 == NULL)
	{
		DbgPrint("Eprocess 获取失败");
		return;
	}
	__try {

		ULONG64  peb = *(PULONG64)((ULONG64)Eprocess2 + PEB_OFFSET_IN_EPROCESS);
		KeStackAttachProcess(Eprocess2, &ks);
		ULONG64 idr = *(PULONG64)(peb + LDR_OFFSET_IN_PEB);
		PLIST_ENTRY  pListHead = (idr + InLoadOrderModuleList_OFFSET);
		PLIST_ENTRY pMod = pListHead->Flink;   //下一个链表

		while (pMod != pListHead)
		{


			PCUNICODE_STRING name = &(((PLDR_DATA_TABLE_ENTRY)pMod)->ModuleName);
			//DbgPrint("name = %wZ\n  Base= %p", name, (PVOID)(((PLDR_DATA_TABLE_ENTRY)pMod)->ModuleBaseAddress));
	
			if (RtlCompareUnicodeString(name, &UnicodeString2, TRUE))
			{
	
				DbgPrint("name = %wZ\n  Base= %p", name, (PVOID)(((PLDR_DATA_TABLE_ENTRY)pMod)->ModuleBaseAddress));
				base = (PVOID)(((PLDR_DATA_TABLE_ENTRY)pMod)->ModuleBaseAddress);
		
			}

			pMod = pMod->Flink;
		}

	}
	__except (EXCEPTION_EXECUTE_HANDLER) {

		DbgPrint("EXCEPTION_EXECUTE_HANDLER is occure...\n");


	}

	KeUnstackDetachProcess(&ks);

}

  

 

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM