【知识库】DDCTF2019官方Write Up——Android篇
官方Write Up发布时间线

对于没有被选手探索到的出题预设路径,出题人将现身说法,带来官方解读。
Android作者:bin233
唐山师范学院/大四/Android积分610 TOP2?
第一题:Breaking LEM
首先将apk拖入JEB进行反编译,来到入口类并找到点击事件函数。

观察到Java层只负责传递输入内容到native层,因此直接分析so文件的Java_com_didictf_guesskey2019lorenz_MainActivity_stringFromJNI函数即可。

该函数首先会将输入内容与字符串"ddctf-android-lorenz-"比较,如果输入长度不足则直接失败,否则将进行截断操作(如输入ddctf-android-lorenz-XXX将截断为XXX)。

之后会对“XXX”进行逐字符验证,字符必须属于字符串"ABCDEFGHIJKLMNOPQRSTUVWXYZ123456"。接下来就是洛伦兹加密了,在GitHub找到该算法实现,发现该算法加解密是同一个函数。因此只需要拿到密文,再让apk跑一次就是明文。不出所料,洛伦兹加密只对XXX进行加密(设加密后为YYY)。随后会对YYY进行sha256运算。

分析发现是五层sha256算法进行加密,最后与shaCorrect进行比较。通过查找交叉引用便能找到shaCorrect的真实字符串(在init_array中进行初始化)。

接下来的任务便是暴力破解该sha256,比赛当晚我就跑完了7位及以下所有字符串。最后等到了提示,是8位字符串并告诉了前两位字符。因此,将其补齐为八位字符串,就能保证经过洛伦兹加密后的前两位密文是不变的,只需要暴力破解后六位字符串即可。最终运气爆棚,倒着爆一分钟就出来了。

将爆出来的结果拼接上ddctf-android-lorenz-,让apk自动为我们解密出明文。
第二题:Have Fun
首先拖入JEB发现标识符被混淆成了不可见字符,由于文件不大,直接手动重命名反混淆。

很容易追踪到对输入内容第一次加密的函数,o()、p()函数会将Assets中的dex文件释放到一个隐藏文件夹中,还偷偷改了字节码。

Apk使用到第一代加固保护技术,通过DEXClassLoader热加载dex文件,继续跟进dexLoader函数中。

为了更快更准确的拿到dex文件,使用IDA动态调试dex,便能直接得到dex文件路径以及即将被加载的dex文件(直接从assets中拿到的dex文件算法是错误的)。

正确的算法实现如下:

接下来程序会删除该dex文件,最后调用so层函数。So文件进行了section加密,但直接静态分析就够了。从JNI_Onload中得到动态注册的三元组,并找到具体函数位置。


程序会对输入内容进行16进制转换并与内存中的固定数据进行比较,该数据如下图所示。

解题脚本如下:

第三题:不一样的Service

出题人是希望选手能找到多个干扰分支的控制点,从控制条件的逻辑分辨出正确分支。这次给的干扰分支较少,所以选手用到的爆破也可行,如果干扰分支多的话会比较耗时。
-------------------------------------------------------------
本题使用了控制流平坦化,画面实在是太美,强行带混淆调试。首先JAVA层会开启一个service参与输入内容的验证,没有什么关键逻辑,重点关注so层。从JNI_OnLoad找到动态注册的函数如下:

很容易发现如下反调试检测的函数,这里先不去关心。


接下来留意到Parcel的处理函数,创建结构体方便后续分析,动态调试中重点关注readString的调用。

单步跟踪发现如下函数会使用到readString函数(偏移0x1DB50)。


跟到如上图位置(偏移0x10458),终于拿到java层输入的内容,接着进入到sendInput1函数(偏移0x1B0D4)。

这里会发现程序使用socket将输入内容发送了出去,接着进入recvResult函数(偏移0x1470C)。

发现recv的数据竟然与send的数据不同,而且调试多次发现每次recv到的内容还都不一样,暂且放下该问题。接着接收的数据进行分析,程序会将该内容与固定的内存数据(称之为enFlag)进行比较(偏移0x8540)。


后来想到还有一个service进程,开始调试service进程。跟踪到validate函数,发现如果输入长度为32位就会返回dd字符串(并且在主进程也有对recv的结果是否为ddd的验证,否则都不会接收到那个奇怪的内容)。

第一次加密操作:单步慢慢跟进很容易发现,这里使用python实现如下:

第二次加密操作:会先保存前两个元素,后面元素每两个进行异或,处理完后将刚才保存的元素放到最后。伪代码如下:



第三次加密操作:会再与某个内存数据(称之为key)进行逐位异或,最后send出去,这就是在主线程recv的数据与send的数据不同的原因(主进程与服务进程进行socket通信,因而之前IDA只能控制主进程空间)。
将key与enFlag逐位异或就完成了一次解密,但发现最后两个元素明显不处于ASCII码表中,所以推测自己得到了一个错误的key(印证了之前recv多个不同结果的现象)。
因此先随便输入32位字符串,自行实现第一二次加密操作进行加密,然后将其与主进程recv的数据进行异或,这样就得到了多组key,必然有一个key是真实的。
将这些key继续与enFlag异或,其中一个key异或结果如下图所示。

68对应字符‘D’,而69正好是第一次加密加了下标1导致的,因此也是‘D’(不正好像DDCTF吗?可以推断出自己已经得到了正确的数据)。接下来的问题就是破解“第二次加密”了,直接无脑爆破不太现实,这里提供两种解密方式:
一、逆向猜解法:
可以推测最后一个元素数据是“}”,那么“第一次加密后”他就是“}”+31=156。所以只需要猜解倒数第二个元素,然后逆着异或。具体脚本如下:
def?myPrint(res):
????ret=[]
????for?i?in?range(32):
????????ret+=chr(res[i]-i)
????print?"".join(ret)
for?j?in?range(160):
??????ispass=0
????????flag=[?1?,?18?,?15?,?215?,?22?,?254?,?12?,?9?,?42?,?21?,?20?,?50?,?232?,?22?,?242?,?204?,?1?,?248?,?2?,?246?,?244?,?248?,?4?,?251?,?221?,?202?,?22?,?3?,?27?,?210?,?68?,?69?]
????????flag[30]=j
????????flag[31]=156
????????for?i?in?range(1,31):
????????????flag[30-i]?=?flag[32-i]^flag[30-i]
????????????if(flag[30-i]< 33?or?flag[30-i]>160):
????????????????ispass=1
????????????????break
????????if(ispass==0):
????????????flag[0]=68
????????????flag[1]=69
????????????myPrint(flag)

二、正向异或法
既然我们已经看“DD”字符串了,那么后面必然是“CTF”,正向再异或一遍,具体脚本如下:
flag=[?1?,?18?,?15?,?215?,?22?,?254?,?12?,?9?,?42?,?21?,?20?,?50?,?232?,?22?,?242?,?204?,?1?,?248?,?2?,?246?,?244?,?248?,?4?,?251?,?221?,?202?,?22?,?3?,?27?,?210?,?68?,?69?]
tmp=[]
tmp.append(flag.pop(30))
tmp.append(flag.pop(30))
tmp+=flag
tmp[2]=ord('C')+2
tmp[3]=ord('T')+3
for?i?in?range(0,30):
????tmp[i+2]=?tmp[i]?^?flag[i]
for?i?in?range(32):
????tmp[i]-=i
print?"".join(map(lambda?x:chr(x),tmp))

—————?End?—————
? ? 延伸阅读? ??
官网题目仍开放访问,点击“阅读原文“前往
? ? 关于漏洞 ? ?
滴滴出行相关漏洞请提交至
http://sec.didichuxing.com/

关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号随时掌握互联网精彩
- 1 习近平将发表二〇二六年新年贺词 7904141
- 2 2026年国补政策来了 7808738
- 3 东部战区:开火!开火!全部命中! 7712893
- 4 2026年这些民生政策将惠及百姓 7616985
- 5 小学食堂米线过期2.5小时被罚5万 7519709
- 6 解放军喊话驱离台军 原声曝光 7428214
- 7 为博流量直播踩烈士陵墓?绝不姑息 7327605
- 8 每月最高800元!多地发放养老消费券 7238391
- 9 数字人民币升级 1月1日起将计付利息 7141831
- 10 2026年1月1日起 一批新规将施行 7040675








滴滴安全应急响应中心
