国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

驅動開發(fā):取進程模塊的函數(shù)地址

這篇具有很好參考價值的文章主要介紹了驅動開發(fā):取進程模塊的函數(shù)地址。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

在筆者上一篇文章《驅動開發(fā):內核取應用層模塊基地址》中簡單為大家介紹了如何通過遍歷PLIST_ENTRY32鏈表的方式獲取到32位應用程序中特定模塊的基地址,由于是入門系列所以并沒有封裝實現(xiàn)太過于通用的獲取函數(shù),本章將繼續(xù)延申這個話題,并依次實現(xiàn)通用版GetUserModuleBaseAddress()取遠程進程中指定模塊的基址和GetModuleExportAddress()取遠程進程中特定模塊中的函數(shù)地址,此類功能也是各類安全工具中常用的代碼片段。

首先封裝一個lyshark.h頭文件,此類頭文件中的定義都是微軟官方定義好的規(guī)范,如果您想獲取該結構的詳細說明文檔請參閱微軟官方,此處不做過多的介紹。

// 署名權
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com

#include <ntifs.h>
#include <ntimage.h>
#include <ntstrsafe.h>

// 導出未導出函數(shù)
NTKERNELAPI PPEB NTAPI PsGetProcessPeb(IN PEPROCESS Process);
NTKERNELAPI PVOID NTAPI PsGetProcessWow64Process(IN PEPROCESS Process);

typedef struct _PEB32
{
  UCHAR InheritedAddressSpace;
  UCHAR ReadImageFileExecOptions;
  UCHAR BeingDebugged;
  UCHAR BitField;
  ULONG Mutant;
  ULONG ImageBaseAddress;
  ULONG Ldr;
  ULONG ProcessParameters;
  ULONG SubSystemData;
  ULONG ProcessHeap;
  ULONG FastPebLock;
  ULONG AtlThunkSListPtr;
  ULONG IFEOKey;
  ULONG CrossProcessFlags;
  ULONG UserSharedInfoPtr;
  ULONG SystemReserved;
  ULONG AtlThunkSListPtr32;
  ULONG ApiSetMap;
} PEB32, *PPEB32;

typedef struct _PEB_LDR_DATA
{
  ULONG Length;
  UCHAR Initialized;
  PVOID SsHandle;
  LIST_ENTRY InLoadOrderModuleList;
  LIST_ENTRY InMemoryOrderModuleList;
  LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

typedef struct _PEB
{
  UCHAR InheritedAddressSpace;
  UCHAR ReadImageFileExecOptions;
  UCHAR BeingDebugged;
  UCHAR BitField;
  PVOID Mutant;
  PVOID ImageBaseAddress;
  PPEB_LDR_DATA Ldr;
  PVOID ProcessParameters;
  PVOID SubSystemData;
  PVOID ProcessHeap;
  PVOID FastPebLock;
  PVOID AtlThunkSListPtr;
  PVOID IFEOKey;
  PVOID CrossProcessFlags;
  PVOID KernelCallbackTable;
  ULONG SystemReserved;
  ULONG AtlThunkSListPtr32;
  PVOID ApiSetMap;
} PEB, *PPEB;

typedef struct _PEB_LDR_DATA32
{
  ULONG Length;
  UCHAR Initialized;
  ULONG SsHandle;
  LIST_ENTRY32 InLoadOrderModuleList;
  LIST_ENTRY32 InMemoryOrderModuleList;
  LIST_ENTRY32 InInitializationOrderModuleList;
} PEB_LDR_DATA32, *PPEB_LDR_DATA32;

typedef struct _LDR_DATA_TABLE_ENTRY32
{
  LIST_ENTRY32 InLoadOrderLinks;
  LIST_ENTRY32 InMemoryOrderLinks;
  LIST_ENTRY32 InInitializationOrderLinks;
  ULONG DllBase;
  ULONG EntryPoint;
  ULONG SizeOfImage;
  UNICODE_STRING32 FullDllName;
  UNICODE_STRING32 BaseDllName;
  ULONG Flags;
  USHORT LoadCount;
  USHORT TlsIndex;
  LIST_ENTRY32 HashLinks;
  ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32;

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;
  LIST_ENTRY HashLinks;
  ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

GetUserModuleBaseAddress(): 實現(xiàn)取進程中模塊基址,該功能在《驅動開發(fā):內核取應用層模塊基地址》中詳細介紹過原理,這段代碼核心原理如下所示,此處最需要注意的是如果是32位進程則我們需要得到PPEB32 Peb32結構體,該結構體通??梢灾苯邮褂?code>PsGetProcessWow64Process()這個內核函數(shù)獲取到,而如果是64位進程則需要將尋找PEB的函數(shù)替換為PsGetProcessPeb(),其他的枚舉細節(jié)與上一篇文章中的方法一致。

// 署名權
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com

#include <ntifs.h>
#include <windef.h>
#include "lyshark.h"

// 獲取特定進程內特定模塊的基址
PVOID GetUserModuleBaseAddress(IN PEPROCESS EProcess, IN PUNICODE_STRING ModuleName, IN BOOLEAN IsWow64)
{
	if (EProcess == NULL)
		return NULL;
	__try
	{
		// 設置延遲時間為250毫秒
		LARGE_INTEGER Time = { 0 };
		Time.QuadPart = -250ll * 10 * 1000;

		// 如果是32位則執(zhí)行如下代碼
		if (IsWow64)
		{
			// 得到PEB進程信息
			PPEB32 Peb32 = (PPEB32)PsGetProcessWow64Process(EProcess);
			if (Peb32 == NULL)
			{
				return NULL;
			}

			// 延遲加載等待時間
			for (INT i = 0; !Peb32->Ldr && i < 10; i++)
			{
				KeDelayExecutionThread(KernelMode, TRUE, &Time);
			}

			// 沒有PEB加載超時
			if (!Peb32->Ldr)
			{
				return NULL;
			}

			// 搜索模塊 InLoadOrderModuleList
			for (PLIST_ENTRY32 ListEntry = (PLIST_ENTRY32)((PPEB_LDR_DATA32)Peb32->Ldr)->InLoadOrderModuleList.Flink; ListEntry != &((PPEB_LDR_DATA32)Peb32->Ldr)->InLoadOrderModuleList; ListEntry = (PLIST_ENTRY32)ListEntry->Flink)
			{
				UNICODE_STRING UnicodeString;
				PLDR_DATA_TABLE_ENTRY32 LdrDataTableEntry32 = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks);
				RtlUnicodeStringInit(&UnicodeString, (PWCH)LdrDataTableEntry32->BaseDllName.Buffer);

				// 找到了返回模塊基址
				if (RtlCompareUnicodeString(&UnicodeString, ModuleName, TRUE) == 0)
				{
					return (PVOID)LdrDataTableEntry32->DllBase;
				}
			}
		}
		// 如果是64位則執(zhí)行如下代碼
		else
		{
			// 同理,先找64位PEB
			PPEB Peb = PsGetProcessPeb(EProcess);
			if (!Peb)
			{
				return NULL;
			}

			// 延遲加載
			for (INT i = 0; !Peb->Ldr && i < 10; i++)
			{
				KeDelayExecutionThread(KernelMode, TRUE, &Time);
			}

			// 找不到PEB直接返回
			if (!Peb->Ldr)
			{
				return NULL;
			}

			// 遍歷鏈表
			for (PLIST_ENTRY ListEntry = Peb->Ldr->InLoadOrderModuleList.Flink; ListEntry != &Peb->Ldr->InLoadOrderModuleList; ListEntry = ListEntry->Flink)
			{
				// 將特定鏈表轉換為PLDR_DATA_TABLE_ENTRY格式
				PLDR_DATA_TABLE_ENTRY LdrDataTableEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);

				// 找到了則返回地址
				if (RtlCompareUnicodeString(&LdrDataTableEntry->BaseDllName, ModuleName, TRUE) == 0)
				{
					return LdrDataTableEntry->DllBase;
				}
			}
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		return NULL;
	}
	return NULL;
}

那么該函數(shù)該如何調用傳遞參數(shù)呢,如下代碼是DriverEntry入口處的調用方法,首先要想得到特定進程的特定模塊地址則第一步就是需要PsLookupProcessByProcessId找到模塊的EProcess結構,接著通過PsGetProcessWow64Process得到當前被操作進程是32位還是64位,通過調用KeStackAttachProcess附加到進程內存中,然后調用GetUserModuleBaseAddress并傳入需要獲取模塊的名字得到數(shù)據(jù)后返回給NtdllAddress變量,最后調用KeUnstackDetachProcess取消附加即可。

// 署名權
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	HANDLE ProcessID = (HANDLE)7924;

	PEPROCESS EProcess = NULL;
	NTSTATUS Status = STATUS_SUCCESS;
	KAPC_STATE ApcState;

	DbgPrint("Hello LyShark.com \n");

	// 根據(jù)PID得到進程EProcess結構
	Status = PsLookupProcessByProcessId(ProcessID, &EProcess);
	if (Status != STATUS_SUCCESS)
	{
		DbgPrint("獲取EProcessID失敗 \n");
		return Status;
	}

	// 判斷目標進程是32位還是64位
	BOOLEAN IsWow64 = (PsGetProcessWow64Process(EProcess) != NULL) ? TRUE : FALSE;

	// 驗證地址是否可讀
	if (!MmIsAddressValid(EProcess))
	{
		DbgPrint("地址不可讀 \n");
		Driver->DriverUnload = UnDriver;
		return STATUS_SUCCESS;
	}

	// 將當前線程連接到目標進程的地址空間(附加進程)
	KeStackAttachProcess((PRKPROCESS)EProcess, &ApcState);

	__try
	{
		UNICODE_STRING NtdllUnicodeString = { 0 };
		PVOID NtdllAddress = NULL;

		// 得到進程內ntdll.dll模塊基地址
		RtlInitUnicodeString(&NtdllUnicodeString, L"Ntdll.dll");
		NtdllAddress = GetUserModuleBaseAddress(EProcess, &NtdllUnicodeString, IsWow64);
		if (!NtdllAddress)
		{
			DbgPrint("沒有找到基址 \n");
			Driver->DriverUnload = UnDriver;
			return STATUS_SUCCESS;
		}

		DbgPrint("[*] 模塊ntdll.dll基址: %p \n", NtdllAddress);
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
	}

	// 取消附加
	KeUnstackDetachProcess(&ApcState);

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

替換DriverEntry入口函數(shù)處的ProcessID并替換為當前需要獲取的應用層進程PID,運行驅動程序即可得到該進程內Ntdll.dll的模塊基址,輸出效果如下;

驅動開發(fā):取進程模塊的函數(shù)地址

GetModuleExportAddress(): 實現(xiàn)獲取特定模塊中特定函數(shù)的基地址,通常我們通過GetUserModuleBaseAddress()可得到進程內特定模塊的基址,然后則可繼續(xù)通過GetModuleExportAddress()獲取到該模塊內特定導出函數(shù)的內存地址,至于獲取導出表中特定函數(shù)的地址則可通過如下方式循環(huán)遍歷導出表函數(shù)獲取。

// 署名權
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com

// 獲取特定模塊下的導出函數(shù)地址
PVOID GetModuleExportAddress(IN PVOID ModuleBase, IN PCCHAR FunctionName, IN PEPROCESS EProcess)
{
	PIMAGE_DOS_HEADER ImageDosHeader = (PIMAGE_DOS_HEADER)ModuleBase;
	PIMAGE_NT_HEADERS32 ImageNtHeaders32 = NULL;
	PIMAGE_NT_HEADERS64 ImageNtHeaders64 = NULL;
	PIMAGE_EXPORT_DIRECTORY ImageExportDirectory = NULL;
	ULONG ExportDirectorySize = 0;
	ULONG_PTR FunctionAddress = 0;

	// 為空則返回
	if (ModuleBase == NULL)
	{
		return NULL;
	}

	// 是不是PE文件
	if (ImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
	{
		return NULL;
	}

	// 獲取NT頭
	ImageNtHeaders32 = (PIMAGE_NT_HEADERS32)((PUCHAR)ModuleBase + ImageDosHeader->e_lfanew);
	ImageNtHeaders64 = (PIMAGE_NT_HEADERS64)((PUCHAR)ModuleBase + ImageDosHeader->e_lfanew);

	// 是64位則執(zhí)行
	if (ImageNtHeaders64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
	{
		ImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(ImageNtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + (ULONG_PTR)ModuleBase);
		ExportDirectorySize = ImageNtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
	}
	// 是32位則執(zhí)行
	else
	{
		ImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(ImageNtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + (ULONG_PTR)ModuleBase);
		ExportDirectorySize = ImageNtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
	}

	// 得到導出表地址偏移和名字
	PUSHORT pAddressOfOrds = (PUSHORT)(ImageExportDirectory->AddressOfNameOrdinals + (ULONG_PTR)ModuleBase);
	PULONG  pAddressOfNames = (PULONG)(ImageExportDirectory->AddressOfNames + (ULONG_PTR)ModuleBase);
	PULONG  pAddressOfFuncs = (PULONG)(ImageExportDirectory->AddressOfFunctions + (ULONG_PTR)ModuleBase);

	// 循環(huán)搜索導出表
	for (ULONG i = 0; i < ImageExportDirectory->NumberOfFunctions; ++i)
	{
		USHORT OrdIndex = 0xFFFF;
		PCHAR  pName = NULL;

		// 搜索導出表下標索引
		if ((ULONG_PTR)FunctionName <= 0xFFFF)
		{
			OrdIndex = (USHORT)i;
		}
		// 搜索導出表名字
		else if ((ULONG_PTR)FunctionName > 0xFFFF && i < ImageExportDirectory->NumberOfNames)
		{
			pName = (PCHAR)(pAddressOfNames[i] + (ULONG_PTR)ModuleBase);
			OrdIndex = pAddressOfOrds[i];
		}
		else
		{
			return NULL;
		}

		// 找到設置返回值并跳出
		if (((ULONG_PTR)FunctionName <= 0xFFFF && (USHORT)((ULONG_PTR)FunctionName) == OrdIndex + ImageExportDirectory->Base) || ((ULONG_PTR)FunctionName > 0xFFFF && strcmp(pName, FunctionName) == 0))
		{
			FunctionAddress = pAddressOfFuncs[OrdIndex] + (ULONG_PTR)ModuleBase;
			break;
		}
	}
	return (PVOID)FunctionAddress;
}

如何調用此方法,首先將ProcessID設置為需要讀取的進程PID,然后將上圖中所輸出的0x00007FF9553C0000賦值給BaseAddress接著調用GetModuleExportAddress()并傳入BaseAddress模塊基址,需要讀取的LdrLoadDll函數(shù)名,以及當前進程的EProcess結構。

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	HANDLE ProcessID = (HANDLE)4144;
	PEPROCESS EProcess = NULL;
	NTSTATUS Status = STATUS_SUCCESS;

	// 根據(jù)PID得到進程EProcess結構
	Status = PsLookupProcessByProcessId(ProcessID, &EProcess);
	if (Status != STATUS_SUCCESS)
	{
		DbgPrint("獲取EProcessID失敗 \n");
		return Status;
	}

	PVOID BaseAddress = (PVOID)0x00007FF9553C0000;
	PVOID RefAddress = 0;

	// 傳入Ntdll.dll基址 + 函數(shù)名 得到該函數(shù)地址
	RefAddress = GetModuleExportAddress(BaseAddress, "LdrLoadDll", EProcess);
	DbgPrint("[*] 函數(shù)地址: %p \n", RefAddress);

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

運行這段程序,即可輸出如下信息,此時也就得到了x64.exe進程內ntdll.dll模塊里面的LdrLoadDll函數(shù)的內存地址,如下所示;

驅動開發(fā):取進程模塊的函數(shù)地址文章來源地址http://www.zghlxwxcb.cn/news/detail-503918.html

到了這里,關于驅動開發(fā):取進程模塊的函數(shù)地址的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 驅動開發(fā):內核實現(xiàn)進程匯編與反匯編

    驅動開發(fā):內核實現(xiàn)進程匯編與反匯編

    在筆者上一篇文章 《驅動開發(fā):內核MDL讀寫進程內存》 簡單介紹了如何通過MDL映射的方式實現(xiàn)進程讀寫操作,本章將通過如上案例實現(xiàn)遠程進程反匯編功能,此類功能也是ARK工具中最常見的功能之一,通常此類功能的實現(xiàn)分為兩部分,內核部分只負責讀寫字節(jié)集,應用層部

    2024年02月06日
    瀏覽(20)
  • C++ Qt開發(fā):QProcess進程管理模塊

    C++ Qt開發(fā):QProcess進程管理模塊

    Qt 是一個跨平臺C++圖形界面開發(fā)庫,利用Qt可以快速開發(fā)跨平臺窗體應用程序,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現(xiàn)圖形化開發(fā)極大的方便了開發(fā)效率,本章將重點介紹如何運用 QProcess 組件實現(xiàn)針對進程的控制管理等。 當你在使用Qt進行跨平臺應

    2024年03月22日
    瀏覽(21)
  • 一篇讀懂 Android 開發(fā)中模塊化、組件化、插件化和熱修復

    一篇讀懂 Android 開發(fā)中模塊化、組件化、插件化和熱修復

    網上關于 “Android 開發(fā)\\\" 的文章很多,我本人學習 Android 開發(fā)的過程也借鑒了網上先輩們的文章;但大多數(shù)文章都從底層的細枝末節(jié)開始講述,由下而上給人一種這門技術“博大精深”望而生畏的感覺;而我寫這篇文章的初衷就是由上而下,希望別人在閱讀的過程中能夠覺得

    2023年04月08日
    瀏覽(24)
  • C++64位游戲軟件安全匯編與反匯編反調試 x64驅動開發(fā)進程保護進程隱藏驅動讀寫過保護 視頻教程

    ├─課程1 x32dbgx64dbg驅動調試器反反調試器驅動調試環(huán)境搭載 │ 1.為什么要搭載驅動調試環(huán)境.mp4 │ 2.驅動調試環(huán)境搭載1.mp4 │ 3.三種過PG的方法.mp4 │ 4.驅動調試環(huán)境搭載2.mp4 │ 5.驅動調試與驅動進程保護對抗.mp4 │ ├─課程2 C++64位游戲軟件安全匯編與反匯編反調試2021年新

    2024年02月02日
    瀏覽(24)
  • linux驅動開發(fā)--day1(驅動、內核模塊及相關命令、內核模塊傳參)
  • Linux驅動開發(fā)——內核模塊

    Linux驅動開發(fā)——內核模塊

    目錄 內核模塊的由來 第一個內核模塊程序? 內核模塊工具? 將多個源文件編譯生成一個內核模塊? 內核模塊參數(shù) 內核模塊依賴 關于內核模塊的進一步討論? 習題 最近一直在玩那些其它的技術,眼看快暑假了,我決定夯實一下我的驅動方面的技能,迎接我的實習,找了一本

    2024年02月04日
    瀏覽(100)
  • 驅動開發(fā) day2 (led模塊化驅動操控)

    head.h fun.c mycdev.c Makefile

    2024年02月15日
    瀏覽(28)
  • 2、Linux驅動開發(fā):模塊_引用符號

    ??點擊這里查看所有博文 ??隨著自己工作的進行,接觸到的技術棧也越來越多。給我一個很直觀的感受就是,某一項技術/經驗在剛開始接觸的時候都記得很清楚。往往過了幾個月都會忘記的差不多了,只有經常會用到的東西才有可能真正記下來。存在很多在特殊情況下有

    2024年02月15日
    瀏覽(21)
  • 1、Linux驅動開發(fā):模塊_加載卸載

    ??點擊這里查看所有博文 ??隨著自己工作的進行,接觸到的技術棧也越來越多。給我一個很直觀的感受就是,某一項技術/經驗在剛開始接觸的時候都記得很清楚。往往過了幾個月都會忘記的差不多了,只有經常會用到的東西才有可能真正記下來。存在很多在特殊情況下有

    2024年02月16日
    瀏覽(23)
  • 3、Linux驅動開發(fā):模塊_傳遞參數(shù)

    ??點擊這里查看所有博文 ??隨著自己工作的進行,接觸到的技術棧也越來越多。給我一個很直觀的感受就是,某一項技術/經驗在剛開始接觸的時候都記得很清楚。往往過了幾個月都會忘記的差不多了,只有經常會用到的東西才有可能真正記下來。存在很多在特殊情況下有

    2024年02月15日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包