首页
社区
课程
招聘
[旧帖] 认真请教:有没有人实现过从内存运行EXE? 0.00雪花
发表于: 2016-8-10 10:11 15115

[旧帖] 认真请教:有没有人实现过从内存运行EXE? 0.00雪花

2016-8-10 10:11
15115
收藏
免费 0
支持
分享
最新回复 (35)
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
26
没有试过。
2016-9-28 10:06
0
雪    币: 267
活跃值: (438)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
27
没有什么不可能的!这样功能的代码是完全可以做出来的!
2016-9-28 13:26
0
雪    币: 106
活跃值: (574)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
28
我有现成的代码
2016-9-28 14:57
0
雪    币: 26
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
29
2013年干过这事, 当时是在windows xp上试的, 原理是把exe当成资源编译到你的程序中, 然后读到内在加载, 如果还不放心, 可以先把exe用upx加壳, 再放到资源中, 代码如下:
///////////////////////////////////////////////////
//    date: 2013.08.15
//    author: 刘立向
//    email: llxxhm@126.com
//    qq: 515311445
///////////////////////////////////////////////////
#include <windows.h>
#pragma pack(push, 1)
typedef struct
{
DWORD VirtualAddress;
    DWORD SizeOfBlock;
} *PImageBaseRelocation;
#pragma pack(pop)
typedef IMAGE_SECTION_HEADER (*PIMAGE_SECTION_HEADERS)[1];
HANDLE MemExecute(VOID *MemBuffer, DWORD dwBufSize);
BOOL AlignPEToMem( VOID *MemBuffer, DWORD dwBufSize, PIMAGE_NT_HEADERS &peHead, PIMAGE_SECTION_HEADERS &peSecHead, VOID *&MemPtr, DWORD &ImageSize);
DWORD CalcTotalImageSize(PIMAGE_DOS_HEADER szMzHead, DWORD dwBufSize, PIMAGE_NT_HEADERS peHead, PIMAGE_SECTION_HEADERS peSecHead);
DWORD GetAlignedSize(DWORD Origin, DWORD Alignment);
HANDLE AttachPE(PIMAGE_NT_HEADERS peHead, VOID *MemPtr, DWORD ImageSize);
BOOL CreateMemProcess(CONTEXT &Context, HANDLE &hHandle, HANDLE &hThread, DWORD &BaseAddr, DWORD &ImageSize);
BOOL UnloadShell(HANDLE hProcess, DWORD BaseAddr);
BOOL HasRelocationTable(PIMAGE_NT_HEADERS peHead);
VOID DoRelocation(PIMAGE_NT_HEADERS peHead, VOID *OldBase, VOID *NewBase);
/* 运行资源中的EXE文件使用方法:
HRSRC hResource = FindResource(GetModuleHandle(NULL),MAKEINTRESOURCE(IDR_FILE_STC_ISP),TEXT("File"));
if(hResource)
{
HGLOBAL hg = LoadResource(GetModuleHandle(NULL),hResource);
if(hg)
{
  LPVOID pData = LockResource(hg);
  if(pData)
  {
   DWORD dwSize = SizeofResource(GetModuleHandle(NULL),hResource);
   hProcess = MemExecute(pData,dwSize);
   if(hProcess != INVALID_HANDLE_VALUE)
   {
    CloseHandle(CreateThread(NULL,0,WaitProcessExit,hWnd,NULL,0));
    return TRUE;
   }
  }
}
}
*/
///////////////////////////////////////////////////
//    date: 2013.08.15
//    author: 刘立向
//    email: llxxhm@126.com
//    qq: 515311445
///////////////////////////////////////////////////
#include "PeApi.h"
HANDLE MemExecute(VOID *MemBuffer, DWORD dwBufSize)
{
DWORD ImageSize = 0;
VOID *MemPtr = NULL;
PIMAGE_NT_HEADERS peHead;
    PIMAGE_SECTION_HEADERS peSecHead;   
HANDLE hProcess = INVALID_HANDLE_VALUE;
    if(AlignPEToMem(MemBuffer, dwBufSize, peHead, peSecHead, MemPtr, ImageSize))
    {
        hProcess = AttachPE(peHead, MemPtr, ImageSize);
        VirtualFree(MemPtr, ImageSize, MEM_DECOMMIT);
    }   
    return hProcess;
}
// 加载pe到内存并对齐所有节
BOOL AlignPEToMem( VOID *MemBuffer, DWORD dwBufSize, PIMAGE_NT_HEADERS &peHead, PIMAGE_SECTION_HEADERS &peSecHead, VOID *&MemPtr, DWORD &ImageSize)
{
PIMAGE_SECTION_HEADERS szPeSecHead;// 节表
PIMAGE_DOS_HEADER szMzHead = (PIMAGE_DOS_HEADER)MemBuffer; // DOS头
if( dwBufSize < sizeof(IMAGE_DOS_HEADER) )
  return FALSE;
if( szMzHead->e_magic != IMAGE_DOS_SIGNATURE )
  return FALSE;
if( dwBufSize < szMzHead->e_lfanew + (DWORD)sizeof(IMAGE_NT_HEADERS) )
  return FALSE;
PIMAGE_NT_HEADERS SrcPeH = (PIMAGE_NT_HEADERS)((int)szMzHead + szMzHead->e_lfanew); //PE头
if( SrcPeH->Signature != IMAGE_NT_SIGNATURE )
  return FALSE;
if( (SrcPeH->FileHeader.Characteristics & IMAGE_FILE_DLL)
  || (SrcPeH->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE == 0)
  || (SrcPeH->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER))
  )
  return FALSE;
szPeSecHead = (PIMAGE_SECTION_HEADERS)((int)SrcPeH + sizeof(IMAGE_NT_HEADERS));
ImageSize = CalcTotalImageSize( szMzHead, dwBufSize, SrcPeH, szPeSecHead);
if(ImageSize == 0)
  return FALSE;
MemPtr = VirtualAlloc( NULL, ImageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // 分配内存
if( MemPtr != NULL )
{
  // 计算需要复制的PE头字节数
  DWORD dwHeadSize = SrcPeH->OptionalHeader.SizeOfHeaders;
  for( int i = 0; i < SrcPeH->FileHeader.NumberOfSections; ++i)
  {
   if( (szPeSecHead[i]->PointerToRawData) && (szPeSecHead[i]->PointerToRawData < dwHeadSize) )
   {
    dwHeadSize = szPeSecHead[i]->PointerToRawData;
   }
  }
  memmove( MemPtr, szMzHead, dwHeadSize);
  peHead = (PIMAGE_NT_HEADERS)((int)MemPtr + ((PIMAGE_DOS_HEADER)MemPtr)->e_lfanew);
  peSecHead = (PIMAGE_SECTION_HEADERS)((int)peHead + sizeof(IMAGE_NT_HEADERS));
  VOID *Pt = (VOID *)((DWORD)MemPtr + GetAlignedSize( peHead->OptionalHeader.SizeOfHeaders, peHead->OptionalHeader.SectionAlignment));
  for( i = 0; i < peHead->FileHeader.NumberOfSections; ++i)
  {
   // 定位该节在内存中的位置
   if(peSecHead[i]->VirtualAddress)
    Pt = (VOID *)((DWORD)MemPtr + peSecHead[i]->VirtualAddress);
   if(peSecHead[i]->SizeOfRawData)
   {
    // 复制数据到内存
    memmove(Pt, (CONST VOID *)((DWORD)(szMzHead) + peSecHead[i]->PointerToRawData), peSecHead[i]->SizeOfRawData);
    if(peSecHead[i]->Misc.VirtualSize < peSecHead[i]->SizeOfRawData)
     Pt = (VOID *)((DWORD)Pt + GetAlignedSize(peSecHead[i]->SizeOfRawData, peHead->OptionalHeader.SectionAlignment));
    else // pt 定位到下一节开始位置
     Pt = (VOID *)((DWORD)Pt + GetAlignedSize(peSecHead[i]->Misc.VirtualSize, peHead->OptionalHeader.SectionAlignment));
   }
   else
   {
    Pt = (VOID *)((DWORD)Pt + GetAlignedSize(peSecHead[i]->Misc.VirtualSize, peHead->OptionalHeader.SectionAlignment));
   }
  }
}
return TRUE;
}   
// 计算加载pe并对齐需要占用多少内存
// 未直接使用OptionalHeader.SizeOfImage作为结果是因为据说有的编译器生成的exe这个值会填0
DWORD CalcTotalImageSize(PIMAGE_DOS_HEADER szMzHead, DWORD dwBufSize, PIMAGE_NT_HEADERS peHead, PIMAGE_SECTION_HEADERS peSecHead)
{   
    DWORD ImageSize = GetAlignedSize( peHead->OptionalHeader.SizeOfHeaders, peHead->OptionalHeader.SectionAlignment);// 计算pe头的大小
    // 计算所有节的大小
    for( int i = 0; i < peHead->FileHeader.NumberOfSections; ++i)
    {
        // 超出文件范围
        if(peSecHead[i]->PointerToRawData + peSecHead[i]->SizeOfRawData > dwBufSize)
  {
            return 0;
  }
        else if(peSecHead[i]->VirtualAddress)//计算对齐后某节的大小
        {
            if(peSecHead[i]->Misc.VirtualSize)
   {
    ImageSize = GetAlignedSize( peSecHead[i]->VirtualAddress + peSecHead[i]->Misc.VirtualSize, peHead->OptionalHeader.SectionAlignment);
   }
            else
   {
    ImageSize = GetAlignedSize( peSecHead[i]->VirtualAddress + peSecHead[i]->SizeOfRawData, peHead->OptionalHeader.SectionAlignment);
   }
        }
        else if( peSecHead[i]->Misc.VirtualSize < peSecHead[i]->SizeOfRawData )
        {
            ImageSize += GetAlignedSize( peSecHead[i]->SizeOfRawData, peHead->OptionalHeader.SectionAlignment);
        }
        else
        {
            ImageSize += GetAlignedSize( peSecHead[i]->Misc.VirtualSize, peHead->OptionalHeader.SectionAlignment);
        }
    }
    return ImageSize;
}
// 计算对齐后的大小
DWORD GetAlignedSize(DWORD Origin, DWORD Alignment)
{
    return (Origin + Alignment - 1) / Alignment * Alignment;
}
// 创建外壳进程并用目标进程替换它然后执行
HANDLE AttachPE(PIMAGE_NT_HEADERS peHead, VOID *MemPtr, DWORD ImageSize)
{
CONTEXT Context;
DWORD BaseAddr = 0;
DWORD imageSize = 0;
    HANDLE hProcess = INVALID_HANDLE_VALUE;
    HANDLE hThread = INVALID_HANDLE_VALUE;
    if(CreateMemProcess(Context, hProcess, hThread, BaseAddr, imageSize))
{
        VOID *pBaseAddr = NULL;
        DWORD OldProtect = 0;
        if((peHead->OptionalHeader.ImageBase == BaseAddr) && (imageSize >= ImageSize))
  {// 外壳进程可以容纳目标进程并且加载地址一致   
            pBaseAddr = (VOID *)BaseAddr;
            VirtualProtectEx(hProcess, pBaseAddr, imageSize, PAGE_EXECUTE_READWRITE, &OldProtect);
        }
        else
  {
            if(UnloadShell(hProcess, BaseAddr))
   {// 卸载外壳进程占有内存
                pBaseAddr = VirtualAllocEx((VOID *)hProcess, (VOID *)peHead->OptionalHeader.ImageBase, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
            }
            if((pBaseAddr == NULL) && HasRelocationTable(peHead))
   {// 分配内存失败并且目标进程支持重定向
                pBaseAddr = VirtualAllocEx((VOID *)hProcess, NULL, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                if(pBaseAddr) DoRelocation(peHead, MemPtr, pBaseAddr); // 重定向
            }
        }
        if(pBaseAddr)
  {
            WriteProcessMemory(hProcess, (VOID *)(Context.Ebx+8), &pBaseAddr, sizeof(DWORD), &OldProtect); // 重置目标进程运行环境中的基址
            peHead->OptionalHeader.ImageBase = (DWORD)pBaseAddr;
            
   if(WriteProcessMemory(hProcess, pBaseAddr, MemPtr, ImageSize, &OldProtect))
   {// 复制PE数据到目标进程
                Context.ContextFlags = CONTEXT_FULL;
                if((DWORD)pBaseAddr == BaseAddr)
                    Context.Eax = peHead->OptionalHeader.ImageBase + peHead->OptionalHeader.AddressOfEntryPoint; // 重置运行环境中的入口地址
                else
                    Context.Eax = (DWORD)pBaseAddr + peHead->OptionalHeader.AddressOfEntryPoint;
                SetThreadContext(hThread, &Context);// 更新运行环境
                ResumeThread(hThread);// 执行
                CloseHandle(hThread);
            }
            else
   {// 加载失败,杀掉外壳进程
                TerminateProcess(hProcess, 0);
                CloseHandle(hThread);
    hThread = INVALID_HANDLE_VALUE;
                CloseHandle(hProcess);
                hProcess = INVALID_HANDLE_VALUE;
            }
        }
        else
  {// 加载失败,杀掉外壳进程   
            TerminateProcess(hProcess, 0);
            CloseHandle(hThread);
   hThread = INVALID_HANDLE_VALUE;
            CloseHandle(hProcess);
            hProcess = INVALID_HANDLE_VALUE;
        }
    }
    return hProcess;
}
// 创建外壳进程并获取其基址、大小和当前运行状态
BOOL CreateMemProcess(CONTEXT &Context, HANDLE &hProcess, HANDLE &hThread, DWORD &BaseAddr, DWORD &ImageSize)
{
STARTUPINFOA si;
DWORD dwReadSize = 0;
    PROCESS_INFORMATION pi;
    MEMORY_BASIC_INFORMATION MemInfo;
    memset(&si, 0, sizeof(si));
    memset(&pi, 0, sizeof(pi));
    si.cb = sizeof(si);
char szCmd[MAX_PATH] = {0};
GetModuleFileName(0, szCmd, MAX_PATH);
    if(CreateProcess(NULL, szCmd, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))// 以挂起方式运行进程
{
        hProcess = pi.hProcess;
        hThread = pi.hThread;
        // 获取外壳进程运行状态,[Context.Ebx+8]内存处存的是外壳进程的加载基址,Context.Eax存放有外壳进程的入口地址
        Context.ContextFlags = CONTEXT_FULL;
        GetThreadContext(hThread, &Context);
        ReadProcessMemory(hProcess, (VOID *)(Context.Ebx+8), &BaseAddr, sizeof(DWORD), &dwReadSize); // 读取加载基址
        VOID *pBaseAddr = (VOID *)BaseAddr;
        // 计算外壳进程占有的内存
        while(VirtualQueryEx(hProcess, pBaseAddr, &MemInfo, sizeof(MemInfo)))
        {
            if(MemInfo.State = MEM_FREE) break;
            pBaseAddr = (VOID *)((DWORD)pBaseAddr + MemInfo.RegionSize);
        }
        ImageSize = (DWORD)pBaseAddr - (DWORD)BaseAddr;
  return TRUE;
    }
    return FALSE;
}
// 卸载原外壳占用内存
BOOL UnloadShell(HANDLE hProcess, DWORD BaseAddr)
{
BOOL bRet = FALSE;
    typedef DWORD (__stdcall *pfZwUnmapViewOfSection)(DWORD, DWORD);
    pfZwUnmapViewOfSection ZwUnmapViewOfSection = NULL;
    HMODULE hModel = LoadLibrary("ntdll.dll");
    if(hModel)
{
        ZwUnmapViewOfSection = (pfZwUnmapViewOfSection)GetProcAddress(hModel, "ZwUnmapViewOfSection");   
        if(ZwUnmapViewOfSection)
            bRet = (ZwUnmapViewOfSection((DWORD)hProcess, BaseAddr) == 0);
        FreeLibrary(hModel);
    }
    return bRet;
}
// 是否包含可重定向列表
BOOL HasRelocationTable(PIMAGE_NT_HEADERS peHead)
{
return (peHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) && (peHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
}
// 重定向PE用到的地址
VOID DoRelocation(PIMAGE_NT_HEADERS peHead, VOID *OldBase, VOID *NewBase)
{
DWORD Delta = (DWORD)NewBase - peHead->OptionalHeader.ImageBase;
    PImageBaseRelocation pImageBaseRelocation = (PImageBaseRelocation)((DWORD)OldBase + peHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
    while(pImageBaseRelocation->VirtualAddress + pImageBaseRelocation->SizeOfBlock)
    {
        DWORD *pImageBaseRelocationW = (DWORD *)((DWORD)pImageBaseRelocation + sizeof(*pImageBaseRelocation));   
        for(unsigned int i=1; i <= (pImageBaseRelocation->SizeOfBlock - sizeof(*pImageBaseRelocation)) / 2; ++i)   
        {   
            if((*pImageBaseRelocationW) & 0xF000 == 0x3000){   
                DWORD *t = (DWORD *)((DWORD)(OldBase) + pImageBaseRelocation->VirtualAddress + ((*pImageBaseRelocationW) & 0x0FFF));   
                *t += Delta;   
            }   
            ++pImageBaseRelocationW;   
        }   
        pImageBaseRelocation = (PImageBaseRelocation)pImageBaseRelocationW;   
    }   
}
2016-9-28 15:13
1
雪    币: 4522
活跃值: (5154)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
30
我之前做过这个研究,写了完美的内存EXE及DLL加载器。
2016-10-2 00:38
0
雪    币: 35
活跃值: (612)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
31
有多完美 支持MFC DLL内存加载吗  我试过不少 都是只支持WIN32的
2016-10-21 00:15
0
雪    币: 4522
活跃值: (5154)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
32
支持 只要是windows下能运行的PE文件 基本什么都支持 .net的和64位的除外 .net和64位的还没处理 暂时没那个需求
2016-10-21 10:04
0
雪    币: 35
活跃值: (612)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
33
代码求分享试试!
2016-10-21 13:58
0
雪    币: 4522
活跃值: (5154)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
34
不会免费分享花了巨量时间的研究出来的成果
2016-10-21 15:35
0
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
35
感谢各位,我已经完全实现了我自己需要的功能,EXE完美实现了加密,支持win7,win8,win10,32,64位。不过过程有点跟预先设想的不大一样,谢谢大家:)
2016-11-17 14:42
0
雪    币: 96
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
36
讲讲实现过程
2017-2-2 10:04
0
游客
登录 | 注册 方可回帖
返回
//