设为首页 加入收藏

TOP

驱动开发:PE导出函数与RVA转换(二)
2023-07-23 13:29:18 】 浏览:96
Tags:RVA 转换
Names; // 遍历节结构进行地址运算 pSectionHeader = pOldSectionHeader; for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) { if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData) { FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData; } } AddressOfNames = (PULONG)((ULONGLONG)BaseAddress + FileOffset); // 分析导出表 ULONG uOffset; LPSTR FunName; ULONG uAddressOfNames; ULONG TargetOff = 0; for (ULONG uIndex = 0; uIndex < pExportDirectory->NumberOfNames; uIndex++, AddressOfNames++, AddressOfNameOrdinals++) { uAddressOfNames = *AddressOfNames; pSectionHeader = pOldSectionHeader; for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) { if (pSectionHeader->VirtualAddress <= uAddressOfNames && uAddressOfNames <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData) { uOffset = uAddressOfNames - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData; } } FunName = (LPSTR)((ULONGLONG)BaseAddress + uOffset); // 如果找到则返回RVA if (!_stricmp((const char *)FunctionName, FunName)) { // 等于1则返回RVA if (Flag == 1) { TargetOff = (ULONG)AddressOfFunctions[*AddressOfNameOrdinals]; // DbgPrint("索引 [ %p ] 函数名 [ %s ] 相对RVA [ %p ] \n", *AddressOfNameOrdinals, FunName, TargetOff); return TargetOff; } // 返回索引 else if (Flag == 0) { return *AddressOfNameOrdinals; } } } // 结束后释放内存 ExFreePoolWithTag(BaseAddress, (ULONG)"LyShark"); return 0; }

调用该函数很容易,传入模块路径以及该模块内的函数名,解析出RVA地址或Index下标。

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	// 函数分别传入 [模块路径,函数名,标志=1] 返回该导出函数的RVA
	ULONG64 get_rva = GetRvaFromModuleName(L"\\SystemRoot\\system32\\ntoskrnl.exe", "NtReadFile", 1);
	DbgPrint("NtReadFile RVA = %p \n", get_rva);

	// 函数分别传入 [模块路径,函数名,标志=0] 返回该导出函数的ID下标
	ULONG64 get_id = GetRvaFromModuleName(L"\\SystemRoot\\system32\\ntoskrnl.exe", "NtReadFile", 0);
	DbgPrint("NtReadFile ID = %d \n", get_id);

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

编译并运行程序,分别获取到ntoskrnl.exe模块内NtReadFile函数的RVA,Index索引,调用效果如下;

第二个函数GetModuleNameFromRVA()则实现传入RVA或者函数Index序号,解析出函数名,具体实现方法与如上函数基本一致,仅仅只是在过滤时做了调整。

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

// 根据传入的函数RVA或Index下标,获取该函数的函数名
PCHAR GetModuleNameFromRVA(WCHAR *wzFileName, ULONG64 uRVA, INT Flag)
{
	// 加载内核模块
	PVOID BaseAddress = LoadKernelFile(wzFileName);

	// 取出导出表
	PIMAGE_DOS_HEADER pDosHeader;
	PIMAGE_NT_HEADERS pNtHeaders;
	PIMAGE_SECTION_HEADER pSectionHeader;
	ULONGLONG FileOffset;
	PIMAGE_EXPORT_DIRECTORY pExportDirectory;

	// DLL内存数据转成DOS头结构
	pDosHeader = (PIMAGE_DOS_HEADER)BaseAddress;

	// 取出PE头结构
	pNtHeaders = (PIMAGE_NT_HEADERS)((ULONGLONG)BaseAddress + pDosHeader->e_lfanew);

	// 判断PE头导出表是否为空
	if (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_EN
首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇第6章 分支语句和逻辑运算符 下一篇C++面试八股文:static和const的..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目