您的位置:首页 > 编程语言

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

2012-06-21 00:24 274 查看
EPO+插缝植入用户自定义代码的一种方法

2008-10-04 19:45
以前听很多人问如何零字节插入,就是在一个pe内写入了我们的代码后,pe文件并不增加大小.可想而知道这种方法的隐蔽性.那么我们怎么才能把一些代码加入pe,而使它的大小不发生改变呢.还好windows的这个格式对齐给我们提供了可能性.pe中的节以一定的基数(也称对齐因数)对齐,而这种对齐导致的最直观的效果是每个节中有大量的空闲的空间,没有数据,没有代码,都是以0填充.这样我们就可以把这块宝地利用起来,把我们的代码写入.因为只是覆盖写入所以pe不会增加大小.好了第一个问题解决了.那么如何让pe执行那段代码呢?修改入口点(这是大部分类似程序所用的方法),不是太好。这样杀软很容易检测到pe入口点遭到修改而报警,这样我们岂不是徒劳了.那又如何解决它呢?答案就是EPO(入口点模糊技术),这种技术没有严格的规格规定,一般是修改API的跳转地址.一下为编译器的两种API调用方法:
; E8 xx xx xx xx: call xxxxxxxx ; relative address

; ...

; FF 25 xx xx xx xx: jmp dword ptr [xxxxxxxx]

;

; or:

;

; FF 15 xx xx xx xx: call dword ptr [xxxxxxxx] ; API 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";

char szFormat[]="0x%02x ";

void usage();

int main(int argc, char* argv[])

{

HANDLE hFile ;

HANDLE hMap ;

LPVOID pMapping ;

DWORD dwGapSize ;

unsigned char *pGapEntry ;

int i ;

int x = 0x18 ;

int vir_len ;

unsigned char *pSearch ;

BYTE *addr_found=(BYTE *)-1;

DWORD Section_Number;

BYTE data_hex[6]; //用于暂存宿主的6字节代码

BYTE data_jmp[6]={0xe9,0x90,0x90,0x90,0x90,0x90}; //用于转移到自定义处

DWORD dwCodeDistance,max_search,_eax,_esi,image;

HMODULE hModule_user32=LoadLibrary("user32");

HMODULE hModule_kernel32=LoadLibrary("kernel32");
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) ;

max_search=GetFileSize(hFile,0);
if (hFile==INVALID_HANDLE_VALUE)

{

printf("Open host file failed!\n") ;

return -1 ;

}



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) ;

if (!pMapping)

{

printf("Map view of file failed!\n") ;

return -1 ;

}
//::::::打开目标宿主文件,先检测文件是否PE格式,定位到代码的末尾

pImageDosHeader = (PIMAGE_DOS_HEADER)pMapping ;

if (pImageDosHeader->e_magic!=IMAGE_DOS_SIGNATURE)

{ printf("DOS_Invalid file format!\n");

return -1;

}

pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pMapping+pImageDosHeader->e_lfanew) ;



if (pImageNtHeaders->Signature!=IMAGE_NT_SIGNATURE)

{

printf("NT_Invalid file format!\n");

return -1;

}



pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pMapping+

pImageDosHeader->e_lfanew+sizeof(IMAGE_NT_HEADERS));

//:::计算第一个节的空隙大小

dwGapSize = pImageSectionHeader->SizeOfRawData - pImageSectionHeader->Misc.VirtualSize ;



//:::如果代码缝隙小于thunk code的大小则感染失败

if (sizeof(thunkcode)+6>dwGapSize)

{

printf("no more space to fill!\n") ;

goto Close ;

}

//:::定位到代码末尾

Section_Number=pImageNtHeaders->FileHeader.NumberOfSections;

pGapEntry = (unsigned char *)(pImageSectionHeader->PointerToRawData+

(DWORD)pMapping+

pImageSectionHeader->Misc.VirtualSize) ;

image=pImageNtHeaders->OptionalHeader.ImageBase;



vir_len = (int)pImageSectionHeader->Misc.VirtualSize+pImageSectionHeader->VirtualAddress-pImageNtHeaders->OptionalHeader.AddressOfEntryPoint;



pSearch = (unsigned char *)(pImageNtHeaders->OptionalHeader.AddressOfEntryPoint+

-pImageSectionHeader->VirtualAddress+pImageSectionHeader->PointerToRawData+

(DWORD)pMapping);



max_search=DWORD(max_search+(DWORD)pMapping);

__asm

{

xor eax,eax

mov esi,pSearch

epo_search: lodsb

dec vir_len

jz asm_exit

cmp al,0e8h

jz epo_e8_found

cmp al,0ffh

jnz epo_search

dec vir_len

lodsb

cmp al,15h

jnz epo_search

jmp epo_got_it

epo_e8_found: mov _esi, esi

lodsd

add eax,esi

cmp eax,pMapping

jb epo_search

cmp eax,max_search

ja epo_search

cmp word ptr [eax],25ffh

mov esi,_esi

jnz epo_search

xchg eax,esi

inc esi

inc esi



epo_got_it: pushad

mov ebx,image

lodsd

sub eax,ebx

mov esi,pImageSectionHeader

mov ecx,Section_Number

call __rva2raw

mov edx,pMapping

add eax,edx

mov eax,DWORD ptr [eax]

call __rva2raw

lea eax,[eax+edx+2]

mov _eax,eax

push eax

push hModule_kernel32

mov eax,0x7c80ada0

call eax

or eax,eax

popad

jnz epo_got_api

mov eax,_eax

push eax

push hModule_user32

mov eax,0x7c80ada0 //本地系统的GetProcAddress的地址可能需要修正

call eax

or eax,eax

jnz epo_got_api

xor ebx,ebx

jmp epo_search

epo_got_api: dec esi

dec esi

mov addr_found,esi

jmp asm_exit
//此函数为RVA转RAW

//input:

// eax --- RVA to convert

// esi --- pointz to the first IMAGE_SECTION_HEADER

// ecx --- number of section header

// Output:

// eax --- RAW (offset in the file)

__rva2raw: pushad

r2r_sec_loop: mov ebx,[esi+12]

mov edx,ebx

cmp eax,ebx

jl r2r_next

add ebx,[esi+8]

cmp eax,ebx

jg r2r_next

sub eax,edx

add eax,[esi+20]

mov [esp+28],eax

jmp r2r_ret

r2r_next: add esi,28h

loop r2r_sec_loop

xor eax,eax

mov [esp+28],eax

r2r_ret: popad

ret

}

asm_exit:



if((DWORD)addr_found==-1)

{

printf("在我们制定的区段内并没找到符合要求的API");

goto Close;

}

printf("从这个地址开始查找:%08x \n",(pSearch-((DWORD)pMapping+pImageSectionHeader->PointerToRawData))+pImageSectionHeader->VirtualAddress+pImageNtHeaders->OptionalHeader.ImageBase);

printf("我们找到的第一个符合要求的API是%s ",_eax);

printf("它的地址:%08x \n",(addr_found-((DWORD)pMapping+pImageSectionHeader->PointerToRawData))+pImageSectionHeader->VirtualAddress+pImageNtHeaders->OptionalHeader.ImageBase);

printf("我们的代码写入的位置为:%08x \n",(pGapEntry-((DWORD)pMapping+pImageSectionHeader->PointerToRawData))+pImageSectionHeader->VirtualAddress+pImageNtHeaders->OptionalHeader.ImageBase);

dwCodeDistance =((DWORD)pGapEntry - ((DWORD)addr_found+5));

for (i=3;i>=0;i--)

{

data_jmp[i+1] = ((unsigned int)dwCodeDistance>>x)&0xff ;

x -= 8 ;

}

for(i=0;i<6;i++)

{

data_hex[i]=addr_found[i];



}

for(i=0;i<6;i++)

{

addr_found[i]=data_jmp[i];

}

for (i=0;i<sizeof(thunkcode);i++)

{

pGapEntry[i]= thunkcode[i] ;

}

for(i=0;i<6;i++)

{

pGapEntry[i+sizeof(thunkcode)-1]=data_hex[i];



}

dwCodeDistance=(-(dwCodeDistance+10+sizeof(thunkcode)));

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+6]=data_jmp[i];



}

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通过
点击下载

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐