獲取內核進程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