• 一次游戏安全SO静态分析记录:腾讯ACE与FairGuard加固强度对比


    最近用GPT-5.6 Sol分析了几份Android SO,感受比较明显:AI已经可以承担不少二进制静态分析中的重复工作。把ELF头、节区、符号、字符串、重定位和函数展开信息交给它批量整理,再回到工具输出逐项核对,效率比手工来回翻结果高很多。

    这次我选择了两款手游中的安全模块,分别来自FairGuard和腾讯ACE。目的很直接:在相同分析口径下,看看两个SO向常规工具暴露了多少结构与语义信息,以及分析者能否快速建立代码地图。

    下面记录完整的样本信息、复现命令、指标口径和量化结果。

    一、测试对象与分析环境

    项目 FairGuard 腾讯ACE
    游戏 《闪烁之光》 《火影忍者》
    游戏版本 4.4.8 1.79.79.9
    测试文件 libFairGuard.so libtersafe.so
    SHA-256 e34dd793cb58f360fc235e0375486a9a116154d664724ce5e688a46c611bf4fe 517f1e3891e7a7c5dd8254bedcb09a5fe1d2acb0147cec757efb3a06ec5b2a10
    架构 AArch64 AArch64
    文件大小 5.16 MiB 5.52 MiB
    ELF类型 64位共享库 64位共享库
    Strip 是 是

    解压安装包后,可以在lib/arm64-v8a目录中找到对应模块。两份样本架构一致、体积接近,并且都已经Strip,适合放在同一套静态指标下观察。

    AI辅助部分使用GPT-5.6 Sol,推理强度设置为“极高”,基础指令为:

    分析两个SO文件的加固强度并进行量化对比。

    这里让模型负责整理检查项、批量统计数据和发现异常,再用ELF工具输出复核关键结论。常用基础命令如下:

    sha256sum libFairGuard.so libtersafe.so
    file libFairGuard.so libtersafe.so
    
    readelf -hW -lW -SW -sW -rW -dW libFairGuard.so
    readelf -hW -lW -SW -sW -rW -dW libtersafe.so
    
    readelf --debug-dump=frames libFairGuard.so
    readelf --debug-dump=frames libtersafe.so
    
    strings -a -n 8 libFairGuard.so
    strings -a -n 8 libtersafe.so
    

    这些命令可以复核ELF头、程序段、节区、动态符号、重定位、动态项、字符串和FDE记录。节区覆盖率、无节区区域、分档字符串数量以及局部熵值,则需要在这些结果的基础上继续用脚本统计。

    本次采用的几个指标口径如下:

    • 节区表覆盖文件比例:有文件内容的节区所描述的文件范围,占整个文件的比例。
    • 最大无节区描述区域:文件偏移范围内,没有被节区表描述的最大连续区间。
    • 可打印字符串:连续可打印ASCII内容,按长度≥8、≥16和≥32分别统计。
    • FDE记录:.eh_frame中能够正常解析的Frame Description Entry。
    • 局部熵值:将RX段按64 KiB分块,统计熵值≥7.8和熵值<1的块。

    二、先看ELF结构:工具能否直接找到代码主体

    指标 FairGuard 腾讯ACE
    节区数量 21 28
    程序段数量 6 9
    节区表覆盖文件比例 6.94% 99.96%
    最大无节区描述区域 4,805,144字节 1,799字节
    最大无节区区域占比 88.80% 0.03%
    声明的.text大小 16字节 3,590,944字节
    .text零字节比例 100% 10.10%
    RX段中可执行节区覆盖率 0.0039% 65.74%

    FairGuard样本最明显的特征是.text只有16字节,而且内容全部为零。它的ELF入口为0xfe00,落在节区表没有描述的区域。整个文件最大的无节区区域达到4,805,144字节,占比88.8%。

    对IDA、Ghidra、radare2一类工具来说,标准节区原本是建立初始代码地图的重要依据。遇到这种布局后,只按节区表分析会漏掉主体内容,需要转向程序段、入口地址和运行时装载逻辑继续识别。

    腾讯ACE样本的节区表覆盖率为99.96%,.text、.rodata、.eh_frame、重定位表和版本表均能正常定位。常规工具导入后,可以直接依据标准ELF结构开始分析。

    这一组数据也是两个样本拉开差距最大的地方:FairGuard优先破坏了工具赖以建立结构的静态地图,腾讯ACE则保留了更标准的共享库布局。

    三、动态符号:符号很多,未必能提供有效信息

    指标 FairGuard 腾讯ACE
    动态符号总数 1,028 288
    空名称符号 1,002(97.47%) 1(0.35%)
    可读符号比例 2.24% 99.65%
    可读导出接口 0 71
    唯一导入函数名 4 216
    4字节伪函数条目 999 2
    不落在声明节区的符号 1,007 0
    readelf一致性警告 10条 0

    单看数量,FairGuard拥有1,028个动态符号,比腾讯ACE更多。继续检查会发现,其中1,002个没有名称,999个函数条目的长度固定为4字节,还有1,007个符号地址与声明节区对不上。

    它另外保留了3个非空导出名称,但内容属于不可读字节序列,因此可读导出接口统计为0。readelf还给出了10条本地符号顺序异常。这样的符号表很难充当有效的分析导航,更接近干扰信息。

    腾讯ACE样本中的288个动态符号结构正常,可读符号比例达到99.65%,其中可直接识别71个导出接口,例如:

    • JNI_OnLoad
    • tss_sdk_init
    • tss_sdk_encryptpacket
    • tss_sdk_decryptpacket
    • tss_sdk_ischeatpacket
    • tss_recv_sec_signature

    部分名称属于SDK需要公开的接口,但它们同样会成为静态分析中的路标。分析者可以从初始化、数据收发或加解密接口进入,再沿交叉引用向内部追踪。

    四、字符串:还能看到多少功能语义

    短字符串容易受到高熵数据随机组合的影响,因此这里重点统计8字节以上的连续可打印ASCII内容。

    指标 FairGuard 腾讯ACE
    长度≥8的字符串 427 4,224
    长度≥16的字符串 27 1,624
    长度≥32的字符串 12 370
    .rodata可打印字符串 6 10,880
    源码路径 0 6
    明文JNI_OnLoad 未发现 可见

    腾讯ACE中长度达到16字符的字符串有1,624条,约为FairGuard的60倍。样本里还可以看到NDK版本、Build ID和部分指向.cpp、LLVM源码的编译路径。

    FairGuard主要保留依赖库名称及GCC 4.9编译痕迹,没有提取到能够直接指向反调试、Hook或签名校验等功能的明文关键词。只从字符串入手,很难快速还原模块内部的功能分布。

    字符串保护看起来只是“少暴露一些文字”,实际会影响整个分析节奏。错误提示、日志、文件路径、接口名称和协议字段经常被用来给未知函数命名;这些线索收敛以后,后续交叉引用也会失去一批明确锚点。

    五、重定位、初始化入口与函数边界

    指标 FairGuard 腾讯ACE
    重定位总数 93 25,380
    INIT/FINI目标 4 66
    位于标准.text的INIT/FINI目标 0 66
    位于无节区区域的INIT/FINI目标 4 0
    可恢复FDE记录 0 16,286
    .eh_frame零字节比例 100% 32.51%
    .gcc_except_table零字节比例 100% 38.33%

    FairGuard的4个构造与析构目标全部位于无节区描述区域。.eh_frame和.gcc_except_table虽然保留了节区名称,内容却全部为零,readelf只能识别一个终止符,无法恢复有效FDE记录。

    腾讯ACE可以解析出16,286条FDE记录。即使这些记录不带函数名称,IDA、Ghidra等工具仍然可以利用它们识别函数边界和栈展开关系。

    重定位总数会受到代码规模、编译器和链接方式影响,单项数值不适合直接判定强弱。这里将它和节区布局、符号表、初始化入口、FDE一起观察,可以看到腾讯ACE保留了更多标准化交叉引用信息;FairGuard则让多个静态入口同时失效。

    六、为什么整体熵值不能直接代表加固强度

    指标 FairGuard 腾讯ACE
    整体信息熵 4.626 6.456
    文件零字节占比 54.43% 21.89%
    RX段中熵≥7.8的64 KiB块 35/83,42.17% 4/84,4.76%
    RX段中熵<1的64 KiB块 42/83,50.60% 0/84

    如果只比较整体熵,腾讯ACE的6.456高于FairGuard的4.626,很容易把这个结果直接理解成腾讯ACE的加密或压缩程度更高。但FairGuard文件中有54.43%的零字节,大量零填充会显著拉低整体熵。

    换成64 KiB分块后,FairGuard的RX段里有35个高熵块,同时存在42个低熵零块。结合88.8%的无节区区域,这种“高熵载荷与大块零区并存”的分布更接近加密数据、隐藏载荷或自定义布局。

    腾讯ACE的整体数据分布更连续,RX段中仅有4个分块达到7.8以上。由此看,熵值要和文件布局、零字节比例及分块位置一起解释,单一平均值很容易掩盖真实结构。

    七、基础ELF安全属性

    属性 FairGuard 腾讯ACE
    NX Stack 通过 通过
    GNU RELRO 通过 通过
    BIND_NOW 通过 通过
    Full RELRO 通过 通过
    TEXTREL 无 无
    RWX加载段 无 无

    这一部分双方表现基本一致:都开启了NX、GNU RELRO、BIND_NOW和Full RELRO,也没有TEXTREL或RWX加载段。基础编译和链接安全属性都比较完整。

    八、静态抗分析强度量化

    业内没有统一的SO加固百分制。为了汇总本次观察结果,我按“常规静态工具能够直接利用的信息量”设计了一个百分制模型。总分方便快速对照,具体判断仍以原始指标为准。

    评分维度 权重 FairGuard 腾讯ACE
    ELF结构与节区隐藏 25 23 8
    符号与接口信息隐藏 20 18 11
    字符串与构建信息保护 15 14 8
    初始化、重定位及FDE隐藏 15 14 7
    数据不透明度与局部熵特征 15 13 9
    基础ELF安全属性 10 10 10
    总分 100 92 53

    libFairGuard.so在这套静态指标下得到92分。它的代码主体没有通过常规节区完整呈现,动态符号中存在大量无名、定长及越界条目,字符串、重定位和函数展开信息也明显收敛。常规工具很难直接恢复有效代码地图。

    libtersafe.so得到53分。该样本同样完成Strip,并具备完整的基础ELF安全属性;它保留了较标准的共享库布局,符号、接口、字符串、重定位和FDE信息可以被工具较完整地提取,初始结构恢复相对直接。

    九、这次分析留下的几个检查思路

    做完这轮对比,我觉得判断SO静态强度时,下面几项值得形成固定检查顺序:

    1. 先看程序段和节区表是否一致。 .text大小正常,并不代表全部可执行内容都被节区完整描述;入口和构造函数落点同样重要。
    2. 统计有效符号,不只看符号总数。 空名称比例、固定长度函数、异常地址和可读导出数量,更能反映符号表是否可用。
    3. 字符串要分长度并结合所在节区。 单纯运行一次strings很容易被随机短字符串干扰。
    4. 把FDE当成函数边界线索。 经过Strip的SO仍可能从.eh_frame恢复出大量函数范围。
    5. 熵值必须分块看。 整体均值会被零填充拉低,也会掩盖局部高熵区域。
    6. 最后再做量化评分。 原始数据负责提供证据,分数只用于汇总差异。

    小结

    GPT-5.6 Sol在这次分析中的价值,主要体现在统计和整理:它能快速把分散在多条命令中的数据归到同一套指标下,也能提醒我关注符号地址、节区覆盖率和局部熵分布等异常点。涉及关键结论时,仍要回到readelf、strings和脚本统计结果逐项确认,这样输出才方便复现。

    回到两个样本,双方的基础ELF安全配置相近,真正拉开静态分析难度的是结构和语义信息的暴露程度。FairGuard在节区隐藏、符号干扰、字符串收敛和函数边界隐藏方面更彻底;腾讯ACE保留了较多标准ELF结构及可读接口,常规工具更容易建立初始分析框架。

    这也说明,只确认SO有没有Strip远远不够。把ELF布局、符号、字符串、重定位、初始化入口和FDE放到一起检查,才能更接近常用逆向工具实际面对的分析阻力。

  • 相关阅读:
    Docker安装canal、mysql进行简单测试与实现redis和mysql缓存一致性
    使用java解析hashMap
    C++ Vector的模拟实现
    rar文件如何打开
    L1-020 帅到没朋友(Python3)
    Java8函数式编程-lambda表达式与stream流
    技能在赛题解析:交换机防环路设置
    如何实现矩阵的重采样问题
    Linux:vi和vim编辑器
    idea2022没有springboot脚手架
  • 原文地址:https://www.cnblogs.com/bytehidden/p/23046349