android trace

title: android trace
categories: trace
toc: true
mathjax: true
tags: 
- trace
- 逆向
widgets:
-
    type: toc
    position: left
-
    type: profile
    position: left
    author: Runope
    # Author title
    author_title: 不知不论,不做不论
    # Author's current location
    location: Nanjin,jiangsu
    # URL or path to the avatar image
    avatar: https://en.gravatar.com/userimage/194935117/7129e2095de79a9dd97e5cc344acaba2?size=200
    # Whether show the rounded avatar image
    avatar_rounded: false
    # Email address for the Gravatar
    gravatar: 275358499@qq.com
    # URL or path for the follow button
    follow_link: 'https://github.com/runope'
-
    type: recent_posts
    position: left

Art trace :hook artmethod

JNI trace : jnitrace

libc trace:frida-trace

syscall trace:strace https://mp.weixin.qq.com/s/PIiGZKW6oQnOAwlCqvcU0g

Wallbreaker: https://github.com/hluwa/Wallbreaker

批量hook

如何使用objection去批量hook和trace?比如一次性hook几千个类?

  1. 把~/.objection/objection.log删掉;
  2. 到objection界面中运行android hooking list classes,列出所有的类;
  3. 对新生成的~/.objection/objection.log文件进行过滤,比如只关心http相关的。cat objection.log|grep -i http
  4. 将输出结果保存到一个excel列中,前面补全android hooking watch class xxxxx,另存为文本文件。如附件所示
  5. 加载这个文件:objection -g com.android.settings explore -c "2.txt" ,这样一下子就hook上了几千个相关类的所有方法及其所有重载。
  6. 如果trace感兴趣的方法也是同理,android hooking search methods * ,会打印出所有的方法。

frida Script

延时注入(Latency injection)

固定时间之后注入

使用setTimeout() 方法,例如:3 秒(3000 毫秒)后弹出 "Hello" :

setTimeout(function(){ alert("Hello"); }, 3000);

// frida's javascript
setImmediate(function () {
    setTimeout(native_hook, 5000)
})

在特定so库加载之后注入

有的库在程序启动时,并不会立刻加载。我们直接hook会提示无法找到此库,这时我们可以借助dlopen函数,在so库加载完成之后再去hook。hook框架如下:

Interceptor.attach(Module.findExportByName(null, "dlopen"), {
    onEnter: function (args) {
        this.path = Memory.readUtf8String(args[0]);
        console.log("[*] import :" + this.path);
    },
    onLeave: function (retval) {
        // libwukong_ua.so改为要hook的so库
        if(!this.path.isNull() && !retval.isNull() && this.path.includes('libwukong_ua.so')) {
            // 匿名函数hook,libwukong_ua.so改为要hook的so库,'0x426DE0'为函数在ida中查看的偏移地址
            var fstatat = resolveAddress('libwukong_ua.so', '0x0', '0x426DE0');
            Interceptor.attach(fstatat, {
                onEnter: function (args) {
                    console.log("=======  used!  ======")
                },
                onLeave: function (retval) {

                }
            });
			
            // 根据函数名Hook,'libwukong_ua.so'为库名, 'ssl3_send_client_certificate'为函数名
            var fstatat = Module.findExportByName('libwukong_ua.so', 'ssl3_send_client_certificate');
            Interceptor.attach(fstatat, {
                onEnter: function (args) {
                    console.log("=======  used!  ======")
                },
                onLeave: function (retval) {

                }
            });
        }
    }
});
function resolveAddress(name, idaBase, idaAddr) {
    var baseAddr = Module.findBaseAddress(name);
    console.log('[+] BaseAddr of ' + name + ': ' + baseAddr);
      
    // Calculate offset in memory from base address in IDA database
    var offset = ptr(idaAddr).sub(idaBase);
      
    // Add current memory base address to offset of function to monitor
    var result = baseAddr.add(offset);
      
    // Write location of function in memory to console
    console.log('[+] Address in memory: ' + result);
    return result;
}

格式化输出(Formatted printing)

Hook动态注册方法frida hook libart(RegisterNatives)

脚本详情见:https://github.com/lasting-yang/frida_hook_libart

function hook_RegisterNatives() {
    var symbols = Module.enumerateSymbolsSync("libart.so");
    var addrRegisterNatives = null;
    for (var i = 0; i < symbols.length; i++) {
        var symbol = symbols[i];
        
        //_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi
        if (symbol.name.indexOf("art") >= 0 &&
                symbol.name.indexOf("JNI") >= 0 && 
                symbol.name.indexOf("RegisterNatives") >= 0 && 
                symbol.name.indexOf("CheckJNI") < 0) {
            addrRegisterNatives = symbol.address;
            console.log("RegisterNatives is at ", symbol.address, symbol.name);
        }
    }

    if (addrRegisterNatives != null) {
        Interceptor.attach(addrRegisterNatives, {
            onEnter: function (args) {
                console.log("[RegisterNatives] method_count:", args[3]);
                var env = args[0];
                var java_class = args[1];
                var class_name = Java.vm.tryGetEnv().getClassName(java_class);
                //console.log(class_name);

                var methods_ptr = ptr(args[2]);

                var method_count = parseInt(args[3]);
                for (var i = 0; i < method_count; i++) {
                    var name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
                    var sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
                    var fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));

                    var name = Memory.readCString(name_ptr);
                    var sig = Memory.readCString(sig_ptr);
                    var find_module = Process.findModuleByAddress(fnPtr_ptr);
                    console.log("[RegisterNatives] java_class:", class_name, "name:", name, "sig:", sig, "fnPtr:", fnPtr_ptr, "module_name:", find_module.name, "module_base:", find_module.base, "offset:", ptr(fnPtr_ptr).sub(find_module.base));

                }
            }
        });
    }
}

setImmediate(hook_RegisterNatives);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值