首页
社区
课程
招聘
[原创]编程获取PE文件信息的方法
发表于: 2008-12-20 22:24 14311

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

xhK 活跃值
3
2008-12-20 22:24
14311

前几天,一个学习破解的同学问我一个问题: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文件的其他信息,还是那句话,要举一反三了。熟能生巧。

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

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


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

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

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

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

误导了大家,不好意思
2009-3-8 10:17
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
18
发个源代码,看着更方便 一点.....
上传的附件:
2009-3-9 12:31
0
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
很强大,学习了
2009-3-9 14:15
0
雪    币: 563
活跃值: (95)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
厉害啊学习下
2009-3-9 15:04
0
雪    币: 277
活跃值: (1976)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
21
学习了,谢谢
2009-3-9 15:15
0
雪    币: 220
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
很有用.谢谢了...........
2009-3-9 16:30
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
[QUOTE=;]...[/QUOTE]
2009-3-12 23:00
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
我顶,学习。
2009-3-24 23:19
0
雪    币: 100
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
学习了````
2009-3-25 01:25
0
游客
登录 | 注册 方可回帖
返回
//