frida - 如何在android中打印被调用的函数?

标签 frida

我在 APK 上使用 frida,我试图打印出正在调用的函数,尤其是向它发送了哪些参数。我的环境设置正确,因为我可以打印出类,并根据文档执行各种操作。

这是我找到的最接近的: https://codeshare.frida.re/@razaina/get-a-stack-trace-in-your-hook/

但是代码给出了错误(ThreadDef undefined 等等)

而且 frida 文档没有帮助我到达我想要的地方。

有什么指导吗?建议?帮助?

最佳答案

来自 codeshare@razaina 的代码存在可以轻松修复的错误 (threadef != ThreadDef)

var printBacktrace = function () {
    Java.perform(function() {
        var JLog = Java.use('android.util.Log'), JException = Java.use('java.lang.Exception');
        // getting stacktrace by throwing an exception
        console.warn(JLog.getStackTraceString(JException.$new()));
    });
};

只需调用 printBacktrace() w/e 你想看看谁调用了你的钩子(Hook)函数。

如果你想 Hook Java 类的所有方法,你可以使用这个片段;


var Color = {
    RESET: "\x1b[39;49;00m", Black: "0;01", Blue: "4;01", Cyan: "6;01", Gray: "7;11", Green: "2;01", Purple: "5;01", Red: "1;01", Yellow: "3;01",
    Light: {
        Black: "0;11", Blue: "4;11", Cyan: "6;11", Gray: "7;01", Green: "2;11", Purple: "5;11", Red: "1;11", Yellow: "3;11"
    }
};

/**
 *
 * @param input. 
 *      If an object is passed it will print as json 
 * @param kwargs  options map {
 *     -l level: string;   log/warn/error
 *     -i indent: boolean;     print JSON prettify
 *     -c color: @see ColorMap
 * }
 */
var LOG = function (input, kwargs) {
    kwargs = kwargs || {};
    var logLevel = kwargs['l'] || 'log', colorPrefix = '\x1b[3', colorSuffix = 'm';
    if (typeof input === 'object')
        input = JSON.stringify(input, null, kwargs['i'] ? 2 : null);
    if (kwargs['c'])
        input = colorPrefix + kwargs['c'] + colorSuffix + input + Color.RESET;
    console[logLevel](input);
};

var printBacktrace = function () {
    Java.perform(function() {
        var android_util_Log = Java.use('android.util.Log'), java_lang_Exception = Java.use('java.lang.Exception');
        // getting stacktrace by throwing an exception
        LOG(android_util_Log.getStackTraceString(java_lang_Exception.$new()), { c: Color.Gray });
    });
};

function traceClass(targetClass) {
    var hook;
    try {
        hook = Java.use(targetClass);
    } catch (e) {
        console.error("trace class failed", e);
        return;
    }

    var methods = hook.class.getDeclaredMethods();
    hook.$dispose();

    var parsedMethods = [];
    methods.forEach(function (method) {
        var methodStr = method.toString();
        var methodReplace = methodStr.replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1];
         parsedMethods.push(methodReplace);
    });

    uniqBy(parsedMethods, JSON.stringify).forEach(function (targetMethod) {
        traceMethod(targetClass + '.' + targetMethod);
    });
}

function traceMethod(targetClassMethod) {
    var delim = targetClassMethod.lastIndexOf('.');
    if (delim === -1)
        return;

    var targetClass = targetClassMethod.slice(0, delim);
    var targetMethod = targetClassMethod.slice(delim + 1, targetClassMethod.length);

    var hook = Java.use(targetClass);
    var overloadCount = hook[targetMethod].overloads.length;

    LOG({ tracing: targetClassMethod, overloaded: overloadCount }, { c: Color.Green });

    for (var i = 0; i < overloadCount; i++) {
        hook[targetMethod].overloads[i].implementation = function () {
            var log = { '#': targetClassMethod, args: [] };

            for (var j = 0; j < arguments.length; j++) {
                var arg = arguments[j];
                // quick&dirty fix for java.io.StringWriter char[].toString() impl because frida prints [object Object]
                if (j === 0 && arguments[j]) {
                    if (arguments[j].toString() === '[object Object]') {
                        var s = [];
                        for (var k = 0, l = arguments[j].length; k < l; k++) {
                            s.push(arguments[j][k]);
                        }
                        arg = s.join('');
                    }
                }
                log.args.push({ i: j, o: arg, s: arg ? arg.toString(): 'null'});
            }

            var retval;
            try {
                retval = this[targetMethod].apply(this, arguments); // might crash (Frida bug?)
                log.returns = { val: retval, str: retval ? retval.toString() : null };
            } catch (e) {
                console.error(e);
            }
            LOG(log, { c: Color.Blue });
            return retval;
        }
    }
}

// remove duplicates from array
function uniqBy(array, key) {
    var seen = {};
    return array.filter(function (item) {
        var k = key(item);
        return seen.hasOwnProperty(k) ? false : (seen[k] = true);
    });
}


var Main = function() {
    Java.perform(function () { // avoid java.lang.ClassNotFoundException
        [
            // "java.io.File",
            'java.net.Socket',
            'com.package.MyCustomClass'
        ].forEach(traceClass);

    });
};

Java.perform(Main);

关于frida - 如何在android中打印被调用的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57449977/

相关文章:

android - 如何为嵌套类函数编写 Frida 钩子(Hook)?

javascript - 如何使用 Frida 迭代函数

android - 证书固定绕过实践的示例 apk

javascript - 你如何使用 frida Hook 原生剥离库?

java - frida 调用了错误的构造函数

android - 无法连接到 frida 服务器 : need Gadget to attach on jailed Android

java - 如何使用 Frida 获取 ANDROID_ID

javascript - 如何将多个 Frida JS 文件/函数导入到运行时 CLI 中?

reverse-engineering - 如何使用 Frida 从 Android 中 Hook 的 native 函数打印变量