前言
上周末前公司内部组织了一年一度的CTF比赛。作为一个mobile小白,花了一天时间才做出这道题,踩了很多坑的同时也收获了很多,特此记录一下。
题目描述
根据弹出的提示,并得到一串字符。
附件中是一个apk,打开后只有一个界面。
反编译apk
使用jadx-gui打开apk,看反编译代码:
先看入口MainActivity。使用DES解密函数解密一个base64字符串,将结果传入getflag函数(该函数是通过native接口调用的so库中的函数),对比getflag结果和在界面上输入的key值。如果不一致,显示“这是个陷阱,快醒醒!”,如果一致,提示“再使用函数获取 Flag”。
其中DES解密函数在CryptoUtil类:
乍一看,需要让这个判断相等,就能得到flag。现在回过头看,这里并没有获取flag的代码,仅仅是弹一个消息框。
apk中还有另外两个资源文件:Addon.jar
和libnative.so
。前者是MainApplication.java中使用,用于通过字节异或的方式生成CryptoUtil.jar,调用其中的DES解密方法进行解密。后者是通过native接口加载,调用其getflag方法。
对于一个小白来说,每个线索都不想放过,所以我针对Addon.jar一顿研究和操作,最后得到的代码是这样的:
WTF??!解密函数直接throw一个异常。上当的我这才发现事情不对,转去研究libnative.so。
逆向so库
ida打开,定位getFlag函数:
大致逻辑为:对一个字符串先进行base64解密,再进行AES解密,返回最后的result。中间穿插着各种无用的代码。。
字符串是已知的,双击texta就能刚看到:
接下来解决AES解密。
AES解密
首先要知道,AES解密需要有密文、密钥、初始向量、密钥长度、填充模式、加密模式。decryptAES256cbc函数已经告诉了密钥长度是256位(32字节)、加密模式cbc。初始向量iv双击也可以看到,仅剩密钥未知。
目光聚焦至v7变量。v7调用了GetStringUTFChars函数(该函数声明如下),获取了传入的参数a3的地址。
根据MainActivity中对getflag的调用,传入的参数是一串密文经过base64和DES解密后的值。盲猜这个解密后的密文就是这里的密钥。
对MainActivity中的密文进行base64
+DES
解密,得FebRuAry*29th^TweNty-0ne_hUndrEd
,刚好32位。
参数齐了,在线AES解密一波,得flag。
参考链接
Inception.zip (2.0 MB)