直接运行内存中的程序[转]

001  /*
002  Windows的PE加载器在启动程序的时候,会将磁盘上的文件加载到内存,然后做很多操作,如函数导入表重定位,变量预处理之类的。这位仁兄等于是自己写了一个PE加载器。直接将内存中的程序启动。记得以前的“红色代码”病毒也有相同的特性。
003  直接启动内存中的程序相当于加了一个壳,可以把程序加密保存,运行时解密到内存,然后启动,不过对于增加破解难度还要稍微复杂点。否则人家把内存中的进程DUMP出来然后修复导入表就被拖出来了。
004  */

005  #include  "stdafx.h"  
006  #include
007  
008  typedef IMAGE_SECTION_HEADER (*PIMAGE_SECTION_HEADERS)[1];   
009  
010  // 计算对齐后的大小  
011  unsigned  long GetAlignedSize( unsigned  long Origin, unsigned  long Alignment)   
012  {   
013      return (Origin + Alignment - 1) / Alignment * Alignment;   
014  }   
015  
016  // 计算加载pe并对齐需要占用多少内存  
017  // 未直接使用OptionalHeader.SizeOfImage作为结果是因为据说有的编译器生成的exe这个值会填0  
018  unsigned  long CalcTotalImageSize(PIMAGE_DOS_HEADER MzH, 
019                  unsigned  long FileLen,
020                  PIMAGE_NT_HEADERS peH,
021                  PIMAGE_SECTION_HEADERS peSecH)   
022  {   
023      unsigned  long res;   
024      // 计算pe头的大小  
025      res = GetAlignedSize( peH->OptionalHeader.SizeOfHeaders, peH->OptionalHeader.SectionAlignment);   
026      
027      // 计算所有节的大小  
028      for( int i = 0; i < peH->FileHeader.NumberOfSections; ++i)   
029      {   
030          // 超出文件范围  
031          if(peSecH[i]->PointerToRawData + peSecH[i]->SizeOfRawData > FileLen)   
032              return 0;   
033          else  if(peSecH[i]->VirtualAddress) //计算对齐后某节的大小  
034          {   
035              if(peSecH[i]->Misc.VirtualSize)   
036              {   
037                  res = GetAlignedSize( peSecH[i]->VirtualAddress + peSecH[i]->Misc.VirtualSize,
038                              peH->OptionalHeader.SectionAlignment);   
039              }   
040              else  
041              {   
042                  res = GetAlignedSize(peSecH[i]->VirtualAddress + peSecH[i]->SizeOfRawData, 
043                          peH->OptionalHeader.SectionAlignment);   
044              }   
045          }   
046          else  if( peSecH[i]->Misc.VirtualSize < peSecH[i]->SizeOfRawData )   
047          {   
048              res += GetAlignedSize( peSecH[i]->SizeOfRawData, peH->OptionalHeader.SectionAlignment);   
049          }   
050          else  
051          {   
052              res += GetAlignedSize( peSecH[i]->Misc.VirtualSize, peH->OptionalHeader.SectionAlignment);   
053          } // if_else  
054      } // for  
055      
056      return res;   
057  }   
058  
059  
060  
061  
062  // 加载pe到内存并对齐所有节  
063  BOOL AlignPEToMem( void *Buf,
064              long Len,
065              PIMAGE_NT_HEADERS &peH,
066              PIMAGE_SECTION_HEADERS &peSecH,
067              void *&Mem,
068              unsigned  long &ImageSize)   
069  {   
070      PIMAGE_DOS_HEADER SrcMz; // DOS头  
071      PIMAGE_NT_HEADERS SrcPeH; // PE头  
072      PIMAGE_SECTION_HEADERS SrcPeSecH; // 节表  
073      
074      SrcMz = (PIMAGE_DOS_HEADER)Buf;   
075      
076      if( Len < sizeof(IMAGE_DOS_HEADER) )    
077          return  FALSE;   
078      
079      if( SrcMz->e_magic != IMAGE_DOS_SIGNATURE )   
080          return  FALSE;   
081      
082      if( Len < SrcMz->e_lfanew + ( long) sizeof(IMAGE_NT_HEADERS) )   
083          return  FALSE;   
084      
085      SrcPeH = (PIMAGE_NT_HEADERS)(( int)SrcMz + SrcMz->e_lfanew);   
086      if( SrcPeH->Signature != IMAGE_NT_SIGNATURE )   
087          return  FALSE;   
088      
089      if( (SrcPeH->FileHeader.Characteristics & IMAGE_FILE_DLL) ||   
090          (SrcPeH->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE == 0) ||   
091          (SrcPeH->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER)) 
092          )   
093      {   
094          return  FALSE;   
095      }   
096      
097      
098      SrcPeSecH = (PIMAGE_SECTION_HEADERS)(( int)SrcPeH + sizeof(IMAGE_NT_HEADERS));   
099      ImageSize = CalcTotalImageSize( SrcMz, Len, SrcPeH, SrcPeSecH);   
100      
101      if( ImageSize == 0 )   
102      return  FALSE;   
103      
104      Mem = VirtualAlloc( NULL, ImageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // 分配内存  
105      if( Mem != NULL )   
106      {   
107          // 计算需要复制的PE头字节数  
108          unsigned  long l = SrcPeH->OptionalHeader.SizeOfHeaders;   
109          for( int i = 0; i < SrcPeH->FileHeader.NumberOfSections; ++i)   
110          {   
111              if( (SrcPeSecH[i]->PointerToRawData) &&   
112                  (SrcPeSecH[i]->PointerToRawData < l) )   
113              {   
114                  l = SrcPeSecH[i]->PointerToRawData;   
115              }   
116          }   
117          memmove( Mem, SrcMz, l);   
118          peH = (PIMAGE_NT_HEADERS)(( int)Mem + ((PIMAGE_DOS_HEADER)Mem)->e_lfanew);   
119          peSecH = (PIMAGE_SECTION_HEADERS)(( int)peH + sizeof(IMAGE_NT_HEADERS));   
120          
121          void *Pt = ( void *)(( unsigned  long)Mem + GetAlignedSize( peH->OptionalHeader.SizeOfHeaders, 
122              peH->OptionalHeader.SectionAlignment));   
123          
124          for( i = 0; i < peH->FileHeader.NumberOfSections; ++i)   
125          {   
126              // 定位该节在内存中的位置  
127              if(peSecH[i]->VirtualAddress)   
128              Pt = ( void *)(( unsigned  long)Mem + peSecH[i]->VirtualAddress);   
129              
130              if(peSecH[i]->SizeOfRawData)   
131              {   
132                  // 复制数据到内存  
133                  memmove(Pt,
134                      (const void *)(( unsigned  long)(SrcMz) + peSecH[i]->PointerToRawData), 
135                      peSecH[i]->SizeOfRawData);   
136                      
137                  if(peSecH[i]->Misc.VirtualSize < peSecH[i]->SizeOfRawData)   
138                  {
139                      Pt = ( void *)(( unsigned  long)Pt + GetAlignedSize(peSecH[i]->SizeOfRawData, 
140                          peH->OptionalHeader.SectionAlignment));   
141                  }
142                  else  // pt 定位到下一节开始位置  
143                  {
144                      Pt = ( void *)(( unsigned  long)Pt + GetAlignedSize(peSecH[i]->Misc.VirtualSize, 
145                          peH->OptionalHeader.SectionAlignment));   
146                  }
147              }   
148              else  
149              {   
150                  Pt = ( void *)(( unsigned  long)Pt + GetAlignedSize(peSecH[i]->Misc.VirtualSize,
151                      peH->OptionalHeader.SectionAlignment));   
152              }   
153          }   
154      }   
155      return  TRUE;   
156  }   
157  
158  
159  
160  typedef  void *( __stdcall *pfVirtualAllocEx)( unsigned  long, void *, unsigned  long, unsigned  long, unsigned  long);   
161  pfVirtualAllocEx MyVirtualAllocEx = NULL;   
162  
163  BOOL IsNT()   
164  {   
165      return MyVirtualAllocEx!=NULL;   
166  }   
167  
168  // 生成外壳程序命令行  
169  char *PrepareShellExe( char *CmdParam, unsigned  long BaseAddr, unsigned  long ImageSize)   
170  {   
171      if(IsNT())   
172      {   
173          char *Buf = new  char[256];   
174          memset(Buf, 0, 256);   
175          GetModuleFileName(0, Buf, 256);   
176          strcat(Buf, CmdParam);   
177          return Buf; // 请记得释放内存;-)  
178      }   
179      else  
180      {   
181          // Win98下的处理请参考原文;-)  
182          // http://community.csdn.net/Expert/topic/4416/4416252.xml?temp=8.709133E-03  
183          return NULL;   
184      }   
185  }   
186  
187  // 是否包含可重定向列表  
188  BOOL HasRelocationTable(PIMAGE_NT_HEADERS peH)   
189  {   
190      return (peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
191          && (peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);   
192  }   
193  
194  
195  
196  
197  #pragma pack( push, 1)   
198  typedef  struct{   
199      unsigned  long VirtualAddress;   
200      unsigned  long SizeOfBlock;   
201  }*PImageBaseRelocation;   
202  #pragma pack( pop)   
203  
204  // 重定向PE用到的地址  
205  void DoRelocation(PIMAGE_NT_HEADERS peH, void *OldBase, void *NewBase)   
206  {   
207      unsigned  long Delta = ( unsigned  long)NewBase - peH->OptionalHeader.ImageBase;   
208                  PImageBaseRelocation p = (PImageBaseRelocation)(( unsigned  long)OldBase    
209                  + peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);   
210      while(p->VirtualAddress + p->SizeOfBlock)   
211      {   
212          unsigned  short *pw = ( unsigned  short *)(( int)p + sizeof(*p));   
213          for( unsigned  int i=1; i <= (p->SizeOfBlock - sizeof(*p)) / 2; ++i)   
214          {   
215              if((*pw) & 0xF000 == 0x3000)
216              {   
217                  unsigned  long *t = ( unsigned  long *)(( unsigned  long)(OldBase) + p->VirtualAddress + ((*pw) & 0x0FFF));   
218                  *t += Delta;   
219              }   
220              ++pw;   
221          }   
222          p = (PImageBaseRelocation)pw;   
223      }   
224  }   
225  
226  // 卸载原外壳占用内存  
227  BOOL UnloadShell(HANDLE ProcHnd, unsigned  long BaseAddr)   
228  {   
229      typedef  unsigned  long ( __stdcall *pfZwUnmapViewOfSection)( unsigned  long, unsigned  long);   
230      pfZwUnmapViewOfSection ZwUnmapViewOfSection = NULL;   
231      BOOL res = FALSE;   
232      HMODULE m = LoadLibrary( "ntdll.dll");   
233      if(m)
234      {   
235          ZwUnmapViewOfSection = (pfZwUnmapViewOfSection)GetProcAddress(m, "ZwUnmapViewOfSection");   
236          if(ZwUnmapViewOfSection)
237          {
238              res = (ZwUnmapViewOfSection(( unsigned  long)ProcHnd, BaseAddr) == 0);   
239          }
240          FreeLibrary(m);   
241      }   
242      return res;   
243  }   
244  
245  // 创建外壳进程并获取其基址、大小和当前运行状态  
246  BOOL CreateChild( char *Cmd, 
247          CONTEXT &Ctx,
248          HANDLE &ProcHnd,
249          HANDLE &ThrdHnd,    
250          unsigned  long &ProcId,
251          unsigned  long &BaseAddr,
252          unsigned  long &ImageSize)   
253  {   
254      STARTUPINFOA si;   
255      PROCESS_INFORMATION pi;   
256      unsigned  long old;   
257      MEMORY_BASIC_INFORMATION MemInfo;   
258      memset(& si, 0, sizeof( si));   
259      memset(&pi, 0, sizeof(pi));   
260      si.cb = sizeof( si);   
261      
262      BOOL res = CreateProcess(NULL, Cmd, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, & si, &pi); // 以挂起方式运行进程;  
263      if(res)
264      {   
265          ProcHnd = pi.hProcess;   
266          ThrdHnd = pi.hThread;   
267          ProcId = pi.dwProcessId;   
268          // 获取外壳进程运行状态,[ctx.Ebx+8]内存处存的是外壳进程的加载基址,ctx.Eax存放有外壳进程的入口地址  
269          Ctx.ContextFlags = CONTEXT_FULL;   
270          GetThreadContext(ThrdHnd, &Ctx);   
271          ReadProcessMemory(ProcHnd, ( void *)(Ctx.Ebx+8), &BaseAddr, sizeof( unsigned  long), &old); // 读取加载基址  
272          void *p = ( void *)BaseAddr;   
273          // 计算外壳进程占有的内存  
274          while(VirtualQueryEx(ProcHnd, p, &MemInfo, sizeof(MemInfo)))   
275          {   
276              if(MemInfo.State = MEM_FREE) break;   
277              p = ( void *)(( unsigned  long)p + MemInfo.RegionSize);   
278          }   
279          ImageSize = ( unsigned  long)p - ( unsigned  long)BaseAddr;   
280      }   
281      return res;   
282  }   
283  
284  // 创建外壳进程并用目标进程替换它然后执行  
285  HANDLE AttachPE( char *CmdParam,
286          PIMAGE_NT_HEADERS peH,
287          PIMAGE_SECTION_HEADERS peSecH,
288          void *Ptr,
289          unsigned  long ImageSize,
290          unsigned  long &ProcId)   
291  {   
292      HANDLE res = INVALID_HANDLE_VALUE;   
293      CONTEXT Ctx;   
294      HANDLE Thrd;   
295      unsigned  long Addr, Size;   
296      char *s = PrepareShellExe(CmdParam, peH->OptionalHeader.ImageBase, ImageSize);   
297      if(s==NULL) return res;   
298      if(CreateChild(s, Ctx, res, Thrd, ProcId, Addr, Size))
299      {   
300          void *p = NULL;   
301          unsigned  long old;   
302          if((peH->OptionalHeader.ImageBase == Addr) && (Size >= ImageSize)) // 外壳进程可以容纳目标进程并且加载地址一致  
303          {
304              p = ( void *)Addr;   
305              VirtualProtectEx(res, p, Size, PAGE_EXECUTE_READWRITE, &old);   
306          }   
307          else  if(IsNT())
308          {   
309              if(UnloadShell(res, Addr)) // 卸载外壳进程占有内存
310              {   
311                  p = MyVirtualAllocEx(( unsigned  long)res, 
312                              ( void *)peH->OptionalHeader.ImageBase,
313                              ImageSize, 
314                              MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);   
315              }   
316              if((p == NULL) && HasRelocationTable(peH))
317              { // 分配内存失败并且目标进程支持重定向  
318                  p = MyVirtualAllocEx(( unsigned  long)res, NULL, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);   
319                  if(p) DoRelocation(peH, Ptr, p); // 重定向  
320              }   
321          }   
322          if(p)
323          {   
324              WriteProcessMemory(res, ( void *)(Ctx.Ebx+8), &p, sizeof(DWORD), &old); // 重置目标进程运行环境中的基址  
325              peH->OptionalHeader.ImageBase = ( unsigned  long)p;   
326              if(WriteProcessMemory(res, p, Ptr, ImageSize, &old)) // 复制PE数据到目标进程  
327              {
328                  Ctx.ContextFlags = CONTEXT_FULL;   
329                  if(( unsigned  long)p == Addr)   
330                  {
331                      Ctx.Eax = peH->OptionalHeader.ImageBase + peH->OptionalHeader.AddressOfEntryPoint; // 重置运行环境中的入口地址  
332                  }
333                  else  
334                  {
335                      Ctx.Eax = ( unsigned  long)p + peH->OptionalHeader.AddressOfEntryPoint;   
336                  }
337                  SetThreadContext(Thrd, &Ctx); // 更新运行环境  
338                  ResumeThread(Thrd); // 执行  
339                  CloseHandle(Thrd);   
340              }   
341              else  // 加载失败,杀掉外壳进程 
342              { 
343                  TerminateProcess(res, 0);   
344                  CloseHandle(Thrd);   
345                  CloseHandle(res);   
346                  res = INVALID_HANDLE_VALUE;   
347              }   
348          }   
349          else  // 加载失败,杀掉外壳进程
350          {  
351              TerminateProcess(res, 0);   
352              CloseHandle(Thrd);   
353              CloseHandle(res);   
354              res = INVALID_HANDLE_VALUE;   
355          }   
356      }   
357      delete[] s;   
358      return res;   
359  }   
360  
361  
362  
363  
364  /**/ /**/ /**/ /*******************************************************  
365  { ******************************************************* }  
366  { *                 从内存中加载并运行exe               * }  
367  { ******************************************************* }  
368  { * 参数:                                                }  
369  { * Buffer: 内存中的exe地址                               }  
370  { * Len: 内存中exe占用长度                                }  
371  { * CmdParam: 命令行参数(不包含exe文件名的剩余命令行参数)}  
372  { * ProcessId: 返回的进程Id                               }  
373  { * 返回值: 如果成功则返回进程的Handle(ProcessHandle),   }  
374  {            如果失败则返回INVALID_HANDLE_VALUE           }  
375  { ******************************************************* }  
376  *******************************************************/
  
377  HANDLE MemExecute( void *ABuffer, long Len, char *CmdParam, unsigned  long *ProcessId)   
378  {   
379      HANDLE res = INVALID_HANDLE_VALUE;   
380      PIMAGE_NT_HEADERS peH;   
381      PIMAGE_SECTION_HEADERS peSecH;   
382      void *Ptr;   
383      unsigned  long peSz;   
384      if(AlignPEToMem(ABuffer, Len, peH, peSecH, Ptr, peSz))   
385      {   
386          res = AttachPE(CmdParam, peH, peSecH, Ptr, peSz, *ProcessId);   
387          VirtualFree(Ptr, peSz, MEM_DECOMMIT);   
388      }   
389      return res;   
390  }   
391  
392  // 初始化  
393  class CInit   
394  {   
395  public:   
396      CInit()   
397      {   
398          MyVirtualAllocEx = (pfVirtualAllocEx)GetProcAddress(GetModuleHandle( "Kernel32.dll"), "VirtualAllocEx");   
399      }   
400  }Init;   
401  
402  
403  
404  
405  int main( int argc, char **argv)
406  {   
407      HANDLE hFile = NULL;   
408      hFile = ::CreateFile( "C://Windows//System32//cmd.exe",
409              FILE_ALL_ACCESS,
410              0, NULL, OPEN_EXISTING, 
411              FILE_ATTRIBUTE_NORMAL, NULL   
412              );   
413      if( hFile == INVALID_HANDLE_VALUE )   
414          return -1;   
415      
416      ::SetFilePointer( hFile, 0, NULL, FILE_BEGIN);   
417      DWORD dwFileSize = ::GetFileSize( hFile, NULL);   
418      
419      LPBYTE pBuf = new BYTE[dwFileSize];   
420      memset( pBuf, 0, dwFileSize);   
421      
422      DWORD dwNumberOfBytesRead = 0;   
423      ::ReadFile( hFile, 
424          pBuf, 
425          dwFileSize,
426          &dwNumberOfBytesRead, 
427          NULL );   
428      
429      ::CloseHandle(hFile);   
430      
431      unsigned  long ulProcessId = 0;   
432      MemExecute( pBuf, dwFileSize, "", &ulProcessId);   
433      delete[] pBuf;   
434      
435      
436      return 0;   
437  } 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值