PE读写

// 仿PE文件.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <malloc.h>

/*将文件从硬盘读取到缓冲区中
参数1 :文件路径 参数2:接受读取数据的缓冲区的地址的指针【指针的指针】
读取成功返回文件的长度 读取失败则返回0
*/
//int ReadFileToBuffer(IN LPSTR FilePath,OUT LPVOID* PFileBuffer);

//接下来将EXE从文件缓冲区拷贝到内存镜像缓冲区中
//DWORD CopyFileBufferToImageBuffer(IN LPSTR FileBuffer,OUT LPVOID* PImageBuffer);

int main(int argc, char* argv[])

{
char* FilePath1="E:/notepad++.exe"; //读入的文件路劲

DWORD FileLength=0;

FILE* InputStream=NULL;

void* pFileBuffer=NULL;

InputStream=fopen(FilePath1,"rb");//打开文件流

if(FilePath1=NULL){
printf("文件为空\n");
return 0;
}

int nseek=fseek(InputStream,0,SEEK_END);//将文件流指针指向文件末尾
if(nseek!=0){
printf("设置文件位置指针失败\n");
fclose(InputStream);
return 0;
}

FileLength=ftell(InputStream);
printf("the lentgth of the exe is %d Byte\n",FileLength);

//重新设置文件位置指针指向文件首
fseek(InputStream,0,SEEK_SET);
pFileBuffer=(void*)malloc(FileLength);
if(pFileBuffer==NULL){
printf("文件缓冲区申请失败\n");
fclose(InputStream);
return 0;
}

memset(pFileBuffer,0,FileLength);

int n=fread(pFileBuffer,FileLength,1,InputStream);

if(n==0){
printf("文件读取失败\n");
free(pFileBuffer);
fclose(InputStream);
return 0;
}

//接下来将EXE从文件缓冲区拷贝到内存镜像缓冲区中

PIMAGE_DOS_HEADER pDosHeader=NULL;
PIMAGE_NT_HEADERS pNTHeaders=NULL;
PIMAGE_FILE_HEADER pPEHeader=NULL;
PIMAGE_OPTIONAL_HEADER pOptionalHeader=NULL;
PIMAGE_SECTION_HEADER pSectionHeader=NULL;

//判断文件缓冲区是否有效
if(pFileBuffer==NULL){
printf("文件缓冲区指针无效\n");
return 0;
}

//判断该文件是否是PE文件
if(*((PWORD)pFileBuffer)!=IMAGE_DOS_SIGNATURE){
printf("不是有效的DOS文件\n");
return 0;
}
pDosHeader=(PIMAGE_DOS_HEADER)(pFileBuffer);
if(*((PDWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew))!=IMAGE_NT_SIGNATURE){ //这里注意:FileBuffer是一个指针,也就是一个地址,所以转型为DWROD与pDosHeader->e_lfanew相加
printf("该文件不是有效的PE文件");
return 0;
}

printf("DOS的开始地址是:%x\n",pDosHeader);
//NT头指针
pNTHeaders=(PIMAGE_NT_HEADERS)((DWORD)pDosHeader+pDosHeader->e_lfanew);
printf("NT的开始地址是:%x\n",pNTHeaders);
//PE头指针等于NT头指针加四
pPEHeader=(PIMAGE_FILE_HEADER)(((DWORD)pFileBuffer+pDosHeader->e_lfanew)+4);
printf("PE的开始地址是:%x\n",pPEHeader);

//血的教训,一个指针加上一个整数,加上的实际的大小是该指针表示的数据类型【去掉一个*】乘以整数
pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);//指针在加数时务必将其转化为整形
printf("optional的开始地址是:%x\n",pOptionalHeader);

pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pPEHeader->SizeOfOptionalHeader);
printf("section表的开始地址是:%x\n",pSectionHeader);

//根据SIZE_OF_IMAGE来分配内存缓冲区的大小,虽然每一个应用程序在理论上都拥有独立的4GB虚拟内存,但是还是根据SIZE FOF IMAGE来分配内存大小
LPVOID pImageBuffer=NULL;
pImageBuffer=malloc(pOptionalHeader->SizeOfImage);
printf("%x\n",pOptionalHeader->SizeOfImage);
if(pImageBuffer==NULL){
printf("分配内存镜像文件失败\n");
}

memset(pImageBuffer,0,pOptionalHeader->SizeOfImage);

//开始从文件缓冲区拷贝到镜像缓冲区中 1:第一步:将所有的头拷贝到镜像缓冲区中 DosHeader+NTHeader+SectionHeader
memcpy(pImageBuffer,pFileBuffer,pOptionalHeader->SizeOfHeaders);

//第二步:循环将区块拷贝到IMAGBUFFER中
PIMAGE_SECTION_HEADER pTempSectionHeader=pSectionHeader;

for(int i=0;i<pPEHeader->NumberOfSections;i++,pTempSectionHeader++){
memcpy((void*)((DWORD)pImageBuffer+pTempSectionHeader->VirtualAddress),(void*)((DWORD)pDosHeader+pTempSectionHeader->PointerToRawData),pTempSectionHeader->SizeOfRawData);
}

PIMAGE_DOS_HEADER pImageDosHeader=NULL;
PIMAGE_NT_HEADERS pImageNTHeaders=NULL;
PIMAGE_FILE_HEADER pImagePEHeader=NULL;
PIMAGE_OPTIONAL_HEADER pImageOptionalHeader=NULL;
PIMAGE_SECTION_HEADER pImageSectionHeader=NULL;

pImageDosHeader=(PIMAGE_DOS_HEADER)pImageBuffer;
printf("IMAGE中DOS头的首地址是:%x\n",pImageDosHeader);

pImageNTHeaders=(PIMAGE_NT_HEADERS)((DWORD)pImageDosHeader+pImageDosHeader->e_lfanew);
printf("IMAGE中NT头的首地址是:%x\n",pImageNTHeaders);

pImagePEHeader=(PIMAGE_FILE_HEADER)((DWORD)pImageNTHeaders+4);
printf("IMAGE中PE头的首地址是:%x\n",pImagePEHeader);

pImageOptionalHeader=(PIMAGE_OPTIONAL_HEADER)((DWORD)pImagePEHeader+IMAGE_SIZEOF_FILE_HEADER);
printf("IMAGE中OPTIONAL头的首地址是:%x\n",pImageOptionalHeader);

pImageSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader+pImagePEHeader->SizeOfOptionalHeader);

//重新申请一块文件缓冲区,将镜像中的可执行程序还原到文件缓冲区中
LPVOID pNewFileBuffer=NULL;
pNewFileBuffer=malloc(FileLength);
if(pNewFileBuffer==NULL){
printf("重新申请文件缓冲区失败\n");
return 0;
}

memset(pNewFileBuffer,0,FileLength);
//第一步:将第一部分拷贝到新的文件缓冲区中DOSHEADER+NTHEADER+SECTIONHEADER
memcpy(pNewFileBuffer,pImageDosHeader,pImageOptionalHeader->SizeOfHeaders);

//第二步:循环将各个区块拷贝到新的文件缓冲区中
//用一个临时指针来完成pImageSectionHeader指针的自增变化

PIMAGE_SECTION_HEADER pTempImageSectionHeader=NULL;
pTempImageSectionHeader=pImageSectionHeader;

for(i=0;i<pImagePEHeader->NumberOfSections;i++,pTempImageSectionHeader++){
memcpy((void*)((DWORD)pNewFileBuffer+pTempImageSectionHeader->PointerToRawData),(void*)((DWORD)pImageDosHeader+pTempImageSectionHeader->VirtualAddress),pTempImageSectionHeader->SizeOfRawData);
}

//将还原后的文件缓冲区写到一个文件中,并测试是有可以运行

char* FilePath2="E:/zhuhao3.exe"; //文件输出路径
FILE* OutputStream=NULL;
OutputStream=fopen(FilePath2,"w+");

fwrite(pFileBuffer,FileLength,1,OutputStream);

char* pchar;
char arry[]="zhuhao";
pchar=arry;
int a=3;

return 0;
}

时间: 2024-10-10 06:25:21

PE读写的相关文章

独家全功能USB2.0开发板,最强CY7C68013A-128核心板,超强资料不断提供更新服务

       学习USB开发再也不用买书啦,也不用花费重金去上培训班啦,IFLabs开创USB学习开发新模式,你所需要的知识.技术.范例.代码等等统统都在这里.IFLabs打造全网最丰富.最权威的USB开发平台和资料. 热卖的IFLabs精品USB2.0核心板套件再升级,全网独家推出最强.最全功能的Cypress USB 2.0 CY7C68013A-128AXC核心板开发板,全网最全配件和全网最全开发资料.只需这一次投入,即可实现USB接口开发的从入门到精通!并且有长期的全网最全开发手册更新支

[Win32] 直接读写磁盘扇区(磁盘绝对读写)

??本博文由CSDN博主zuishikonghuan所作,版权归zuishikonghuan全部.转载请注明出处:http://blog.csdn.net/zuishikonghuan/article/details/50380313 正讲着驱动开发呢,这里突然插一篇Win32的博文.事实上.还是做引子,上一篇博文"IRP与派遣函数"中,我们知道了驱动程序须要处理I/O请求.我们先来看看怎么发出一个I/O请求. 一般的程序不会直接去訪问磁盘,毕竟有文件系统(FileSystem)帮助我

怎样用通用pe工具箱制作U盘启动盘

U盘启动盘制作过程,随着网络的普及,电脑已经成为我们日常生活中的重要一环,最近自己重装了下电脑系统,无意中发现一个傻瓜式的U盘装系统方法,就把怎么制作通用pe工具箱u盘启动盘的经验拿出来跟大家分享下. 工具/原料 必须是能上网的电脑一台 4G以上U盘一个 方法/步骤 1 一.u盘启动盘制作前的准备 1.我是从通用pe上面下载通用pe工具箱V6.3版来进行制作的. 2.各位在运行制作程序之前最好关闭杀毒软件和安全类软件,个人觉得这种制作软件有涉及对可移动磁盘的读写操作,怕产生杀软的误报使得制作不成

压缩工具,神奇的RAID以及逻辑卷管理的PE,PA,LV,VG

Linux系统中常用的压缩和解压工具 压缩:以时间换空间的操作: 压缩的原理:标记和替换 压缩比:压缩之前与压缩之后的文件的大小的比值 纯文本文件的压缩比比较大,视频图形等压缩比相对比较小 能够实现压缩功能的工具: compress/uncompress:扩展名.z gzip/gunzip:扩展名.gz bzip2/bunzip2:扩展名.bz2 xz/unxz:扩展名.xz  目前压缩比最高的工具 zip/unzip:扩展名.zip  应用在Windows中 gzip: gzip, gunzi

装机员U盘启动PE制作工具V5.0(UEFI+UD+首发自动安装MSDN版系统)

软件名称: 装机员U盘启动PE制作工具V5.0(UEFI+UD) 软件语言: 简体中文 软件大小: 288 大小: MB 发布日期: 2016-10-02 文件名称: ZhuangJiYuanPESetup_V5.0.exe M D 5: E8EBB32CB08E914F3C5E0B8BC1A4ACAB 软件封面: 迅雷下载: thunder://QUFodHRwOi8vZG93bi56aHVhbmdqaXl1YW4uY29tOjk1My9aaHVhbmdKaVl1YW5QRVNldHVwX1Y

PE文件的执行顺序

当一个PE文件被执行时,PE装载器首先检查DOS MZ header里的PE header的偏移量.如果找到,则直接跳转到PE header的位置. 当PE装载器跳转到PE header后,第二步要做的就是检查PE header是否有效.如果该PE header有效,就跳转到PE header的尾部. 紧跟PE header尾部的是节表.PE 装载器执行完第二步后开始读取节表中的节段信息,并采用文件映射方法将这些节段映射到内存,同时附上节表里指定节段的读写属性. PE文件映射入内存后,PE装载器

手写PE文件(一)

DOS Header(IMAGE_DOS_HEADER)->64 Byte DOS头部 DOS Stub 112字节 "PE"00(Signature) 4个字节 IMAGE_FILE_HEADER  20个字节 PE文件头       IMAGE_OPTIONAL_HEADER32  96个字节 数据目录表         16*8=128个字节 IMAGE_SECTION_HEADER    40个字节 块表              IMAGE_SECTION_HEADER

Redis大幅性能提升之Batch批量读写

提示:本文针对的是StackExchange.Redis 一.问题呈现 前段时间在开发的时候,遇到了redis批量读的问题,由于在StackExchange.Redis里面我确实没有找到PipeLine命令,找到的是Batch命令,因此对其用法进行了探究一下. 下面的代码是我之前写的: 1 public List<StudentEntity> Get(List<int> ids) 2 { 3 List<StudentEntity> result = new List&l

PE文件学习

本文链接:http://blog.csdn.net/u012763794/article/details/51469477 1.介绍 什么是PE文件? PE文件是windows操作系统下使用的可执行文件格式.32位就直接叫PE或PE32,64位的就PE+或PE32+,注意不是PE64哦!!!! 学习PE文件其实就是学习结构体,里面储存了如何加载到内存,从何处开始运行,运行需要那些dll,需要多大的栈和内存等 初识PE文件 看看大概包括那些结构体吧 2.PE头 下面实例是利用notepad.exe