redex-aop

Project Url: dodola/redex-aop
Introduction: A bytecode optimizer for Android apps
More: Author   ReportBugs   OfficialWebsite   
Tags:

特性

  1. 灵活,可以使用 js 脚本操作 dex,bytecode
  2. 使用内置的字节码描述语言来编写插桩代码。封装了 dalvik bytecode 中的一些复杂特性,比如-range指令等。

编译

mkdir build
cd build
cmake .. -G Ninja 
ninja

DEMO

在每个函数前面插入一段Log.d

插桩脚本例子

function process_all_classes(all_classes) {

    for (let i in all_classes) {
        let cls_def = all_classes[i];

        std.printf("class name:%s\n", cls_def.c_str())

        cls_def.get_all_methods().forEach(m => {
            std.printf("%s.%s\n", cls_def.c_str(), m.c_str())
            //找到第一条指令,在这条指令前面插入
            let ircode = m.get_code();
            if (!ircode) {
                return;
            }
            let first_pos = null
            code_utils.iterate_code(ircode, (it) => {
                if (!opcode.is_a_load_param(it.insn.opcode())) {
                    first_pos = it;
                    return true;
                }
                return false;
            })
            // 构造要插桩的 code
            let insert_code = `
                    (
                        (new-instance "Ljava/lang/StringBuilder;") 
                        (move-result-pseudo-object v0) 
                        (invoke-direct 
                            (v0) "Ljava/lang/StringBuilder;.<init>:()V") 
                        (const-string "${cls_def.c_str()}") 
                        (move-result-pseudo-object v1) 
                        (invoke-virtual 
                            (v0 v1) "Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;") 
                          (const-string "${m.c_str()}") 
                          (move-result-pseudo-object v2) 
                        (move-object v3 v1)
                        (move-object v1 v2)
                        (invoke-virtual 
                            (v0 v1) "Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;")
                        (move-object v1 v3) 
                        (invoke-virtual 
                            (v0) "Ljava/lang/StringBuilder;.toString:()Ljava/lang/String;") 
                        (move-result-object v0) 
                        (const-string "dodola") 
                        (move-result-pseudo-object v1) 
                        (move-object v2 v0)
                        (invoke-static 
                            (v1 v2) "Landroid/util/Log;.d:(Ljava/lang/String;Ljava/lang/String;)I") 
                        (return-void)
                    )
                    `;
            let dummy_code = code_utils.ircode_from_string(insert_code);
            code_utils.inject_code_after(ircode, dummy_code, first_pos, [])

        });
    }
}

插桩配置

{
  "redex": {
    "passes": [
      "MethodAopPass"
    ]
  },
  "MethodAopPass": {
    "js_file": "../test/aop/test.js"
  },
  "ir_type_checker": {
    "run_after_each_pass": false,
    "verify_moves": false,
    "check_no_overwrite_this": false
  }
}

注意:需要关闭 overwrite_this,verify_moves 检查。

cd build
./redex-all -c ../test/aop/redexjs.json ../test/aop/classes.dex -o ../test/aop/opt/

插桩后:

img.png

后续计划

  1. 完成插桩代码的参数传递,比如 iget 之后获取到内存寄存器
  2. 完善 JS API,将大部分redex api 通过js api的形式开放出去,后续可以使用 js 完成 pass 的编写

License

The ReDex repository is available under the MIT License.

Thanks

redex quickjs quickjscpp

Apps
About Me
GitHub: Trinea
Facebook: Dev Tools