兔八哥极品软件园    运行: 4500天 | 文章:640 篇 | 评论:505 条 | 碎语:1条

C++内存中运行EXE

作者:admin 发布于:2012-7-5 13:00 Thursday 分类:Windows


在内存中运行可执行程序,好处是可以给程序加壳,加密源程序,静态反汇编无法获得PE输入节,但是因为运行后仍然是独立的进程,所以没办法防止远程线程注入,挂接API钩子。

Windows的PE加载器在启动程序的时候,会将磁盘上的文件加载到内存,然后做很多操作,如函数导入表重定位,变量预处理之类的。这位仁兄等于是自己写了一个PE加载器。直接将内存中的程序启动。记得以前的“红色代码”病毒也有相同的特性。

    直接启动内存中的程序相当于加了一个壳,可以把程序加密保存,运行时解密到内存,然后启动,不过对于增加破解难度还要稍微复杂点。否则人家把内存中的进程DUMP出来然后修复导入表就被拖出来了。

#include "stdafx.h"  
  
  
typedef IMAGE_SECTION_HEADER (*PIMAGE_SECTION_HEADERS)[1];   
  
// 计算对齐后的大小   
unsigned long GetAlignedSize(unsigned long Origin, unsigned long Alignment)   
{   
    return (Origin + Alignment - 1) / Alignment * Alignment;   
}   
  
// 计算加载pe并对齐需要占用多少内存   
// 未直接使用OptionalHeader.SizeOfImage作为结果是因为据说有的编译器生成的exe这个值会填0   
unsigned long CalcTotalImageSize(PIMAGE_DOS_HEADER MzH   
                                 , unsigned long FileLen   
                                 , PIMAGE_NT_HEADERS peH   
                                 , PIMAGE_SECTION_HEADERS peSecH)   
{   
    unsigned long res;   
    // 计算pe头的大小   
    res = GetAlignedSize( peH->OptionalHeader.SizeOfHeaders   
        , peH->OptionalHeader.SectionAlignment   
        );   
  
    // 计算所有节的大小   
    for( int i = 0; i < peH->FileHeader.NumberOfSections; ++i)   
    {   
        // 超出文件范围   
        if(peSecH[i]->PointerToRawData + peSecH[i]->SizeOfRawData > FileLen)   
            return 0;   
        else if(peSecH[i]->VirtualAddress)//计算对齐后某节的大小   
        {   
            if(peSecH[i]->Misc.VirtualSize)   
            {   
                res = GetAlignedSize( peSecH[i]->VirtualAddress + peSecH[i]->Misc.VirtualSize   
                    , peH->OptionalHeader.SectionAlignment   
                    );   
            }   
            else  
            {   
                res = GetAlignedSize( peSecH[i]->VirtualAddress + peSecH[i]->SizeOfRawData   
                    , peH->OptionalHeader.SectionAlignment   
                    );   
            }   
        }   
        else if( peSecH[i]->Misc.VirtualSize < peSecH[i]->SizeOfRawData )   
        {   
            res += GetAlignedSize( peSecH[i]->SizeOfRawData   
                , peH->OptionalHeader.SectionAlignment   
                );   
        }   
        else  
        {   
            res += GetAlignedSize( peSecH[i]->Misc.VirtualSize   
                , peH->OptionalHeader.SectionAlignment   
                );   
        }// if_else   
    }// for   
       
    return res;   
}   
  
  
  
  
// 加载pe到内存并对齐所有节   
BOOL AlignPEToMem( void *Buf   
                  , long Len   
                  , PIMAGE_NT_HEADERS &peH   
                  , PIMAGE_SECTION_HEADERS &peSecH   
                  , void *&Mem   
                  , unsigned long &ImageSize)   
{   
    PIMAGE_DOS_HEADER SrcMz;// DOS头   
    PIMAGE_NT_HEADERS SrcPeH;// PE头   
    PIMAGE_SECTION_HEADERS SrcPeSecH;// 节表   
       
    SrcMz = (PIMAGE_DOS_HEADER)Buf;   
  
    if( Len < sizeof(IMAGE_DOS_HEADER) )    
        return FALSE;   
       
    if( SrcMz->e_magic != IMAGE_DOS_SIGNATURE )   
        return FALSE;   
       
    if( Len < SrcMz->e_lfanew + (long)sizeof(IMAGE_NT_HEADERS) )   
        return FALSE;   
  
    SrcPeH = (PIMAGE_NT_HEADERS)((int)SrcMz + SrcMz->e_lfanew);   
    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;   
    }   
  
  
    SrcPeSecH = (PIMAGE_SECTION_HEADERS)((int)SrcPeH + sizeof(IMAGE_NT_HEADERS));   
    ImageSize = CalcTotalImageSize( SrcMz, Len, SrcPeH, SrcPeSecH);   
  
    if( ImageSize == 0 )   
        return FALSE;   
       
    Mem = VirtualAlloc( NULL, ImageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // 分配内存   
    if( Mem != NULL )   
    {   
        // 计算需要复制的PE头字节数   
        unsigned long l = SrcPeH->OptionalHeader.SizeOfHeaders;   
        for( int i = 0; i < SrcPeH->FileHeader.NumberOfSections; ++i)   
        {   
            if( (SrcPeSecH[i]->PointerToRawData) &&   
                (SrcPeSecH[i]->PointerToRawData < l) )   
            {   
                l = SrcPeSecH[i]->PointerToRawData;   
            }   
        }   
        memmove( Mem, SrcMz, l);   
        peH = (PIMAGE_NT_HEADERS)((int)Mem + ((PIMAGE_DOS_HEADER)Mem)->e_lfanew);   
        peSecH = (PIMAGE_SECTION_HEADERS)((int)peH + sizeof(IMAGE_NT_HEADERS));   
  
        void *Pt = (void *)((unsigned long)Mem    
            + GetAlignedSize( peH->OptionalHeader.SizeOfHeaders   
            , peH->OptionalHeader.SectionAlignment)   
            );   
  
        for( i = 0; i < peH->FileHeader.NumberOfSections; ++i)   
        {   
            // 定位该节在内存中的位置   
            if(peSecH[i]->VirtualAddress)   
                Pt = (void *)((unsigned long)Mem + peSecH[i]->VirtualAddress);   
  
            if(peSecH[i]->SizeOfRawData)   
            {   
                // 复制数据到内存   
                memmove(Pt, (const void *)((unsigned long)(SrcMz) + peSecH[i]->PointerToRawData), peSecH[i]->SizeOfRawData);   
                if(peSecH[i]->Misc.VirtualSize < peSecH[i]->SizeOfRawData)   
                    Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->SizeOfRawData, peH->OptionalHeader.SectionAlignment));   
                else // pt 定位到下一节开始位置   
                    Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->Misc.VirtualSize, peH->OptionalHeader.SectionAlignment));   
            }   
            else  
            {   
                Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->Misc.VirtualSize, peH->OptionalHeader.SectionAlignment));   
            }   
        }   
    }   
    return TRUE;   
}   
  
  
  
typedef void *(__stdcall *pfVirtualAllocEx)(unsigned long, void *, unsigned long, unsigned long, unsigned long);   
pfVirtualAllocEx MyVirtualAllocEx = NULL;   
  
BOOL IsNT()   
{   
    return MyVirtualAllocEx!=NULL;   
}   
  
// 生成外壳程序命令行   
char *PrepareShellExe(char *CmdParam, unsigned long BaseAddr, unsigned long ImageSize)   
{   
    if(IsNT())   
    {   
        char *Buf = new char[256];   
        memset(Buf, 0, 256);   
        GetModuleFileName(0, Buf, 256);   
        strcat(Buf, CmdParam);   
        return Buf; // 请记得释放内存;-)   
    }   
    else  
    {   
        // Win98下的处理请参考原文;-)   
        // http://community.csdn.net/Expert/topic/4416/4416252.xml?temp=8.709133E-03   
        return NULL;   
    }   
}   
  
// 是否包含可重定向列表   
BOOL HasRelocationTable(PIMAGE_NT_HEADERS peH)   
{   
    return (peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)   
        && (peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);   
}   
  
  
  
  
#pragma pack(push, 1)   
typedef struct{   
    unsigned long VirtualAddress;   
    unsigned long SizeOfBlock;   
} *PImageBaseRelocation;   
#pragma pack(pop)   
  
// 重定向PE用到的地址   
void DoRelocation(PIMAGE_NT_HEADERS peH, void *OldBase, void *NewBase)   
{   
    unsigned long Delta = (unsigned long)NewBase - peH->OptionalHeader.ImageBase;   
    PImageBaseRelocation p = (PImageBaseRelocation)((unsigned long)OldBase    
        + peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);   
    while(p->VirtualAddress + p->SizeOfBlock)   
    {   
        unsigned short *pw = (unsigned short *)((int)p + sizeof(*p));   
        for(unsigned int i=1; i <= (p->SizeOfBlock - sizeof(*p)) / 2; ++i)   
        {   
            if((*pw) & 0xF000 == 0x3000){   
                unsigned long *t = (unsigned long *)((unsigned long)(OldBase) + p->VirtualAddress + ((*pw) & 0x0FFF));   
                *t += Delta;   
            }   
            ++pw;   
        }   
        p = (PImageBaseRelocation)pw;   
    }   
}   
  
// 卸载原外壳占用内存   
BOOL UnloadShell(HANDLE ProcHnd, unsigned long BaseAddr)   
{   
    typedef unsigned long (__stdcall *pfZwUnmapViewOfSection)(unsigned long, unsigned long);   
    pfZwUnmapViewOfSection ZwUnmapViewOfSection = NULL;   
    BOOL res = FALSE;   
    HMODULE m = LoadLibrary("ntdll.dll");   
    if(m){   
        ZwUnmapViewOfSection = (pfZwUnmapViewOfSection)GetProcAddress(m, "ZwUnmapViewOfSection");   
        if(ZwUnmapViewOfSection)   
            res = (ZwUnmapViewOfSection((unsigned long)ProcHnd, BaseAddr) == 0);   
        FreeLibrary(m);   
    }   
    return res;   
}   
  
// 创建外壳进程并获取其基址、大小和当前运行状态   
BOOL CreateChild(char *Cmd, CONTEXT &Ctx, HANDLE &ProcHnd, HANDLE &ThrdHnd,    
                 unsigned long &ProcId, unsigned long &BaseAddr, unsigned long &ImageSize)   
{   
    STARTUPINFOA si;   
    PROCESS_INFORMATION pi;   
    unsigned long old;   
    MEMORY_BASIC_INFORMATION MemInfo;   
    memset(&si, 0, sizeof(si));   
    memset(&pi, 0, sizeof(pi));   
    si.cb = sizeof(si);   
       
    BOOL res = CreateProcess(NULL, Cmd, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); // 以挂起方式运行进程;   
    if(res){   
        ProcHnd = pi.hProcess;   
        ThrdHnd = pi.hThread;   
        ProcId = pi.dwProcessId;   
        // 获取外壳进程运行状态,[ctx.Ebx+8]内存处存的是外壳进程的加载基址,ctx.Eax存放有外壳进程的入口地址   
        Ctx.ContextFlags = CONTEXT_FULL;   
        GetThreadContext(ThrdHnd, &Ctx);   
        ReadProcessMemory(ProcHnd, (void *)(Ctx.Ebx+8), &BaseAddr, sizeof(unsigned long), &old); // 读取加载基址   
        void *p = (void *)BaseAddr;   
        // 计算外壳进程占有的内存   
        while(VirtualQueryEx(ProcHnd, p, &MemInfo, sizeof(MemInfo)))   
        {   
            if(MemInfo.State = MEM_FREE) break;   
            p = (void *)((unsigned long)p + MemInfo.RegionSize);   
        }   
        ImageSize = (unsigned long)p - (unsigned long)BaseAddr;   
    }   
    return res;   
}   
  
// 创建外壳进程并用目标进程替换它然后执行   
HANDLE AttachPE(char *CmdParam, PIMAGE_NT_HEADERS peH, PIMAGE_SECTION_HEADERS peSecH,    
                void *Ptr, unsigned long ImageSize, unsigned long &ProcId)   
{   
    HANDLE res = INVALID_HANDLE_VALUE;   
    CONTEXT Ctx;   
    HANDLE Thrd;   
    unsigned long Addr, Size;   
    char *s = PrepareShellExe(CmdParam, peH->OptionalHeader.ImageBase, ImageSize);   
    if(s==NULL) return res;   
    if(CreateChild(s, Ctx, res, Thrd, ProcId, Addr, Size)){   
        void *p = NULL;   
        unsigned long old;   
        if((peH->OptionalHeader.ImageBase == Addr) && (Size >= ImageSize)){// 外壳进程可以容纳目标进程并且加载地址一致   
            p = (void *)Addr;   
            VirtualProtectEx(res, p, Size, PAGE_EXECUTE_READWRITE, &old);   
        }   
        else if(IsNT()){   
            if(UnloadShell(res, Addr)){// 卸载外壳进程占有内存   
                p = MyVirtualAllocEx((unsigned long)res, (void *)peH->OptionalHeader.ImageBase, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);   
            }   
            if((p == NULL) && HasRelocationTable(peH)){// 分配内存失败并且目标进程支持重定向   
                p = MyVirtualAllocEx((unsigned long)res, NULL, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);   
                if(p) DoRelocation(peH, Ptr, p); // 重定向   
            }   
        }   
        if(p){   
            WriteProcessMemory(res, (void *)(Ctx.Ebx+8), &p, sizeof(DWORD), &old); // 重置目标进程运行环境中的基址   
            peH->OptionalHeader.ImageBase = (unsigned long)p;   
            if(WriteProcessMemory(res, p, Ptr, ImageSize, &old)){// 复制PE数据到目标进程   
                Ctx.ContextFlags = CONTEXT_FULL;   
                if((unsigned long)p == Addr)   
                    Ctx.Eax = peH->OptionalHeader.ImageBase + peH->OptionalHeader.AddressOfEntryPoint; // 重置运行环境中的入口地址   
                else  
                    Ctx.Eax = (unsigned long)p + peH->OptionalHeader.AddressOfEntryPoint;   
                SetThreadContext(Thrd, &Ctx);// 更新运行环境   
                ResumeThread(Thrd);// 执行   
                CloseHandle(Thrd);   
            }   
            else{// 加载失败,杀掉外壳进程   
                TerminateProcess(res, 0);   
                CloseHandle(Thrd);   
                CloseHandle(res);   
                res = INVALID_HANDLE_VALUE;   
            }   
        }   
        else{// 加载失败,杀掉外壳进程   
            TerminateProcess(res, 0);   
            CloseHandle(Thrd);   
            CloseHandle(res);   
            res = INVALID_HANDLE_VALUE;   
        }   
    }   
    delete[] s;   
    return res;   
}   
  
  
  
  
 /*******************************************************\  
{ ******************************************************* }  
{ *                 从内存中加载并运行exe               * }  
{ ******************************************************* }  
{ * 参数:                                                }  
{ * Buffer: 内存中的exe地址                               }  
{ * Len: 内存中exe占用长度                                }  
{ * CmdParam: 命令行参数(不包含exe文件名的剩余命令行参数)}  
{ * ProcessId: 返回的进程Id                               }  
{ * 返回值: 如果成功则返回进程的Handle(ProcessHandle),   }  
{            如果失败则返回INVALID_HANDLE_VALUE           }  
{ ******************************************************* }  
 \*******************************************************/  
HANDLE MemExecute(void *ABuffer, long Len, char *CmdParam, unsigned long *ProcessId)   
{   
    HANDLE res = INVALID_HANDLE_VALUE;   
    PIMAGE_NT_HEADERS peH;   
    PIMAGE_SECTION_HEADERS peSecH;   
    void *Ptr;   
    unsigned long peSz;   
    if(AlignPEToMem(ABuffer, Len, peH, peSecH, Ptr, peSz))   
    {   
        res = AttachPE(CmdParam, peH, peSecH, Ptr, peSz, *ProcessId);   
        VirtualFree(Ptr, peSz, MEM_DECOMMIT);   
    }   
    return res;   
}   
  
// 初始化   
class CInit   
{   
public:   
    CInit()   
    {   
        MyVirtualAllocEx = (pfVirtualAllocEx)GetProcAddress(GetModuleHandle("Kernel32.dll"), "VirtualAllocEx");   
    }   
}Init;   
  
  
  
  
int APIENTRY WinMain(HINSTANCE hInstance,   
                     HINSTANCE hPrevInstance,   
                     LPSTR     lpCmdLine,   
                     int       nCmdShow)   
{   
    HANDLE hFile = NULL;   
    hFile = ::CreateFile( "f:\\SourceFromCsdn2.exe"  
        , FILE_ALL_ACCESS   
        , 0   
        , NULL   
        , OPEN_EXISTING   
        , FILE_ATTRIBUTE_NORMAL   
        , NULL   
        );   
    if( hFile == INVALID_HANDLE_VALUE )   
        return -1;   
  
    ::SetFilePointer( hFile, 0, NULL, FILE_BEGIN);   
    DWORD dwFileSize = ::GetFileSize( hFile, NULL);   
  
    LPBYTE pBuf = new BYTE[dwFileSize];   
    memset( pBuf, 0, dwFileSize);   
  
    DWORD dwNumberOfBytesRead = 0;   
    ::ReadFile( hFile   
        , pBuf   
        , dwFileSize   
        , &dwNumberOfBytesRead   
        , NULL   
        );   
  
    ::CloseHandle(hFile);   
       
    unsigned long ulProcessId = 0;   
    MemExecute( pBuf, dwFileSize, "", &ulProcessId);   
    delete[] pBuf;   
  
       
    return 0;   
}

/**********************************************************/

typedef IMAGE_SECTION_HEADER ( * PIMAGE_SECTION_HEADERS)[ 1 ];   
  
//  计算对齐后的大小   
unsigned  long  GetAlignedSize(unsigned  long  Origin, unsigned  long  Alignment)   
{   
     return  (Origin  +  Alignment  -   1 )  /  Alignment  *  Alignment;   
}    
  
//  计算加载pe并对齐需要占用多少内存   
//  未直接使用OptionalHeader.SizeOfImage作为结果是因为据说有的编译器生成的exe这个值会填0   
unsigned  long  CalcTotalImageSize(PIMAGE_DOS_HEADER MzH   
                                 , unsigned  long  FileLen   
                                 , PIMAGE_NT_HEADERS peH   
                                 , PIMAGE_SECTION_HEADERS peSecH)   
{   
    unsigned  long  res;   
     //  计算pe头的大小   
    res  =  GetAlignedSize( peH -> OptionalHeader.SizeOfHeaders , peH -> OptionalHeader.SectionAlignment);   
  
     //  计算所有节的大小   
     for (  int  i  =   0 ; i  <  peH -> FileHeader.NumberOfSections;  ++ i)   
     {   
         //  超出文件范围   
         if (peSecH[i] -> PointerToRawData  +  peSecH[i] -> SizeOfRawData  >  FileLen)  
         {
             return   0 ;   
        }
         else   if (peSecH[i] -> VirtualAddress) // 计算对齐后某节的大小   
         {   
             if (peSecH[i] -> Misc.VirtualSize)   
             {   
                res  =  GetAlignedSize( peSecH[i] -> VirtualAddress  +  peSecH[i] -> Misc.VirtualSize   
                    , peH -> OptionalHeader.SectionAlignment);   
            }    
             else   
             {   
                res  =  GetAlignedSize( peSecH[i] -> VirtualAddress  +  peSecH[i] -> SizeOfRawData   
                    , peH -> OptionalHeader.SectionAlignment);   
            }    
        }    
         else   if ( peSecH[i] -> Misc.VirtualSize  <  peSecH[i] -> SizeOfRawData )   
         {   
            res  +=  GetAlignedSize( peSecH[i] -> SizeOfRawData   
                , peH -> OptionalHeader.SectionAlignment);   
        }    
         else   
         {   
            res  +=  GetAlignedSize( peSecH[i] -> Misc.VirtualSize   
                , peH -> OptionalHeader.SectionAlignment);   
        } //  if_else   
    } //  for   
       
     return  res;   
}    
  
  
  
  
//  加载pe到内存并对齐所有节   
BOOL AlignPEToMem(  void   * Buf   
                  ,  long  Len   
                  , PIMAGE_NT_HEADERS  & peH   
                  , PIMAGE_SECTION_HEADERS  & peSecH   
                  ,  void   *& Mem   
                  , unsigned  long   & ImageSize)   
{   
    PIMAGE_DOS_HEADER SrcMz; //  DOS头   
    PIMAGE_NT_HEADERS SrcPeH; //  PE头   
    PIMAGE_SECTION_HEADERS SrcPeSecH; //  节表   
       
    SrcMz  =  (PIMAGE_DOS_HEADER)Buf;   
  
     if ( Len  <   sizeof (IMAGE_DOS_HEADER) )    
         return  FALSE;   
       
     if ( SrcMz -> e_magic  !=  IMAGE_DOS_SIGNATURE )   
         return  FALSE;   
       
     if ( Len  <  SrcMz -> e_lfanew  +  ( long ) sizeof (IMAGE_NT_HEADERS) )   
         return  FALSE;   
  
    SrcPeH  =  (PIMAGE_NT_HEADERS)(( int )SrcMz  +  SrcMz -> e_lfanew);   
     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;   
    }    
  
  
    SrcPeSecH  =  (PIMAGE_SECTION_HEADERS)(( int )SrcPeH  +   sizeof (IMAGE_NT_HEADERS));   
    ImageSize  =  CalcTotalImageSize( SrcMz, Len, SrcPeH, SrcPeSecH);   
  
     if ( ImageSize  ==   0  )   
         return  FALSE;   
       
    Mem  =  VirtualAlloc( NULL, ImageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);  //  分配内存   
     if ( Mem  !=  NULL )   
     {   
         //  计算需要复制的PE头字节数   
        unsigned  long  l  =  SrcPeH -> OptionalHeader.SizeOfHeaders;   
         for (  int  i  =   0 ; i  <  SrcPeH -> FileHeader.NumberOfSections;  ++ i)   
         {   
             if ( (SrcPeSecH[i] -> PointerToRawData)  &&    
                (SrcPeSecH[i] -> PointerToRawData  <  l) )   
             {   
                l  =  SrcPeSecH[i] -> PointerToRawData;   
            }    
        }    
        memmove( Mem, SrcMz, l);   
        peH  =  (PIMAGE_NT_HEADERS)(( int )Mem  +  ((PIMAGE_DOS_HEADER)Mem) -> e_lfanew);   
        peSecH  =  (PIMAGE_SECTION_HEADERS)(( int )peH  +   sizeof (IMAGE_NT_HEADERS));   
  
         void   * Pt  =  ( void   * )((unsigned  long )Mem    
             +  GetAlignedSize( peH -> OptionalHeader.SizeOfHeaders   
            , peH -> OptionalHeader.SectionAlignment)   
            );   
  
         for ( i  =   0 ; i  <  peH -> FileHeader.NumberOfSections;  ++ i)   
         {   
             //  定位该节在内存中的位置   
             if (peSecH[i] -> VirtualAddress)   
                Pt  =  ( void   * )((unsigned  long )Mem  +  peSecH[i] -> VirtualAddress);   
  
             if (peSecH[i] -> SizeOfRawData)   
             {   
                 //  复制数据到内存   
                memmove(Pt, ( const   void   * )((unsigned  long )(SrcMz)  +  peSecH[i] -> PointerToRawData), peSecH[i] -> SizeOfRawData);   
                 if (peSecH[i] -> Misc.VirtualSize  <  peSecH[i] -> SizeOfRawData)   
                    Pt  =  ( void   * )((unsigned  long )Pt  +  GetAlignedSize(peSecH[i] -> SizeOfRawData, peH -> OptionalHeader.SectionAlignment));   
                 else   //  pt 定位到下一节开始位置   
                    Pt  =  ( void   * )((unsigned  long )Pt  +  GetAlignedSize(peSecH[i] -> Misc.VirtualSize, peH -> OptionalHeader.SectionAlignment));   
            }    
             else   
             {   
                Pt  =  ( void   * )((unsigned  long )Pt  +  GetAlignedSize(peSecH[i] -> Misc.VirtualSize, peH -> OptionalHeader.SectionAlignment));   
            }    
        }    
    }    
     return  TRUE;   
}    
  
  
  
typedef  void   * (__stdcall  * pfVirtualAllocEx)(unsigned  long ,  void   * , unsigned  long , unsigned  long , unsigned  long );   
pfVirtualAllocEx MyVirtualAllocEx  =  NULL;   
  
BOOL IsNT()   
{   
     return  MyVirtualAllocEx != NULL;   
}    
  
//  生成外壳程序命令行   
char   * PrepareShellExe( char   * CmdParam, unsigned  long  BaseAddr, unsigned  long  ImageSize)   
{   
     if (IsNT())   
     {   
         char   * Buf  =   new   char [ 256 ];   
        memset(Buf,  0 ,  256 );   
        GetModuleFileName( 0 , Buf,  256 );   
        strcat(Buf, CmdParam);   
         return  Buf;  //  请记得释放内存;-)   
    }    
     else   
     {   
         //  Win98下的处理请参考原文;-)   
         //   http://community.csdn.net/Expert/topic/4416/4416252.xml?temp=8.709133E-03    
         return  NULL;   
    }    
}    
  
//  是否包含可重定向列表   
BOOL HasRelocationTable(PIMAGE_NT_HEADERS peH)   
{   
     return  (peH -> OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)   
         &&  (peH -> OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);   
}    
  
  
  
  
#pragma pack(push,  1 )   
typedef  struct {   
    unsigned  long  VirtualAddress;   
    unsigned  long  SizeOfBlock;   
}   * PImageBaseRelocation;   
#pragma pack(pop)   
  
//  重定向PE用到的地址   
void  DoRelocation(PIMAGE_NT_HEADERS peH,  void   * OldBase,  void   * NewBase)   
{   
    unsigned  long  Delta  =  (unsigned  long )NewBase  -  peH -> OptionalHeader.ImageBase;   
    PImageBaseRelocation p  =  (PImageBaseRelocation)((unsigned  long )OldBase    
         +  peH -> OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);   
     while (p -> VirtualAddress  +  p -> SizeOfBlock)   
     {   
        unsigned  short   * pw  =  (unsigned  short   * )(( int )p  +   sizeof ( * p));   
         for (unsigned  int  i = 1 ; i  <=  (p -> SizeOfBlock  -   sizeof ( * p))  /   2 ;  ++ i)   
         {   
             if (( * pw)  &   0xF000   ==   0x3000 ) {   
                unsigned  long   * t  =  (unsigned  long   * )((unsigned  long )(OldBase)  +  p -> VirtualAddress  +  (( * pw)  &   0x0FFF ));   
                 * t  +=  Delta;   
            }    
             ++ pw;   
        }    
        p  =  (PImageBaseRelocation)pw;   
    }    
}    
  
//  卸载原外壳占用内存   
BOOL UnloadShell(HANDLE ProcHnd, unsigned  long  BaseAddr)   
{   
    typedef unsigned  long  (__stdcall  * pfZwUnmapViewOfSection)(unsigned  long , unsigned  long );   
    pfZwUnmapViewOfSection ZwUnmapViewOfSection  =  NULL;   
    BOOL res  =  FALSE;   
    HMODULE m  =  LoadLibrary( " ntdll.dll " );   
     if (m) {   
        ZwUnmapViewOfSection  =  (pfZwUnmapViewOfSection)GetProcAddress(m,  " ZwUnmapViewOfSection " );   
         if (ZwUnmapViewOfSection)   
            res  =  (ZwUnmapViewOfSection((unsigned  long )ProcHnd, BaseAddr)  ==   0 );   
        FreeLibrary(m);   
    }    
     return  res;   
}    
  
//  创建外壳进程并获取其基址、大小和当前运行状态   
BOOL CreateChild( char   * Cmd, CONTEXT  & Ctx, HANDLE  & ProcHnd, HANDLE  & ThrdHnd,    
                 unsigned  long   & ProcId, unsigned  long   & BaseAddr, unsigned  long   & ImageSize)   
{   
    STARTUPINFOA si;   
    PROCESS_INFORMATION pi;   
    unsigned  long  old;   
    MEMORY_BASIC_INFORMATION MemInfo;   
    memset( & si,  0 ,  sizeof (si));   
    memset( & pi,  0 ,  sizeof (pi));   
    si.cb  =   sizeof (si);   
       
    BOOL res  =  CreateProcess(NULL, Cmd, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL,  & si,  & pi);  //  以挂起方式运行进程;   
     if (res) {   
        ProcHnd  =  pi.hProcess;   
        ThrdHnd  =  pi.hThread;   
        ProcId  =  pi.dwProcessId;   
         //  获取外壳进程运行状态,[ctx.Ebx+8]内存处存的是外壳进程的加载基址,ctx.Eax存放有外壳进程的入口地址   
        Ctx.ContextFlags  =  CONTEXT_FULL;   
        GetThreadContext(ThrdHnd,  & Ctx);   
        ReadProcessMemory(ProcHnd, ( void   * )(Ctx.Ebx + 8 ),  & BaseAddr,  sizeof (unsigned  long ),  & old);  //  读取加载基址   
         void   * p  =  ( void   * )BaseAddr;   
         //  计算外壳进程占有的内存   
         while (VirtualQueryEx(ProcHnd, p,  & MemInfo,  sizeof (MemInfo)))   
         {   
             if (MemInfo.State  =  MEM_FREE)  break ;   
            p  =  ( void   * )((unsigned  long )p  +  MemInfo.RegionSize);   
        }    
        ImageSize  =  (unsigned  long )p  -  (unsigned  long )BaseAddr;   
    }    
     return  res;   
}    
  
//  创建外壳进程并用目标进程替换它然后执行   
HANDLE AttachPE( char   * CmdParam, PIMAGE_NT_HEADERS peH, PIMAGE_SECTION_HEADERS peSecH,    
                 void   * Ptr, unsigned  long  ImageSize, unsigned  long   & ProcId)   
{   
    HANDLE res  =  INVALID_HANDLE_VALUE;   
    CONTEXT Ctx;   
    HANDLE Thrd;   
    unsigned  long  Addr, Size;   
     char   * s  =  PrepareShellExe(CmdParam, peH -> OptionalHeader.ImageBase, ImageSize);   
     if (s == NULL)  return  res;   
     if (CreateChild(s, Ctx, res, Thrd, ProcId, Addr, Size)) {   
         void   * p  =  NULL;   
        unsigned  long  old;   
         if ((peH -> OptionalHeader.ImageBase  ==  Addr)  &&  (Size  >=  ImageSize)) { //  外壳进程可以容纳目标进程并且加载地址一致   
            p  =  ( void   * )Addr;   
            VirtualProtectEx(res, p, Size, PAGE_EXECUTE_READWRITE,  & old);   
        }    
         else   if (IsNT()) {   
             if (UnloadShell(res, Addr)) { //  卸载外壳进程占有内存   
                p  =  MyVirtualAllocEx((unsigned  long )res, ( void   * )peH -> OptionalHeader.ImageBase, ImageSize, MEM_RESERVE  |  MEM_COMMIT, PAGE_EXECUTE_READWRITE);   
            }    
             if ((p  ==  NULL)  &&  HasRelocationTable(peH)) { //  分配内存失败并且目标进程支持重定向   
                p  =  MyVirtualAllocEx((unsigned  long )res, NULL, ImageSize, MEM_RESERVE  |  MEM_COMMIT, PAGE_EXECUTE_READWRITE);   
                 if (p) DoRelocation(peH, Ptr, p);  //  重定向   
            }    
        }    
         if (p) {   
            WriteProcessMemory(res, ( void   * )(Ctx.Ebx + 8 ),  & p,  sizeof (DWORD),  & old);  //  重置目标进程运行环境中的基址   
            peH -> OptionalHeader.ImageBase  =  (unsigned  long )p;   
             if (WriteProcessMemory(res, p, Ptr, ImageSize,  & old)) { //  复制PE数据到目标进程   
                Ctx.ContextFlags  =  CONTEXT_FULL;   
                 if ((unsigned  long )p  ==  Addr)   
                    Ctx.Eax  =  peH -> OptionalHeader.ImageBase  +  peH -> OptionalHeader.AddressOfEntryPoint;  //  重置运行环境中的入口地址   
                 else   
                    Ctx.Eax  =  (unsigned  long )p  +  peH -> OptionalHeader.AddressOfEntryPoint;   
                SetThreadContext(Thrd,  & Ctx); //  更新运行环境   
                ResumeThread(Thrd); //  执行   
                CloseHandle(Thrd);   
            }    
             else { //  加载失败,杀掉外壳进程   
                TerminateProcess(res,  0 );   
                CloseHandle(Thrd);   
                CloseHandle(res);   
                res  =  INVALID_HANDLE_VALUE;   
            }    
        }    
         else { //  加载失败,杀掉外壳进程   
            TerminateProcess(res,  0 );   
            CloseHandle(Thrd);   
            CloseHandle(res);   
            res  =  INVALID_HANDLE_VALUE;   
        }    
    }    
    delete[] s;   
     return  res;   
}    
  
  
  
  
  /**/ /* ******************************************************\  
{ ******************************************************* }  
{ *                 从内存中加载并运行exe               * }  
{ ******************************************************* }  
{ * 参数:                                                }  
{ * Buffer: 内存中的exe地址                               }  
{ * Len: 内存中exe占用长度                                }  
{ * CmdParam: 命令行参数(不包含exe文件名的剩余命令行参数)}  
{ * ProcessId: 返回的进程Id                               }  
{ * 返回值: 如果成功则返回进程的Handle(ProcessHandle),   }  
{            如果失败则返回INVALID_HANDLE_VALUE           }  
{ ******************************************************* }  
 \****************************************************** */   
HANDLE MemExecute( void   * ABuffer,  long  Len,  char   * CmdParam, unsigned  long   * ProcessId)   
{   
    HANDLE res  =  INVALID_HANDLE_VALUE;   
    PIMAGE_NT_HEADERS peH;   
    PIMAGE_SECTION_HEADERS peSecH;   
     void   * Ptr;   
    unsigned  long  peSz;   
     if (AlignPEToMem(ABuffer, Len, peH, peSecH, Ptr, peSz))   
     {   
        res  =  AttachPE(CmdParam, peH, peSecH, Ptr, peSz,  * ProcessId);   
        VirtualFree(Ptr, peSz, MEM_DECOMMIT);   
    }    
     return  res;   
}    
  
//  初始化   
class  CInit   
{   
public :   
    CInit()   
     {   
        MyVirtualAllocEx  =  (pfVirtualAllocEx)GetProcAddress(GetModuleHandle( " Kernel32.dll " ),  " VirtualAllocEx " );   
    }    
} Init;   
  
  
  
  



int  main( int  argc,  char *  argv[])
{
    FILE *  fp;
    fp  =  fopen( " E:\\CProject\\DBGVIEW.EXE " , " rb " );

     if  ( fp )
     {

        fseek(fp, 0l ,SEEK_END);
         int  file_size = ftell(fp); /* 获取文件长度 */
        fseek(fp, 0l ,SEEK_SET); /* 回到文件头部 */    
        
        
        LPBYTE pBuf  =   new  BYTE[file_size];   
        memset( pBuf,  0 , file_size);   

        fread(pBuf,file_size, 1 ,fp);

        DWORD id  =  GetCurrentProcessId();
        unsigned  long  ulProcessId  =   0 ;   
        MemExecute( pBuf, file_size,  "" ,  & ulProcessId);   
        delete[] pBuf;   
        
    }   
    
     return   0 ;
}


Powered by 兔八哥极品软件 苏ICP备12049267号 sitemap