题目

CSDN免积分下载

查壳

先查壳(PKiD等),有壳脱壳,没壳用AndroidKiller等反编译工具打开查看JAVA代码
无壳APK

Java Decompiler - MainActivity-onClick

image.png

答案

Tctf{H3ll0_Do_Y0u_Lov3_Tenc3nt!}

Writeup

解题

文件头

下载后文件后缀为“ab”,拖入010查看,文件头是“ANDROID BACKUP”:
image.png
搜索“ANDROID BACKUP”后确定是安卓备份文件,完整的文件头信息应该是“ANDROID BACKUP.2.1.none”:
image.png
其中参数含义为:
“2”:版本
“1”:是否压缩
“none”:是否加密
这些参数用来确定文件是可以通过工具直接解压不需要密码的。

工具

Android backup extractor(或android-backup-processor等)

使用“abe.jar”对.ab文件进行解压处理:

  1. java -jar abe.jar unpack <backup.ab> <backup.tar>

image.png
将.tar解压后,“tree /f”查看都有哪些文件:
image.png

└─apps
    └─com.example.yaphetshan.tencentwelcome
        │    Encryto.db
        │    _manifest
        │
        ├─a
        │        base.apk
        │
        └─db
                Demo.db

除了一个apk还有两个.db文件,应该是和数据库有关。

解题思路

MainActivity

搜不出来或者没有思路时,应该先看Android程序的入口——一般来说是MainActivity函数,为了保险可以从“AndroidManifest.xml”查找入口点。
本题解压的apk运行后黑屏,入口为“com.example.yaphetshan.tencentwelcome.MainActivity”:
image.png
image.png

代码

MainActivity

public class MainActivity
    extends AppCompatActivity
    implements View.OnClickListener
{
    private SQLiteDatabase a;
    private a b;
    private Button c;

    private void a()
    {
        SQLiteDatabase.loadLibs(this);
        this.b = new a(this, "Demo.db", null, 1);
        ContentValues localContentValues = new ContentValues();
        localContentValues.put("name", "Stranger");
        localContentValues.put("password", Integer.valueOf(123456));
        com.example.yaphetshan.tencentwelcome.a.a locala = new com.example.yaphetshan.tencentwelcome.a.a();
        String str1 = locala.a(localContentValues.getAsString("name"), localContentValues.getAsString("password"));
        String str2 = locala.b(str1, localContentValues.getAsString("password"));
        str2 = locala.a(str1 + str2);
        this.a = this.b.getWritableDatabase(str2.substring(0, 7));
        this.a.insert("TencentMicrMsg", null, localContentValues);
    }

    public void onClick(View paramView)
    {
        if (paramView == this.c)
        {
            paramView = new Intent();
            paramView.putExtra("name", "name");
            paramView.putExtra("password", "pass");
            paramView.setClass(this, AnotherActivity.class);
            startActivity(paramView);
        }
    }

    protected void onCreate(Bundle paramBundle)
    {
        super.onCreate(paramBundle);
        setContentView(2130968603);
        this.c = ((Button)findViewById(2131427417));
        this.c.setOnClickListener(this);
        paramBundle = getSharedPreferences("test", 0).edit();
        paramBundle.putString("Is_Encroty", "1");
        paramBundle.putString("Encryto", "SqlCipher");
        paramBundle.putString("ver_sion", "3_4_0");
        paramBundle.apply();
        a();
    }
}

a类

  1. 实例化一个数据库对象,并赋值“Demo.db”;
  2. 实例化一个对象ContentValues,并赋值“name”字段为“Stranger”和“password”字段为“123456”;
  3. 实例化“com.example.yaphetshan.tencentwelcome.a.a”,调用其中的函数a处理传入的“name”值和“password”值后保存到str1,str1传入函数b后返回str2;
  4. 再调用getWritableDatabase函数处理str2。

    打开数据库

    打开一个名为“TencentMicrMsg”的数据库,前两个参数是列名“name”和“password”,第三列是“F_l_a_g”:

    new a(this, "Demo.db", null, 1);
    ……省略……
    param SQLiteDatabase.execSQL("create table TencentMicrMsg(name text,password integer,F_l_a_g text)");
    

    com.example.yaphetshan.tencentwelcome.a.a

    函数a

    public String a(String paramString1, String paramString2)
    {
     paramString1 = paramString1.substring(0, 4);
     paramString2 = paramString2.substring(0, 4);
     return paramString1 + paramString2;
    }
    

    取前4个字节相加,“Stranger”[0-4]+“123456”[0-4]结果为“Stra1234”。

    函数b

    太长了就不放代码了,语雀放太多代码很卡。传参部分代码为:

    String str2 = locala.b(str1, localContentValues.getAsString("password"));
    *参数1为str1(“Stra1234”)
    
  5. 通过“MessageDigest”类计算字符串“Stra1234”的MD5值;

  6. 将“Stra1234”与MD5值与“yaphetshan”拼接为新字符串;
  7. 计算2中字符串的SHA-1值
  8. 取SHA-1的前7个字符串

    🐍Python🐍调用hashlib库对字符串进行MD5和SHA-1计算

    如果计算机能安装Python的“pycipher”或“pysqlcipher3”等有解密功能的库,就不用下载数据库软件,但是我Python版本太高了,懒得整,没有一气呵成,就有点不舒服😑😑😑 ```python import hashlib md5 = hashlib.md5() sha1 = hashlib.sha1()

a = “yaphetshan” str1 = ‘Stra1234’ md5.update(str1.encode(‘utf8’)) str2 = md5.hexdigest()

tosha1 = str1 + str2 + a sha1.update(tosha1.encode(‘utf8’)) str2SHA1 = sha1.hexdigest()

ae56f99

print(“SHA-1后的字符串前7字节为:”, str2SHA1[0:7]) ```

打开加密数据库

尝试搜索“在线打开.db数据库”,基本都是解析无加密的数据库的,上传文件基本都是解析为无数据。
搜索“db数据库查看器”下载了“DB Browser for SQLite”,打开“DB Browser for SQLCipher.exe”(不是“DB Browser for SQLite.exe”,会出现无法识别的问题),拖入.db文件“Encryto.db”。
加密设置默认是4,手动改成3,输入密码“ae56f99”:
image.png
查看列“F_l_a_g”,值为“VGN0ZntIM2xsMF9Eb19ZMHVfTG92M19UZW5jM250IX0=”:
image.png
明显是Base64编码后的字符串,Base64解码为:
image.png