反作弊游戏如何破解,看看《黑色沙漠》逆向分析过程:使用 IDAPython 和 FLIRT 签名恢复 IAT

gejigeji Web安全 2019年11月27日发布
Favorite收藏

导语:《黑色沙漠》是PearlAbyss Corp开发的一款 MMOARPG 网络游戏,是款在电玩游戏中的动作和战斗的基础上添加大规模攻城战,不动产使用、交易和雇佣等模拟要素的MMORPG。

《黑色沙漠》是PearlAbyss Corp开发的一款 MMOARPG 网络游戏,是款在电玩游戏中的动作和战斗的基础上添加大规模攻城战,不动产使用、交易和雇佣等模拟要素的MMORPG。于2013年10月17开启第一次测试。

在这篇文章开始之前,你有必要先看一下如何使用Scylla和x64dbg转储黑色沙漠(BlackDesert64.exe)的过程。我们将在这篇文章中看到我为了简化静态逆向分析而转储过程时所做的一些事情。

黑色沙漠二进制文件的开发者很早就预料到了,会有人对他们的游戏进行逆向分析,因此早已经使用了Themida进行了预防。Themida是一个强劲的保护系统, 专为了那些想保护自己的软件不被先进的逆向工程和黑客软件破解的软件开发者而开发的。开发者不需要更改任何的原代码,和不需要程式编制的经验使用WinLicense。通常,当你从内存中转储一个进程时,特别是如果该进程已封装,则有很多事情会被破坏或正确地说,不会像预期的那样转储。

1.png

RDB Packer检测器的输出结果

其中之一就是IAT(我们将要了解IAT是什么以及如何识别它们),如果我们转储一个进程,并且由于某种原因而没有IAT表,则逆向分析将会非常困难,并且将看到调用诸如qword_1419FB008之类的函数而不是GetProcAddress的函数。如果我们能够看到IAT表,逆向分析会变得容易得多。

另一个有趣的事情是应用来自IDA的FLIRT签名,这些签名是IDA附带的,你可以在互联网上找到许多公共集合,将这些公共集合装入二进制文件后,它们将尝试从多个库中识别出众所周知的函数。

导入地址表(IAT)

通常,来自dll的函数地址不是静态的,因此,导入地址表用于存储进程使用的已加载dll中的所有函数指针。基本上,它是内存的一部分,你可以在其中找到指向程序所使用的每个函数的指针列表。每当进程需要访问来自kernel32.dll的WriteFile时,程序便会指向IAT表以获取所加载dll中函数的真实地址。

2.png

在该图中,我们可以看到IAT从正在运行的进程中转储出来的数据。可以理解为两个主要的列:第一个列属于内存中每个IAT条目的地址;第二个是从加载的dll指向每个函数的真实地址的指针。这样,每当程序要从dll访问任何函数时,它将指向该表以检索该函数的动态地址。

第三列是x64dbg添加的注释,它根据调试器在内存中加载的符号从每个指针解析函数的名称。当我们从内存中转储进程时,由于所有指针将不再存在于静态转储中,因此我们将无法看到最后的信息,而且我们使用的任何工具都不能像这里的x64dbg那样解析这些指针。

有没有一种方法可以还原此信息以进行静态分析?

当然有,如果我们使用Scylla转储进程,则此工具将自动尝试识别内存中的IAT,但是封装程序很讨厌,通常它们会在解压缩实际二进制文件后删除原始IAT并在内存中分配一个新表。此工具可能无法识别内存中的实际IAT,实际上,如果我们尝试这样做,Sylla会告诉我们IAT表的大小为8字节(一个条目),这是不可能的。

IAT通常是一组指针组成的数组,用一个空指针将每个DLL与另一个DLL分开。在内存中识别它们对于两种情况(静态地使用IDA和动态地使用x64dbg)都是非常简单的。对于x64dbg,你可以简单地寻找任何一块程序集,使调用一个函数从一个dll和遵循的IAT指针:

3.png

调用GetModuleHandleW

为了识别转储中的IAT,我们需要寻找一个指针数组,就像我们之前解释的那样。一种可能是寻找对这种格式为qword_1419FB008的函数的调用,这类似于调用cs:qword_1419FB008。如果我们在IDA中遵循此变量,我们将发现看起来像这样的IAT:

4.png

IAT与IDA

在上图中,我们可以看到IAT的多个条目,并且在右侧,可以看到IDA标识的所有xref。 Black Desert Online IAT表包含大约1000个条目,你可以想象这将如何简化静态反向过程。

5.png

没有符号的反作弊初始化进程

恢复IAT

现在,我们已经在运行的进程以及静态转储中标识了IAT表,我们可以知道尝试将所有符号从进程迁移到IDA。由于x64dbg为我们解决了这些符号,我们可以尝试从运行的进程中复制IAT并在IDA上重命名功能,以便我们在逆向分析时可以使用它们。

我认为有一个更好的方法来执行此操作,但是我决定手动执行第一部分,然后使用IDAPython编写一个小脚本。首先,我们将以x64xdb转到IAT的开头,并在表的第一个条目上执行“右键单击->跟进转储”。这将设置转储1,如下所示:

6.png

x64dbg中的IAT

现在,我们将选择从表的第一个地址开始直到表的最后一个条目的所有值。最后,我们要做的是“右键单击->复制->选定行”。如果我们将其存储在新的txt文件中,则将得到以下内容:

00000001419FB000  00007FFC8F3C38F0  advapi32.SetServiceStatusStub
00000001419FB008  00007FFC8F3C3910  advapi32.CryptGenRandomStub
00000001419FB010  00007FFC8F3C3390  advapi32.CryptReleaseContextStub
00000001419FB018  00007FFC8F3C2F60  advapi32.CryptAcquireContextWStub
00000001419FB020  00007FFC8F3C2F80  advapi32.RegQueryValueExAStub
00000001419FB028  00007FFC8F3C2EA0  advapi32.RegOpenKeyExAStub
00000001419FB030  00007FFC8F3C3320  advapi32.CryptAcquireContextAStub
00000001419FB038  00007FFC8F3C7140  advapi32.RegDeleteValueWStub
00000001419FB040  00007FFC8F3C2A10  advapi32.RegCreateKeyExWStub
...
...
00000001419FB308  00007FFC8FE40D30  kernel32.FindFirstFileA
00000001419FB310  00007FFC8FE40DA0  kernel32.FindNextFileA
00000001419FB318  00007FFC8FE3FB30  kernel32.MoveFileExW
00000001419FB320  00007FFC8FE41050  kernel32.RemoveDirectoryW
00000001419FB328  00007FFC8FE41080  kernel32.SetFileAttributesW
00000001419FB330  00007FFC8FE40E20  kernel32.GetDiskFreeSpaceExW

虽然有三列,但我们只对第一列和最后一列感兴趣。为什么?因为第二列仅包含每个函数的动态地址,所以在使用IDA静态逆向分析时我们并不在乎,因为这些模块的地址不在转储中。如果我们可以使用方法名称重命名每个指针名称,则IDA将自动从Windows API中识别大多数函数,并动态更新转储中的参数和类型。

为了自动执行此操作,IDA向我们提供了一个名为IDAPython的API。这样,我们可以编写一个小的脚本,该脚本基本上可以获取IAT的每一行,搜索转储中的每个内存地址,并使用方法的真实名称重命名函数名称。

结果如下所示:

import idaapi
import idautils
import idc
if __name__ == '__main__':
    file = open( 'IAT.txt', 'r')
    for line in file:
        columns = line.split('  ')
        address = columns[0]
        fnName = columns[2].replace('\r', '').replace('\n', '')
        if '.' in fnName:
            fnName = fnName.split('.')[1]
        print address   ' '   fnName
        idc.MakeNameEx(int(address, 16), fnName, idc.SN_NOWARN)
    file.close()

该脚本将遍历来自IAT的每一行,并将把每个内存地址的正确名称放在转储中。

9.png

修复了IAT在转储里面的问题,IDA将自动识别某些方法,并将适当的参数和函数信息添加到每个条目中。

你还记得有关反作弊初始化的图像吗?现在的情况是这样的:

10.png

现在我们已经向转储IAT导入了将近1000种方法,这些方法将在整个二进制文件中发挥作用。

FLIRT签名

我喜欢做的第二件事是使用快速的库标识和识别技术(FLIRT)签名,特别是对于简化的二进制文件。这允许IDA通过分析反汇编程序的每个字节来从二进制文件内的多个库中搜索函数,以便确定其是否对应于已知库函数的开头。

标识每个函数所需的这些信息存储在包含每个函数的所有模式的文件中,要在IDA中使用此函数,你只需要打开“签名”子视图并执行“右键单击->应用新签名”即可:

11.png

菜单选择要应用的签名,选择每个签名将取决于我们确定相关库的标准。应用它们之后,你将看到类似以下内容:

12.png

总结

在进行反向分析之前,花一些时间来解析和改进二进制文件中可用的信息确实非常重要,这对于那些难以逆向分析的程序(比如反作弊程序)来说是一个很好的开始。IDA有多个像ClassInformer这样的插件,这些插件使得逆向分析c++程序更加容易。

本文翻译自:https://niemand.com.ar/2019/02/21/reversing-a-black-desert-online-dump-restoring-iat-with-idapython-and-flirt-signatures/如若转载,请注明原文地址: https://www.4hou.com/web/21806.html
点赞 0
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论