收获

  • 当给出的 apk 中缺失某个关键函数时,有可能藏在 so 文件里头

  • 涉及到 AES 编码时,例如 AES128 的解密用到字节编码,最好是使用 python 脚本进行解密


(2023年3月30日)【楚慧杯 2023】Level_up


思路

下载解压得到 chall 文件夹:

湖北省第七届楚慧杯-Level_up1.png

注意文件夹里的内容,chall.apk 是打包好的安卓程序,challchall.apk 的源文件,chall.apk.cache 是缓存文件(具体干什么用的不太清楚)

用 jadx-gui 打开 chall.apk,定位到 MainActivity

湖北省第七届楚慧杯-Level_up2.png

注意到关键判断语句:

湖北省第七届楚慧杯-Level_up3.png

将用户的输入、用户输入的长度作为参数,经过 check() 函数进行处理,如果校验成功就显示 “right!!!”

点击 check() 函数,发现程序里只有 check() 函数的声明,却没有函数的内容:

湖北省第七届楚慧杯-Level_up4.png

在程序中搜索 check 关键字依然一无所获

然后比赛的时候进行到这里,我就一直卡在从程序中寻找 check() 函数的逻辑
(有一部分原因可能也是受了前面一道题 Level_One 的影响,以为校验逻辑就在程序里)

后来看了其他队伍【丝绒Velvet】的 Writeup 我才恍然大悟
2023湖北省第七届“楚慧杯”网络空间安全实践能力竞赛-预赛 -丝绒WP
其实这里是用到了动态链接库 so,check() 函数在源代码中没有,但是会从 so 文件中引用

chall 文件夹内查看:

湖北省第七届楚慧杯-Level_up5.png

通过与 jadx-gui 反编译出来的内容进行比对,发现后面这几个文件都是在程序中存在的,只有这个 lib 文件夹中的内容在程序中没有包含

查看 lib 的内容:

湖北省第七届楚慧杯-Level_up6.png

发现这四个文件夹里各有一个文件名为 libmobile2.so 的文件

湖北省第七届楚慧杯-Level_up7.png

但是在第一个文件 arm64-v8a 内,是这样的:

湖北省第七届楚慧杯-Level_up8.png

注意到除 libmobile2.so 外其他文件的后缀,.id0.id1.id2 这不就是 IDA 留下的数据库文件吗

在 exeinfo PE 中看看:

湖北省第七届楚慧杯-Level_up9.png

64 位 elf 文件,用 IDA 打开,选择直接打开现存的数据库文件:

在函数中搜索 main,定位到主函数

湖北省第七届楚慧杯-Level_up10.png

查看一下字符串,shift + F12,发现端倪:

湖北省第七届楚慧杯-Level_up11.png

跟进 gOuWlCTi+hhzCn6rWxDm8IuuBwiOtM+V/m39bthXTeT3E6WYrLU0CDqG76Kvpkmc 所在地址:

湖北省第七届楚慧杯-Level_up12.png

发现他们定义在 start() 函数中

根据形式,函数 std::string::basic_string<decltype(nullptr)> 应该是字符串复制操作
key = "followyourheart!"
enc = "gOuWlCTi+hhzCn6rWxDm8IuuBwiOtM+V/m39bthXTeT3E6WYrLU0CDqG76Kvpkmc"
得到了 main() 函数中的密文 enc,还得到了一个 key 应该是某种加密的密钥

同时,还注意到字符串中有 Base64 加密的码表:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
但是 Base64 本身是不需要密钥的,猜测可能有多种加密方法

继续关注 main() 函数
很明显注意到这里有一个加密函数:

湖北省第七届楚慧杯-Level_up13.png

跟进,到 encode() 函数:

湖北省第七届楚慧杯-Level_up14.png

加密方式已经告知了,一个 AES128,一个 Base64,结合前面观察到的字符串,大体已经可以确定了

由于在 main() 函数中,发现 cipher::Encrypt::encode() 之后虽然有一大堆代码,但是并没有改变 enc 的值

根据代码的意思,加密流程是先对明文进行 AES128(ECB) 加密(密钥是 followyourheart!),然后进行 Base64 加密,得到密文 enc
因此先对 enc 进行 Base64 解码,然后进行 AES128(ECB) 解码,即可得到 flag

但是注意,AES128 是按照 16字节(128 bit)为一组进行加密,所以这里要对字节进行操作
使用普通的在线网站进行解密是不行的,例如:

湖北省第七届楚慧杯-Level_up15.png

因此,利用 python 脚本进行解码


脚本

import base64  
from Crypto.Cipher import AES  
  
enc = b'gOuWlCTi+hhzCn6rWxDm8IuuBwiOtM+V/m39bthXTeT3E6WYrLU0CDqG76Kvpkmc'  
key = b'followyourheart!'  
  
string1 = base64.b64decode(enc)  # 先对enc进行Base64解密  
  
string2 = AES.new(key, AES.MODE_ECB)  # 创建一个AES对象string2,根据题意是ECB加密模式  
flag = string2.decrypt(string1)  # AES128 ECB解密  
  
print(flag)

结果

flag{6b1df900-1284-11ed-9fa7-5405dbe5e745}

湖北省第七届楚慧杯-Level_up16.png