设为首页 加入收藏

TOP

基于VC++实现PE的修改编程(一)
2014-11-23 19:38:17 】 浏览:592
Tags:基于 实现 修改 编程

在Windows系统下的可执行文件的一种(还有NE、LE),是微软设计、TIS(Tool Interface Standard,工具接口标准)委员会批准的一种可执行文件格式。PE的意思是Portable Executable(可移植可执行)。所有Windows下的32位或64位可执行文件都是PE文件格式,其中包括DLL、EXE、FON、OCX、LIB和部分SYS文件。
DOS-stub(DOS-头)
  DOS-根的概念很早从16位windows的可执行文件(当时是“NE”格式)时就广为人知了。根原来是用于OS/2系统的可执行文件的,也用于自解压档案文件和其它的应用程序。对于PE文件来说,它是一个总是由大约100个字节所组成的和MS-DOS 2.0兼容的可执行体,用来输出象“This program needs windows NT”之类的错误信息。
  你可以通过确认DOS-头部分是否为一个IMAGE_DOS_HEADER(DOS头)结构来认出DOS-根,它的前两个字节必须为连续的两个字母“MZ”(有一个#define IMAGE_DOS_SIGNATURE的定义是针对这个WORD单元的)。
  你可以通过跟在后面的签名来将一个PE二进制文件和其它含有根的二进制文件区分开来,跟在后面的签名可由头成员'e_lfanew'(它是从字节偏移地址60处开始的,有32字节长)所设定的偏移地址找到。对于OS/2系统和Windows系统的二进制文件来说,签名是一个16位的word单元;对于PE文件来说,它是一个按照8位字节边界对齐的32位的longword单元,并且IMAGE_NT_SIGNATURE(NT签名)的值已由#defined定义为0x00004550(即字母“PE/0/0”)。
file-header(文件头)
  要到达IMAGE_FILE_HEADER(文件头)结构,请先确认DOS-头“MZ”(起始的2个字节),然后找出DOS-根的头部的成员“e_lfanew”,并从文件开始处跳过那么多的字节。在核实你在那里找到的签名后,IMAGE_FILE_HEADER(文件头)结构的文件头就紧跟其后开始了。
optional header(可选头)
  紧跟在文件头后面的就是IMAGE_OPTIONAL_HEADER(尽管它名叫“可选头”,它却一直都在那里)。它包含有怎样去准确处理PE文件的信息。
data directories(数据目录)
  IMAGE_NUMBEROF_DIRECTORY_ENTRIES (16)(映象文件目录项数目)个IMAGE_DATA_DIRECTORY(映象文件数据目录)数组。这些目录中的每一个目录都描述了一个特定的、位于目录项后面的某一节中的信息的位置(32位的RVA,叫“VirtualAddress(虚拟地址)”)和大小(也是32位,叫“Size(大小)”)。
  例如,安全目录能在索引4中给定的RVA处发现并具有索引4中给定的大小。
section headers(节头)
  节由两个主要部分组成:首先,是一个节描述(IMAGE_SECTION_HEADER[意为“节头”]类型的),然后是原始的节数据。因此,我们会在数据目录后发现一“NumberOfSections”个节头组成的数组,它们按照各节的RVA排序。
sections(节数据)
  所有的节在载入内存后都按“SectionAlignment”(节对齐)对齐,在文件中则以“FileAlignment”(文件对齐)对齐。节由节头中的相关项来描述:在文件中你可通过“PointerToRawData”(原始数据指针)来找到,在内存中你可通过“VirtualAddress”(虚拟地址)来找到;长度由“SizeOfRawData”(原始数据长度)决定。
  根据节中包含的内容,可分为好几种节。大多数(并非所有)情况下,节中至少由一个数据目录,并在可选头的数据目录数组中有一个指针指向它。

下面我们实现编程修改PE
[cpp]
// Pe.cpp: 实现 CPe类.
//
#include "stdafx.h"
#include "Pe.h"

CPe::CPe()
{
}

CPe::~CPe()
{
}

void CPe::ModifyPe(CString strFileName,CString strMsg)
{
CString strErrMsg;

HANDLE hFile, hMapping;
void *basepointer;

// 打开要修改的文件.
if ((hFile = CreateFile(strFileName, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, 0,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0)) == INVALID_HANDLE_VALUE)
{
AfxMessageBox("Could not open file.");
return;
}

// 创建一个映射文件.
if (!(hMapping = CreateFileMapping(hFile, 0, PAGE_READONLY | SEC_COMMIT, 0, 0, 0)))
{
AfxMessageBox("Mapping failed.");
CloseHandle(hFile);
return;
}

// 把文件头映象存入baseointer.
if (!(basepointer = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0)))
{
AfxMessageBox("View failed.");
CloseHandle(hMapping);
CloseHandle(hFile);
return;
}

CloseHandle(hMapping);
CloseHandle(hFile);

CalcAddress(basepointer); // 得到相关地址.
UnmapViewOfFile(basepointer);

if(dwSpace<50)
{
AfxMessageBox("No room to write the data!");
}
else
{
WriteFile(strFileName,strMsg); // 写文件.
}

if ((hFile = CreateFile(strFileName, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, 0,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0)) == INVALID_HANDLE_VALUE)
{
AfxMessageBox("Could not open file.

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇使用GDI+画仪表表盘 下一篇(Visual C++)游戏开发笔记二十..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目