23柏鹭杯-misc
我记得比赛的时候,misc都是0解。
怎么不算另类的1血呢?
help_me实在不会,arm看不了一点
消失的钥匙
先看验证逻辑,能够看到generateZipPassword
和decryptFlag
这两个方法内容不见了
通过在apk中寻找半年,找到一个时间不对的classes3.dex
,查看hex发现是gz压缩
导出解压一下,拿到了一半的dex
再根据时间线索,找到另一个文件
将两个文件合并,得到完整的dex
getPackageSignature
这个方法hook一下,拿到了返回值748124a9239a8f2d79a0de294fbba042
Java.perform(function () {
Java.choose('com.example.test.MainActivity',{
onMatch: function(instance){
console.log(instance.getPackageSignature())
},
onComplete: function(){}
})
})
这里可以确定748124a9239a8f2d79a0de294fbba042
是key,com.example.test
的MD5取前16位是iv
最后密码是对包名后16位进行aes加密,取16-48位,即231287ee4876a3fed4a34bac962d513e
之后解密
采用fridahook的方式,来直接模拟执行其中的方法
Java.perform(function () {
Java.choose('com.example.test.MainActivity', {
onMatch: function (instance) {
var pwd = '231287ee4876a3fed4a34bac962d513e'
var zipContent = instance.zipDecrypt(pwd)
let Flag = Java.use("com.example.test.FlagOuterClass$Flag").$new();
let flagContent = Flag.parseFrom(zipContent)
var key = flagContent.getKey()
var iv = flagContent.getIv()
var keyString = Java.use('java.lang.String').$new(key) //转成Java中的String,来获得getBytes方法
var ivString = Java.use('java.lang.String').$new(iv)
let AESUitls = Java.use('com.example.test.AESUtils').$new(keyString.getBytes(),ivString.getBytes())
console.log(AESUitls.decrypt(flagContent.getFlag(),true))
},
onComplete: function () { }
})
})
最后的flag为flag{ISEC-C4n_U_f1nd_th3_10st_2Ip_p455Word}
代码吞噬者(寻找病毒进化的密码)
这题好像是当时平台答案不对,导致0解
通过反射加载decode.dex,执行代码
loadKey中再次反射
在patch目录下处理dxdiff,但是该文件不会被保留
考虑到dxdiff已经加载到内存,因此直接dump
拿到了代码
根据对password的判断,拿到了输入的明文
_dict = "9>AG3OCP1N2-4L5K6M7+BQD&EVF=0@8$"
password = '+>M=+K-@MN+-MK-@MN++MK+OM=M&MK'
for i in range(len(_dict)-1,-1,-2):
c2 = _dict[i]
c1 = _dict[i-1]
password = password.replace(c2,c1)
print(bytes.fromhex(password))
# you are awesome
读取了DIFF_HEX
,又进行了一次更新
但是在更新之前,将update_1_.dex
删除了
因此对delete进行hook,直接阻止删除
Java.perform(function () {
let File = Java.use("java.io.File");
File["delete"].implementation = function () {
return 0
};
});
本质上就是对解密后的dict和diff进行md5计算