科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网网络频道系统安全之脱壳高级篇Import表的重建

系统安全之脱壳高级篇Import表的重建

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

大家好,我之所以写这篇短文,是由于我在 Dump 时发现,很多加压、加密软件都使得输入表(Import Table)不可用,所以 Dump 出的可执行文件必须要重建输入表。

作者:赛迪网 来源:赛迪网 2007年10月18日

关键字: PE文件 LPCTSTR dword Import表 动态链接库

  • 评论
  • 分享微博
  • 分享邮件

1. 前言

大家好,我之所以写这篇短文,是由于我在 Dump 时发现,很多加压、加密软件都使得输入表(Import Table)不可用,所以 Dump 出的可执行文件必须要重建输入表。而在普通的讲授 Win32 汇编的站点上我没有找到这样的介绍,所以如果你对此感兴趣,那么这篇短文对你会有些帮助。

例如,为了让从内存中 Dump 出的经 PETite v2.1 压缩过的可执行文件正常运行,必须重建输入表。(对于 ASPack、PEPack、PESentry……也同样)这就是所有 Dump 软件都具备重建输入表功能的原因(例如 G-RoM/UCF 制作的 Phoenix Engine(ProcDump 内含),或者由 Virogen/PC 和我制作的 PE Rebuilder)。

鉴于这个问题十分特殊,而且比较复杂,所以我假定你已经了解了 PE 文件结构。

2. 预备知识

首先是一些关于输入表和 RVA/VA 的简介。

输入表的相对虚拟地址(RVA)储存在 PE 文件头部的相应目录入口(它的偏移量为[ PE 文件头偏移量+80h ])。由于是虚拟偏移量,所以它和文件输入表中的偏移量(VA)是不匹配的(除非文件纯粹是刚刚从内存中 Dump 出来的)。于是我们首先要做的事情是,找到 PE 文件的输入表,将 RVA 转换为相应的 VA。为此,我们可以采用不同的办法:你可以自行编制软件来分析块(Sections)目录并计算 VA,但最简单的办法是使用专门为此设计的应用程序接口(API)。这个 API 包括在 IMAGEHLP.DLL(Win9X 和 NT 系统都使用的一个库)中,名为 ImageRvaToVa。下面是对它的描述(完整的内容详见 MSDN 库):

# LPVOID ImageRvaToVa(
# IN PIMAGE_NT_HEADERS NtHeaders,
# IN LPVOID Base,
# IN DWORD Rva,
# IN OUT PIMAGE_SECTION_HEADER *LastRvaSection
#);
#
# 参数:
#
# NtHeaders 
#
# 指示一个 IMAGE_NT_HEADERS 结构。通过调用 ImageNtHeader 函数可以获得这个结构。
#
# Base
#
# 指定通过调用 MapViewOfFile 函数映射入内存的一个映象的基址(Base Address)。
#
# Rva 
#
# 指定相对虚拟地址的位置。
#
# LastRvaSection 
#
# 指向一个指定的最终 RVA 块的 IMAGE_SECTION_HEADER 结构。这是一个可选参数。当被
#指定时,它指向一个变量,该变量包含指定映象的最后块值,以便将 RVA 转换为 VA。

就这么简单。你只需要将 PE 文件映射入内存,然后调用这个函数就能够得到输入表的正确 VA。

注意,下面我会忽略所有的 RVA/VA 注释,但是,当你对重建的 PE 文件进行读出或写入RVAs 操作时,不要忘记它们之间的转换。

3. 完整说明

这里是一个完整改变输入表的例子(这个 PE 文件的输入表已经被 PETite v2.1 压缩过,并且是直接从内存中 Dump 出来的):

我们用“`”表示 00,用“-”表示非字符串

0000C1E8h : 00 00 00 00 00 00 00 00 00 00 00 00 BA C2 00 00 ````````````----
0000C1F8h : 38 C2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ----````````````
0000C208h : C5 C2 00 00 44 C2 00 00 00 00 00 00 00 00 00 00 --------````````
0000C218h : 00 00 00 00 D2 C2 00 00 54 C2 00 00 00 00 00 00 ````--------````
0000C228h : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ````````````````
0000C238h : 7F 89 E7 77 4C BC E8 77 00 00 00 00 E6 9F F1 77 --------````----
0000C248h : 1A 38 F1 77 10 40 F1 77 00 00 00 00 4F 1E D8 77 --------````----
0000C258h : 00 00 00 00 00 00 4D 65 73 73 61 67 65 42 6F 78 ``````MessageBox
0000C268h : 41 00 00 00 77 73 70 72 69 6E 74 66 41 00 00 00 A```wsprintfA```
0000C278h : 45 78 69 74 50 72 6F 63 65 73 73 00 00 00 4C 6F ExitProcess```Lo
0000C288h : 61 64 4C 69 62 72 61 72 79 41 00 00 00 00 47 65 adLibraryA````Ge
0000C298h : 74 50 72 6F 63 41 64 64 72 65 73 73 00 00 00 00 tProcAddress````
0000C2A8h : 47 65 74 4F 70 65 6E 46 69 6C 65 4E 61 6D 65 41 GetOpenFileNameA
0000C2B8h : 00 00 55 53 45 52 33 32 2E 64 6C 6C 00 4B 45 52 ``USER32.dll`KER
0000C2C8h : 4E 45 4C 33 32 2E 64 6C 6C 00 63 6F 6D 64 6C 67 NEL32.dll`comdlg
0000C2D8h : 33 32 2E 64 6C 6C 00 00 00 00 00 00 00 00 00 00 32.dll``````````

正如你看到的,这个输入表被分成三个主要部分:

- C1E8h - C237h:IMAGE_IMPORT_DESCRIPTOR 结构部分,对应着每一个需要输入的动态链接库(DLL)。这部分以关键字 00 结束。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章