论坛首页 逆向工程技术区 阅读主题

[原创]强网杯s9初赛 Qcalc wp

490 浏览 0 回复
#1 楼主 2026-06-01 21:08:55
MainActivity可通过qiangcalc://calculate形式的uri启动

MainActivity收到intent时会调用handleIntent方法

handleIntent会判断Action并取出其中的expression参数并传入processDeeplinkExpression中

processDeeplinkExpression会判断传入的expression是否为intent scheme,是的话将该uri转成intent并存入顶层intent的fallback参数中,并计算哈希一并存入。如果是普通的表达式的话,该方法会取出表达式的两个操作数并调用onEqual()进行计算

onEqual中值得注意的是除法,如果除以0会抛出除0异常,并交由异常处理来处理。catch中取出了fallback并存入了一些新的参数(作用不大),最后将fallback作为bridgeIntent的参数origIntent传入,并启动BridgeActivity

BridgeActivity首先会对传入的intent进行校验,大部分的参数都是onEqual中硬编码的所以不会错,唯一需要注意的是this.validateToken方法,对bridge_token参数进行了校验,将其与包名的sha256进行了比较,这个参数在之前都没有出现过,所以是一开始就要在fallback对应的intent scheme里就要传入

验证通过后,为origIntent赋予通过provider读写(addFlags(3))/data/data/com.qinquang.calc/files/history.yml的权限并启动Activity
上面的分析中,我们最后发现有一个content provider,该provider不导出,但设置了grantUriPermissions=“true”,这样我们可以传入intent来调用该provider。但是目标apk中唯一授权的只有/data/data/com.qinquang.calc/files/history.yml,意味着我们不能直接通过provider读取flag只能读写history.yml

HistoryManager.loadHistory中通过yaml.load反序列化了history.yml文件,并判断其是否为intent,是的话就启动该intent。但是我们在上面已经可以构造一个intent了,再构造一个意义不大

注意到有一个没调用过的类PingUtil,很明显的后门函数,命令拼接,那我们可以直接利用上面的反序列化执行该类的init方法从而实现命令执行

本来考虑直接通过网络传出flag或者先写入外部存储然后再读取,但很不幸apk没有这两个权限。考虑到我们可以对history.yml进行读取,我们可以将flag写入yml文件中再进行读取。剩下的问题就是如何触发反序列化了,loadHistory在onCreate和saveHistory中有调用,saveHistory在onEqual的末尾有调用,我们可以通过传入intent进行一次正常的运算来调用saveHistory但在saveHistory中,调用完loadHistory后他会对yml进行覆写,会把我们的flag给清掉,所以我们需要卡一个timing,在写入flag后和flag被覆写前趁机读取出flag,这就要自己延时慢慢调了
综上,利用链可总结为:由于是复现,就不将flag发送到外网了,这里就直接将flag写到log里,exp如下在日志里获得flag
package com.example.qcalc;

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-289052.htm

暂无回复,快来抢沙发吧!

请登录后参与讨论

立即登录 注册账号