在PE中,新增节,添加代码
在PE中,新增节,添加代码
一、先判断节表后是否有空闲位置,添加节表信息,必须多出两个节表位置,最后以零结尾。
二、新增节后,需要修改以下信息
1、添加一个新节,可以复制一份,最好是拥有可执行属性的节,如.text。
2、在节表区,新增节的后面,填充一个节,用零填充。
3、修改标准PE头中节的数量。
4、修改SizeOfImage的大小。
5、在原有数据的后面,新增一个节的数据(内存对齐的整倍数)。
6、修正新增节表的属性。
三、新节各个属性修改说明
1、Name:名字随便修改,不能超过八个字节。
2、VirtualSize:申请的新节空间大小,比如1000
3、VirtualAddress:等于上一个节的VirtualAddress + SizeOfRawData
4、SizeOfRawData:设置可以和VirtualSize一样,比如1000
5、PointerToRawData:等于上一个节的PointerToRawData+ SizeOfRawData
6、PointerToRelocation:设置成零
7、PointerToLineNumbers:设置成零
8、NumberOfLineRelocations:设置成零
9、NumberOfLineNumbers:设置成零
10、Characteristics:块属性0x20000060 可以取上一个节表和本节表的属性值,进行异或 如x|y
标志(属性块) 常用特征值对照表:
[值:00000020h] [IMAGE_SCN_CNT_CODE // Section contains code.(包含可执行代码)]
[值:00000040h] [IMAGE_SCN_CNT_INITIALIZED_DATA // Section contains initialized data.(该块包含已初始化的数据)]
[值:00000080h] [IMAGE_SCN_CNT_UNINITIALIZED_DATA // Section contains uninitialized data.(该块包含未初始化的数据)]
[值:00000200h] [IMAGE_SCN_LNK_INFO // Section contains comments or some other type of information.]
[值:00000800h] [IMAGE_SCN_LNK_REMOVE // Section contents will not become part of image.]
[值:00001000h] [IMAGE_SCN_LNK_COMDAT // Section contents comdat.]
[值:00004000h] [IMAGE_SCN_NO_DEFER_SPEC_EXC // Reset speculative exceptions handling bits in the TLB entries for this section.]
[值:00008000h] [IMAGE_SCN_GPREL // Section content can be accessed relative to GP.]
[值:00500000h] [IMAGE_SCN_ALIGN_16BYTES // Default alignment if no others are specified.]
[值:01000000h] [IMAGE_SCN_LNK_NRELOC_OVFL // Section contains extended relocations.]
[值:02000000h] [IMAGE_SCN_MEM_DISCARDABLE // Section can be discarded.]
[值:04000000h] [IMAGE_SCN_MEM_NOT_CACHED // Section is not cachable.]
[值:08000000h] [IMAGE_SCN_MEM_NOT_PAGED // Section is not pageable.]
[值:10000000h] [IMAGE_SCN_MEM_SHARED // Section is shareable(该块为共享块).]
[值:20000000h] [IMAGE_SCN_MEM_EXECUTE // Section is executable.(该块可执行)]
[值:40000000h] [IMAGE_SCN_MEM_READ // Section is readable.(该块可读)]
[值:80000000h] [IMAGE_SCN_MEM_WRITE // Section is writeable.(该块可写)]
-----------------------------------------------------------------------------------------------------
// mem.cpp : 定义控制台应用程序的入口点。
//PE文件从文件加载到内存,再从内存读取,然后存盘到文件 #include "stdafx.h"
#include <windows.h>
#include <winnt.h> //#define PATH "C:\\Windows\\System32\\notepad.exe"
#define PATH "C:\\Users\\Administrator\\Desktop\\ipmsg.exe"
#define MsgADD 0x75cffde6
char Shellcode[] =
{
0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00,
0xE8, 0x00, 0x00, 0x00, 0x00,
0xE9, 0x00, 0x00, 0x00, 0x00
}; int Filelength(FILE *fp);
int _tmain(int argc, _TCHAR* argv[])
{
FILE *Fp;
fopen_s(&Fp, PATH, "rb");
int FileSize = Filelength(Fp);//获取文件大小
char * FileBuffer = (char *)malloc(FileSize);//申请存放文件的内存空间
if (FileBuffer == NULL)
{
printf("申请iImageBuffer失败");
}
fread_s(FileBuffer, FileSize, 1, FileSize, Fp); //将文件复制到内存中
//定位一下内存中的数据 各个头表
//定位标准PE头
PIMAGE_FILE_HEADER MyFileHeader;
MyFileHeader = (PIMAGE_FILE_HEADER)(char *)(FileBuffer + *(int *)(FileBuffer + 0x3c) + 0x4);
//定位可选PE头
PIMAGE_OPTIONAL_HEADER MyOptionalHeader;
MyOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((char *)MyFileHeader + 0x14);
//定位节表
PIMAGE_SECTION_HEADER MySectionHeader;
MySectionHeader = (PIMAGE_SECTION_HEADER)((char *)MyOptionalHeader + MyFileHeader->SizeOfOptionalHeader); //拉伸,也就是读到内存中的状态
char * ImageBuffer = (char *)malloc(MyOptionalHeader->SizeOfImage+0x1000);//给拉伸申请内存空间
ZeroMemory(ImageBuffer, MyOptionalHeader->SizeOfImage+0x1000); if (ImageBuffer == NULL)
{
printf("申请iImageBuffer失败");
}
memcpy(ImageBuffer, FileBuffer, MyOptionalHeader->SizeOfHeaders); for (int i = 0; i < MyFileHeader->NumberOfSections; i++)
{
memcpy(ImageBuffer + MySectionHeader->VirtualAddress, FileBuffer + MySectionHeader->PointerToRawData, MySectionHeader->SizeOfRawData);//
MySectionHeader++;
}
//新增节开始
PIMAGE_SECTION_HEADER AddSectionHeader;
AddSectionHeader = MySectionHeader;
MySectionHeader--;
//AddSectionHeader->Name = "cyp";
//AddSectionHeader->Name = { 0 };
AddSectionHeader->Name[0] = '.'; AddSectionHeader->Name[1] = 'c'; AddSectionHeader->Name[2] = 'y'; AddSectionHeader->Name[3] = 'p';
AddSectionHeader->Misc.VirtualSize = 0x1000;
AddSectionHeader->VirtualAddress = MySectionHeader->VirtualAddress + MySectionHeader->SizeOfRawData;
AddSectionHeader->SizeOfRawData = 0x1000;
AddSectionHeader->PointerToRawData = MySectionHeader->PointerToRawData + MySectionHeader->SizeOfRawData;
int x = (MySectionHeader - (MyFileHeader->NumberOfSections-1))->Characteristics;
AddSectionHeader->Characteristics = x;
MyFileHeader->NumberOfSections += 1;
MyOptionalHeader->SizeOfImage + 0x1000;
//新增节结束 //添加代码到PE中
MyFileHeader = (PIMAGE_FILE_HEADER)(char *)(ImageBuffer + *(int *)(ImageBuffer + 0x3c) + 0x4);
MyOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((char *)MyFileHeader + 0x14);
MySectionHeader = (PIMAGE_SECTION_HEADER)((char *)MyOptionalHeader + MyFileHeader->SizeOfOptionalHeader);//重新指一下,前面动过了 //E8后面的硬编码地址 =真正要到的地址 - E8的下一行或E8本行 +0x5
char *CodeAdd = ImageBuffer + MySectionHeader->VirtualAddress + MySectionHeader->Misc.VirtualSize;//为要增加的代码确定位置
memcpy(CodeAdd, Shellcode, sizeof(Shellcode));//把硬编码复制到指定位置
int CallAdd = MsgADD - (MyOptionalHeader->ImageBase + ((int)(CodeAdd + 0xd) - (int)ImageBuffer));
*(int *)(CodeAdd + 0x9) = CallAdd;//定位CALL函数位置
int JmpAdd = MyOptionalHeader->ImageBase + MyOptionalHeader->AddressOfEntryPoint - (MyOptionalHeader->ImageBase + (CodeAdd + 0xd - ImageBuffer));//前面是真正要跳的地址 后面括号是下一条指令的地址
*(int *)(CodeAdd + 0xe) = JmpAdd;//定位JMP 跳回位置,也就是修改程序入口
MyOptionalHeader->AddressOfEntryPoint = CodeAdd - ImageBuffer;//重新定位程序入口处 //添加代码到PE结束 //压缩,为存盘做准备
char *NewBuffer = (char *)malloc(FileSize+0x1000);//给压缩申请内存空间
if (NewBuffer == NULL)
{
printf("申请iImageBuffer失败");
}
memcpy(NewBuffer, ImageBuffer, MyOptionalHeader->SizeOfHeaders);
MySectionHeader = (PIMAGE_SECTION_HEADER)((char *)MyOptionalHeader + MyFileHeader->SizeOfOptionalHeader);//重新指一下,前面动过了 for (int i = 0; i < MyFileHeader->NumberOfSections; i++)
{
memcpy(NewBuffer + MySectionHeader->PointerToRawData, ImageBuffer + MySectionHeader->VirtualAddress, MySectionHeader->SizeOfRawData);
MySectionHeader++;
}
FILE *nFp;
fopen_s(&nFp, "C:\\Users\\Administrator\\Desktop\\CYP.exe", "wb");
fwrite(NewBuffer, FileSize, 1, nFp); //getchar();
fclose(nFp);
free(FileBuffer);
free(ImageBuffer);
free(NewBuffer);
return 0;
} //获取文件大小 int Filelength(FILE *fp)
{
int num;
fseek(fp, 0, SEEK_END);
num = ftell(fp);
fseek(fp, 0, SEEK_SET);
return num;
}
在PE中,新增节,添加代码的更多相关文章
- PE知识复习之PE文件空白区添加代码
PE知识复习之PE文件空白区添加代码 一丶简介 根据上面所讲PE知识.我们已经可以实现我们的一点手段了.比如PE的入口点位置.改为我们的入口位置.并且填写我们的代码.这个就是空白区添加代码. 我们也可 ...
- 【转】在Visual Studio中怎样快速添加代码段
原文网址:http://blog.csdn.net/yl2isoft/article/details/9735527 以前一直只知道,键入prop,再按两次tab键,会生成自动属性代码. 今天闲着无事 ...
- 在Zend Studio中为ThinkPHP添加代码自动提示功能
身边很多朋友都使用ThinkPHP或CodeIgniter等开发框架为自己的项目提高开发效率. 在得力于这些优秀框架良好的设计结构的同时,也头疼于代码的自动完成提示功能没有纯PHP网站那么完善了.经常 ...
- 零基础逆向工程20_PE结构04_任意节空白区_新增节_扩大节添加代码
向代码节添加代码实现 作者经过一周不断的失败,再思考以及无数次调试终于实现. 思路:八个步骤 1. 文件拷到文件缓冲区(FileBuffer) //图示见(零基础逆向工程18之PE加载过程) 2. 文 ...
- 向PE文件中空白处添加代码
// mem.cpp : 定义控制台应用程序的入口点. //PE文件从文件加载到内存,再从内存读取,然后存盘到文件 #include "stdafx.h" #include < ...
- <原创>在PE最后一节中插入补丁程序(附代码)
完整文件 http://files.cnblogs.com/Files/Gotogoo/在PE最后一节中插入补丁程序.zip 在PE文件最后一节中插入补丁程序,是最简单也是最有效的一种,因为PE最后 ...
- PE知识复习之PE新增节
PE知识复习之PE新增节 一丶为什么新增节.以及新增节的步骤 例如前几讲.我们的PE文件在空白区可以添加代码.但是这样是由一个弊端的.因为你的空白区节属性可能是只读的不能执行.如果你修改了属性.那么程 ...
- ES6 第七节 ES6中新增的数组知识(1)
目录 ES6 第七节 ES6中新增的数组知识(1) 第七节 ES6中新增的数组知识(1) JSON数组格式转换 Array.of()方法: find()实例方法: ES6 第七节 ES6中新增的数组知 ...
- netbeans中给jpanl添加背景图片制定代码的理解——匿名内部类继承父类
此测试是为了仿照在netbeans中给jpanl添加背景图片的制定代码的执行过程 在JpDemo中定义了个Car类的数据类型,但在给其赋值对象时使用了匿名内部类,继承了Car类,是其子类,并重写了父类 ...
随机推荐
- 19,Ubuntu安装之python开发
什么??公司要用Ubuntu(乌班图)?不会用??怎么进行python开发??? 乌班图操作系统下载地址:http://releases.ubuntu.com/18.04/ubuntu-18.04 ...
- cocos2d-x 3.0 Node与Node层级结构
节点解释: 节点是场景图的基本元素.场景图的基本元素必须是节点对象或者是节点对象的子类. 其中主要可以看到Layer.MenuItem.Scene.Sprite.TMXTiledMap(解析and渲染 ...
- P1330 封锁阳光大学(染色问题)
P1330 封锁阳光大学 题目描述 曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街.河蟹看到欢快的曹,感到不爽.河蟹决定封锁阳光大学,不让曹刷街. 阳光大学的校园是一张由N个点构 ...
- hadoop集群之Datenode无法启动解决办法
hadoop集群之Datenode无法启动解决办法 我们在启动hadoop集群的时候,通过jps查看进程,发现namenode RM和Secondary NameNode都有,但datanode没有启 ...
- 如何在一个顶级域名下用两个二级域名访问vps下的两个项目网站--完美解决骗
本人是原址是http://www.webzhe.com/server/340 后经过本人的实践修改,增加截图,等具体的步骤,完美解决 如何在vps中设置二级域名开通子网站,这个问题涉及到两步:一首先要 ...
- [译]16-spring基于注解的配置元数据
从spring2.5起spring框架开始支持java注解的配置元数据.所以除了使用xml配置文件来描述bean的装配之外,你还 可以使用基于java注解的配置元数据来完成同样的功能. spring框 ...
- 数据库——mysql内置功能(11)
1.视图 视图是一个虚拟表(非真实存在),其本质是(根据SQL语句获取动态的数据集,并未其命名),用户使用时只需使用(名称)即可获取结果集,可以将该结果集当做表来使用 使用视图我们可以把查询过程中的临 ...
- [部署开发环境][1 vagrant] vagrant部署开发环境--安装vagrant
# 安装教程 # 安装vagrant 教程 # 准备 - windows操作系统 - VirtualBox---Win, - vagrant_1.9.3.msi - 镜像文件https://atlas ...
- [问题解决]ps aux中command命令相同,如何找出自己要的进程号?
问题提出: 我们通过ps aux能够查看各个进程的状态,很多时候启动命令相同,我们没有办法判断,我们要查找的进程到底是那个? 我们该用什么方式来找出我们要操作的进程号呢? 解决步骤: 找出有可能的进程 ...
- A - 最长上升子序列
A - 最长上升子序列 Time Limit: 1000/1000MS (C++/Others) Memory Limit: 65536/65536KB (C++/Others) Problem De ...