menu

FairGuard 业界首创无导入函数 SO 加壳

Android SO 模块逆向分析有一个非常重要的线索就是导入函数,so 使用的系统 api 都可以在导入函数表里看到。

某讯手游保护 SDK 所用 so 的导入表:

image.png

这是某讯手游保护 SDK 所用 so 的导入函数,有184个。通过IDA的导入函数交叉引用功能,可定位到使用 api 的代码使用位置.

snprintf API函数的交叉引用:

image.png

逆向分析者通过导入函数的交叉引用定位到如下图所示的代码位置:

image.png

可以看到 fopen,fgets,snprintf 等函数的调用,以及 /proc/self/cmdline/data/data/%s 字符串,比较明显得看出来是在做进程扫描。

从上述过程可以看到,通过导入函数可轻松定位到功能函数代码位置。

上述过程是静态分析,也可以对导入表的 api 进行动态 hook,通过打印参数来获取模块的各种行为和操作。

导入函数的存在给了分析破解者非常有用的信息,对应用破解帮助很大。既然导入表对破解分析帮助这么大,是不是可以把导入表去掉或者不使用导入函数呢?

一个空白的 C 代码工程,代码里面不调用任何 API,编译后也有 10 个左右的导入函数,因为编译器自动引入的运行时库也需要依赖系统 API。

如果直接把导入表删除行不行?没有导入表,so 加载会因找不到导入表而直接报错,app 无法正常运行。那有没有技术手段可以既把导入表清除掉,同时也让 so 能正常加载呢 ?

这里有几个高难度技术问题:

  1. 没有导入函数,不能调用任何系统 api,但是被加壳 so 会调用很多 api,这些 api 地址如何在不使用系统api的条件下获取,像 dlsym 这样的函数也没有导入,不能使用。

  2. 虽然理论上可以自己从系统模块里解析所有函数地址,但是实际上,Android4.4 到 7.0 系统有些函数没有在系统模块里导出。在这些系统里,有些函数任何系统模块都没有导出。

  3. 同样一个 api 名字,可能有多个系统模块都有导出,如何确定哪个才是正确的,如果用错了,会导致进程崩溃

  4. 兼容模拟器问题。主流模块器都是在 x86 CPU 下运行的,其对 arm 指令集的兼容使用了很多类似硬编码的手段,会对特定函数有非常规的处理。尤其是在运行非 x86 模块的时候,进程里同时存在2套指令集模块,处理尤其复杂。如果存在导入函数,这些工作都由系统完成,无导入函数的话,需要把这些系统规则在没有任何文档的情况下分析清楚。

这几个技术问题,任何一个被卡住,就无法形成可商用的加壳产品。正是这些问题的难度之高,目前还没有其它厂家能做出无导入函数加壳的实现。

FairGuard 技术团队凭借 10 多年的安全技术积累,完美解决上述所有难题。做成了可商用的产品,并已被多个游戏采用,线上稳定运行。

下面是无导入函数 SO 加壳后的效果,Imports 下面无任何函数:

image.png

除了无导入函数的实现,FairGuard SO 加壳还提供了如下安全功能:

  1. 导出函数清除和加密, 不给破解者留下导出函数的分析线索。SO 加壳后,导出函数列表空白:
    image.png

  2. 虚拟化 elf 结构。对 so 进行结构虚拟化,使得 so 原始结构被破解重构掉,无法还原出原始 so,也就无法脱壳。

  3. 系统调用。接管系统函数可被通过动态 hook 的方式监控调用参数,FairGuard so 加壳后对这些系统函数进行接管,使得动态 hook 无效。

  4. 代码加密,这是加壳的基本操作。

So 加壳是手游加固的基石,关系着手游加固的保护强度、兼容性、启动耗时等安全核心指标,尤其是对于游戏引擎加固。因此花了很多精力来打磨这块技术,构建自己的技术壁垒。

FairGuard 建立之初即定位为技术驱动型公司,深耕技术,致力于打造业界顶尖的游戏加固产品。公司开发团队都是来自于网易易盾的核心人员,创始人专注于安全领域 10 多年,前网易易盾手游保护负责人,从 0 到 1 主导了易盾手游保护项目。欢迎访问 www.fair-guard.com 了解更多内容。