【屠夫科普】感染PE增加导入项实现注入

原文:http://www.ghoffice.com/bbs/read-htm-tid-94760.html


【屠夫科普】感染PE增加导入项实现注入

.
上篇文章<<【屠夫话题】关于MMRPG型辅助相对通用框架的讨论>>承诺放出源码分享.今天实现.  
 
之前有朋友说此方法还不够通用.原因有个别国外游戏会启动后,对自身加载的所有文件进行HASH效验,不过它可以检测自带的文件.难道连系统文件也效验.先判断当前系统.  
 
再取得微软的效验碼?这强度未免太大了吧. 我一个人实在没有那么多精力测试.希望朋友们帮忙.  
 
微软的Detours也在使用这种方法注入,我的和它的有一点区别.它的比较温柔.主要攻击EXE,启动进程挂起.然后修改动态PE.我攻击所有PE文件.静态修改. 
 
 
 
编程语言:C  
 
编程环境:Microsoft Visual Studio 2008  
 
系统平台:Windows server 2008  
 
实现原理: 启动进程系统是通过其导入表确定该为其加载那些动态连接库.它是一个数组.每个成员代表一个动态连接库.我们要做的就是为这个数组增加一个成员. 
 
                  而这个成员就是我们的动态连接库.只是这个数组是固定大小的,它的前面后面.都没有位置让我们新增一个成员.所以我们只能随便找一个空地新构造一个这样的数组即可
 
 
 
 
 
复制代码
  1. 函数名称:InfectImport
  2. 函数返回:true or false
  3. 第一参数:目标文件路径
  4. 第二参数:将注入的动态连接库
  5. int InfectImport(const char* Path,const char* Library)
  6. {
  7.     char                    Sign[0x10]={0};
  8.     FILE*                    File=0x0;
  9.     char*                    Buffer=0x0;
  10.     const char*                    Test=TEXT("Butcher's");
  11.     unsigned long                 Size=0;
  12.     unsigned long                Offset=0;
  13.     IMAGE_DOS_HEADER                Dos={0};
  14.     IMAGE_NT_HEADERS                NT={0};
  15.     IMAGE_SECTION_HEADER            Section={0};
  16.     IMAGE_IMPORT_DESCRIPTOR*             Import=0;
  17.     IMAGE_DATA_DIRECTORY*             Directory=0;
  18.     //申请所需的局部变量并为其初始化
  19.     if (fopen_s(&File,Path,TEXT("rb+"))!=0)
  20.     {
  21.         return 0;
  22.     }
  23.     //以读写权限打开目标文件
  24.     __try
  25.     {
  26.         __try
  27.         {
  28.             fread(&Dos,sizeof(IMAGE_DOS_HEADER),1,File);
  29.             if (Dos.e_magic!= IMAGE_DOS_SIGNATURE)
  30.             {
  31.                 return 0;
  32.             }
  33.             //读取文件DOS头到缓存,并判断DOS签名
  34.             fseek(File,0x28,SEEK_SET);
  35.             fread(Sign,0x10,1,File);
  36.             if (strcmp(Test,Sign)==0)
  37.             {
  38.                 return 0;
  39.             }
  40.             //读取文件第28字节处到缓存,此为IMAGE_DOS_HEADER结构e_res2[10]域的位置.
  41.             //原为微软定义的保留位.就是微软还没想好用这个地方做点什么,只是空一个空留着以后想到了再用.
  42.             //那它现在不用,我们就拿来用一下.用来做效验.判断当前文件是否已经被感染过了.如没有才继续
  43.             fseek(File,Dos.e_lfanew,SEEK_SET);
  44.             fread(&NT,sizeof(IMAGE_NT_HEADERS),1,File);
  45.             if (NT.Signature!=IMAGE_NT_SIGNATURE)
  46.             {
  47.                 return 0;
  48.             }
  49.             //读取文件NT头到缓存,并判断NT签名
  50.             fseek(File,Dos.e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER),SEEK_SET);
  51.             fread(&Section,sizeof(IMAGE_SECTION_HEADER),1,File);
  52.             if (Section.VirtualAddress!=NT.OptionalHeader.BaseOfData)
  53.             {
  54.                 return 0;
  55.             }
  56.             //读取文件rdata节到缓存,并判断正确性.
  57.             Size=NT.OptionalHeader.DataDirectory[1].Size;
  58.             if (Size+0x20>Section.SizeOfRawData-Section.Misc.VirtualSize)
  59.             {
  60.                 return 0;
  61.             }
  62.             //获取文件导入表尺寸,并判断rdata节剩余空间是否能容纳新增一个导入项的新导入表.
  63.             Offset=Section.PointerToRawData+Section.Misc.VirtualSize;
  64.             //获取节空隙起始位置
  65.             Buffer=calloc(0x20,sizeof(char));
  66.             memset(Buffer,0,0x20);
  67.             strcpy_s((char*)Buffer,strlen(Library)+1,Library);
  68.             *(int*)((int)Buffer+0x10)=0x80000001;
  69.             *(int*)((int)Buffer+0x14)=0x0;
  70.             *(int*)((int)Buffer+0x18)=0x0;
  71.             *(int*)((int)Buffer+0x1c)=0x0;
  72.             
  73.             //申请20字节堆,用以构造新导入项结构
  74.             fseek(File,Offset,SEEK_SET);
  75.             fwrite(Buffer,sizeof(char),0x20,File);
  76.             //把新构造的导入项结构写入文件rdata节空隙起始位置
  77.             Import=malloc(sizeof(IMAGE_IMPORT_DESCRIPTOR));
  78.             Import->FirstThunk            =Offset+0x10;
  79.             Import->ForwarderChain        =0;
  80.             Import->Name            =Offset;
  81.             Import->OriginalFirstThunk        =Offset+0x18;
  82.             Import->TimeDateStamp        =0;
  83.             //申请堆,用以构造新导入项.
  84.             fseek(File,NT.OptionalHeader.DataDirectory[1].VirtualAddress+Size-0x14,SEEK_SET);
  85.             fwrite(Import,sizeof(IMAGE_IMPORT_DESCRIPTOR),1,File);
  86.             //在文件导入表结尾处写入新构造的导入项
  87.             Buffer=realloc(Buffer,Size);
  88.             memset(Buffer,0,Size);
  89.             fseek(File,NT.OptionalHeader.DataDirectory[1].VirtualAddress,SEEK_SET);
  90.             fread(Buffer,sizeof(char),Size,File);
  91.             fseek(File,Offset+0x20,SEEK_SET);
  92.             fwrite(Buffer,sizeof(char),Size,File);
  93.             //复制新导入表到新位置
  94.             Directory=malloc(sizeof(IMAGE_DATA_DIRECTORY));
  95.             Directory->Size                =Size+0x14;
  96.             Directory->VirtualAddress            =Offset+0x20;
  97.             fseek(File,Dos.e_lfanew+sizeof(IMAGE_NT_HEADERS)-0x78,SEEK_SET);
  98.             fwrite(Directory,sizeof(IMAGE_DATA_DIRECTORY),1,File);
  99.             //修改文件目录使导入表指向新位置,报告新尺寸
  100.             fseek(File,0x28,SEEK_SET);
  101.             fwrite(Test,strlen(Test),1,File);
  102.             //成功后在文件第28字节处,也就是IMAGE_DOS_HEADER结构e_res2[10]域的位置
  103.       //写入我们自定义的感染标志.这里标志为:Butcher's
  104.         }
  105.         __except(EXCEPTION_EXECUTE_HANDLER)
  106.         {
  107.             return 0;
  108.         }
  109.     }
  110.     __finally
  111.     {
  112.         free(Buffer);
  113.         free(Import);
  114.         free(Directory);
  115.         fclose(File);
  116.     }
  117.     return 1;
  118. }
 
                   
 
 
PS:此代码居然破坏性.请先备份目标文件再行使用 (使用前请把想要注入的动态连接库放入与目标相同的文件夹内) 
 

你可能感兴趣的:(【屠夫科普】感染PE增加导入项实现注入)