首页
社区
课程
招聘
[求助]增加PE文件节区+修改IID结构(静态干预输入表)---参考加密与解密第4版P450-P455
发表于: 2020-1-2 11:04 1738

[求助]增加PE文件节区+修改IID结构(静态干预输入表)---参考加密与解密第4版P450-P455

2020-1-2 11:04
1738

恰巧看到了加密与解密第4版的静态干预输入表,便想着尝试代码实现一番,在具体实现中遇到了部分BUG,不知道在什么情况下,导致了很多程序修改完后无法启动(0xC0000005),而修改自己编写的一些程序,大部分都可以成功。

步骤:

1.PE文件添加区块

2.将原始输入表拷贝到新节区

3.加入新的IID结构

4.使用原始输入表位置来存放新的IID内容

5.修复镜像大小以及输入表RVA


#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);
}
 新人发帖!如有问题请指出,及时更正。


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2020-4-27 01:52 被yeanhoo编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//