XCTF_MOBILE4_app3

下载附件后是一个.ab文件。无其它提示信息。

ab文件

百度一下,.ab 后缀名的文件是 Android 系统的备份文件格式。

分为加密和未加密两种类型,.ab 文件的前 24 个字节是类似文件头的东西,如果是加密的,在前 24 个字节中会有 AES-256 的标志,如果未加密,则在前 24 个字节中会有 none 的标志。

用UE打卡这个样本,看到文件头中有none:

 表明未加密。

可以通过abe.jar(android-backup-extractor)将其转换成.tar文件然后进行解压。

用法:java -jar abe.jar unpack xxx.ab xx.tar:

 解压后目录如下:

 目录a下有个base.apk:

题目提供ab文件就是这个apk的备份,我们下面重点分析它。

APK

拖到模拟器里运行一下:

 随便输入用户名和密码,点击登录,弹出一条提示信息,让等几分钟:

 不知道要等什么,我们就把它放在那里不管了,先反编译一下。

反编译

老步骤,apk重命名为zip,解压,使用dex2jar反编译解压后的dex:

 用jd-gui打开得到的jar,找到MainActivity,先看构造函数:

构造函数主要工作:

  • 调用setOnClickListener将自身设置为按钮点击事件响应函数,也就是点击按钮会调用MainActivity的onClick函数。
  • 通过putString向数据存储区存入三个值
  • 调用函数a

函数a的反编译代码为:

 主要工作为:

  1. 打开数据库Demo.db
  2. 创建ContentValues对象并设置两个值
  3. 以不同参数调用类a的a、b、a函数计算数据库密码
  4. 以算出的密码打开数据库并插入数据

我们从tar解压后的内容中有两个db,一个Demo.db,一个Encrypto.db,并且这两个数据库都是有密码的,猜测这道题的重点就是获得密码,解密这两个数据库。

这次我们换一个思路,不去搞清计算密码的算法到底是啥,而是通过在Smali代码中插入LOG来将原程序计算好的密码输出到日志。

根据函数a的反编译代码,结合资料搜集,我们能知道getWritableDatabase函数是用来打开并得到数据库对象的函数,它的参数就是数据库的密码。在这里密码就是str1字符串的前7个字符。

我们只要在调用getWritableDatabase函数的代码之前插入Log函数,打印str1字符串就能得到密码。

修改Smali

首先使用apktool得到smali代码。Apktool能将apk反编译得到Smali代码。

Apktool会创建一个apk同名的目录,保存反编译的内容。为了不和之前zip解压的目录名冲突,这里我们将apk备份一个,重命名为base1.apk,之后对base1.apk进行操作。

使用apktool反编译base1.apk:

 在apktool生成的目录中,我们找到MainActivity的Smali文件:

用文本编辑器打开MainActivity.smali,根据前面对jar的分析我们知道,数据库密码在MainActivity类的a函数中计算得到。在该smali文件中搜索getWritableDatabase,找到调用getWritableDatabase函数的代码:

.line 55
iget-object v2, p0, Lcom/example/yaphetshan/tencentwelcome/MainActivity;->b:Lcom/example/yaphetshan/tencentwelcome/a;

const/4 v3, 0x0

const/4 v4, 0x7

invoke-virtual {v1, v3, v4}, Ljava/lang/String;->substring(II)Ljava/lang/String;

move-result-object v1

invoke-virtual {v2, v1}, Lcom/example/yaphetshan/tencentwelcome/a;->getWritableDatabase(Ljava/lang/String;)Lnet/sqlcipher/database/SQLiteDatabase;

move-result-object v1

iput-object v1, p0, Lcom/example/yaphetshan/tencentwelcome/MainActivity;->a:Lnet/sqlcipher/database/SQLiteDatabase;

从中可以看出,第一个invoke-virtual调用substring来截取子串,这和jar代码一致。这里的第一个参数v1就是完整的字符串,也就是我们想获得的内容。

直接在这段代码前面插入smali代码,调用Log函数:

.line 55
invoke-static {v1, v1}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I

.line 56
iget-object v2, p0, Lcom/example/yaphetshan/tencentwelcome/MainActivity;->b:Lcom/example/yaphetshan/tencentwelcome/a;

const/4 v3, 0x0

const/4 v4, 0x7

invoke-virtual {v1, v3, v4}, Ljava/lang/String;->substring(II)Ljava/lang/String;

move-result-object v1

invoke-virtual {v2, v1}, Lcom/example/yaphetshan/tencentwelcome/a;->getWritableDatabase(Ljava/lang/String;)Lnet/sqlcipher/database/SQLiteDatabase;

move-result-object v1

iput-object v1, p0, Lcom/example/yaphetshan/tencentwelcome/MainActivity;->a:Lnet/sqlcipher/database/SQLiteDatabase;

这里我们调用Log函数时,两个参数都设置为v1。

这里要注意,Log函数调用语句占用源代码中的一行,在这里就占据了.line 55。所以smali代码中后面的所有行号都要+1。

修改之后使用apktool打包成apk:

这里打包好的apk是没有签名的,无法安装。需要使用signapk进行签名:

到这里修改后的APK就准备好了。

查看LOG得到FLAG

打开Android Studio,在底部切换到Logcat窗口。左上角的下拉菜单是设备列表,这里选择我们的模拟器:

 在模拟器中安装并运行修改后的apk,在Logcat窗口中就看到了密码:

 用字符串的前7个字符解密Encryto.db,得到FLAG:

 FLAG字符串以=结尾,怀疑是BASE64编码后的,对这个字符串进行BASE64解码,就得到了最终结果:

Tctf{H3ll0_Do_Y0u_Lov3_Tenc3nt!}

欢迎关注我的微博:大雄_RE。专注软件逆向,分享最新的好文章、好工具,追踪行业大佬的研究成果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值