道。道。道

安全特性不等于安全的特性

   :: 首页 :: 联系 :: 聚合  :: 管理

常用链接

搜索

  •  

最新评论

       在内存中运行可执行程序,好处是可以给程序加壳,加密源程序,静态反汇编无法获得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 
posted on 2007-01-19 22:28 独孤九剑 阅读(1708) 评论(0)  编辑 收藏 引用 所属分类: Win32