在内存中运行可执行程序

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


 
 
  1  typedef IMAGE_SECTION_HEADER (  *  PIMAGE_SECTION_HEADERS)[  1  ];      2       3    //   计算对齐后的大小       4   unsigned   long   GetAlignedSize(unsigned   long   Origin, unsigned   long   Alignment)      5    {      6        return   (Origin   +   Alignment   -     1  )   /   Alignment   *   Alignment;      7  }       8       9    //   计算加载pe并对齐需要占用多少内存     10    //   未直接使用OptionalHeader.SizeOfImage作为结果是因为据说有的编译器生成的exe这个值会填0      11   unsigned   long   CalcTotalImageSize(PIMAGE_DOS_HEADER MzH     12                                   , unsigned   long   FileLen     13                                   , PIMAGE_NT_HEADERS peH     14                                   , PIMAGE_SECTION_HEADERS peSecH)     15    {     16      unsigned   long   res;     17        //   计算pe头的大小      18       res   =   GetAlignedSize( peH  ->  OptionalHeader.SizeOfHeaders , peH  ->  OptionalHeader.SectionAlignment);     19      20        //   计算所有节的大小      21         for  (   int   i   =     0  ; i   <   peH  ->  FileHeader.NumberOfSections;   ++  i)     22        {     23            //   超出文件范围      24             if  (peSecH[i]  ->  PointerToRawData   +   peSecH[i]  ->  SizeOfRawData   >   FileLen)    25            {  26                return     0  ;     27          }   28            else     if  (peSecH[i]  ->  VirtualAddress)  //  计算对齐后某节的大小      29              {     30                if  (peSecH[i]  ->  Misc.VirtualSize)     31                {     32                  res   =   GetAlignedSize( peSecH[i]  ->  VirtualAddress   +   peSecH[i]  ->  Misc.VirtualSize     33                      , peH  ->  OptionalHeader.SectionAlignment);     34              }      35                else      36                {     37                  res   =   GetAlignedSize( peSecH[i]  ->  VirtualAddress   +   peSecH[i]  ->  SizeOfRawData     38                      , peH  ->  OptionalHeader.SectionAlignment);     39              }      40          }      41            else     if  ( peSecH[i]  ->  Misc.VirtualSize   <   peSecH[i]  ->  SizeOfRawData )     42            {     43              res   +=   GetAlignedSize( peSecH[i]  ->  SizeOfRawData     44                  , peH  ->  OptionalHeader.SectionAlignment);     45          }      46            else      47            {     48              res   +=   GetAlignedSize( peSecH[i]  ->  Misc.VirtualSize     49                  , peH  ->  OptionalHeader.SectionAlignment);     50          }  //   if_else      51       }  //   for      52            53        return   res;     54  }      55      56      57      58      59    //   加载pe到内存并对齐所有节      60   BOOL AlignPEToMem(   void     *  Buf     61                    ,   long   Len     62                    , PIMAGE_NT_HEADERS   &  peH     63                    , PIMAGE_SECTION_HEADERS   &  peSecH     64                    ,   void     *&  Mem     65                    , unsigned   long     &  ImageSize)     66    {     67      PIMAGE_DOS_HEADER SrcMz;  //   DOS头      68       PIMAGE_NT_HEADERS SrcPeH;  //   PE头      69       PIMAGE_SECTION_HEADERS SrcPeSecH;  //   节表      70            71      SrcMz   =   (PIMAGE_DOS_HEADER)Buf;     72      73        if  ( Len   <     sizeof  (IMAGE_DOS_HEADER) )      74            return   FALSE;     75           76        if  ( SrcMz  ->  e_magic   !=   IMAGE_DOS_SIGNATURE )     77            return   FALSE;     78           79        if  ( Len   <   SrcMz  ->  e_lfanew   +   (  long  )  sizeof  (IMAGE_NT_HEADERS) )     80            return   FALSE;     81      82      SrcPeH   =   (PIMAGE_NT_HEADERS)((  int  )SrcMz   +   SrcMz  ->  e_lfanew);     83        if  ( SrcPeH  ->  Signature   !=   IMAGE_NT_SIGNATURE )     84            return   FALSE;     85      86        if  ( (SrcPeH  ->  FileHeader.Characteristics   &   IMAGE_FILE_DLL)   ||       87          (SrcPeH  ->  FileHeader.Characteristics   &   IMAGE_FILE_EXECUTABLE_IMAGE   ==     0  )   ||       88          (SrcPeH  ->  FileHeader.SizeOfOptionalHeader   !=     sizeof  (IMAGE_OPTIONAL_HEADER)) )     89        {     90            return   FALSE;     91      }      92      93      94      SrcPeSecH   =   (PIMAGE_SECTION_HEADERS)((  int  )SrcPeH   +     sizeof  (IMAGE_NT_HEADERS));     95      ImageSize   =   CalcTotalImageSize( SrcMz, Len, SrcPeH, SrcPeSecH);     96      97        if  ( ImageSize   ==     0   )     98            return   FALSE;     99          100      Mem   =   VirtualAlloc( NULL, ImageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);   //   分配内存     101         if  ( Mem   !=   NULL )    102        {    103            //   计算需要复制的PE头字节数     104           unsigned   long   l   =   SrcPeH  ->  OptionalHeader.SizeOfHeaders;    105            for  (   int   i   =     0  ; i   <   SrcPeH  ->  FileHeader.NumberOfSections;   ++  i)    106            {    107                if  ( (SrcPeSecH[i]  ->  PointerToRawData)   &&      108                  (SrcPeSecH[i]  ->  PointerToRawData   <   l) )    109                {    110                  l   =   SrcPeSecH[i]  ->  PointerToRawData;    111              }     112          }     113          memmove( Mem, SrcMz, l);    114          peH   =   (PIMAGE_NT_HEADERS)((  int  )Mem   +   ((PIMAGE_DOS_HEADER)Mem)  ->  e_lfanew);    115          peSecH   =   (PIMAGE_SECTION_HEADERS)((  int  )peH   +     sizeof  (IMAGE_NT_HEADERS));    116     117            void     *  Pt   =   (  void     *  )((unsigned   long  )Mem     118                +   GetAlignedSize( peH  ->  OptionalHeader.SizeOfHeaders    119              , peH  ->  OptionalHeader.SectionAlignment)    120              );    121     122            for  ( i   =     0  ; i   <   peH  ->  FileHeader.NumberOfSections;   ++  i)    123            {    124                //   定位该节在内存中的位置     125                 if  (peSecH[i]  ->  VirtualAddress)    126                  Pt   =   (  void     *  )((unsigned   long  )Mem   +   peSecH[i]  ->  VirtualAddress);    127     128                if  (peSecH[i]  ->  SizeOfRawData)    129                {    130                    //   复制数据到内存     131                   memmove(Pt, (  const     void     *  )((unsigned   long  )(SrcMz)   +   peSecH[i]  ->  PointerToRawData), peSecH[i]  ->  SizeOfRawData);    132                    if  (peSecH[i]  ->  Misc.VirtualSize   <   peSecH[i]  ->  SizeOfRawData)    133                      Pt   =   (  void     *  )((unsigned   long  )Pt   +   GetAlignedSize(peSecH[i]  ->  SizeOfRawData, peH  ->  OptionalHeader.SectionAlignment));    134                    else     //   pt 定位到下一节开始位置     135                       Pt   =   (  void     *  )((unsigned   long  )Pt   +   GetAlignedSize(peSecH[i]  ->  Misc.VirtualSize, peH  ->  OptionalHeader.SectionAlignment));    136              }     137                else     138                {    139                  Pt   =   (  void     *  )((unsigned   long  )Pt   +   GetAlignedSize(peSecH[i]  ->  Misc.VirtualSize, peH  ->  OptionalHeader.SectionAlignment));    140              }     141          }     142      }     143        return   TRUE;    144  }     145     146     147     148  typedef   void     *  (__stdcall   *  pfVirtualAllocEx)(unsigned   long  ,   void     *  , unsigned   long  , unsigned   long  , unsigned   long  );    149  pfVirtualAllocEx MyVirtualAllocEx   =   NULL;    150     151  BOOL IsNT()    152    {    153        return   MyVirtualAllocEx  !=  NULL;    154  }     155     156    //   生成外壳程序命令行     157    char     *  PrepareShellExe(  char     *  CmdParam, unsigned   long   BaseAddr, unsigned   long   ImageSize)    158    {    159        if  (IsNT())    160        {    161            char     *  Buf   =     new     char  [  256  ];    162          memset(Buf,   0  ,   256  );    163          GetModuleFileName(  0  , Buf,   256  );    164          strcat(Buf, CmdParam);    165            return   Buf;   //   请记得释放内存;-)     166       }     167        else     168        {    169            //   Win98 170 171             return   NULL;    172      }     173  }     174     175    //   是否包含可重定向列表     176   BOOL HasRelocationTable(PIMAGE_NT_HEADERS peH)    177    {    178        return   (peH  ->  OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)    179            &&   (peH  ->  OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);    180  }     181     182     183     184     185  #pragma pack(push,   1  )    186  typedef   struct   {    187      unsigned   long   VirtualAddress;    188      unsigned   long   SizeOfBlock;    189  }    *  PImageBaseRelocation;    190  #pragma pack(pop)    191     192    //   重定向PE用到的地址     193    void   DoRelocation(PIMAGE_NT_HEADERS peH,   void     *  OldBase,   void     *  NewBase)    194    {    195      unsigned   long   Delta   =   (unsigned   long  )NewBase   -   peH  ->  OptionalHeader.ImageBase;    196      PImageBaseRelocation p   =   (PImageBaseRelocation)((unsigned   long  )OldBase     197            +   peH  ->  OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);    198        while  (p  ->  VirtualAddress   +   p  ->  SizeOfBlock)    199        {    200          unsigned   short     *  pw   =   (unsigned   short     *  )((  int  )p   +     sizeof  (  *  p));    201            for  (unsigned   int   i  =   1  ; i   <=   (p  ->  SizeOfBlock   -     sizeof  (  *  p))   /     2  ;   ++  i)    202            {    203                if  ((  *  pw)   &     0xF000     ==     0x3000  )  {    204                  unsigned   long     *  t   =   (unsigned   long     *  )((unsigned   long  )(OldBase)   +   p  ->  VirtualAddress   +   ((  *  pw)   &     0x0FFF  ));    205                    *  t   +=   Delta;    206              }     207                ++  pw;    208          }     209          p   =   (PImageBaseRelocation)pw;    210      }     211  }     212     213    //   卸载原外壳占用内存     214   BOOL UnloadShell(HANDLE ProcHnd, unsigned   long   BaseAddr)    215    {    216      typedef unsigned   long   (__stdcall   *  pfZwUnmapViewOfSection)(unsigned   long  , unsigned   long  );    217      pfZwUnmapViewOfSection ZwUnmapViewOfSection   =   NULL;    218      BOOL res   =   FALSE;    219      HMODULE m   =   LoadLibrary(  "  ntdll.dll  "  );    220        if  (m)  {    221          ZwUnmapViewOfSection   =   (pfZwUnmapViewOfSection)GetProcAddress(m,   "  ZwUnmapViewOfSection  "  );    222            if  (ZwUnmapViewOfSection)    223              res   =   (ZwUnmapViewOfSection((unsigned   long  )ProcHnd, BaseAddr)   ==     0  );    224          FreeLibrary(m);    225      }     226        return   res;    227  }     228     229    //   创建外壳进程并获取其基址、大小和当前运行状态     230   BOOL CreateChild(  char     *  Cmd, CONTEXT   &  Ctx, HANDLE   &  ProcHnd, HANDLE   &  ThrdHnd,     231                   unsigned   long     &  ProcId, unsigned   long     &  BaseAddr, unsigned   long     &  ImageSize)    232    {    233      STARTUPINFOA si;    234      PROCESS_INFORMATION pi;    235      unsigned   long   old;    236      MEMORY_BASIC_INFORMATION MemInfo;    237      memset(  &  si,   0  ,   sizeof  (si));    238      memset(  &  pi,   0  ,   sizeof  (pi));    239      si.cb   =     sizeof  (si);    240          241      BOOL res   =   CreateProcess(NULL, Cmd, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL,   &  si,   &  pi);   //   以挂起方式运行进程;     242          if  (res)  {    243          ProcHnd   =   pi.hProcess;    244          ThrdHnd   =   pi.hThread;    245          ProcId   =   pi.dwProcessId;    246            //   获取外壳进程运行状态,[ctx.Ebx+8]内存处存的是外壳进程的加载基址,ctx.Eax存放有外壳进程的入口地址     247           Ctx.ContextFlags   =   CONTEXT_FULL;    248          GetThreadContext(ThrdHnd,   &  Ctx);    249          ReadProcessMemory(ProcHnd, (  void     *  )(Ctx.Ebx  +   8  ),   &  BaseAddr,   sizeof  (unsigned   long  ),   &  old);   //   读取加载基址     250             void     *  p   =   (  void     *  )BaseAddr;    251            //   计算外壳进程占有的内存     252             while  (VirtualQueryEx(ProcHnd, p,   &  MemInfo,   sizeof  (MemInfo)))    253            {    254                if  (MemInfo.State   =   MEM_FREE)   break  ;    255              p   =   (  void     *  )((unsigned   long  )p   +   MemInfo.RegionSize);    256          }     257          ImageSize   =   (unsigned   long  )p   -   (unsigned   long  )BaseAddr;    258      }     259        return   res;    260  }     261     262    //   创建外壳进程并用目标进程替换它然后执行     263   HANDLE AttachPE(  char     *  CmdParam, PIMAGE_NT_HEADERS peH, PIMAGE_SECTION_HEADERS peSecH,     264                    void     *  Ptr, unsigned   long   ImageSize, unsigned   long     &  ProcId)    265    {    266      HANDLE res   =   INVALID_HANDLE_VALUE;    267      CONTEXT Ctx;    268      HANDLE Thrd;    269      unsigned   long   Addr, Size;    270        char     *  s   =   PrepareShellExe(CmdParam, peH  ->  OptionalHeader.ImageBase, ImageSize);    271        if  (s  ==  NULL)   return   res;    272        if  (CreateChild(s, Ctx, res, Thrd, ProcId, Addr, Size))  {    273            void     *  p   =   NULL;    274          unsigned   long   old;    275            if  ((peH  ->  OptionalHeader.ImageBase   ==   Addr)   &&   (Size   >=   ImageSize))  {  //   外壳进程可以容纳目标进程并且加载地址一致     276               p   =   (  void     *  )Addr;    277              VirtualProtectEx(res, p, Size, PAGE_EXECUTE_READWRITE,   &  old);    278          }     279            else     if  (IsNT())  {    280                if  (UnloadShell(res, Addr))  {  //   卸载外壳进程占有内存     281                   p   =   MyVirtualAllocEx((unsigned   long  )res, (  void     *  )peH  ->  OptionalHeader.ImageBase, ImageSize, MEM_RESERVE   |   MEM_COMMIT, PAGE_EXECUTE_READWRITE);    282              }     283                if  ((p   ==   NULL)   &&   HasRelocationTable(peH))  {  //   分配内存失败并且目标进程支持重定向     284                   p   =   MyVirtualAllocEx((unsigned   long  )res, NULL, ImageSize, MEM_RESERVE   |   MEM_COMMIT, PAGE_EXECUTE_READWRITE);    285                    if  (p) DoRelocation(peH, Ptr, p);   //   重定向     286               }     287          }     288            if  (p)  {    289              WriteProcessMemory(res, (  void     *  )(Ctx.Ebx  +   8  ),   &  p,   sizeof  (DWORD),   &  old);   //   重置目标进程运行环境中的基址     290               peH  ->  OptionalHeader.ImageBase   =   (unsigned   long  )p;    291                if  (WriteProcessMemory(res, p, Ptr, ImageSize,   &  old))  {  //   复制PE数据到目标进程     292                   Ctx.ContextFlags   =   CONTEXT_FULL;    293                    if  ((unsigned   long  )p   ==   Addr)    294                      Ctx.Eax   =   peH  ->  OptionalHeader.ImageBase   +   peH  ->  OptionalHeader.AddressOfEntryPoint;   //   重置运行环境中的入口地址     295                     else     296                      Ctx.Eax   =   (unsigned   long  )p   +   peH  ->  OptionalHeader.AddressOfEntryPoint;    297                  SetThreadContext(Thrd,   &  Ctx);  //   更新运行环境     298                   ResumeThread(Thrd);  //   执行     299                   CloseHandle(Thrd);    300              }     301                else   {  //   加载失败,杀掉外壳进程     302                   TerminateProcess(res,   0  );    303                  CloseHandle(Thrd);    304                  CloseHandle(res);    305                  res   =   INVALID_HANDLE_VALUE;    306              }     307          }     308            else   {  //   加载失败,杀掉外壳进程     309               TerminateProcess(res,   0  );    310              CloseHandle(Thrd);    311              CloseHandle(res);    312              res   =   INVALID_HANDLE_VALUE;    313          }     314      }     315      delete[] s;    316        return   res;    317  }     318     319     320     321     322     /**/   /**/   /**/   /*  ******************************************************/   323  { ******************************************************* }   324  { *                 从内存中加载并运行exe               * }   325  { ******************************************************* }   326  { * 参数:                                                }   327  { * Buffer: 内存中的exe地址                               }   328  { * Len: 内存中exe占用长度                                }   329  { * CmdParam: 命令行参数(不包含exe文件名的剩余命令行参数)}   330  { * ProcessId: 返回的进程Id                               }   331  { * 返回值: 如果成功则返回进程的Handle(ProcessHandle),   }   332  {            如果失败则返回INVALID_HANDLE_VALUE           }   333  { ******************************************************* }   334   /******************************************************  */     335  HANDLE MemExecute(  void     *  ABuffer,   long   Len,   char     *  CmdParam, unsigned   long     *  ProcessId)    336    {    337      HANDLE res   =   INVALID_HANDLE_VALUE;    338      PIMAGE_NT_HEADERS peH;    339      PIMAGE_SECTION_HEADERS peSecH;    340        void     *  Ptr;    341      unsigned   long   peSz;    342        if  (AlignPEToMem(ABuffer, Len, peH, peSecH, Ptr, peSz))    343        {    344          res   =   AttachPE(CmdParam, peH, peSecH, Ptr, peSz,   *  ProcessId);    345          VirtualFree(Ptr, peSz, MEM_DECOMMIT);    346      }     347        return   res;    348  }     349     350    //   初始化     351    class   CInit    352    {    353    public  :    354      CInit()    355        {    356          MyVirtualAllocEx   =   (pfVirtualAllocEx)GetProcAddress(GetModuleHandle(  "  Kernel32.dll  "  ),   "  VirtualAllocEx  "  );    357      }     358  } Init;    359     360     361     362     363  364  365  366    int   main(  int   argc,   char   *   argv[]) 367    { 368      FILE  *   fp; 369      fp   =   fopen(  "  E://CProject//DBGVIEW.EXE  "  ,  "  rb  "  ); 370  371        if   ( fp ) 372        { 373  374          fseek(fp,  0l  ,SEEK_END); 375            int   file_size  =  ftell(fp);  /**/   /*  获取文件长度  */   376           fseek(fp,  0l  ,SEEK_SET);  /**/   /*  回到文件头部  */      377           378           379          LPBYTE pBuf   =     new   BYTE[file_size];    380          memset( pBuf,   0  , file_size);    381  382          fread(pBuf,file_size,  1  ,fp); 383  384          DWORD id   =   GetCurrentProcessId(); 385          unsigned   long   ulProcessId   =     0  ;    386          MemExecute( pBuf, file_size,   ""  ,   &  ulProcessId);    387          delete[] pBuf;    388           389      }    390       391        return     0  ; 392 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值