从内存中加载Pe文件

DLL加载器-远程线程注入(常规dll注入) 注入思路 先获取到LoadLibrary的函数地址,之后使用CreateRemoteThread加载这段地址即可 简单例子: D:\VS项目\Dll3\x64\Debug\Dll3.dll kernel.dll加载的地址在所有进程都是一样的 https://zhuanlan.zhihu.com/p/599915628?utm_id=0 DLL进程注入 dll注入器 生成dll-2-1.exe 这里注入的exe是notepad++,找到其进程,注入的dll是我cs生成的beacon.dll 主要思路是: 阅读详情
从内存中加载 Pe 文件
 
作者:Sunline               lisunlin0@yahoo.com.cn 日期:2007年7月
关键字: 代码重定位,代码注入,远程代码 , 加载 exe 文件 , 加载 dll 文件
Remotthread, injectcode, relocation code, load dll from memory, load pe from memory load pe from memory, execute from meory
 
代码下载:
第二版:(代码几乎完全重写了一遍,修正了很多bug)
概述:
在某些特殊场合下需要将Pe文件(.exe, .dll等)直接从内存中启动,比如一段验证软件注册的核心代码, 防Dump的代码, 一些补丁,外挂,当然病毒也常常用这种技术。网上流传了几种解决方案,不过都或多或少存在一些不足,最主要是对MFC程序和带有资源的Pe支持不稳定,或者需要按某些特殊的约定编程,总之不太适合初学者,我这里给出了一个PeBlock的解决方法,可以加载绝大多数的执行文件。
我的这个解决方案克服了前面提到的一些不足,但也没有做到完美。那就是推荐编译时给Pe文件带上重定位信息(一般的Dll是带的,编译自己的exe时需要使用/fixed:no 的编译选项产生重定位表)。更具体的信息请参看示例代码。
这里以库的方式给出LoadPe(…)在自身空间内加载Pe,和LoadPeEx(…)在其它进程空间加载Pe,欢迎大家测试使用。
另外,如果代码不要求加载.exe,仅要求支持Dll,适当修改源代码就可以做到近乎完美了。
具体实现:
       Pe文件的加载大体过程是:申请Pe文件建议的内存地址,沿此地址将磁盘中的Pe文件按内存对齐拷贝到内存中,按节属性初始化节,初始化导入函数表,跳入Pe入口执行之。因为网上很早就有这方面知识的相关文章了,这里不再详细叙述,请自己从网上搜索。或参看Bo2000的源代码。
在测试Bo2000的源代码时发现可以使多数的简单.dll文件正确加载,却无法正确加载用MFC生成的.dll文件以及压缩过的可执行文件,仔细调试发现GetModuleFileName是罪魁祸首(另外BO2k里面dll_load存在好几个BUG,这也是其不稳定的直接原因.),调用这个函数将返回NULL,而一般的Dll编写者都默认这个返回结果不会是NULL,并且依赖这个返回结果。
既然找到了原因,那么就可以使用相应的对策来克服之。在这里,我是通过在Pe的映象尾部附加了一个PeBlock的块来解决这个问题(如果仅要求在进程本身加载.dll,这个PeBlock是没有必要的,但是为了能够在其它进程中加载和兼顾加载.exe,使用这个PeBlock是必要的),通过这个PeBlock,不但可以加载.dll,还可以加载.exe( 包括压缩的DLL和EXE.)。
注意:这些代码仅作测试,如果要用作非法用途,本人不承担任何法律责任。
其它细节请看打包的源工程文件。
源代码:
// LoadPe.h
// 
// wirite by Sunline 13.July 2007
// 
#pragma once
         // 在内存中加载PE文件(主要支持EXE,DLL以及由之衍生的OCX,AX等)
         // 最原始的代码参见Bo2000中dll_load.cpp。
         // 要求:
         //               推荐带重定位信息,否则对于多数Pe文件是无法成功加载的。
         // 注意:
         //               仅在本人机器上测试,环境:CPU: Celeron 1.7G Memory: 256M OS:WinXp sp2 Complier: VC++6.0 Editor: VS2005
         //               支持Win2000,WinXp,Win2003,WinVista; 
         //               不支持WinMe,Win98,Win95以及更早的Windows产品
         // 限制:
         //               Commandline 应该是"ModuleFileName Param1 param2 ...", 如果ModuleFileName为空,GetModuleFileName将返回空,这对于多数程序是无法接受的。
         //               不支持通过间接途径或通过函数序号调用GetModuleHandle,GetModuleFileName,GetCommandLine且依赖这些函数其返回值的Pe文件。
         //               对于MFC程序,ModuleFileName必须带有"."(参看MFC源代码AppInit.cpp中CWinApp::SetCurrentHandles()函数,要求文件名中必须有"."的存在,比如"my.dll", "my.", ".my"都合法)。
         //               不支持动态链接的MFC程序(原因是在动态链接MFC库的程序中GetModuleHandle,GetModuleFileName,GetCommandLine是在MFC*.dll中调用,违反上述限制)。
         // 如何正确地使用:
         //               fSuicid是一个必须仔细考虑的一个标志:
         //                        设定了fSuicid,且Pe文件是多线程的,则应该保证ExeEntry或DllEntry是最后一个返回的线程,否则会卸载仍有活动线程的内存区域,导致线程访问已卸载的内存空间而出错。
         //                        带apiHook目的的Pe不应该指定fSuicid=TRUE;
 
         // 本人的英语能力有限,大约着用英语作了些注释,呵呵,促进国际化嘛
         // 
         // Load pe file from memory(support exe, dll or other pe file derived from exe/dll, for instances .ocx, .ax eg.)
         // the source file reference dll_load.cpp in Bo2000, you can get more details from it.
         // desire:
         //               desire the pe file with relocation information, or it will failed for most pe files.
         // notice:
         //               It's only test on my machion, Environment: CPU: Celeron 1.7G Memory: 256M OS:WinXp sp2 compile: VC++6.0 Editor: VS2005
         //               surpport Win2000,WinXp,Win2003,WinVista; 
         //               not surpport WinMe,Win98,Win95 or other early Windows os
         //               Commandline contain the modulename, so please assure the Commandline is not NULL
         // Limit:
         //               not surpport the pe file which depend on the GetModuleHandle,GetModuleFileName,GetCommandLine functions but call them indirect.
         //               not suport the pe file which use the MFC in a share dll
         //               CommandLine form as "ModuleFileName Param1 param2 ...", if ModuleFileName is NULL, GetModuleFileName() will return NULL,
         //                        for most pe file, the LoadPeXX() will failed, and 哪位英语好一点的仁兄有时间的话帮忙给把这补全啊, 哈哈, 上面这段英语估计中国人看不懂,外国人也看不懂
         //       
#ifdef __cplusplus
extern "C" {
#endif
        typedef int (__stdcall *PROCUNLOAD)(int uExitCode);
         HINSTANCE __stdcall _LoadLibraryA( LPVOID lpRawRelocPe, LPCSTR lpLibFileName);
         HINSTANCE __stdcall _LoadLibraryW( LPVOID lpRawRelocPe, LPCWSTR lpLibFileName);
         HINSTANCE __stdcall _LoadLibraryExA(LPVOID lpRawRelocPe, LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
         HINSTANCE __stdcall _LoadLibraryExW(LPVOID lpRawRelocPe, LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
         BOOL      __stdcall      _FreeLibrary(   HMODULE hLibModule);
 
         HANDLE __stdcall LoadPeA(LPVOID lpRawRelocPe, LPCSTR lpCommandLine, HINSTANCE *phInst = NULL, BOOL fSuicid = FALSE, PROCUNLOAD *pfUnload = NULL); // if fSuicid is FASLE, the pfUnload should NOT be NULL;
         HANDLE __stdcall LoadPeW(LPVOID lpRawRelocPe, LPCWSTR lpwCommandLine, HINSTANCE *phInst = NULL, BOOL fSuicid = FALSE, PROCUNLOAD *pfUnload = NULL);
         HANDLE __stdcall LoadPeExA(DWORD dwProcessID, LPVOID lpRawRelocPe, LPCSTR lpCommandLine, HINSTANCE *phRemotInst = NULL, BOOL fSuicid = FALSE, PROCUNLOAD *pfUnload = NULL);
         HANDLE __stdcall LoadPeExW(DWORD dwProcessID, LPVOID lpRawRelocPe, LPCWSTR lpwCommandLine, HINSTANCE *phRemotInst = NULL, BOOL fSuicid = FALSE, PROCUNLOAD *pfUnload = NULL);
 
        int __stdcall UnloadPe(PROCUNLOAD pFouncUnload);
        int __stdcall UnloadPeEx(DWORD dwProcessID, PROCUNLOAD pFouncUnload);
         FARPROC __stdcall _GetProcAddress(HMODULE hModule, LPCSTR FuncName);
#ifdef __cplusplus
}
#endif
 
#ifdef UNICODE
         #define LoadPe LoadPeW
         #define LoadPeEx LoadPeExW
#else
         #define LoadPe LoadPeA
         #define LoadPeEx LoadPeExA
#endif
 
 
 
// LoadPe.cpp
#include <windows.h>
#include "libc.h"
#include "RawPeApi.h"
#include "LoadPe.h"
 
extern unsigned char pRawPeBlock[];
char * pzUnLoad = "UnLoad"; // the export function UnLoad name string;
 
// if function succed return the new thread handle, lphInstance point to the memPe instance, pfUnload point to the address to unload the instance
// otherwise return NULL;
HANDLE __stdcall LoadPeA(LPVOID lpRawRelocPe, LPCSTR lpCommandLine, HINSTANCE *phInst, BOOL fSuicid, PROCUNLOAD *pfUnload)
{
         HANDLE hRet = NULL;
        int nCmdLineLen = lstrlenA(lpCommandLine) + 1;
         PWCHAR pwCmdLine = (PWCHAR)_malloc(nCmdLineLen * sizeof(WCHAR));
        if ( MultiByteToWideChar(CP_THREAD_ACP, MB_COMPOSITE, lpCommandLine, -1, pwCmdLine, nCmdLineLen))
                 hRet = LoadPeW(lpRawRelocPe, pwCmdLine, phInst, fSuicid, pfUnload);
         _free(pwCmdLine);
        return hRet;
}
 
HANDLE __stdcall LoadPeW(LPVOID lpRawRelocPe, LPCWSTR lpwCommandLine, HINSTANCE *phInst, BOOL fSuicid, PROCUNLOAD *pfUnload)
{
        int nRet = ERROR_UNKNOWN;
        int nPeBlockImageSize = 0;
        int nRawRelocPeImageSize = 0;
        int nCmdLineLenA = 0; // the string length for commandlinea include the end flag.
        int nCmdLineLenW = 0;
        int nMemNead = 0;
         HANDLE hRet = 0;
         LPVOID lpPeBlock = NULL;
         LPVOID lpRelocPe = NULL;
         LPWSTR lpwCmdLine = NULL; // point to the WideByte commandline in lpPeblock
         LPSTR lpCommandLine = NULL; // multibyte commandline;
         LPSTR lpCmdLine = NULL; // point to the multibyte commandline in lpPeblock
         LPPEPARAM pPeParam = NULL;
         MEMORY_BASIC_INFORMATION mbi = {0};
         PIMAGE_DOS_HEADER pDosHeader = NULL;
         PIMAGE_NT_HEADERS pNTHeader = NULL;
         __try
        {
               if ( lpwCommandLine == NULL)
                          __leave;
                 nCmdLineLenA = lstrlenW(lpwCommandLine);
                 nCmdLineLenA += sizeof(CHAR);
                 nCmdLineLenW = lstrlenW(lpwCommandLine) * sizeof(WCHAR);
                 nCmdLineLenW += sizeof(WCHAR);
                 lpCommandLine = (LPSTR)_malloc(nCmdLineLenA);
               if ( 0 == WideCharToMultiByte(CP_THREAD_ACP, 0, lpwCommandLine, -1, lpCommandLine, nCmdLineLenA, NULL, NULL))
                          __leave;
                 nRet = VerifyPE(pRawPeBlock);
               if ( nRet)
                          __leave;
                 nRet = VerifyPE(lpRawRelocPe);
               if ( nRet)
                          __leave;
 
                 pDosHeader = (PIMAGE_DOS_HEADER)pRawPeBlock;
                 pNTHeader = PIMAGE_NT_HEADERS((LPBYTE)pDosHeader + pDosHeader->e_lfanew);
                 nPeBlockImageSize = pNTHeader->OptionalHeader.SizeOfImage;
               if ( pNTHeader->FileHeader.Characteristics & IMAGE_FILE_DLL) // the pRawPeBlock should not be a Dll
               {
                          nRet = ERROR_INVALID_MEMPEBLOCK;
                          __leave;
               }
                 pDosHeader = (PIMAGE_DOS_HEADER)lpRawRelocPe;
                 pNTHeader = PIMAGE_NT_HEADERS((LPBYTE)pDosHeader + pDosHeader->e_lfanew);
                 LPVOID pImageBase = (LPVOID)(ULONG_PTR)pNTHeader->OptionalHeader.ImageBase;
                 nRawRelocPeImageSize = pNTHeader->OptionalHeader.SizeOfImage;
 
                 nMemNead = nRawRelocPeImageSize + nPeBlockImageSize + nCmdLineLenA + nCmdLineLenW + sizeof(PEPARAM);
               if ( 0 == VirtualQuery(pImageBase, &mbi, sizeof(MEMORY_BASIC_INFORMATION)))
                          __leave;
                 //HANDLE hmapping=CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0, nMemNead,NULL);
                 //if(hmapping==NULL) return NULL;
                 //LPVOID pImgBase=MapViewOfFileEx(hmapping,FILE_MAP_WRITE,0,0,0,pImageBase);
                 //if(pImgBase==NULL) {
                 //       pImgBase=MapViewOfFileEx(hmapping,FILE_MAP_WRITE,0,0,0,NULL);
                 //}
                 //CloseHandle(hmapping); 
                 //if(pImageBase == NULL)
                 //       return 0;
                 //lpRelocPe = pImgBase;
               if (( MEM_FREE == mbi.State) && ((SIZE_T)nMemNead < mbi.RegionSize))
               {
                          lpRelocPe = (HINSTANCE)VirtualAlloc(pImageBase, nMemNead, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
               }
               if ( lpRelocPe == NULL)
               {
                          lpRelocPe = (HINSTANCE)VirtualAlloc(NULL, nMemNead, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                       if ( NULL == lpRelocPe)
                       {
                                   nRet = ERROR_MEMLESS;
                                   __leave;
                       }
               }
                 lpPeBlock = (LPBYTE)lpRelocPe + nRawRelocPeImageSize;
                 lpwCmdLine = LPWSTR((LPBYTE)lpPeBlock + nPeBlockImageSize);
                 lpCmdLine = (LPSTR)((LPBYTE)lpwCmdLine + nCmdLineLenW);
                 pPeParam = (LPPEPARAM)((LPBYTE)lpCmdLine + nCmdLineLenA);
 
                 nRet = AlignPEToMem(lpRawRelocPe, lpRelocPe);
               if ( nRet)
                          __leave;
                 nRet = AlignPEToMem(pRawPeBlock, lpPeBlock);
               if ( nRet)
                          __leave;
               if ( lpRelocPe != pImageBase)
               {
                          nRet = RelocatePe(lpRelocPe, 0, lpRelocPe);
                       if ( nRet)
                                   __leave;
               }
 
                 nRet = FillImportTable(lpPeBlock);
               if ( nRet)
                          __leave;
                 nRet = RelocatePe(lpPeBlock, 0, lpPeBlock);
               if ( nRet)
                          __leave;
                 lstrcpyA(lpCmdLine, lpCommandLine);
                 lstrcpyW(lpwCmdLine, lpwCommandLine);
                 pPeParam->fSuicid = fSuicid;
 
                 pDosHeader = (PIMAGE_DOS_HEADER)pRawPeBlock;
                 pNTHeader = PIMAGE_NT_HEADERS((LPBYTE)pDosHeader + pDosHeader->e_lfanew);
                 FARPROC pEntryPoint = (FARPROC) ((LPBYTE)lpPeBlock + (unsigned int)pNTHeader->OptionalHeader.AddressOfEntryPoint);
                 DWORD dwThreadId;
                 hRet = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pEntryPoint, lpRelocPe, 0, &dwThreadId);
        }
         __except(EXCEPTION_EXECUTE_HANDLER)
        {
                 nRet = ERROR_UNKNOWN;
        }
        if ( nRet)
        {
               if ( lpRelocPe)
               {
                          VirtualFree(lpRelocPe, 0, MEM_FREE);
                          lpRelocPe = NULL;
                          hRet = NULL;
               }
        }
        if ( lpCommandLine)
                 _free(lpCommandLine);
        if ( phInst)
               * phInst = (HINSTANCE)lpRelocPe;
        if ( fSuicid == FALSE)
               * pfUnload = (PROCUNLOAD)_GetProcAddress((HMODULE)lpPeBlock, pzUnLoad);
        return hRet;
}
 
HANDLE __stdcall LoadPeExA(DWORD dwProcessID, LPVOID lpRawRelocPe, LPCSTR lpCommandLine, HINSTANCE *phRemotInst, BOOL fSuicid, PROCUNLOAD *pfUnload)
{
         HANDLE hRet = NULL;
        int nCmdLineLen = lstrlenA(lpCommandLine) + 1;
         PWCHAR pwCmdLine = (PWCHAR)_malloc(nCmdLineLen * sizeof(WCHAR));
        if ( MultiByteToWideChar(CP_THREAD_ACP, MB_COMPOSITE, lpCommandLine, -1, pwCmdLine, nCmdLineLen))
                 hRet = LoadPeExW(dwProcessID, lpRawRelocPe, pwCmdLine, phRemotInst, fSuicid, pfUnload);
         _free(pwCmdLine);
        return hRet;
}
 
HANDLE __stdcall LoadPeExW(DWORD dwProcessID, LPVOID lpRawRelocPe, LPCWSTR lpwCommandLine, HINSTANCE *phRemotInst, BOOL fSuicid, PROCUNLOAD *pfUnload)
{
         HANDLE hRet = 0;
        int nRet = ERROR_UNKNOWN;
        int nPeBlockImageSize = 0;
        int nRawRelocPeImageSize = 0;
        int nCmdLineLenA = 0;
        int nCmdLineLenW = 0;
         UINT nMemNead = 0;
         PIMAGE_DOS_HEADER pDosHeader = NULL;
         PIMAGE_NT_HEADERS pNTHeader = NULL;
         MEMORY_BASIC_INFORMATION mbi = {0};
         HANDLE hProcess = INVALID_HANDLE_VALUE;
         LPVOID pRelocPe = NULL;
         LPVOID pRemotRelocPe = NULL;
         LPVOID pPeBlock = NULL;
         LPVOID lpRemotePeBlock = NULL;
         LPSTR lpCommandLine = NULL;
         LPSTR  lpCmdLine = NULL;
         LPWSTR lpwCmdLine = NULL;
         LPPEPARAM pPeParam = NULL;
//       LPWSTR lpwRemotCmdLine = NULL;
         LPVOID pRelocPeImageBase = NULL;
         __try
        {
               if ( lpwCommandLine == NULL)
                          __leave;
                 nCmdLineLenA = lstrlenW(lpwCommandLine);
                 nCmdLineLenA += sizeof(CHAR);
                 nCmdLineLenW = lstrlenW(lpwCommandLine) * sizeof(WCHAR);
                 nCmdLineLenW += sizeof(WCHAR);
                 lpCommandLine = (LPSTR)_malloc(nCmdLineLenA);
               if ( 0 == WideCharToMultiByte(CP_THREAD_ACP, 0, lpwCommandLine, -1, lpCommandLine, nCmdLineLenA, NULL, NULL))
                          __leave;
 
                 nRet = VerifyPE(pRawPeBlock);
               if ( nRet)
                          __leave;
                 nRet = VerifyPE(lpRawRelocPe);
               if ( nRet)
                          __leave;
 
                 hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, FALSE, dwProcessID);
               if ( hProcess == NULL)
               {
                          nRet = ERROR_INVALID_OPENPROCESS;
                          __leave;
               }
                 pDosHeader = (PIMAGE_DOS_HEADER)pRawPeBlock;
                 pNTHeader = PIMAGE_NT_HEADERS((LPBYTE)pDosHeader + pDosHeader->e_lfanew);
               if ( pNTHeader->FileHeader.Characteristics & IMAGE_FILE_DLL) // the pRawPeBlock should not be a Dll
               {
                          nRet = ERROR_INVALID_MEMPEBLOCK;
                          __leave;
               }
                 nPeBlockImageSize = pNTHeader->OptionalHeader.SizeOfImage;
                 pDosHeader = (PIMAGE_DOS_HEADER)lpRawRelocPe;
                 pNTHeader = PIMAGE_NT_HEADERS((LPBYTE)pDosHeader + pDosHeader->e_lfanew);
                 pRelocPeImageBase = (LPVOID)(ULONG_PTR)pNTHeader->OptionalHeader.ImageBase;
                 nRawRelocPeImageSize = pNTHeader->OptionalHeader.SizeOfImage;
                 nMemNead = nRawRelocPeImageSize + nPeBlockImageSize + nCmdLineLenA + nCmdLineLenW + sizeof(PEPARAM);
               if ( 0 == VirtualQueryEx(hProcess, pRelocPeImageBase, &mbi, sizeof(MEMORY_BASIC_INFORMATION)))
                          __leave;
               if (( MEM_FREE == mbi.State) && ((SIZE_T)nMemNead < mbi.RegionSize))
                          pRemotRelocPe = VirtualAllocEx(hProcess, pRelocPeImageBase, nMemNead, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
               if ( pRemotRelocPe == NULL)
               {
                          pRemotRelocPe = VirtualAllocEx(hProcess, NULL, nMemNead, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                          VirtualQuery(pRemotRelocPe, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
                       if ( NULL == pRemotRelocPe)
                                   __leave;
               }
                 pRelocPe = VirtualAlloc(NULL, nMemNead, MEM_COMMIT, PAGE_READWRITE);
                 pPeBlock = (LPBYTE)pRelocPe + nRawRelocPeImageSize;
                 lpRemotePeBlock = (LPBYTE)pRemotRelocPe + nRawRelocPeImageSize;
                 lpwCmdLine = LPWSTR((LPBYTE)pPeBlock + nPeBlockImageSize);
                 lpCmdLine = LPSTR((LPBYTE)lpwCmdLine + nCmdLineLenW);
                 pPeParam = LPPEPARAM((LPBYTE)lpCmdLine + nCmdLineLenA);
//               lpwRemotCmdLine = LPWSTR((LPBYTE)lpRemotePeBlock + nPeBlockImageSize);
                 nRet = AlignPEToMem(lpRawRelocPe, pRelocPe);
               if ( nRet)
                          __leave;
                 nRet = AlignPEToMem(pRawPeBlock, pPeBlock);
               if ( nRet)
                          __leave;
                 nRet = FillImportTable(pPeBlock);
               if ( nRet)
                          __leave;
 
               if ( pRelocPeImageBase != pRemotRelocPe)
               {
                          nRet = RelocatePe(pRelocPe, 0, pRemotRelocPe);
                       if ( nRet)
                                   __leave;
               }
                 nRet = RelocatePe(pPeBlock, 0, lpRemotePeBlock);
               if ( nRet)
                          __leave;
                 lstrcpyA(lpCmdLine, lpCommandLine);
                 lstrcpyW(lpwCmdLine, lpwCommandLine);
                 pPeParam->fSuicid = fSuicid;
 
                 pDosHeader = (PIMAGE_DOS_HEADER)pRawPeBlock;
                 pNTHeader = PIMAGE_NT_HEADERS((LPBYTE)pDosHeader + pDosHeader->e_lfanew);
                 FARPROC pEntryPoint = (FARPROC) ((LPBYTE)lpRemotePeBlock + pNTHeader->OptionalHeader.AddressOfEntryPoint);
                 DWORD dwNumByteWrite = 0;
               if (( FALSE == WriteProcessMemory(hProcess, pRemotRelocPe, pRelocPe, nMemNead, &dwNumByteWrite)) || /
                       ( dwNumByteWrite != nMemNead))
               {
                          nRet = ERROR_FAILED_WRITEMEMORY;
                          __leave;
               }
               else
               {
                          DWORD dwThreadId;
                          hRet = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pEntryPoint, pRemotRelocPe, 0, &dwThreadId);
               }
        }
         __except(EXCEPTION_EXECUTE_HANDLER)
        {
                 nRet = ERROR_UNKNOWN;
        }
        if ( nRet)
        {
               if ( pRemotRelocPe)
               {
                          VirtualFreeEx(hProcess, pRemotRelocPe, 0, MEM_FREE);
                          pRemotRelocPe = NULL;
               }
        }
        if ( pRelocPe)
                 VirtualFree(pRelocPe, 0, MEM_FREE);
        if ( hProcess)
                 CloseHandle(hProcess);
        if ( lpCommandLine)
                 _free(lpCommandLine);
        if ( phRemotInst)
               * phRemotInst = (HINSTANCE)pRemotRelocPe;
        if ( fSuicid == FALSE)
        {
                 FARPROC pfProc = _GetProcAddress((HMODULE)pPeBlock, pzUnLoad);
               * pfUnload = (PROCUNLOAD)((LPBYTE)lpRemotePeBlock + ((LPBYTE)pPeBlock - (LPBYTE)pfProc));
        }
        return hRet;
}
 
int __stdcall UnloadPe(PROCUNLOAD pFouncUnload)
{
         DWORD dwRet = 0;
         DWORD uThreadId;
         HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pFouncUnload, 0, 0, &uThreadId);
         WaitForSingleObject(hThread, -1);
        if ( 0 == GetExitCodeThread(hThread, &dwRet))
        {
                 dwRet = GetLastError();
        }
        return ( int ) dwRet;
}
 
int __stdcall UnloadPeEx(DWORD dwProcessID, PROCUNLOAD pProcUnload)
{
        int nRet = 0;
         DWORD uThreadId;
         HANDLE hProcess;
         HANDLE hThread;
        if ( hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, FALSE, dwProcessID))
        {
               if ( hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pProcUnload, 0, 0, &uThreadId))
               {
                          CloseHandle(hThread);
                          nRet = GetLastError();
               }
                 CloseHandle(hProcess);
        }
        else
        {
                 nRet = GetLastError();
        }
        return nRet;
}
 
// Like GetProcAddress(), returns null if the procedure/ordinal is not there, otherwise returns function addr.
FARPROC __stdcall _GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
{
        if (( hModule == NULL) || (lpProcName == NULL))
               return NULL;
         // Get header   
         PIMAGE_OPTIONAL_HEADER   poh;
    poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (hModule);
   
         // Get number of image directories in list
        int nDirCount;
         nDirCount = poh->NumberOfRvaAndSizes;
        if ( nDirCount < 16)
               return NULL;
 
         // - Sift through export table -----------------------------------------------
        if ( poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size == 0)
               return NULL;
 
         // Good, we have an export table. Lets get it.
         PIMAGE_EXPORT_DIRECTORY ped;
         ped = (IMAGE_EXPORT_DIRECTORY *)RVATOVA(hModule, poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);   
        
         // Get ordinal of desired function
        int nOrdinal;
       
        if ( HIWORD((DWORD)(ULONG_PTR)lpProcName)==0) {
                 nOrdinal = (LOWORD((DWORD)(ULONG_PTR)lpProcName)) - ped->Base;
        } else {
        
                 // Go through name table and find appropriate ordinal
              
               int i,count;
                 DWORD *pdwNamePtr;
                 WORD *pwOrdinalPtr;
                
                 count=ped->NumberOfNames;
                 pdwNamePtr=(DWORD *)RVATOVA(hModule,ped->AddressOfNames);
                 pwOrdinalPtr=(WORD *)RVATOVA(hModule,ped->AddressOfNameOrdinals);
               
               for ( i=0;i < count;i++) {
                         
                          // XXX should be a binary search, but, again, fuck it.
                       char * svName;
                          svName = (char *)RVATOVA(hModule, *pdwNamePtr);
                       if ( s_strcmpiA(svName,lpProcName) == 0) {
                                   nOrdinal = *pwOrdinalPtr;
                               break ;
                       }
                          pdwNamePtr++;
                          pwOrdinalPtr++;
               }
               if ( i == count)
                       return NULL;
        }
        
         // Look up RVA of this ordinal
         DWORD *pAddrTable;
         DWORD dwRVA;
         pAddrTable = (DWORD *)RVATOVA(hModule, ped->AddressOfFunctions);
        
         dwRVA = pAddrTable[nOrdinal];    
        
         // Check if it's a forwarder, or a local addr
         // XXX Should probably do this someday. Just don't define forwarders. You're
         // XXX not loading kernel32.dll with this shit anyway.
 
         FARPROC dwAddr;
         dwAddr = (FARPROC)RVATOVA(hModule,dwRVA);
 
        return dwAddr;
}
 
HINSTANCE __stdcall _LoadLibraryA( LPVOID lpRawRelocPe, LPCSTR lpLibFileName)
{
        return _LoadLibraryExA(lpRawRelocPe, lpLibFileName, NULL, 0);
}
 
HINSTANCE __stdcall _LoadLibraryW( LPVOID lpRawRelocPe, LPCWSTR lpLibFileName)
{
        return _LoadLibraryExW(lpRawRelocPe, lpLibFileName, NULL, 0);
}
 
HINSTANCE __stdcall _LoadLibraryExA(LPVOID lpRawRelocPe, LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{
         HINSTANCE hRet = NULL;
        int nLibNameLen = lstrlenA(lpLibFileName) + 1;
         PWCHAR pwLibName = (PWCHAR)_malloc(nLibNameLen * sizeof(WCHAR));
        if ( MultiByteToWideChar(CP_THREAD_ACP, MB_COMPOSITE, lpLibFileName, -1, pwLibName, nLibNameLen))
                 hRet = _LoadLibraryExW(lpRawRelocPe, pwLibName, NULL, 0);
         _free(pwLibName);
        return hRet;
}
 
HINSTANCE __stdcall _LoadLibraryExW(LPVOID lpRawRelocPe, LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{
         HINSTANCE phInst;
         HANDLE hLib = LoadPeW(lpRawRelocPe, lpLibFileName, &phInst, FALSE, NULL);
         WaitForSingleObject(hLib, -1);
        return phInst;
}
 
BOOL      __stdcall       _FreeLibrary( HMODULE hLibModule)
{
         PROCUNLOAD pProcUnload;
         pProcUnload = (PROCUNLOAD)_GetProcAddress(hLibModule, pzUnLoad);
         DWORD dwRet = 0;
         DWORD uThreadId;
         HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pProcUnload, 0, 0, &uThreadId);
         WaitForSingleObject(hThread, -1);
        if ( 0 == GetExitCodeThread(hThread, &dwRet))
        {
                 dwRet = GetLastError();
        }
        return ! dwRet;
} 
滴水逆向三期 内存注入/无模块注入 找文章看了一下, 讲的很好, 但是地址没了…尴尬, 03年的技术, 大致内容就是介绍了两种注入技术, 一个为常规的远程线程注入, 另一个就是内存注入. 只不过文章思路是只插入一段代码, 也就是编写shellcode. 而无模块注入则是将模块整体以内存写入的形式加载实现隐藏 . 杀软依然秒杀…但是我封装起来写后就检测不到, 特征码竟然消失了… 原理与问题 思路是将自己复制一份加载到目标进程中, 即注入进程和寄生程序是一个东西.不过想想也知道, 注入dll也是一个原理, 无非是拉伸之后再贴到目标进程, 最后依然 阅读详情

相关推荐

PE(dll、exe)文件内存加载(手动映射)小记

前言 PE文件即Windos操作系统下的可执行文件的文件结构名称,其中包含但不限于.dll .exe .sys .ocx等等。内存加载PE顾名思义就是通过内存,而非文件。这里的内存指代的是直接加载源。 这个技术其实很早之前就有了,网上也有很多开源可参考的代码,但是仅做一个伸手党那是绝对不行的,首先这些历史悠久的代码存在或多或少的bug,或莫名的崩溃咯,或32和64不兼容咯,各种问题皆是。当然,这些前辈先贤的代码一定是具有非常大的参考和开拓意义的。 技术用途 ...

qq_31314583的博客 2900

Pe研究之:从内存中加载Pe文件(代码重定位,进程隐藏,代码注入)

  Pe研究之: 从内存中加载Pe文件 作者:Sunline              lisunlin0@yahoo.com.cn 日期:2007年7月关键字:代码重定位,代码注入,远程代码, 加载exe文件, 加载dll文件Remotthread, injectcode, relocation code, load dll from memory, load pe

Dustfly的专栏 1万+

Windows PE文件加载器原理剖析:从文件偏移到虚拟内存的5步映射过程

本文深入剖析Windows PE文件加载器的工作原理,详细解析从文件偏移到虚拟内存的5步映射过程。通过分析PE文件结构、内存布局规划和动态链接处理等核心步骤,帮助开发者理解逆向工程中的关键技术和优化方法。

weixin_30984001的博客 354

win10 x64实现内存注入DLL

win10 x64内存注入DLL,可以躲避相关api检测模块

weixin_41725706的博客 3124

win10任务栏文件夹设置成竖形列表样式

win10任务栏文件夹设置成竖形列表样式

ftzchina的博客 7085

操作系统课程项目 OS project —— Pintos from Project 1 to Project 3

Pintos Project 陪伴我们操作系统课程大半个学期了…… 虽然做了这么长时间,个人能力有限,pintos代码,看过的可能也就看懂了一半吧,更不用说没看过的了…… 但是也找到了一些有价值的资料,整理一下,供后辈们参考…… 关于环境的问题,最好是用ubuntu 16.04 windows用户不要折腾装双系统了,特别是win10,动不动更新一下,说不定双系统就出问题了,linux...

Deserted Land 8557

Windows注入与拦截(6) -- 从内存中加载DLL

Windows提供的API(LoadLibrary, LoadLibraryEx)只支持从文件系统上加载DLL文件,我们无法使用这些API从内存中加载DLL。 但是有些时候,我们的确需要从内存中加载DLL,比如: 对发布的文件数量有限制。我们可以将DLL打包到exe的资源中,程序运行时从调用LoadResource等API读取DLL文件到内存中,然后从内存中加载DLL。 需要对DLL进行压缩...

while(1) { smile(); } 4万+

馈电网络设计:通过Smith圆图工具完成微带线到同轴探针的阻抗匹配

Smith圆图通过图形化阻抗变换路径,显著简化微带线到同轴探针的匹配设计。设计需结合理论计算(微带线阻抗公式、探针等效模型)、圆图操作(串联/并联元件移动规则)及仿真验证,最终实现宽带低反射匹配。

百态·数智思维 | 聚焦大数据、量化与未来AI 1108

分析内存动态加载PE文件

在Windows操作系统中,PE(Portable Executable)文件格式是用于可执行文件、DLL文件和其他类型文件的格式。通常,PE文件是通过操作系统的加载器加载到内存中并执行的。加载器会解析PE文件,获取详细的装入参数,并根据这些参数将文件映射到内存中执行。然而,有时我们需要在不使用操作系统加载器的情况下加载和执行PE文件,比如在开发自定义的加载器或进行反病毒与逆向工程研究时。

微软技术分享 2701

利用 Docker Distribution 搭建私有的 Docker Registry

1、拓扑

weixin_44983653的博客 1068

dolphinscheduler集群服务一键安装启动实现流程剖析

通过以上分析我们基本梳理清楚了整个dolphinscheduler项目的一键安装启动逻辑, 我们现在在通过一张图正好理一下整个实现流程。关于一键停止集群服务及一件查询集群各个角色服务实例运行状态的实现也都在stop-all.sh/status-all.sh及dolphinscheduler-daemon.sh这三个脚本中, 有兴趣自行研究。写这篇文章的核心目的不仅在于给大家分享如何优秀的开源项目的一键安装部署的实现过程。

最爱嫣夜来 1208

写一个PE的壳_Part 1:加载PE文件到内存

前面都是PE的零散的知识,可以通过给PE文件写一个壳将前面的PE相关知识进行汇总 网上看到了一个英文教程(详细看参考),里面包含了给PE加壳和调用LIEF库的操作(这个库很简单);按照教程实现一遍(错误都进行了修正,主要是Part4),对理解PE文件格式和脱壳很有帮助 下面是结合自己的实践写的笔记,不是教程的原版翻译 教程主要实现的壳的整体功能: 1.A PE File will be copied as-is (at first) in a custom section. 2.The unpacke.

可乐松子的博客 1482

沙猫群优化算法(SCSO)详解:从沙漠生存智慧到全局优化引擎

本文详细介绍了沙猫群优化算法(SCSO),这是一种新型元启发式优化算法,灵感来源于沙猫在沙漠环境中的卓越狩猎行为。SCSO通过模拟沙猫的低频探测能力和精确攻击策略,将优化问题转化为搜索和捕获"猎物"的过程。算法核心包括探索阶段(全局搜索)和开发阶段(局部精细搜索),通过灵敏度范围模型和自适应控制参数实现两者的平衡。SCSO具有参数简单、收敛性能好等优点,适用于解决复杂全局优化问题。

qq_42212808的博客 202

PE文件加载到内存的主要步骤

1 当PE文件被执行,PE加载器会首先检查DOS MZ header里的PE header偏移量。如果找到则忽视DOS stub 部分直接跳转到PE header。 2 PE 加载器会检查PE header是否有效,有效则跳到PE header的尾部。3 PE 加载器读取节表中的信息,然后采用内存文件映射的方法将这些节映射到内存,同时按照节表的属性设置内存块的属性。 4 PE 文件映射到内存后,P

gzfqh的专栏 →底层代码研究 8040

自学 ABAP 和自学 SAP 的差别

有朋友在我的 ABAP 学习教程里留言: > 自学SAP是不是都要搭建虚拟服务器,然后自己去官网下载新版本SAP就可以吗 对于初学者,我们要搞清楚 ABAP 和 SAP 的区别。 ABAP 是一门编程语言,SAP 首先是德国软件公司的名称,也代表这家公司开发的一系列软件。SAP 公司开发的软件,我们有时也称产品,其功能能满足客户一个或者多个领域的业务需求。这些不同领域,我们也称为不同的业务模块,比如 ERP,CRM,SRM,HR 等等。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 6863

【Altium designer】如何添加过孔阵列

按下图1指示,执行【Tool】菜单栏下【Via Stitching/Shielding】选项卡中的【Add Stitching to Net...】选项 图1 “添加过孔阵列”选项 点击【Add Stitching to Net...】选项后,会跳出一个窗口,让我们设置过孔阵列的参数信息,如下图2所示。 图2 过孔阵列参数设置 过孔阵列区域:勾选该选项框,即可绘制多边形区域; 过孔内径与焊盘直径:比如内径 【Hole Size】设为12mil,焊盘直径【Diameter】设为24mil; .

夜半少年的博客 2万+

探索 PE 文件内存加载器:PEMemoryLoader

探索 PE 文件内存加载器:PEMemoryLoader 在软件开发和逆向工程的世界中,PEMemoryLoader 是一个值得探索的开源工具。它允许你在不依赖于传统的文件系统加载方式的情况下,动态地在内存中加载PE(Portable Executable)文件。对于那些想要进行二进制分析、安全研究或者调试工作的开发者和研究人员来说,这是一个非常有用的技术。 项目简介 是一个简洁且高效的 C++ ...

gitblog_00068的博客 619

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

关于PE文件的内存加载分享

当我们想要加载执行一个程序或者shellcode时,通常的做法就是双击exe执行,然而在攻防场景中这并不容易做到,考虑到有杀软或EDR设备的环境下,命令行执行很大概率也会报毒,这是因为进程的调用链是cmd→灰进程,对于av来说这种调用很可疑,为了规避这种敏感调用,一种方法是断链, 关于断链的内容这里不多赘述,读者可自行查找学习,另一种方法就是内存加载,把DLL或者exe等PE格式的文件从内存中直接加载到内存中去执行,不需要通过LoadLibrary等API函数去操作,这样做的好处是。

2401_84434570的博客 1465

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

PE文件在内存中的加载

PE文件分为 文件头,各个数据节 在PE文件中,各个部分不满200h个字节的,用0填充,直到满足200h个字节 PE文件加载进内存后,各个部分不满4KB个字节的,用0填充,直到满足4KB个字节 这里说的各个部分包括文件头和各个数据节,特别需要注意的是文件头也是这样的单独一部分!

duangduang2020的博客 3014

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

.net core image怎么保存_通过.NET实现内存加载PE文件

0x00 前言在之前的文章《从内存加载.NET程序集(execute-assembly)的利用分析》和《从内存加载.NET程序集(Assembly.Load)的利用分析》曾介绍了使用C Sharp从内存加载.NET程序集的方法,这次将要更近一步,介绍使用C Sharp从内存加载PE文件的方法。0x01 简介本文将要介绍以下内容:· 实现原理·Casey Smith开源的PELoader...

weixin_39631316的博客 314

memexec:内存加载并执行PE文件,无需触碰磁盘

memexec:内存加载并执行PE文件,无需触碰磁盘 项目介绍 memexec 是一个功能强大的Rust语言库,它使得开发者可以加载并执行PE(Portable Executable)文件,而无需将这些文件写入磁盘。这样的特性对于提高程序的安全性和性能有着重要的意义,因为它减少了磁盘I/O操作,同时降低了潜在的安全风险。 项目技术分析 memexec 的设计理念是直接在内存中处理PE文件,它适用于...

gitblog_00804的博客 610

如何实现一个(PE 文件)内存加载器(来自ChatGPT)

实现一个内存加载器(通常指的是一个PE Loader,用于在内存中加载和执行Windows可执行文件)是一项复杂的工作,它涉及对PE文件格式的深入了解以及对Windows操作系统内部工作机制的理解。下面是一个简化版本的概述,用于描述在Windows平台上实现一个内存加载器的一般步骤。

BlackNight168的博客 907

内存PE加载器:一种绕过EDR检测的无文件攻击技术

摘要:一种新型内存PE加载器技术正被用于绕过EDR检测,该技术通过在受信进程内存中直接加载远程PE文件(不落地),利用自定义加载器重建结构并执行,成功规避了基于文件扫描和传统行为分析的防御。攻击流程包括下载、解析、映射、修复依赖和执行五个阶段,其有效性源于信任继承、无文件特征和模仿合法行为等特点。该技术暴露了依赖静态检测的安全产品局限性,防御需转向实时内存扫描、深度行为分析和最小权限等纵深防护策略。

Bruce_xiaowei的博客 1166

从原理到实现:深入解析pe_to_shellcode如何将PE文件转为内存加载的shellcode

本文深入解析pe_to_shellcode技术如何将PE文件转换为内存加载的shellcode,详细探讨PE文件结构、内存加载关键技术及转换实现路径。通过实战案例和优化策略,帮助开发者掌握免杀技术中的核心加载器设计,提升对Windows系统底层的理解和应用能力。

weixin_33738555的博客 519

深度解析内存加载机制:PE文件与shellcode生成的技术实现

Donut是一款革命性的**内存加载**工具,能够生成位置无关的shellcode,直接从内存中加载并执行.NET程序集、原生**PE文件**和其他Windows载荷。作为现代安全研究的重要工具,Donut通过创新的技术架构解决了传统文件落地执行的安全检测难题,为红蓝对抗提供了全新的技术思路。 ## 技术背景与安全需求分析 在当前的网络安全攻防对抗中,传统的基于磁盘文件执行的恶意代码检测技术已

gitblog_00556的博客 1043
上一篇: detours, x86 kernel hook 以及 x64 kernel hook
下一篇: Debugging a Stack Overflow
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值