首页
论坛
课程
招聘
[原创]编程获取PE文件信息的方法
2008-12-20 22:24 12871

[原创]编程获取PE文件信息的方法

xhK 活跃值
3
2008-12-20 22:24
12871
前几天,一个学习破解的同学问我一个问题:pe文件的入口点是怎么获取的。我就给他说了一些pe文件格式的东西,并用C编程实现获取了OEP,想想可能很多新手也有此问题,于是就写点东西出来,希望对初学者有所帮助吧

pe文件的相关内容,看雪论坛上有很多资料的http://www.pediy.com/Document.htm 还有一些pe文件的结构图,望初学者一定看下,对您的学习会有很大的帮助的。 我在这里只写一些常用的pe结构信息了,建议大家结合着详细的pe结构图(http://www.pediy.com/document/PE.rar)看此文章。

今天,我以获取pe文件的oep为例,介绍一个获取pe文件信息的方法,当然只是一个比较笨的方法,一般笨的都是不需要很多知识的,应该符合初学者的口味吧

为了便于大家阅读本文,我也做了个几个简单的图片,希望可以对大家有所帮助。
看下面这个图片

这个是对配pe文件头的简单展开,信息并不全,本文只讨论oep的获取,其他信息的获取和此法一样,大家要学会举一反三,相信大家都有这个能力。

也许有人会认为获取pe文件信息不会很简单,因为pe文件是二进制的。其实不然,虽然是二进制的,但毕竟是硬盘上的数据,只要有数据,我就可以读取呀,二进制的确难搞,但是我们可以转换下,转换成我们能够看懂的不就行了。
在说方法之前,大家先看下面这个图片,这pe是我自己写的,弹出一个对话框的程序。

可以看到里面有MZ 、PE,分别是DOS头标志和PE头标志,还有几个段(也就是节区)的标记。从中可以知,有些信息我们还可以从记事本里看得到的,我们甚至可以直接在记事本里修改一些信息而不会破坏程序的运行,然由于编码问题,大多数情况下会破坏pe文件的结构,从而导致pe文件无法正确地执行。

好了其他方面的不多说了,现在专心点吧,只说下oep的获取,我把原理画成了一张图,大家可以先看图,图后来解释。

其实在第一个图中我就画出了,获取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上运行情况如下:

查看C:\1.exe的oep,获取的和OD的是一致的,说明方法是正确的。还有一种方法是从内存镜像中获取,对初学者来说会有一定的难度,就先不讨论了

如果你有些函数看不明白,可以看微软的msdn,建议看英文的,全!以前在中文的上面找,很多东西都找不到,在英文版生都能够找的到。

这个仅获取了pe文件的oep,你可以用此方法获取pe文件的其他信息,还是那句话,要举一反三了。熟能生巧。

在此感谢一个同学帮我整理了图片。

大家有问题可以和我交流下。

看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~

上传的附件:
  • 1.gif (10.33kb,869次下载)
  • 2.gif (12.46kb,860次下载)
  • 3.gif (9.99kb,855次下载)
  • 4.gif (19.46kb,862次下载)
收藏
点赞0
打赏
分享
最新回复 (27)
雪    币: 245
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
Winter-Night 活跃值 5 2008-12-20 22:46
2
0
用记事本的牛人,膜拜~
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
coldwinter 活跃值 2008-12-21 00:02
3
0
学习,学习,谢谢…
雪    币: 130
活跃值: 活跃值 (13)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
xhK 活跃值 3 2008-12-21 15:49
4
0
我只是用记事本看了下信息而已,我很菜的,算不得上牛人,呵呵
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
botdoor 活跃值 2008-12-22 00:05
5
0
学习了 很好很强大啊 希望还能看到你有关PE的文章
雪    币: 3847
活跃值: 活跃值 (880)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
五德转移 活跃值 2008-12-22 11:04
6
0
args[1];要改成args[0]吧。
雪    币: 2273
活跃值: 活跃值 (25)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
北极狐狸 活跃值 7 2008-12-22 11:28
7
0
支持原创,支持开源...
雪    币: 130
活跃值: 活跃值 (13)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
xhK 活跃值 3 2008-12-22 12:10
8
0
[QUOTE=五德转移;554189]args[1];要改成args[0]吧。[/QUOTE]

命令行下是这样的
xx c:\1.exe
则args[0]="xx"         args[1]="c:\1.exe"

你试试看下
雪    币: 97
活跃值: 活跃值 (65)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
hash 活跃值 2008-12-28 19:47
9
0
运行没成功  hehe
left of '.OptionalHeader' must have struct/union type
雪    币: 130
活跃值: 活跃值 (13)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
xhK 活跃值 3 2009-2-8 11:35
10
0
可能是你没有弄好头文件吧。OptionalHeader是一个结构体,你再看下
雪    币: 367
活跃值: 活跃值 (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
petnt 活跃值 12 2009-2-8 15:06
11
0
支持一下。。
雪    币: 215
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
COMPUTE 活跃值 2009-2-8 15:19
12
0
支持.....
雪    币: 151
活跃值: 活跃值 (32)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
modi 活跃值 2009-2-8 23:31
13
0
学习,正需要这方面知识..:
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
babywoshe 活跃值 2009-2-9 00:06
14
0
学习学习啊啊啊
雪    币: 205
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zxn 活跃值 2009-2-9 12:16
15
0
顶,学习学习啊啊啊
雪    币: 151
活跃值: 活跃值 (32)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
modi 活跃值 2009-2-11 23:54
16
0
dosHeader 变量LZ笔漏了两处.
还有args[1],我的也是要args[0]才能编译通过,郁闷;
雪    币: 130
活跃值: 活跃值 (13)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
xhK 活跃值 3 2009-3-8 10:17
17
0
哦,可能大家用的编译器不同吧,我的确是这样

误导了大家,不好意思
雪    币: 1481
活跃值: 活跃值 (154)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
cntrump 活跃值 13 2009-3-9 12:31
18
0
发个源代码,看着更方便 一点.....
上传的附件:
雪    币: 212
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
狼头头 活跃值 2009-3-9 14:15
19
0
很强大,学习了
雪    币: 564
活跃值: 活跃值 (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lixupeng 活跃值 2009-3-9 15:04
20
0
厉害啊学习下
雪    币: 89
活跃值: 活跃值 (540)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
gjianbo 活跃值 2 2009-3-9 15:15
21
0
学习了,谢谢
雪    币: 213
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
绿豆青蛙 活跃值 2009-3-9 16:30
22
0
很有用.谢谢了...........
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zcdesign 活跃值 2009-3-12 23:00
23
0
[QUOTE=;]...[/QUOTE]
雪    币: 207
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dafeiqiqi 活跃值 2009-3-24 23:19
24
0
我顶,学习。
雪    币: 100
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
爱转角 活跃值 2009-3-25 01:25
25
0
学习了````
游客
登录 | 注册 方可回帖
返回