type
status
date
slug
summary
tags
category
icon
password
 
 
 
NotionNext对于cnblog站图片访问还有点问题,暂时只能访问源站了

一、引言

这是一道有关Magisk模块的题目,虽然一直在用Magisk,但是对其模块作弊机制还不是很了解,之前比赛的时候没做出来(之前没恢复OpenSSL的符号,看起来很难看放弃了),有时间翻出来再看看。难点在于这道题目是采取静态分析的手段看的,暂时没找到什么办法对模块内的so文件进行动调和Hook,之后再研究研究(在内存中找到加载so的基址后就可以使用frida进行Hook)。

二、解题

  • 将APP和题目给出的zygisk模块安装后打开APP,发现左上角出现一个作弊窗口,但是需要进行校验,这里它读取/data/data/re.ctf.flappybird/file/key.txt进行校验,如果通过才会打开作弊功能。题目中给出了另一个流量包,这个流量包有一个对/auth接口的访问流量。
notion image
  • 一般情况下对模块内的so进行分析入口点在zygisk_module_entry,这里off_4B3C08指向几个地址,其中有进行包名匹配的,也有进行Hook的,重点对Hook部分进行分析。
notion image
  • Hook部分创建一个线程,内使用DobbyHook将两so中的两个方法Hook到sub_19D0D4sub_19DF40,第二个函数内部大致是一些按键或者图像相关API,而非作弊器校验,因此主要分析19D0D4位置的函数
    • notion image
  • 19D0D4位置的函数则能够看到在Auth处进行了校验,此处的符号是需要自己猜测恢复的,则主要分析0x19D5C4位置的函数。
    • notion image
  • 分析发现逻辑大概就是打开/data/data/re.ctf.flappybird/file/key.txt读取内容并且计算sha1,拼接为token-sha1(key),附加在流量中Http头部,这里的sha1也是通过恢复符号才能分析,再后面又是很多加密操作
    • notion image
  • 重点是符号的恢复,否则后面很难看,这里可以提取手机中的libcrypto.so或者编译一份arm64架构的共享库,这里直接编译,因为编译出来的符号全一点
首先在github拉一份OpenSSL的源码,题目中so字符串中有指示版本为3.0.5 https://github.com/openssl/openssl checkout出3.0.5版本 git checkout openssl-3.0.5 然后配置NDK,先从google下一份NDK,这里用的是r25c,配好环境变量
然后编译就行 ./Configure android-arm64 -D__ANDROID_API__=21 shared no-testsmake -j4
  • 编译完成后得到libcrypto.so,直接拖入IDA,等IDA处理完成后关闭IDA并pack database。使用bindiff的IDA插件,导入libcrypto.so.i64进行比对,完成后再打开插件选择Import symbol and comments,然后相似度和置信度最小都设置为0.7即可。
    • notion image
  • 恢复后的分析会好很多,后面先是获取了DEVICE_NAME、cmdline、tcp、tcp6 等信息然后作为内容进行加密,加密完成后通过/auth接口发请求
    • notion image
  • 重点分析encypto,主要加密经过几个阶段
  1. rand 随机生成一个AES密钥
  1. 用AES密钥加密数据
  1. 用RSA公钥A加密AES密钥
  1. 拿到sha256(session_key_enc + data_enc)
  1. 用私钥B签名数据
先是通过
notion image
具体是因为在生成随机数后传入0019BBBC位置的函数,该函数是对传入的数据(即包括文件内容和其他信息的内容)进行AES-CBC加密,EVP_EncryptInit声明是这个
notion image
notion image
然后使用公钥加密随机的32字节数据,然后对结果进行了拼接
notion image
notion image
然后获取sha256摘要,这里的摘要是计算
notion image
最后使用私钥进行签名,并再次进行拼接,最终的结构就是SessionKey_enc + data_enc + sign
notion image
  • 将数据发送出去后收到响应数据,对于响应数据先是用公钥验证签名,然后用AES解密数据,但是这里的AES的密钥不是之前的随机数,而是写死的一个密钥位于byte_515220, 然后就是sub_19CDA4内有一个看起来比较复杂的解密运算,所以参考https://arcovegle.github.io/2023/04/05/XCTF%20Final%20flappy-bird-cheat/给出的方案,伪造一个服务器,直接Patch模块让它自己解包。
notion image
  • 到此并未结束,因为在Get FLag按钮被触发后会开始构造flag,在内部先是拿到sha256(DEVICE_NAME)的前16 字节的 hex,然后是服务端返回内容进行解密并且反序列化后sha256的后16字节的 hex,因此需要手动解密第一部分的DEVICE_NAME,这里用官方给出的脚本
  • 最终Flag就是flag{941d52d3ca23967191aee16dd541778da4f1a8ff674264e8c1e4e404afc1ccdd}

三、总结

总的来说这题还是很难做的。 主要问题在于单靠静态看很难看,存在大量字符串结构体和一个大的作弊结构体,还是想找个办法动调或者Hook一下。 再者就是符号恢复,不进行符号恢复看破脑袋都解不出来。 然后就是尽管恢复完符号,但是还是存在一些序列化和加密的内容,arm64架构编出来又很难看。

四、Frida Hook作弊模块的so

有时间研究了一下Magisk和zygisk注入,这块稍微熟悉了一点后回头看这道题,能够成功对模块的so进行Hook操作。
  • 在Magisk源码中如果开启了zygisk,那么在模块挂载阶段会将通过__NR_memfd_create打开对应模块的so,然后为每一个模块的so,创建匿名内存文件jit-cache并返回描述符进行保存,在后续应用启动时通过android_dlopen_ext打开描述符指向的内存,然后找到入口执行。
  • 所以就可以在模块作用的APP内存区域找到匿名的内存空间,其中jit-cache只有部分是我们的目标,直接找最低基址的即可
    • notion image
  • 也可以使用frida定位
  • 使用Frida hook EVP_EncryptUpdate可以看到这里的参数,在args[3]为输入的数据,即通过fmt构造的一些设备信息,但是这个模块没有读到/proc/self/tcp的信息,所以长度只有0x47,验证了Frida Hook的可行性
notion image
  • 也可以直接patch http的请求ip,就不需要打patch再重新安装了

五、参考

  • https://arcovegle.github.io/2023/04/05/XCTF Final flappy-bird-cheat
  • https://mp.weixin.qq.com/s?__biz=MzI2MDE4MzkzMQ==&mid=2247484521&idx=1&sn=8f5119a0cd930ce5355a6b0c9446e182&chksm=ea6cc67ddd1b4f6bdb0651408a5d03c539c65d84050519c9eb35308833357bb8c55e8c11cfb5#rd
 
Magisk V26.1 编译MRCTF2022 Stuuuuub WP
Loading...
LLeaves
LLeaves
Happy Hacking
最新发布
Uprobe及其对抗
2025-3-4
CVE-2021-0928漏洞分析
2025-3-2
ByteDance-AppShark静态分析工具
2025-3-2
Android 悬浮窗覆盖攻击
2025-3-2
基于eBPF实现一个简单的隐蔽脱壳工具-eBPFDexDumper
2025-2-28
Zygisk源码分析
2025-2-27
公告