跳转至

frida 高级 api 食用方法(二)

1. 前提准备

本文章是对看雪教程的简单总结,可快速了解 frida hook api 的使用方法

这里提供下参考文档及其注意事项

2. frida 的使用

2.1. 解决 app 启动弹出警告

不是俄罗斯设备的警告提示

打开 app 跳出This app can only run on Russian devices. 的提示解决。Systemjava 自带库。

只要将 property 的值(即 System.getProperty("user.home") 方法返回的值)固定返回 Russia 即可。

image-20220428225219533

frida spawn 启动 app,对应的 frida 代码如下:

image-20220428225324802

2.2. 解决用户不在白名单警告

解决启动 app 后提示用户不在白名单中的问题。

和上步中的图示一样,需要 str (即 System.getenv("USER")) 的值和 getResources().getString(R.string.User)) 一样。而 User 的值如下:

image-20220428230354943

对应的 frida hook 代码如下:

1
2
3
4
5
6
System.getenv.overload('java.lang.String').implementation = function (key) {
    var result = this.getProperty(key);
    result = "RkxBR3s1N0VSTDFOR180UkNIM1J9Cg==";
    console.log("System.getenv:", key, result);
    return result;
};

2.3. 用户登录解决

image-20220428231156527

2.3.1. 用户 User not recognized 问题解决

image-20220428231228584

则只需要将用户名输入为 codenameduchess 即可。

2.3.2. 密码 Incorrect password 问题解决

image-20220428231442475

由图可知,密码 o 是经过 j 函数,即经过 MD5 后转变成 hex84e343a0486ff05530df6c705c8bb4 才能验证成功。

我们可以将 j 函数 hook 固定返回 true 即可。

也很方便即可知上图中的 passwordguestMD5 得到,则直接输入 guest 密码即可。

2.4. app 主页面解决

package com.tlamb96.kgbmessenger;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.c;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import com.tlamb96.kgbmessenger.a.a;
import com.tlamb96.spetsnazmessenger.R;
import java.util.ArrayList;
import java.util.List;
import org.a.a.b;

/* loaded from: classes.dex */
public class MessengerActivity extends c {
    private RecyclerView m;
    private a n;
    private List<com.tlamb96.kgbmessenger.b.a> o;
    private String q;
    private String s;
    private String p = "V@]EAASB\u0012WZF\u0012e,a$7(&am2(3.\u0003";
    private String r = "\u0000dslp}oQ\u0000 dks$|M\u0000h +AYQg\u0000P*!M$gQ\u0000";

    private String a(String str) {
        char[] charArray = str.toCharArray();
        for (int i = 0; i < charArray.length / 2; i++) {
            char c = charArray[i];
            charArray[i] = (char) (charArray[(charArray.length - i) - 1] ^ '2');
            charArray[(charArray.length - i) - 1] = (char) (c ^ 'A');
        }
        return new String(charArray);
    }

    private String b(String str) {
        char[] charArray = str.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            charArray[i] = (char) ((charArray[i] >> (i % 8)) ^ charArray[i]);
        }
        for (int i2 = 0; i2 < charArray.length / 2; i2++) {
            char c = charArray[i2];
            charArray[i2] = charArray[(charArray.length - i2) - 1];
            charArray[(charArray.length - i2) - 1] = c;
        }
        return new String(charArray);
    }

    private String i() {
        if (this.q == null || this.s == null) {
            return "Nice try but you're not that slick!";
        }
        char[] charArray = this.q.substring(19).toCharArray();
        charArray[1] = (char) (charArray[1] ^ 'U');
        charArray[2] = (char) (charArray[2] ^ 'F');
        charArray[3] = (char) (charArray[3] ^ 'F');
        charArray[5] = (char) (charArray[5] ^ '_');
        Log.i("MessengerActivity", "flag: " + new String(charArray));
        char[] charArray2 = this.s.substring(7, 13).toCharArray();
        charArray2[1] = (char) (charArray2[1] ^ '}');
        charArray2[2] = (char) (charArray2[2] ^ 'v');
        charArray2[3] = (char) (charArray2[3] ^ 'u');
        return new String(charArray) + "_" + new String(charArray2);
    }

    private String j() {
        return new b().a("hh:mm a");
    }

    @Override // android.support.v4.b.l, android.app.Activity
    public void onBackPressed() {
        Intent intent = new Intent("android.intent.action.MAIN");
        intent.addCategory("android.intent.category.HOME");
        intent.setFlags(268435456);
        startActivity(intent);
    }

    /* JADX INFO: Access modifiers changed from: protected */
    @Override // android.support.v7.app.c, android.support.v4.b.l, android.support.v4.b.h, android.app.Activity
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.activity_messenger);
        getResources().getString(R.string.katya);
        getResources().getString(R.string.user);
        this.o = new ArrayList<com.tlamb96.kgbmessenger.b.a>() { // from class: com.tlamb96.kgbmessenger.MessengerActivity.1
            {
                add(new com.tlamb96.kgbmessenger.b.a(R.string.katya, "Archer, you up?", "2:20 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.user, "no", "2:22 am", false));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.nikolai, "Omg Katya you're being so transparent...", "7:16 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.crenshaw, "LOL you should deport her", "7:28 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.user, "Why am I in this gc again?", "7:48 am", false));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.katya, "DEPORT me!? Where tf would you send me!?? I'm already stuck living in Russia", "8:02 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.boris, "Pls don't deport me", "8:05 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.katya, "Boris no one is talking about you", "8:06 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.nikolai, "Omg he's such a moron", "8:10 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.crenshaw, "ikr", "8:11 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.nikolai, "Remember that time he gave away the password to all KGB systems?", "8:12 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.crenshaw, "Yeah, all they had to do was ask for it", "8:13 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.katya, "You're joking, right? No one is that dumb", "8:13 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.crenshaw, "I'm 100% serious", "8:13 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.boris, "Well that's not all they had to do", "8:15 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.katya, "Wait, why do all KGB systems have the same password?", "9:20 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.nikolai, "We got tired of writing them down on sticky notes so we held a meeting and agreed on a password for the entire department", "9:22 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.crenshaw, "Idk why we didn't think of this solution earlier", "9:25 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.katya, "Does Boris know the password?", "9:26 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.nikolai, "Nah, he only has the password for his personal computer which is different than the dept's password", "9:27 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.crenshaw, "You thought we'd tell him again? If he told someone we would have to hold another dept meeting to come up with a new one", "9:28 am", true));
                add(new com.tlamb96.kgbmessenger.b.a(R.string.nikolai, "It took us three hours to agree on one last time", "9:27 am", true));
            }
        };
        this.m = (RecyclerView) findViewById(R.id.reyclerview_message_list);
        this.n = new a(this, this.o);
        this.m.setAdapter(this.n);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.a(true);
        this.m.setLayoutManager(linearLayoutManager);
        this.m.setNestedScrollingEnabled(false);
    }

    public void onSendMessage(View view) {
        EditText editText = (EditText) findViewById(R.id.edittext_chatbox);
        String obj = editText.getText().toString();
        if (!TextUtils.isEmpty(obj)) {
            this.o.add(new com.tlamb96.kgbmessenger.b.a(R.string.user, obj, j(), false));
            this.n.c();
            if (a(obj.toString()).equals(this.p)) {
                Log.d("MessengerActivity", "Successfully asked Boris for the password.");
                this.q = obj.toString();
                this.o.add(new com.tlamb96.kgbmessenger.b.a(R.string.boris, "Only if you ask nicely", j(), true));
                this.n.c();
            }
            if (b(obj.toString()).equals(this.r)) {
                Log.d("MessengerActivity", "Successfully asked Boris nicely for the password.");
                this.s = obj.toString();
                this.o.add(new com.tlamb96.kgbmessenger.b.a(R.string.boris, "Wow, no one has ever been so nice to me! Here you go friend: FLAG{" + i() + "}", j(), true));
                this.n.c();
            }
            this.m.b(this.m.getAdapter().a() - 1);
            editText.setText("");
        }
    }
}

用户登录成功后,提示 FLAG(GooG13_PRO) 解决。

这时查看 onCreate 中的 com.tlamb96.kgbmessenger.b.a 的构造方法:

image-20220428233246544

hook 构造函数,打印其调用栈,print_stack 方法最后会补充。

image-20220428233458841

堆栈结果:

image-20220428235053552

搜索上图的方法,进入:

image-20220428235333582

对应的 this.p 的值如下:

image-20220428235436039

由上可知,a(obj.toString()).equals(this.p) 要成立,需要 hook a 函数的值返回 this.p 的值。

重要:此中的 a 方法要与原 app 的逻辑相反,两处异或的地方('A' 和 '2')的顺序要相反,得到 this.p 处理前的值是什么。

image-20220429000342764

class 文件打包成 jar 文件:

image-20220429000453838

jar 转成 dex 文件:

image-20220429000535825

frida hook 脚本中引入此 dex:

1
2
3
4
5
6
7
8
9
var ddex2 = Java.openClassFile("/data/local/tmp/ddex2.dex");

Java.perform(function () {
    //frida动态加载了dex
    ddex2.load();
    var DecodeUtils = Java.use("com.example.androiddemo.DecodeUtils");
    console.log("DecodeUtils.decode_p:", DecodeUtils.decode_p());
    console.log("r to hex", DecodeUtils.r_to_hex());
... ...

2.5. app 主页面输入后问题解决

2.5.1. Only if you ask nicely 问题解决

直接看上步骤的代码块中,需要 b(obj.toString()).equals(this.r) 成立:

先将 this.r 转成 hex,因为 this.r 有不可见字符。

image-20220429002624944

同样转 jar 再转 dex,最后在 frida 中引入:

image-20220429002811993

然后可使用 z3 写个解密函数,或将 b 函数用 python 重写,两种方式分别如下:

from z3 import *
from binascii import b2a_hex, a2b_hex

def main():
    s = Solver()

    r = "0064736c707d6f510020646b73247c4d0068202b4159516700502a214d24675100"
    r_result = bytearray(a2b_hex(r))
    print(r_result)
    for i in range(int(len(r_result) / 2)):
        c = r_result[i]
        r_result[i] = r_result[len(r_result) - i - 1]
        r_result[len(r_result) - i - 1] = c

    print(b2a_hex(r_result))

    x = [BitVec("x%s" % i, 32) for i in range(len(r_result))]
    for i in range(len(r_result)):
        c = r_result[i]
        print(i, hex(c))
        s.add(((x[i] >> (i % 8)) ^ x[i]) == r_result[i])        #z3
    if (s.check() == sat):
        model = (s.model())
        # 这是打印的 int 型
        print(model)
        # 将上步结果转为 char 型
        flag = ""
        for i in range(len(r_result)):
            if (model[x[i]] != None):
                flag += chr(model[x[i]].as_long().real)
            else:
                flag += " "
        print('"' + flag + '"')
        print(len(flag), len(r_result))


if __name__ == "__main__":
    main()


'''
    private String b(String str) {
        char[] charArray = str.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            charArray[i] = (char) ((charArray[i] >> (i % 8)) ^ charArray[i]);
        }
        for (int i2 = 0; i2 < charArray.length / 2; i2++) {
            char c = charArray[i2];
            charArray[i2] = charArray[(charArray.length - i2) - 1];
            charArray[(charArray.length - i2) - 1] = c;
        }
        return new String(charArray);
    }
'''

3. 总结及补充

这里放上所涉及到的 frida js hook 脚本:

function hook_java() {
    //var ddex = Java.openClassFile("/data/local/tmp/ddex.dex");
    //frida动态加载了dex
    /*
    jar -cvf ddex.jar com/example/androiddemo/DecodeUtils.class
    /Users/yang/Library/Android/sdk/build-tools/28.0.3/dx --dex --output=ddex.dex ddex.jar
    */
    var ddex2 = Java.openClassFile("/data/local/tmp/ddex2.dex");

    Java.perform(function () {
        //frida动态加载了dex
        ddex2.load();
        var DecodeUtils = Java.use("com.example.androiddemo.DecodeUtils");
        console.log("DecodeUtils.decode_p:", DecodeUtils.decode_p());
        console.log("r to hex", DecodeUtils.r_to_hex());

        var System = Java.use("java.lang.System");
        console.log(System);
        //frida -U --no-pause -f  com.tlamb96.spetsnazmessenger -l hook.js
        //hook System, 
        System.getProperty.overload('java.lang.String').implementation = function (key) {
            var result = this.getProperty(key);
            result = "Russia";
            console.log("System.getProperty:", key, result);
            return result;
        };

        System.getenv.overload('java.lang.String').implementation = function (key) {
            var result = this.getProperty(key);
            result = "RkxBR3s1N0VSTDFOR180UkNIM1J9Cg==";
            console.log("System.getenv:", key, result);
            return result;
        };

        var a = Java.use("com.tlamb96.kgbmessenger.b.a");
        //hook 构造函数
        a.$init.implementation = function (i, str, str2, z) {
            this.$init(i, str, str2, z);
            console.log("a.$init:", i, str, str2, z);
            print_stack();       //打印了调用栈
        };

        var MessengerActivity = Java.use("com.tlamb96.kgbmessenger.MessengerActivity");
        MessengerActivity.a.implementation = function (str) {
            console.log("MessengerActivity.a:", str);
            var result = this.a(str);
            console.log("MessengerActivity.a:", str, result);
            return result;
        };
    });
}

function print_stack() {
    Java.perform(function () {
        var Exception = Java.use("java.lang.Exception");
        var instance = Exception.$new("print_stack");
        var stack = instance.getStackTrace();
        console.log(stack);
        instance.$dispose();
    });
}


function main() {
    hook_java();
}

setImmediate(main);

评论

回到页面顶部