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;
}
PE读写的更多相关文章
- 一文说清OpenCL框架
背景 Read the fucking official documents! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: 对不 ...
- PE文件头
pe文件头查看器下载与原文地址: http://www.pc6.com/softview/SoftView_109840.html PE文件入门: PE文件总的来说是由DOS文件头.DOS加载模块.P ...
- EF架构~通过EF6的DbCommand拦截器来实现数据库读写分离~再续~添加对各只读服务器的心跳检测
回到目录 上一讲中基本实现了对数据库的读写分离,而在选择只读数据库上只是随机选择,并没有去检测数据库服务器是否有效,如服务器挂了,SQL服务停了,端口被封了等等,而本讲主要对以上功能进行一个实现,并对 ...
- PE文件的执行顺序
当一个PE文件被执行时,PE装载器首先检查DOS MZ header里的PE header的偏移量.如果找到,则直接跳转到PE header的位置. 当PE装载器跳转到PE header后,第二步要做 ...
- 手写PE文件(一)
DOS Header(IMAGE_DOS_HEADER)->64 Byte DOS头部 DOS Stub 112字节 "PE"00(Signature) 4个字节 IMAGE ...
- 通用PE u盘启动盘制作
导读 通用pe工具箱是现在最老牌的的U盘装系统和维护电脑的专用工具之一,一键式制作.操作简单便捷,几乎100%支持所有U盘,不再为装机烦恼们,抓紧时间下载通用pe工具箱体验下吧. 准备工作 ①从通用p ...
- 怎样用通用pe工具箱制作U盘启动盘
U盘启动盘制作过程,随着网络的普及,电脑已经成为我们日常生活中的重要一环,最近自己重装了下电脑系统,无意中发现一个傻瓜式的U盘装系统方法,就把怎么制作通用pe工具箱u盘启动盘的经验拿出来跟大家分享下. ...
- 如何用Java语言向串口读写数据
原作者:赛迪网作者 shihuchen ,我在他的基础上进行了部分修改 [赛迪网讯]串口, RS-232-C(又称EIA RS-232-C,以下简称RS232)是在1970年由美国电子工业协会(EIA ...
- 《Windows驱动开发技术详解》之读写操作
缓冲区方式读写操作 设置缓冲区读写方式:
随机推荐
- format not a string literal and no format arguments
今天cocos2d-x打包 android的时候报错:format not a string literal and no format arguments 报错点是:__String::create ...
- FREEBSD手工配置网络
在FreeBSD系统中,网络能力十分重要,对于一个标准的FreeBSD系统,至少要有一个网络界面以便与其他计算机通信.最常见的网络界面为以太网卡.此外FreeBSD也支持Token Ring和FDDI ...
- 15 个 Android 通用流行框架大全(转)
1. 缓存 DiskLruCache Java实现基于LRU的磁盘缓存 2.图片加载 Android Universal Image Loader 一个强大的加载,缓存,展示图片的库 Picas ...
- angular路由——ui.route
angular路由 使用案例 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- Winform 后台将指定的控件集合添加到制定容器中
/// <summary> /// 把按钮按照行数分割排列 /// </summary> /// <param name="ControlArry"& ...
- 【Beta】Scrum06
Info 时间:2016.12.15 21:35 时长:25min 地点:大运村1号公寓5楼楼道 类型:日常Scrum会议 NXT:2016.12.17 21:30 Task Report Name ...
- ssl
在Java加密技术(八)中,我们模拟了一个基于RSA非对称加密网络的安全通信.现在我们深度了解一下现有的安全网络通信--SSL. 我们需要构建一个由CA机构签发的有效证书,这里我们使用上文中生 ...
- c# 动态调用WCF方法笔记!
//动态调用wcf方法 string url = "http://localhost:54379/ServiceWCF.svc"; IDoubleService proxy = W ...
- radio 切换内容
<!DOCTYPE html><html><head> <meta charset=utf-8 /> <title>test</tit ...
- TransMac Win系统下制作 OS X启动盘图文教程超详细小白版
1软件安装好后把准备好的8G或者8G以上U盘插到电脑上:右键以管理员身份运行如 <ignore_js_op> 2打开软件后右键先格式化U盘操作如下图 ...