Frida与Android CTF
字数 1195 2025-08-12 11:34:02

Frida与Android CTF实战教学文档

前言

本教学文档基于TideSec团队在FreeBuf上发布的《Frida与Android CTF》文章,详细讲解三个Android CTF题目的解题思路和技术要点,涵盖Frida Java Hook、动态加载Dex的Hook以及Native层反调试绕过等技术。

第一题:Frida静态函数的主动调用

题目分析

  1. 应用行为

    • 输入要求为5位纯数字
    • 输入错误时提示"请继续加油"
  2. 静态分析

    • 用户名和密码拼接后传入vvvv方法
    • VVVV函数限制输入长度为5位
    • 输入经过eeeee方法处理后需与预设值p匹配
    • eeeee方法调用链:
      • sssss获取字符串SHA-1值
      • ccccc将SHA-1摘要转为16进制字符串

解题思路

  1. 暴力破解

    • 遍历00000-99999所有5位数字组合
    • 使用Frida主动调用验证函数
  2. Hook绕过

    • 直接Hook返回值为true(不推荐,失去题目意义)

Frida脚本实现

var CONTEXT = null;

// 获取对象类名
function getObjClassName(obj) {
    if (!jclazz) var jclazz = Java.use("java.lang.Class");
    if (!jobj) var jobj = Java.use("java.lang.Object");
    return jclazz.getName.call(jobj.getClass.call(obj));
}

// Hook VVVV方法获取上下文
function hookReturn() {
    Java.perform(function () {
        Java.use("com.kanxue.pediy1.VVVVV").VVVV.implementation = function (context, str) {
            var result = this.VVVV(context, str);
            console.log("context,str,result => ", context, str, result);
            console.log("context className is => ", getObjClassName(context));
            CONTEXT = context;
            return true;
        }
    })
}

// 主动调用爆破
function invoke() {
    Java.perform(function () {
        var MainActivity = null;
        Java.choose("com.kanxue.pediy1.MainActivity", {
            onMatch: function (instance) { MainActivity = instance; },
            onComplete: function () {}
        });
        
        var CONTEXT2 = Java.use("com.kanxue.pediy1.MainActivity$1").$new(MainActivity);
        
        for (var x = 0; x <= 99999; x++) {
            var result = Java.use("com.kanxue.pediy1.VVVVV").VVVV(CONTEXT2, String(x));
            console.log("now x is => ", String(x));
            if (result) {
                console.log("found result is => ", String(x));
                break;
            }
        }
    })
}

function main() {
    hookReturn();
}

setImmediate(main);

验证结果

成功爆破得到flag:66888

第二题:Frida Hook动态加载Dex

题目分析

  1. 特点

    • 动态加载dex文件
    • 引入Native函数处理
  2. 静态分析

    • 算法与第一题类似
    • 增加了stringFromJNI Native函数处理层

解题思路

  1. 枚举ClassLoader

    • 找到正确的ClassLoader来加载动态dex中的类
  2. 双层调用

    • 先调用Native函数处理输入
    • 再调用动态dex中的验证函数

Frida脚本实现

function invoke2() {
    Java.perform(function () {
        // 获取MainActivity实例
        var MainActivity = null;
        Java.choose("com.kanxue.pediy1.MainActivity", {
            onMatch: function(instance) { MainActivity = instance; },
            onComplete: function() {}
        });
        
        // 枚举ClassLoader
        var loader1 = null;
        var loader2 = null;
        Java.enumerateClassLoaders({
            onMatch: function (loader) {
                try {
                    if (loader.findClass("com.kanxue.pediy1.VVVVV")) {
                        console.log("Successfully found loader");
                        console.log(loader);
                        loader2 = loader;
                        Java.classFactory.loader = loader2;
                    } else if(loader.findClass("com.kanxue.pediy1.MainActivity")) {
                        console.log("Successfully found loader");
                        console.log(loader);
                        loader1 = loader;
                    }
                } catch (error) {
                    console.log("find error:" + error);
                }
            },
            onComplete: function () { console.log("end1"); }
        });
        
        // 双层调用爆破
        for (var x = 0; x <= 99999; x++) {
            var result1 = MainActivity.stringFromJNI(String(100000 - x));
            var result2 = Java.use("com.kanxue.pediy1.VVVVV").VVVV(String(result1));
            console.log("now x is => ", String(x));
            if (result2) {
                console.log("found result2 is => ", String(100000 - x));
                break;
            }
        }
    })
}

function main() {
    invoke2();
}

setImmediate(main);

补充分析

通过IDA分析stringFromJNI函数发现:

  • 将输入数字字符串转为int后加1返回
  • 因此正确flag应为66999 - 1 = 66998

验证结果

成功爆破得到flag:66998

第三题:Native层去反调试

反调试机制分析

  1. 检测逻辑
    • 循环创建Socket连接遍历端口
    • 检查端口是否被占用
    • 收到"REJECT"响应时判定frida-server运行
    • 直接调用kill终止进程

绕过思路

  1. 替换kill函数
    • 拦截libc.so中的kill函数调用
    • 替换为自定义空实现

Frida脚本实现

function replaceKill() {
    var kill_addr = Module.findExportByName("libc.so", "kill");
    Interceptor.replace(kill_addr, new NativeCallback(function(arg0, arg1) {
        console.log("arg0=> ", arg0);
        console.log("arg1=> ", arg1);
    }, "int", ['int', 'int']));
}

function main() {
    replaceKill();
}

setImmediate(main);

使用方法

frida -U -f com.kanxue.pediy1 -l /path/to/script.js --no-pause

验证结果

成功绕过反调试,爆破得到flag:99998

总结

  1. 技术要点

    • Frida Java Hook与主动调用
    • 动态加载Dex的ClassLoader处理
    • Native层反调试检测与绕过
    • 暴力破解数字组合
  2. 通用解题思路

    • 静态分析确定验证逻辑
    • 动态验证确认关键函数
    • 编写Frida脚本实现自动化
    • 处理可能的反调试机制
  3. 工具链

    • Jadx:静态分析APK
    • Frida:动态分析与Hook
    • Objection:辅助分析
    • IDA:Native层分析

参考资料

Frida与Android CTF实战教学文档 前言 本教学文档基于TideSec团队在FreeBuf上发布的《Frida与Android CTF》文章,详细讲解三个Android CTF题目的解题思路和技术要点,涵盖Frida Java Hook、动态加载Dex的Hook以及Native层反调试绕过等技术。 第一题:Frida静态函数的主动调用 题目分析 应用行为 : 输入要求为5位纯数字 输入错误时提示"请继续加油" 静态分析 : 用户名和密码拼接后传入 vvvv 方法 VVVV 函数限制输入长度为5位 输入经过 eeeee 方法处理后需与预设值 p 匹配 eeeee 方法调用链: sssss 获取字符串SHA-1值 ccccc 将SHA-1摘要转为16进制字符串 解题思路 暴力破解 : 遍历00000-99999所有5位数字组合 使用Frida主动调用验证函数 Hook绕过 : 直接Hook返回值为true(不推荐,失去题目意义) Frida脚本实现 验证结果 成功爆破得到flag: 66888 第二题:Frida Hook动态加载Dex 题目分析 特点 : 动态加载dex文件 引入Native函数处理 静态分析 : 算法与第一题类似 增加了 stringFromJNI Native函数处理层 解题思路 枚举ClassLoader : 找到正确的ClassLoader来加载动态dex中的类 双层调用 : 先调用Native函数处理输入 再调用动态dex中的验证函数 Frida脚本实现 补充分析 通过IDA分析 stringFromJNI 函数发现: 将输入数字字符串转为int后加1返回 因此正确flag应为 66999 - 1 = 66998 验证结果 成功爆破得到flag: 66998 第三题:Native层去反调试 反调试机制分析 检测逻辑 : 循环创建Socket连接遍历端口 检查端口是否被占用 收到"REJECT"响应时判定frida-server运行 直接调用 kill 终止进程 绕过思路 替换kill函数 : 拦截libc.so中的kill函数调用 替换为自定义空实现 Frida脚本实现 使用方法 验证结果 成功绕过反调试,爆破得到flag: 99998 总结 技术要点 : Frida Java Hook与主动调用 动态加载Dex的ClassLoader处理 Native层反调试检测与绕过 暴力破解数字组合 通用解题思路 : 静态分析确定验证逻辑 动态验证确认关键函数 编写Frida脚本实现自动化 处理可能的反调试机制 工具链 : Jadx:静态分析APK Frida:动态分析与Hook Objection:辅助分析 IDA:Native层分析 参考资料 看雪论坛相关讨论 Frida官方文档 Android逆向工程相关技术资料