Article catalog
preface
1.ab documents
When obtaining evidence for Android phones, it is often necessary to back up the application data of the phone. The data file obtained after backup is in ab format. Although most forensics software can analyze ab files, sometimes you may need to parse the file system of ab files and then manually analyze the application data. ab files are generally divided into two types. One is not encrypted. This file is preceded by a 24 byte file header, which contains the none flag, followed by data; One is an encrypted backup file. Its file header is more complex. The file header contains AES-256 flag.
2.Android backup extractor
Android backup extractor is an open source project. You can download the latest source code from sourceforge and github. It is written in java, so it needs a java environment when running. Android backup extractor can convert ab format to tar format we are familiar with. The most important thing is that it supports adb backup without encryption and data encryption at the same time. The following describes the command format during conversion:
For ab files without encryption, the command format is: Java - jar Abe jar unpack . If the execution is successful, there is no information prompt; If an error message appears, the ab file may be damaged and a backup needs to be made again.
For encrypted ab files, the conversion is troublesome. You need to install Java Cryptography Extension. You can download the file local from the java official website_ policy. Jar and US_export_policy.jar and copy it to the corresponding java directory of the current system. For specific details, please refer to readme.com of Android backup extractor Txt file. For the conversion of encrypted ab backup, the specific command format is: java - jar Abe jar unpack [password]. If the execution is successful, there is no information prompt; If an error message appears, the ab file may be damaged or the password may be incorrect.
In addition to converting AB to tar, Android backup extractor can also convert tar to ab. For example, you need to modify some application data, but the mobile phone cannot root, so you can first backup the mobile phone data into AB file, convert AB backup into tar and modify the data, then convert the modified tar into AB backup, and finally restore the modified AB backup to the device.
1, app3
Title Link: https://adworld.xctf.org.cn/task/task_list?type=mobile&number=6&grade=0&page=1
2, Answer steps
1.Android backup extractor
Download address: https://github.com/nelenkov/android-backup-extractor
Compiling Android files
mvn clean package
The target folder is generated

Restore ab Android backup files
java -jar abe.jar unpack app3.ab app3.tar

Next, unzip app3 Tar, after a search, found base Apk, that is, the program we need to analyze

2.jadx decompile apk file
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.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");//user name contentValues.put("password", (Integer) 123456);//password a aVar = new a(); String a = aVar.a(contentValues.getAsString("name"), contentValues.getAsString("password"));//Stra1234 function 1 is shown below this.a = this.b.getWritableDatabase(aVar.a(a + aVar.b(a, contentValues.getAsString("password"))).substring(0, 7));//Function 2 is below 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); } } }
Function 1
public String a(String str, String str2) { String substring = str.substring(0, 4); return substring + str2.substring(0, 4); }
Execution result: Stra1234
- The first line sqlitedatabase loadLibs(((Context)this)); Load the required sqlitecipher library file.
- The second line instantiates a sqlitehelper class.
- The third, fourth and fifth lines instantiate a ContentValues class and pair the key value to name:Stranger password:123456 in it.
- The sixth line instantiates a com example. yaphetshan. tencentwelcome. a. Class A.
- The seventh line gets the value of the v2 variable.
- The eighth line calls the getWritableDatabase function, and the string parameter passed in is the key to decrypt the database.
Now the goal is very clear, that is to obtain the database decryption key (guess the flag is hidden in the encrypted sqlite number) According to the database), and the key is provided by com example. yaphetshan. tencentwelcome. a. A is generated by the method inside, and This class calls the methods in b.java, as shown in the figure:

Function 2
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; } } }

Execution:
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 here is added by itself for the normal operation of the program 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 here is added by itself for the normal operation of the program 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)); that is ⬇ this.f32a = this.f33b.getWritableDatabase("ae56f99");
Get: ae56f99
Log in to the database with ae56f99 and find: VGN0ZntIM2xsMF9Eb19ZMHVfTG92M19UZW5jM250IX0=

base64 decrypts to get the final flag of the problem: Tctf{H3ll0_Do_Y0u_Lov3_Tenc3nt!}

summary
- Android backup extractor
- jadx
- base64