PE文件——导入表&导出表&函数覆盖

本文详细介绍了PE文件结构,包括PE头、导入表、导出表的识别与解析。通过Winhex工具展示了如何判断PE文件、查找导入与导出表,并讲解了如何通过修改导出函数实现特定功能,如.exe以动画方式打开和弹出messagebox。此外,还涉及了病毒获取Kernel32模块基地址的重要性以及PEditor与Winhex的使用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PE文件的基本结构图

在这里插入图片描述

  • 第一个字段4D 5A被定义成字符“MZ”作为识别标志,后面的一些字段指明了入口地址、堆栈位置和重定位表位置等。
  • 对于PE文件来说,有用的是最后的e_lfanew字段,这个字段指出了真正的PE文件头在文件中的位置,这个位置总是以8字节为单位对齐的。
    在这里插入图片描述

判断是否是PE文件

1.使用Winhex工具,从文件头4D 5A(MZ)开始,跳转3C(即偏移3C);
2.跳转后可读取到数据为0000 00B0;
3.再跳转到地址0000 00B0;
4.若该地址数据为50 45(即PE)就为PE文件。
在这里插入图片描述

导入表

导入表结构:

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD   Characteristics;            
        DWORD   OriginalFirstThunk; // 指向 导入名称表INT(ImportNameTable)的RVA
    } DUMMYUNIONNAME;
    DWORD   TimeDateStamp;                  
    DWORD   ForwarderChain;                 
    DWORD   Name;                   // 指向 DLL名称的地址 RVA
    DWORD   FirstThunk;             // 指向 导入地址表IAT(ImportAddressTable)的RVA
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

导入表&桥1&桥2位置

注意!WinHex右往左读
如:在这里插入图片描述
读值:2084
使用软件:PEditor、WinHex
1.WinHex打开,PE头偏移80H得到导入表的RVA。
2.根据节表(可用PEditor查看),将RVA转成FOA,WinHex跳转该FOA得到一串20个字节描述的一个dll文件,如下图蓝色部分。
FOA=(RVA-Virtual Offset)+Raw Offset
在这里插入图片描述
节表结构
如:
在这里插入图片描述

3.第一个字节为桥1的RVA,计算其FOA并跳转得到桥1的数组,每四个字节为一组,到四个字节均为00结束。每一组的FOA跳转得到对应函数。
4.第四个字节,计算其FOA跳转得到winresult.dd.
5.第五个字节为桥2RVA,计算其FOA并跳转得到静态指向桥2的数组。
注意!桥2动态和静态指向数组不一样
动态时桥2组数里是user32.dll的函数地址,所以指向桥2的地址会是

导出表

导出表结构:

typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;
    DWORD   TimeDateStamp;
    WORD    MajorVersion;
    WORD    MinorVersion;
    DWORD   Name;
    DWORD   Base;
    DWORD   NumberOfFunctions;
    DWORD   NumberOfNames;
    DWORD   AddressOfFunctions;     // RVA from base of image
    DWORD   AddressOfNames;         // RVA from base of image
    DWORD   AddressOfNameOrdinals;  // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

导出表位置

软件:WinHex
1.PE偏移78H,得到导出表RVA。
2.根据节表将RVA转成FOA,并跳转该FOA。
3.从这开始对应导出表的数据结构写出对应名称的数值。
其中Address of Functions要计算FOA,跳转得到该值为第一个导出函数RVA,依次往下分别为其余三个函数地址的RVA值,再转FOA跳转得到函数名。
Address of NameOrdinal与Address of Functions方式相同。

实现两种方式的导出函数覆盖

达到.exe以动画打开效果

(修改导出结构中函数入口地址)
1.先找到两个函数FadeInOpen和AnimatOpen的入口地址;
2.将两个地址进行交换(exe文件想要调用FadeInOpen时实际是调用了AnimateOpen)

使.exe运行会弹出messagebox

(覆盖fadeinopen函数的指令代码)
1.在winhex找到fadeinopen的地址从那里开始修改
2.保存原始栈基地址
3.维持栈平衡的返回命令
4.到OD单步执行user32.messageboxA看缓冲区的地址,将其地址覆盖到该函数最好四个字节。

练习题

1.某变量的FOA为410H,试分析其位于哪一节(给出分析过程。)?该变量的RVA为多少(给出计算过程)?
在这里插入图片描述由节表可知,.text的起始为00000400,大小为00000200;所以变量的FOA为410H属于.text节;
因为400<410<600
RVA = (410-400)+1000=1100H
2.查阅资料,简述病毒获取Kernel32模块基地址的重要性
答:获取了kernel32.dll基址后就可以获取LoadLibrary()和GetProcAddress()的地址,有了它们之后我们就不用大费周章的去找API了。使用Kernel32.DLL中的LoadLibrary 和GetProcAddress 两个API可以获取任意DLL中导出的任意函数在进程空间中的位置即可进行入侵。
3.利用PEditor打开firstwindow.exe,分析该PE的导入表。该PE文件描述导入表的数据目录项的偏移是多少?导入表的VA和大小分别是多少?该EXE用到多少个DLL文件。验证与PEditor中查看到的是否一致?
在这里插入图片描述
在这里插入图片描述

导入表的数据目录项的偏移是:80H;
导入表的VA和大小分别是:00402084(RVA是2084;基址是00400000;VA=RVA+基址),大小FOA=RVA-virtual offest+Raw offest=684;跳到FOA(文件偏移处)可以看见;
该EXE用到3个DLL文件,因为在winhex打开找到导入表对应数组时连续3个20个字节才到全为0的20字节。
在这里插入图片描述
对比PEditor:一致!
4.利用Winhex查看Winresult.DLL 并分析其提供函数的名字及对应入口地址。画出导出表结构图(类似图2)
在这里插入图片描述
分析:
在这里插入图片描述
导出表:
RVA:00002140,Vitual Offset:00002000,Raw Offset:800
因此FOA:940,跳到地址940既是导出表的地址:
在这里插入图片描述
标志:00000000
时间日期记录:4D510EEE
Dll的首版本号:0000
Dll的次版本号:0000
Dll的模块名(RVA):00002190,FOA:990,跳转可得文件名为winresult.dll
在这里插入图片描述
基数:00000010
函数的总数:00000004
有名函数的总数:00000004
FAT表RVA值(AddressOfFunctions):00002168 FOA(968),跳转的得到968地址值为00001183
在这里插入图片描述
该值为第一个导出函数RVA,依次往下分别为其余三个函数地址的RVA值:00001022、00001282、00001323
在这里插入图片描述

与Peditor查看到的一致:
在这里插入图片描述
FAT表RVA值(AddressOfNames):00002178 FOA:(978)
跳转到978地址得到地址为0000219E
第一个导出函数RVA值:0000219E,FOA=99E
第二个导出函数RVA值:000021AB,FOA=9AB
第三个导出函数RVA值:000021B7,FOA=9B7
第四个导出函数RVA值:000021C2,FOA=9C2
查看对应文件偏移量处的函数名:
在这里插入图片描述
5.pedtior打开本机的kernel32.DLL,其导出表RVA?导出表大小?找到无导入表情况下需要的两个函数的名称及其入口地址。 (本机的kernel32.DLL用winhex存到桌面)
在这里插入图片描述
导出表RVA:00092D30导出表大小:0000DC14
在得到kernel32.dll的基地址后,就可以获得LoadLibray()函数来继续加载其他的动态链接库,再通过GetProcAdress()函数来获得相应需要的api函数地址,这样也就做到了可移植性的要求。
LoadLibray:
在这里插入图片描述
GetProcAddress:
在这里插入图片描述
6.实现两种方式的导出函数覆盖-1
修改winResult.dll导出结构中的函数入口地址,达到firstwindow.EXE以动画方式打开的效果。描述你所做的工作。
1.先找到两个函数FadeInOpen和AnimateOpen的入口地址:00001022和0001282
在这里插入图片描述
2.将两个地址进行交换(exe文件想要调用FadeInOpen时实际是调用了AnimateOpen)
在这里插入图片描述

7.实现两种方式的导出函数覆盖-2 (P166)
覆盖fadeinopen函数的指令代码:使得运行firstwindow.EXE程序时会弹出messagebox(OD打开看地址)。如下图所示:
1.Winhex打开winResult.dll,修改函数FadeInOpen(文件起始偏移0x0682)定义部分:保存原始栈基地址、维持栈平衡的返回命令:
原始得:
在这里插入图片描述
修改后:
在这里插入图片描述
在这里插入图片描述

红框部分是messageboxA在user32.dll的地址,可以通过OD打开其他导入了messageboxA的文件查看其所在的地址,例如上次作业的Helloworld.exe,注意在Winhex上使用小端方式!
运行:
在这里插入图片描述

以上是学习PE文件的一些笔记,欢迎大家查阅指正~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值