【原创】编程获取PE文件信息的方法(转)
2009-02-09 16:08
375 查看
标 题: 【原创】编程获取PE文件信息的方法
作 者: xhK
时 间: 2008-12-20,22:24
链 接: http://bbs.pediy.com/showthread.php?t=79108
前几天,一个学习破解的同学问我一个问题:pe文件的入口点是怎么获取的。我就给他说了一些pe文件格式的东西,并用C编程实现获取了OEP,想想可能很多新手也有此问题,于是就写点东西出来,希望对初学者有所帮助吧
pe文件的相关内容,看雪论坛上有很多资料的http://www.pediy.com/Document.htm 还有一些pe文件的结构图,望初学者一定看下,对您的学习会有很大的帮助的。 我在这里只写一些常用的pe结构信息了,建议大家结合着详细的pe结构图(http://www.pediy.com/document/PE.rar)看此文章。
今天,我以获取pe文件的oep为例,介绍一个获取pe文件信息的方法,当然只是一个比较笨的方法,一般笨的都是不需要很多知识的,应该符合初学者的口味吧
为了便于大家阅读本文,我也做了个几个简单的图片,希望可以对大家有所帮助。
看下面这个图片
![](http://bbs.pediy.com/attachment.php?attachmentid=21752&d=1229782616)
screen.width*0.6) {this.width=screen.width*0.6;this.alt='此图已经缩小,点击察看原图。';}" border=0>
这个是对配pe文件头的简单展开,信息并不全,本文只讨论oep的获取,其他信息的获取和此法一样,大家要学会举一反三,相信大家都有这个能力。
也许有人会认为获取pe文件信息不会很简单,因为pe文件是二进制的。其实不然,虽然是二进制的,但毕竟是硬盘上的数据,只要有数据,我就可以读取呀,二进制的确难搞,但是我们可以转换下,转换成我们能够看懂的不就行了。
在说方法之前,大家先看下面这个图片,这pe是我自己写的,弹出一个对话框的程序。
![](http://bbs.pediy.com/attachment.php?attachmentid=21753&d=1229782616)
screen.width*0.6) {this.width=screen.width*0.6;this.alt='此图已经缩小,点击察看原图。';}" border=0>
可以看到里面有MZ 、PE,分别是DOS头标志和PE头标志,还有几个段(也就是节区)的标记。从中可以知,有些信息我们还可以从记事本里看得到的,我们甚至可以直接在记事本里修改一些信息而不会破坏程序的运行,然由于编码问题,大多数情况下会破坏pe文件的结构,从而导致pe文件无法正确地执行。
好了其他方面的不多说了,现在专心点吧,只说下oep的获取,我把原理画成了一张图,大家可以先看图,图后来解释。
![](http://bbs.pediy.com/attachment.php?attachmentid=21754&d=1229782626)
screen.width*0.6) {this.width=screen.width*0.6;this.alt='此图已经缩小,点击察看原图。';}" border=0>
其实在第一个图中我就画出了,获取oep的方法,下面分析下
Oep是保存在AddressOfEntryPoint里面的,这个是OptionalHeader中的一个成员,OptionalHeader是pe头的中的一个成员,所以只要获取了pe头peHeader,那么(peHeader.OptionalHeader).AddressOfEntryPoint就是oep的值了,而pe头怎么获取呢,在dos头中有一个e_lfanew里面保存的是pe头的地址,那么就要获得dos头,那么dos头该怎么获取呢?如果你也有这样问,而且没有想到答案的话,可以知道,你的编程水平的确有待提高,或者要多写点代码了。
这和我那个同学当时问的一样,我就有笑了。
Dos头是打开文件的首指针指的就是dos头的标志信息的第一个字符M,所以dos头就不用定位了,打开一个pe文件,指针指的就是dos头了。所以我们的方法可分一下几个步骤(结合上图):
1. 打开一个pe文件
2. 把从dos头起始复制长度为sizeof(dos头)的数据,然后写到一个IMAGE_DOS_HEADER结构的变量中,再次命名为dosHeader.
3. 读取dosHeader.elfanew的值,这是pe头的地址,有了起始地址,用和获取dosHeader同样的方法获取pe头信息。
4. 最后获取oep信息。
代码如下:
#include <stdio.h>
#include <windows.h>
void main(int m,char *args[])
{
char *fileName=args[1];
HANDLE hFile=CreateFile(fileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0);
if(hFile==INVALID_HANDLE_VALUE)
{
printf("Open error\n");
return;
}
IMAGE_DOS_HEADER dosHeader;
BOOL bRet;
DWORD readSize;
bRet=ReadFile(hFile,&dosHeader,sizeof(dosHeader),&readSize,NULL);
if(!bRet)
{
printf("Read Error!\n");
CloseHandle(hFile);
return;
}
printf("%X\n",dosHead.e_lfanew);
IMAGE_NT_HEADERS peHeader;
SetFilePointer(hFile,dosHead.e_lfanew,NULL,FILE_BEGIN);
bRet=ReadFile(hFile,&peHeader,sizeof(peHeader),&readSize,NULL);
if(!bRet)
{
printf("Read Error!\n");
return;
CloseHandle(hFile);
}
IMAGE_OPTIONAL_HEADER32 imOpHeader;
imOpHeader=peHeader.OptionalHeader;
printf("%X\n",imOpHeader.AddressOfEntryPoint);
CloseHandle(hFile);
}
编译环境:visual C++ 6.0
在我的xp sp3上运行情况如下:
![](http://bbs.pediy.com/attachment.php?attachmentid=21755&d=1229782626)
screen.width*0.6) {this.width=screen.width*0.6;this.alt='此图已经缩小,点击察看原图。';}" border=0>
查看C:\1.exe的oep,获取的和OD的是一致的,说明方法是正确的。还有一种方法是从内存镜像中获取,对初学者来说会有一定的难度,就先不讨论了
如果你有些函数看不明白,可以看微软的msdn,建议看英文的,全!以前在中文的上面找,很多东西都找不到,在英文版生都能够找的到。
这个仅获取了pe文件的oep,你可以用此方法获取pe文件的其他信息,还是那句话,要举一反三了。熟能生巧。
在此感谢一个同学帮我整理了图片。
大家有问题可以和我交流下。
作 者: xhK
时 间: 2008-12-20,22:24
链 接: http://bbs.pediy.com/showthread.php?t=79108
前几天,一个学习破解的同学问我一个问题:pe文件的入口点是怎么获取的。我就给他说了一些pe文件格式的东西,并用C编程实现获取了OEP,想想可能很多新手也有此问题,于是就写点东西出来,希望对初学者有所帮助吧
pe文件的相关内容,看雪论坛上有很多资料的http://www.pediy.com/Document.htm 还有一些pe文件的结构图,望初学者一定看下,对您的学习会有很大的帮助的。 我在这里只写一些常用的pe结构信息了,建议大家结合着详细的pe结构图(http://www.pediy.com/document/PE.rar)看此文章。
今天,我以获取pe文件的oep为例,介绍一个获取pe文件信息的方法,当然只是一个比较笨的方法,一般笨的都是不需要很多知识的,应该符合初学者的口味吧
为了便于大家阅读本文,我也做了个几个简单的图片,希望可以对大家有所帮助。
看下面这个图片
screen.width*0.6) {this.width=screen.width*0.6;this.alt='此图已经缩小,点击察看原图。';}" border=0>
这个是对配pe文件头的简单展开,信息并不全,本文只讨论oep的获取,其他信息的获取和此法一样,大家要学会举一反三,相信大家都有这个能力。
也许有人会认为获取pe文件信息不会很简单,因为pe文件是二进制的。其实不然,虽然是二进制的,但毕竟是硬盘上的数据,只要有数据,我就可以读取呀,二进制的确难搞,但是我们可以转换下,转换成我们能够看懂的不就行了。
在说方法之前,大家先看下面这个图片,这pe是我自己写的,弹出一个对话框的程序。
screen.width*0.6) {this.width=screen.width*0.6;this.alt='此图已经缩小,点击察看原图。';}" border=0>
可以看到里面有MZ 、PE,分别是DOS头标志和PE头标志,还有几个段(也就是节区)的标记。从中可以知,有些信息我们还可以从记事本里看得到的,我们甚至可以直接在记事本里修改一些信息而不会破坏程序的运行,然由于编码问题,大多数情况下会破坏pe文件的结构,从而导致pe文件无法正确地执行。
好了其他方面的不多说了,现在专心点吧,只说下oep的获取,我把原理画成了一张图,大家可以先看图,图后来解释。
screen.width*0.6) {this.width=screen.width*0.6;this.alt='此图已经缩小,点击察看原图。';}" border=0>
其实在第一个图中我就画出了,获取oep的方法,下面分析下
Oep是保存在AddressOfEntryPoint里面的,这个是OptionalHeader中的一个成员,OptionalHeader是pe头的中的一个成员,所以只要获取了pe头peHeader,那么(peHeader.OptionalHeader).AddressOfEntryPoint就是oep的值了,而pe头怎么获取呢,在dos头中有一个e_lfanew里面保存的是pe头的地址,那么就要获得dos头,那么dos头该怎么获取呢?如果你也有这样问,而且没有想到答案的话,可以知道,你的编程水平的确有待提高,或者要多写点代码了。
这和我那个同学当时问的一样,我就有笑了。
Dos头是打开文件的首指针指的就是dos头的标志信息的第一个字符M,所以dos头就不用定位了,打开一个pe文件,指针指的就是dos头了。所以我们的方法可分一下几个步骤(结合上图):
1. 打开一个pe文件
2. 把从dos头起始复制长度为sizeof(dos头)的数据,然后写到一个IMAGE_DOS_HEADER结构的变量中,再次命名为dosHeader.
3. 读取dosHeader.elfanew的值,这是pe头的地址,有了起始地址,用和获取dosHeader同样的方法获取pe头信息。
4. 最后获取oep信息。
代码如下:
#include <stdio.h>
#include <windows.h>
void main(int m,char *args[])
{
char *fileName=args[1];
HANDLE hFile=CreateFile(fileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0);
if(hFile==INVALID_HANDLE_VALUE)
{
printf("Open error\n");
return;
}
IMAGE_DOS_HEADER dosHeader;
BOOL bRet;
DWORD readSize;
bRet=ReadFile(hFile,&dosHeader,sizeof(dosHeader),&readSize,NULL);
if(!bRet)
{
printf("Read Error!\n");
CloseHandle(hFile);
return;
}
printf("%X\n",dosHead.e_lfanew);
IMAGE_NT_HEADERS peHeader;
SetFilePointer(hFile,dosHead.e_lfanew,NULL,FILE_BEGIN);
bRet=ReadFile(hFile,&peHeader,sizeof(peHeader),&readSize,NULL);
if(!bRet)
{
printf("Read Error!\n");
return;
CloseHandle(hFile);
}
IMAGE_OPTIONAL_HEADER32 imOpHeader;
imOpHeader=peHeader.OptionalHeader;
printf("%X\n",imOpHeader.AddressOfEntryPoint);
CloseHandle(hFile);
}
编译环境:visual C++ 6.0
在我的xp sp3上运行情况如下:
screen.width*0.6) {this.width=screen.width*0.6;this.alt='此图已经缩小,点击察看原图。';}" border=0>
查看C:\1.exe的oep,获取的和OD的是一致的,说明方法是正确的。还有一种方法是从内存镜像中获取,对初学者来说会有一定的难度,就先不讨论了
如果你有些函数看不明白,可以看微软的msdn,建议看英文的,全!以前在中文的上面找,很多东西都找不到,在英文版生都能够找的到。
这个仅获取了pe文件的oep,你可以用此方法获取pe文件的其他信息,还是那句话,要举一反三了。熟能生巧。
在此感谢一个同学帮我整理了图片。
大家有问题可以和我交流下。
相关文章推荐
- C# 获取往控件中拖进的文件或文件夹的信息(原创)
- ASP.NET获取IP及电脑名等信息的简单方法+通用类文件源码 (转载)
- Go 获取文件基本信息方法
- Java如何从XML文件中获取节点信息的代码解析 Document方法
- C# 获取网络路径文件大小信息的方法
- C#编程实现动态改变配置文件信息的方法
- python获取Linux下文件版本信息、公司名和产品名的方法
- python获取mp3文件信息的方法
- PE文件信息获取工具-PEINFO
- C#基于OLEDB获取Excel文件表结构信息的方法
- 使用getCurrentPosition方法实时获取当前Geolocation信息(附源码文件)--html5、JavaScript
- 获取文件详细信息的方法
- linux系统编程之文件与IO:stat()系统调用获取文件信息
- 壳的编写(4)-- 获取被加壳文件的PE信息
- android获取APK文件,及应用内部签名信息方法
- Android编程获取sdcard音乐文件的方法
- C#获取程序文件相关信息的方法
- python获取文件版本信息、公司名和产品名的方法
- python获取文件版本信息、公司名和产品名的方法
- (原创)关于WR获取文件大小的解决方法