在对安卓手机进行取证时,经常需要备份手机的应用程序数据,备份后得到的数据文件为ab格式。虽然大部分的取证软件都可以对ab文件进行分析,但是,有时候你可能需要解析ab文件的文件系统,然后对应用程序数据进行手动分析。ab文件一般分两种,一种是没有加密,这种文件前面有24字节的文件头,文件头包含none标志,文件头之后就是数据;一种是加密的备份文件,它的文件头就比较复杂了,文件头包含AES-256标志。
Androidbackup extractor是一个开源项目,从sourceforge和github都可以下载最新的源码,它采用java编写,因此运行的时候需要java环境。Android backup extractor可以将ab格式转换为我们熟悉的tar格式,最重要的是它同时支持没有加密和数据加密的adb备份。下面分别介绍一下转换时的命令格式:
对于没有加密的ab文件,命令格式为:java -jar abe.jar unpack
对于加密的ab文件,转换就比较麻烦,需要安装Java Cryptography Extension,可以从java官网下载文件local_policy.jar和US_export_policy.jar,复制到当前系统的java相应目录下,具体细节大家可以参考Android backup extractor的readme.txt文件。对于加密ab备份的转换,具体命令格式为:java -jar abe.jar unpack
Androidbackup extractor除了可以将ab转化为tar,还可以将tar转换为ab。例如,你需要修改一些应用程序数据,但是手机又无法root,因此可以先将手机数据备份为ab文件,将ab备份转换为tar后修改数据,然后将修改后的tar转换为ab备份,最后恢复修改后的ab备份到设备。
题目链接:adworld.xctf.org.cn/task/task_l…
下载地址:github.com/nelenkov/an…
编译安卓文件
mvn clean package
还原ab安卓备份文件
java -jar abe.jar unpack app3.ab app3.tar
package com.example.yaphetshan.tencentwelcome;
import android.content.ContentValues;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import com.example.yaphetshan.tencentwelcome.a.a;
import net.sqlcipher.database.SQLiteDatabase;
/* loaded from: classes.dex */
public class MainActivity extends AppCompatActivity implements View.OnClickListener {private SQLiteDatabase a;private a b;private Button c;/* JADX INFO: Access modifiers changed from: protected */@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityGingerbread, android.app.Activitypublic void onCreate(Bundle bundle) {super.onCreate(bundle);setContentView(R.layout.activity_main);this.c = (Button) findViewById(R.id.add_data);this.c.setOnClickListener(this);SharedPreferences.Editor edit = getSharedPreferences("test", 0).edit();edit.putString("Is_Encroty", "1");edit.putString("Encryto", "SqlCipher");edit.putString("ver_sion", "3_4_0");edit.apply();a();}private void a() {SQLiteDatabase.loadLibs(this);this.b = new a(this, "Demo.db", null, 1);ContentValues contentValues = new ContentValues();contentValues.put("name", "Stranger");//用户名contentValues.put("password", (Integer) 123456);//密码a aVar = new a();String a = aVar.a(contentValues.getAsString("name"), contentValues.getAsString("password"));//Stra1234 函数1在下面this.a = this.b.getWritableDatabase(aVar.a(a + aVar.b(a, contentValues.getAsString("password"))).substring(0, 7));//函数2在下面this.a.insert("TencentMicrMsg", null, contentValues);}@Override // android.view.View.OnClickListenerpublic void onClick(View view) {if (view == this.c) {Intent intent = new Intent();intent.putExtra("name", "name");intent.putExtra("password", "pass");intent.setClass(this, AnotherActivity.class);startActivity(intent);}}
}
函数1
public String a(String str, String str2) {String substring = str.substring(0, 4);return substring + str2.substring(0, 4);
}
执行结果:Stra1234
SQLiteDatabase.loadLibs(((Context)this));
将所需要的 sqlitecipher 库文件加载进来。name:Stranger
、 password:123456
放入其中。com.example.yaphetshan.tencentwelcome.a.a
类。getWritableDatabase
函数,传进去的字符串参数即是数据库解密的密钥。现在目标已经很明确了,就是获取数据库解密密钥(猜一下 flag 就藏在加密的 sqlite 数 据库中),而该密钥由com.example.yaphetshan.tencentwelcome.a.a
里面的方法生成,而 这个类又调用了 b.java 里面的方法,如图所示:
package com.example.yaphetshan.tencentwelcome.a;
import java.security.MessageDigest;
/* compiled from: SHA1Manager.java */
/* loaded from: classes.dex */
public class b {public static final String a(String str) {char[] cArr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};try {byte[] bytes = str.getBytes();MessageDigest instance = MessageDigest.getInstance("MD5");instance.update(bytes);byte[] digest = instance.digest();int length = digest.length;char[] cArr2 = new char[length * 2];int i = 0;for (byte b : digest) {int i2 = i + 1;cArr2[i] = cArr[(b >>> 4) & 15];i = i2 + 1;cArr2[i2] = cArr[b & 15];}return new String(cArr2);} catch (Exception e) {return null;}}public static final String b(String str) {char[] cArr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};try {byte[] bytes = str.getBytes();MessageDigest instance = MessageDigest.getInstance("SHA-1");instance.update(bytes);byte[] digest = instance.digest();int length = digest.length;char[] cArr2 = new char[length * 2];int i = 0;for (byte b : digest) {int i2 = i + 1;cArr2[i] = cArr[(b >>> 4) & 15];i = i2 + 1;cArr2[i2] = cArr[b & 15];}return new String(cArr2);} catch (Exception e) {return null;}}
}
import java.security.MessageDigest;
class SHA1Manager {public static final String m24a(String str) {char[] cArr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};try {byte[] bytes = str.getBytes();MessageDigest instance = MessageDigest.getInstance("MD5");instance.update(bytes);// 这里的r4是自己添加的,为了程序正常运行int r4 = instance.getDigestLength();char[] cArr2 = new char[(r4 * 2)];int i = 0;for (byte b : instance.digest()) {int i2 = i + 1;cArr2[i] = cArr[(b >>> 4) & 15];i = i2 + 1;cArr2[i2] = cArr[b & 15];}return new String(cArr2);} catch (Exception e) {return null;}}/* renamed from: b */public static final String m25b(String str) {char[] cArr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};try {byte[] bytes = str.getBytes();MessageDigest instance = MessageDigest.getInstance("SHA-1");instance.update(bytes);// 这里的r4是自己添加的,为了程序正常运行int r4 = instance.getDigestLength();char[] cArr2 = new char[(r4 * 2)];int i = 0;for (byte b : instance.digest()) {int i2 = i + 1;cArr2[i] = cArr[(b >>> 4) & 15];i = i2 + 1;cArr2[i2] = cArr[b & 15];}return new String(cArr2);} catch (Exception e) {return null;}}public static void main(String[] args){String s = SHA1Manager.m25b("Stra1234" + SHA1Manager.m24a("Stra1234") + "yaphetshan").substring(0, 7);System.out.println(s);}
}
this.f32a = this.f33b.getWritableDatabase(aVar.mo6316a(a + aVar.mo6318b(a, contentValues.getAsString("password"))).substring(0, 7));也就是 ⬇
this.f32a = this.f33b.getWritableDatabase("ae56f99");
得到:ae56f99
用ae56f99登录数据库找到:VGN0ZntIM2xsMF9Eb19ZMHVfTG92M19UZW5jM250IX0=