- 前言
- 1.ab文件
- 2.Android backup extractor
- 一、app3
- 二、答题步骤
- 1.Android backup extractor
- 2.jadx反编译apk文件
- 总结
前言 1.ab文件
在对安卓手机进行取证时,经常需要备份手机的应用程序数据,备份后得到的数据文件为ab格式。虽然大部分的取证软件都可以对ab文件进行分析,但是,有时候你可能需要解析ab文件的文件系统,然后对应用程序数据进行手动分析。ab文件一般分两种,一种是没有加密,这种文件前面有24字节的文件头,文件头包含none标志,文件头之后就是数据;一种是加密的备份文件,它的文件头就比较复杂了,文件头包含AES-256标志。
2.Android backup extractorAndroidbackup 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备份到设备。
一、app3题目链接:https://adworld.xctf.org.cn/task/task_list?type=mobile&number=6&grade=0&page=1
二、答题步骤 1.Android backup extractor下载地址:https://github.com/nelenkov/android-backup-extractor
编译安卓文件
mvn clean package
会生成target文件夹
还原ab安卓备份文件
java -jar abe.jar unpack app3.ab app3.tar
接下来解压app3.tar,一番搜寻后,发现了base.apk,也就是我们需要分析的程序
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; public class MainActivity extends AppCompatActivity implements View.onClickListener { private SQLiteDatabase a; private a b; private Button c; @Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.baseFragmentActivityGingerbread, android.app.Activity public 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.OnClickListener public 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 库文件加载进来。
- 第二行实例化一个 sqlitehelper 类。
- 第三、四、五行实例化了一个 ContentValues 类 并 将 键 值 对 name:Stranger 、
password:123456放入其中。 - 第六行实例化了一个com.example.yaphetshan.tencentwelcome.a.a类。
- 第七行获取了 v2 变量的值。
- 第八行调用了getWritableDatabase函数,传进去的字符串参数即是数据库解密的密钥。
现在目标已经很明确了,就是获取数据库解密密钥(猜一下 flag 就藏在加密的 sqlite 数
据库中),而该密钥由com.example.yaphetshan.tencentwelcome.a.a里面的方法生成,而
这个类又调用了 b.java 里面的方法,如图所示:
函数2
package com.example.yaphetshan.tencentwelcome.a; import java.security.MessageDigest; 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; } } 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=
base64进行解密得到本题最终的flag:Tctf{H3ll0_Do_Y0u_Lov3_Tenc3nt!}
总结
- Android backup extractor
- jadx
- base64
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)