安卓逆向|菜鸟的objection学习笔记:分析一个简单的CTF
本文所使用的样本app来自于XCTF社区,如有侵权,请告知删除,谢谢。
安装后打开app,随便输入一个字符串,提示:"Failed"。
将apk拖入jadx,搜索"Failed"定位到这里:
看着逻辑很简单,只要:
getSecret(getFlag()).equals(getSecret(encrypt(this.etFlag.getText().toString())))
这行代码的返回值为真即可。
这里有三个方法,分别是"getSecret","getFlag","encrypt",发现都在这个
"MainActivity"类下面,因此,我们使用objection来监视这三个方法:
Hook getFlag 方法的命令:
android hooking watch class_method com.ph0en1x.android_c rackme.MainActivity.getFlag --dump-args --dump-backtrace --dump-return
Hook encrypt 方法的命令:
android hooking watch class_method com.ph0en1x.android_c rackme.MainActivity.encrypt --dump-args --dump-backtrace --dump-return
Hook getSecret 方法的命令:
android hooking watch class_method com.ph0en1x.android_c rackme.MainActivity.getSecret --dump-args --dump-backtrace --dump-return
这个时候,我们输入一个字符串,有结果了:
getFlag 方法返回的字符串:
ek`aaa@qq.com^x/t^fn0mF^6/^rb`qanqntfg^E`hq|
encrypt 方法返回的字符串:
实参为"KE3TLNE6M43EK4GM34LKMLETG"时,返回了:
JD2SKMD5L32DJ3FL23KJLKDSF
在jadx中看到getSecret方法有这么一行代码:
byte[] hash = MessageDigest.getInstance(encrypt("KE3TLNE6M43EK4GM34LKMLETG").substring(5, 8)).digest(string.getBytes("UTF-8"));
其中:
encrypt("KE3TLNE6M43EK4GM34LKMLETG").substring(5, 8)
结果替换进来,也就是:
JD2SKMD5L32DJ3FL23KJLKDSF.substring(5, 8)
刚好是"MD5",原来getSecret方法就是一个对字符串进行md5的摘要哈希。这样逻辑就清晰了,只需要 getFlag 方法的结果与
encrypt(this.etFlag.getText().toString())
相同即可, 而getFlag的结果是:
ek`aaa@qq.com^x/t^fn0mF^6/^rb`qanqntfg^E`hq|
所以只需要弄懂 encrypt 方法即可。
从实参"KE3TLNE6M43EK4GM34LKMLETG" 和结果:
"JD2SKMD5L32DJ3FL23KJLKDSF"大致可以猜出这个方法是干嘛的。
K - 1 = J
E - 1 = D
3 - 1 = 2
T - 1 = S
..........
这就显而易见了。
因此
ek`aaa@qq.com^x/t^fn0mF^6/^rb`qanqntfg^E`hq|
在经过encrypt 方法前的字符串是:
flag{Ar3_y0u_go1nG_70_scarborough_Fair}
将这个字符串输入到输入框中,结果是正确的:
还原的Python代码:
s = "ek`aaa@qq.com^x/t^fn0mF^6/^rb`qanqntfg^E`hq|";
r = [chr(ord(ch)+1) for ch in s]
print (''.join(r))
样本下载地址:
https://adworld.xctf.org.cn/media/task/attachments/f6adc401d0eb472892a4ac4481f76a85.apk
上一篇: 20行C语言递归求十进制转换为二进制
下一篇: C#十进制转二进制