攻防世界 XCTF 【Mobile】ill-intentions 题解 | frida 和 objection 的简单安装及在 android 渗透测试中的入门

730 阅读5分钟

初步了解题目

先打开题目,下载附件,是一个 apk 文件,然后直接拖动到 JADX-gui 中去:

然后直接保存到文件夹里去,我们用 IDEA 打开,方便我们编辑

简单看看 AndroidManifest.xml ,直接看 MainActivity 吧

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    TextView tv = new TextView(getApplicationContext());
    tv.setText("Select the activity you wish to interact with.To-Do: Add buttons to select activity, for now use Send_to_Activity");
    setContentView(tv);
    IntentFilter filter = new IntentFilter();
    filter.addAction("com.ctf.INCOMING_INTENT");
    Send_to_Activity receiver = new Send_to_Activity();
    registerReceiver(receiver, filter, Manifest.permission._MSG, null);
}

代码的意思是,将 Send_to_Activity 类注册成了一个广播接收器,接受的广播动作是 com.ctf.INCOMING_INTENT 而且设定了 Manifest.permission._MSG 权限,只有拥有这个权限的广播发送者发出的广播,当前的这个广播接受者才能接受广播。那我们看看这个权限是什么,能不能伪造。

<permission android:name="ctf.permission._MSG" android:protectionLevel="signature" android:description="@string/android_permission__msg"/>

观察 AndroidManifest.xml 里的关于 ctf.permission._MSG 的定义,发现,我们好像无法伪造,因为保护级别是 signature,(大概是这个意思,有知道的师傅,还请指出)

尴尬,线索到这里其实就断了,因为我们无法发出广播给这个 Send_to_Activity 广播接受者。

但是先不管了,我们看看这个 Send_to_Activity 的实现。

public void onReceive(Context context, Intent intent) {
    String msgText = intent.getStringExtra("msg");
    if (msgText.equalsIgnoreCase("ThisIsTheRealOne")) {
        Intent outIntent = new Intent(context, ThisIsTheRealOne.class);
        context.startActivity(outIntent);
    } else if (msgText.equalsIgnoreCase("IsThisTheRealOne")) {
        Intent outIntent2 = new Intent(context, IsThisTheRealOne.class);
        context.startActivity(outIntent2);
    } else if (msgText.equalsIgnoreCase("DefinitelyNotThisOne")) {
        Intent outIntent3 = new Intent(context, DefinitelyNotThisOne.class);
        context.startActivity(outIntent3);
    } else {
        Toast.makeText(context, "Which Activity do you wish to interact with?", 1).show();
    }
}

其实就是打开一个又一个 Activity ,那么思路就有了,我们虽然无法发送广播,但是我们直接使用工具,打开对应的 Activity 就行了。

然后再观察一下这三个 Activity 的内容

public native String definitelyNotThis(String str, String str2);

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    TextView tv = new TextView(this);
    tv.setText("Activity - Is_this_the_real_one");
    Button button = new Button(this);
    button.setText("Broadcast Intent");
    setContentView(button);
    button.setOnClickListener(new View.OnClickListener() { // from class: com.example.application.DefinitelyNotThisOne.1
        @Override // android.view.View.OnClickListener
        public void onClick(View v) {
            Intent intent = new Intent();
            intent.setAction("com.ctf.OUTGOING_INTENT");
            DefinitelyNotThisOne.this.getResources().getString(R.string.str1);
            String b = Utilities.doBoth(DefinitelyNotThisOne.this.getResources().getString(R.string.test));
            String c = Utilities.doBoth("Test");
            intent.putExtra("msg", DefinitelyNotThisOne.this.definitelyNotThis(b, c));
            DefinitelyNotThisOne.this.sendBroadcast(intent, Manifest.permission._MSG);
        }
    });
}

其他两个类我就不继续粘贴了,都和这个一样,都是调用 Native 方法,所以这道题要么用 IDA 去分析 Native 实现,要么去 Hook 这些方法。 我们这里尝试使用 frida 去 hook 这些方法。

下面简单介绍一下工具安装


工具安装

frida 和 objection 的简单安装及在 android 渗透测试中的入门级教程

frida 是一个 hook 框架,可运行在android、ios、linux、win、osx等各平台,主要使用动态二进制插桩技术。

你可以通过 frida 来注入安卓代码,进而获取特定函数的输入值,输出值,返回值,或者直接更改这些值等等。

Frida 安装

因为 frida 是基于 python 的,所以这里默认已经搭建好了 python 环境。

直接一键安装即可

pip install -i https://pypi.doubanio.com/simple/ frida-tools
% pip list | grep frida
frida                        16.2.1
frida-tools                  12.3.0

这个时候,就可以看到已经帮你安装好了 frida 和 frida-tools

然后顺便安装一下 objection 一款基于 frida 的安卓应用渗透框架

pip install objection

安装 frida 安卓服务端

% adb shell
$ getprop ro.product.cpu.abi
arm64-v8a

获取一下你的安卓的架构,然后去下载对应的服务端文件

Github:Releases · frida/frida (github.com)

image.png

记得点击 Show all 257 assets,然后搜索 server 字样,找一下自己对应的架构的 安卓包

image.png

然后解压,传输到安卓端

adb push ~/Downloads/frida-server-16.2.1-android-arm64 /data/local/tmp/

请注意!:如果你的模拟器使用的是带 play store 的,那么你是无法获取 root 权限的, 而且传入到文件夹也是不能随便传,有的文件夹是无法设置运行权限的 请选择不带这个图案的版本

继续使用 adb 操作安卓系统,提升到管理员权限并运行

adb root
adb shell
cd /data/local/tmp/
mv frida-server-16.2.1-android-arm64 frida-server
chmod 777 frida-server && ls -al
./frida-server

这个时候如果没报错,那说明安卓端的就安装好了,再测试一下,电脑端执行

frida-ps -U

如果输出安卓端的一些信息,那么就成功了


尝试解题

回到解题环节,因为这部分设计到各个工具的使用,所以就简单演示一下,至于为什么要这样写,还需要各位去自行学习工具使用。 我们先编写这三个函数的 hook 函数

function main() {
    Java.perform(function() {
        var DefinitelyNotThisOneHandler = Java.use('com.example.application.DefinitelyNotThisOne')
        DefinitelyNotThisOneHandler.definitelyNotThis.implementation = function(arg0, arg1) {
            console.log('进入 DefinitelyNotThisOneHandler 函数,参数1: ' + arg0 + " 参数2: " + arg1)
            var ret = this.definitelyNotThis(arg0, arg1)
            console.log('完成 DefinitelyNotThisOneHandler 函数,返回值: ' + ret )
            return ret
        }

        var ThisIsTheRealOneHandler = Java.use('com.example.application.ThisIsTheRealOne')
        ThisIsTheRealOneHandler.orThat.overload('java.lang.String', 'java.lang.String', 'java.lang.String').implementation = function(arg0, arg1, arg2) {
            console.log('进入 ThisIsTheRealOneHandler 函数,参数1: ' + arg0 + " 参数2: " + arg1 + "  参数3: " + arg2)
            var ret =  this.orThat(arg0, arg1, arg2)
            console.log('完成 ThisIsTheRealOneHandler 函数,返回值:' + ret )
            return ret
        }

        var IsThisTheRealOneHandler = Java.use('com.example.application.IsThisTheRealOne')
        IsThisTheRealOneHandler.perhapsThis.overload('java.lang.String', 'java.lang.String', 'java.lang.String').implementation = function(arg0, arg1, arg2) {
            console.log('进入 IsThisTheRealOneHandler 函数,参数1: ' + arg0 + "  参数2: " + arg1 + "  参数3: " + arg2)
            var ret =  this.perhapsThis(arg0, arg1, arg2)
            console.log('完成 IsThisTheRealOneHandler 函数,返回值: ' + ret )
            return ret
        }
    })
}

setImmediate(main)

将文件保存为 hook.js 将 题目的 apk 安装到安卓上,点击运行

image.png

开启 frida 注入

frida -U -f com.example.hellojni -l hook.js

# 然后再开个命令行输入:
adb shell am start -n com.example.hellojni/com.example.application.IsThisTheRealOne

经过一下午的研究,发现 objection 的版本太老了,已经和最新的 frida 产生了不兼容,而且我安装老版本的 frida 的时候遇到了很奇葩的错误,所以这里没法使用 objection 了,我就使用 adb 调用 activity 吧

image.png

这个时候点击一下 Broadcast Intent 按钮即可发布广播,frida 成功 hook 数据。其他两个 activity 试了一下是干扰项。