欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

程序员文章站 2022-05-15 19:31:24
...

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

一、题目来源

    题目来源:XCTF app3题目


二、解题过程

    1、下载好题目,下载完后发现是.ab后缀名的文件,如下图所示:

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

    2、什么是.ab文件?.ab后缀名的文件是Android系统的备份文件格式,它分为加密和未加密两种类型,.ab文件的前24个字节是类似文件头的东西,如果是加密的,在前24个字节中会有AES-256的标志,如果未加密,则在前24个字节中会有none的标志,如下图所示:

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

    3、怎么获取.ab文件中的数据?在github上有个开源项目Android backup extractor可以将.ab文件转换为.tar文件,然后用解压软件打开即可!!!项目地址:https://github.com/nelenkov/android-backup-extractor

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

    4、使用ade.jar将1.ab文件转为tar文件解压发现有一个apk文件和两个sqlite数据库文件,将apk安装到夜神中,发现没什么有用的东西,去查看数据库,直接使用sqlitebrowser打开,提示需要密码,看来数据库多半被加密了,如下图所示:

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

    5、直接使用AndroidKiller和jeb将该APK反编译,发现了存在asset目录和libs目录,并且这两个目录下存放了和sqlitecipher相关的文件,可以推断数据库被sqlitecipher加密了,再搜索一下在夜神里点击登陆后弹出的信息Wait …,发现该信息在AnotherActivity.java文件中,转为java后,发现没什么有用的信息。。。

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

    6、于是打开MainActivity.java文件,果然发现了一个函数a(),代码如下:

private void a() {
    SQLiteDatabase.loadLibs(((Context)this));
    this.b = new a(((Context)this), "Demo.db", null, 1);
    ContentValues v0 = new ContentValues();
    v0.put("name", "Stranger");
    v0.put("password", Integer.valueOf(123456));
    com.example.yaphetshan.tencentwelcome.a.a v1 = new com.example.yaphetshan.tencentwelcome.a.a();
    String v2 = v1.a(v0.getAsString("name"), v0.getAsString("password"));
    this.a = this.b.getWritableDatabase(v1.a(v2 + v1.b(v2, v0.getAsString("password"))).substring(0, 7));
    this.a.insert("TencentMicrMsg", null, v0);
}
  • 第一行SQLiteDatabase.loadLibs(((Context)this));将所需要的sqlitecipher库文件加载进来。
  • 第二行实例化一个sqlitehelper类。
  • 第三、四、五行实例化了一个ContentValues类并将键值对name:Strangerpassword:123456放入其中。
  • 第六行实例化了一个com.example.yaphetshan.tencentwelcome.a.a类。
  • 第七行获取了v2变量的值。
  • 第八行调用了getWritableDatabase函数,传进去的字符串参数即是数据库解密的**。

    7、现在目标已经很明确了,就是获取数据库解***(猜一下flag就藏在加密的sqlite数据库中),而该**由com.example.yaphetshan.tencentwelcome.a.a里面的方法生成,而这个类又调用了b.java里面的方法,如图所示:

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

    8、a、b类里面生成**的算法涉及到了sha-1、md5等算法,没必要去重新写一编,搞清楚**生成逻辑然后把b类里面的两个函数复制出来调用即可生成**,简单分析一下**生成逻辑:首先得到变量v2,v2调用了a类中的a(String,String)方法获取,该方法返回第一个参数前四个字符加第二个参数的前四个字符,而调用该方法传进去的参数为(Stranger,123456),所以v2 = Stra1234,**为v1.a(String).sunstring()(调用v1.a()方法然后将返回值截取前7位作为**),关键就在传进去的这个字符串,可以看到这个字符串是v2 + v1.b(v2,'123456'),而v1.b(String,String)这个函数将调用了b类的a(String)函数,传进去的参数是变量v2,获取到返回值后,我们就可以得到这个字符串,然后调用v1.a(String)函数得到**,这个函数将传进去的字符串加上yaphetshan字符串作为参数调用b类的b方法,其返回值取前7位即是**,写了一个java获取**的代码,运行结果如下(ps:代码粘贴在文末中):

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

    9、获取到**后,使用sqlitebrowser打开加密数据库,发现了一串Base64的字符串,解码得到了flag

从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库


三、总结

    刚下载下来题目发现一看后缀名就慌了,重来没见过的文件了,百度了n久,终于弄懂了android备份文件和ssqlitecipher这两个东西。
    给大家分享一下有关这两个东西的知识点我觉得写的比较好的博客!!!


四、附件

    题目以及所用到的工具:百度网盘链接https://pan.baidu.com/s/1Wam_Hjg8rNlpqywVqqASpQ,密码0y89

    获取**java代码如下:

import java.security.MessageDigest;
import java.util.*;

public class b {
    public b() {
        super();
    }
	
	public static void main(String[] args)
	{
		String varV2 = "Stra1234";
		String varV1B = a(varV2);
		String varKey = varV2 + varV1B + "yaphetshan";
		System.out.print("KEY = ");
		System.out.print(b(varKey).substring(0,7));
	}

    public static final String a(String arg9) {
        String v0_2;
        int v0 = 0;
        char[] v2 = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            byte[] v1 = arg9.getBytes();
            MessageDigest v3 = MessageDigest.getInstance("MD5");
            v3.update(v1);
            byte[] v3_1 = v3.digest();
            int v4 = v3_1.length;
            char[] v5 = new char[v4 * 2];
            int v1_1 = 0;
            while(v0 < v4) {
                int v6 = v3_1[v0];
                int v7 = v1_1 + 1;
                v5[v1_1] = v2[v6 >>> 4 & 15];
                v1_1 = v7 + 1;
                v5[v7] = v2[v6 & 15];
                ++v0;
            }

            v0_2 = new String(v5);
        }
        catch(Exception v0_1) {
            v0_2 = null;
        }

        return v0_2;
    }

    public static final String b(String arg9) {
        String v0_2;
        int v0 = 0;
        char[] v2 = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            byte[] v1 = arg9.getBytes();
            MessageDigest v3 = MessageDigest.getInstance("SHA-1");
            v3.update(v1);
            byte[] v3_1 = v3.digest();
            int v4 = v3_1.length;
            char[] v5 = new char[v4 * 2];
            int v1_1 = 0;
            while(v0 < v4) {
                int v6 = v3_1[v0];
                int v7 = v1_1 + 1;
                v5[v1_1] = v2[v6 >>> 4 & 15];
                v1_1 = v7 + 1;
                v5[v7] = v2[v6 & 15];
                ++v0;
            }

            v0_2 = new String(v5);
        }
        catch(Exception v0_1) {
            v0_2 = null;
        }

        return v0_2;
    }
}