深自弹 發表於 2021-9-16 18:57:00

fridahookjava

<p></p><div class="toc"><div class="toc-container-header">目录</div><ul><li>Frida 启动<ul><li>attach 启动</li><li>spawn 启动</li></ul></li><li>frida-server 自定义端口<ul><li>frida server</li><li>frida</li><li>python</li></ul></li><li>Frida rpc 远程调用<ul><li>python</li><li>js</li><li>压力测试</li><li>nps 进行内网穿透</li></ul></li><li>Hook 普通方法</li><li>Hook 重载方法</li><li>Hook 构造方法</li><li>Hook 对象</li><li>Hook 动静态成员属性</li><li>Hook 内部类</li><li>Hook 匿名类</li><li>Hook 类的所有方法</li><li>Hook 类的所有方法及重载</li><li>Hook 动态加载的 dex</li><li>Hook 主动构造数组</li><li>Hook cast 强制类型转换</li><li>Hook 打印类实现的接口</li><li>Hook enum 枚举</li><li>Hook 获取 context</li><li>Hook 主动调用构造方法</li><li>Hook 主动调用静态方法</li><li>Hook 主动调用动态方法</li><li>Hook frida 和 python 交互</li><li>Hook 打印 char</li><li>Hook 打印 char 数组</li><li>Hook 打印和修改 HashMap</li><li>Hook 打印 byte 数组</li><li>Hook 打印调用栈</li><li>Hook gson 打印</li><li>Hook 打印 non-ascii 和特殊字符</li><li>简易 wallbreaker 内存打印</li><li>hook frida 实现 runnable</li><li>Hook 监控控件 onClick</li><li>Hook startActivity</li><li>Hook frida 绕过 root 检测</li><li>Hook frida 强制在主线程运行</li><li>Hook frida 指定方法中过滤打印</li><li>Hook 禁止 app 退出</li><li>Hook 修改设备参数</li><li>Hook 打印请求调用栈</li><li>Hook UI thread 注入</li><li>常用打印转换</li></ul></div><p></p>
<h1 id="frida-启动">Frida 启动</h1>
<h2 id="attach-启动">attach 启动</h2>
<p>直接附加到指定包名的应用中</p>
<pre><code>BASH
frida -U com.kevin.android -l hook.js --no-pause
</code></pre>
<p>直接附加到当前应用中</p>
<pre><code>BASH
frida -UF -l hook.js --no-pause
import sys
import time
import frida

def on_message(message,data):
    print("message",message)
    print("data",data)

device = frida.get_usb_device()
session = device.attach("com.kevin.demo1")

with open("./demo1.js","r") as f:
    script = session.create_script(f.read())

script.on("message",on_message)
script.load()
sys.stdin.read()
</code></pre>
<h2 id="spawn-启动">spawn 启动</h2>
<pre><code>BASH
frida -U -f com.kevin.android -l demo1.js --no-pause
import sys
import time
import frida

def on_message(message,data):
    print("message",message)
    print("data",data)

device = frida.get_usb_device()
pid = device.spawn(["com.kevin.demo1"])
device.resume(pid)
session = device.attach(pid)

with open("./rpc_demo.js",'r') as f:
    script = session.create_script(f.read())

script.on("message",on_message)
script.load()

sys.stdin.read()
</code></pre>
<h1 id="frida-server-自定义端口">frida-server 自定义端口</h1>
<h2 id="frida-server">frida server</h2>
<p>更改 frida server 默认端口: 27042 并开启远程连接</p>
<pre><code>BASH
adb shell
su -
cd /data/local/tmp

# 输入 wifiadb 对应的 ip 和自定义端口
./frida-server -l 192.168.0.1:6666

# 也可以使用默认端口启动
./frida-server -l 192.168.0.1
</code></pre>
<h2 id="frida">frida</h2>
<p>frida 远程连接自定义端口</p>
<pre><code>BASH
# 连接指定 6666 端口
frida -H 192.168.0.1:6666 com.demo1.app -l demo1.js

# 默认使用端口 27042
frida -H 192.168.0.1 -l demo1.js
</code></pre>
<h2 id="python">python</h2>
<pre><code>PYTHON
# -*- coding: UTF-8 -*-

import frida, sys

jsCode = """
console.log("test");
"""

def message(message, data):
    if message['type'] == 'send':
      print(f"[*] {message['payload']}")
                else:
                                print(message)
# ./fs120800 -l "0.0.0.0:6666"
# adb wifi 10.0.0.23
process = frida.get_device_manager().add_remote_device('127.0.0.1:6666').attach('com.kevin.app')
script = process.create_script(jsCode)
script.on("message",message)
script.load()
input()
</code></pre>
<h1 id="frida-rpc-远程调用">Frida rpc 远程调用</h1>
<h2 id="python-1">python</h2>
<pre><code>PYTHON
import frida
import json
from flask import Flask, jsonify, request

def message(message, data):
        if message['type'] == 'send':
                print(f"[*] {message['payload']}")
        else:
                print(message)

# ./fs120800 -l "0.0.0.0:6666"
# adb wifi 10.0.0.123
# 远程 frida-server 路径 adb wifi 的 ip : frida-server 启动的端口
session = frida.get_device_manager().add_remote_device('10.0.0.123:6666').attach('com.example.demoso1')
with open("/Users/zhangyang/codes/fridaProject/rpcDemo/hook.js") as f:
    jsCode = f.read()

# print("加载代码", jsCode)
script = session.create_script(jsCode)
script.on("message",message)
script.load()

# print("加密","1213")
# encodeResult = script.exports.invokemethod01("123")
# decodeResult = script.exports.invokemethod02(encodeResult)
# print(decodeResult)

app = Flask(__name__)

@app.route('/encrypt', methods=['POST'])#data解密
def decrypt_class():
    data = request.get_data()
    json_data = json.loads(data.decode("utf-8"))
    postdata = json_data.get("data")
    res = script.exports.invokemethod01(postdata)
    return res


@app.route('/decrypt', methods=['POST'])#url加密
def encrypt_class():
    data = request.get_data()
    json_data = json.loads(data.decode("utf-8"))
    postdata = json_data.get("data")
    print(postdata)
    res = script.exports.invokemethod02(postdata)
    return res

if __name__ == "__main__":
        app.run()
</code></pre>
<h2 id="js">js</h2>
<pre><code>JSX
///&lt;reference path='/Users/zhangyang/node_modules/@types/frida-gum/index.d.ts'/&gt;

// 先 hook 方法 method01
// function hookmethod1(){
//   Java.perform(function(){
//         var targetClass = Java.use("com.example.demoso1.MainActivity");
//         targetClass.method01.implementation = function(str){
//             console.log("str is ", str);
//             var result = this.method01(str);
//             console.log("result is ", result);
//             return result;
//         }
//   })
// };

// 主动调用
function fridamethod01(inputStr){
    var result = null;
    Java.perform(function(){
      var targetClass = Java.use("com.example.demoso1.MainActivity");
      result = targetClass.method01(inputStr);
    });
    return result;
}

function fridamethod02(inputStr){
    var result = null;
    // public native String method02(String str);
    Java.perform(function(){
      Java.choose("com.example.demoso1.MainActivity",{
            onMatch: function(ins){
                result = ins.method02(inputStr);
            },
            onComplete: function(){}
      })
    });
    return result;
}

// 优先测试 js 中的主动调用
// function main(){
//   console.log("你好 -&gt; 结果为:", fridamethod01("你好"));
//   console.log("27cae29a0913f6791705ca10be31a3e0 -&gt; 结果为", fridamethod02("27cae29a0913f6791705ca10be31a3e0"))
   
// }
// setImmediate(main);

// 基于主动调用设置 rpc
rpc.exports = {
    invokemethod01: fridamethod01,
    invokemethod02: fridamethod02,
}
</code></pre>
<h2 id="压力测试">压力测试</h2>
<p>tmp.json</p>
<pre><code>JSON{"data": "62feb9a98a01945ab06c0dd7823adc57"}
</code></pre>
<p>命令</p>
<pre><code>BASHsiege -c30 -r1 "&lt;http://127.0.0.1:5000/encrypt&gt; POST &lt; tmp.json"
</code></pre>
<h2 id="nps-进行内网穿透">nps 进行内网穿透</h2>
<ol>
<li>
<p>nps server 启动</p>
<p>mac: <code>sudo nps start</code></p>
</li>
<li>
<p>新建客户端</p>
<p><img src="https://kevinspider-1258012111.cos.ap-shanghai.myqcloud.com/2021-01-14-032324.png" alt="https://kevinspider-1258012111.cos.ap-shanghai.myqcloud.com/2021-01-14-032324.png" loading="lazy"></p>
<p>安卓手机连接客户端 <code>./npc -server=10.0.0.124:8024 -vkey=hm40rtjpf2j3c1up -type=tcp</code></p>
</li>
<li>
<p>给客户端添加和 frida server 的端口映射</p>
<p>安卓手机启动 frida-server: <code>./fs12800 -l 0.0.0.0:6666</code></p>
<p><img src="https://kevinspider-1258012111.cos.ap-shanghai.myqcloud.com/2021-01-14-032703.png" alt="https://kevinspider-1258012111.cos.ap-shanghai.myqcloud.com/2021-01-14-032703.png" loading="lazy"></p>
<p>将目标 frida-server 的端口映射到 56666 端口上</p>
</li>
<li>
<p>python 脚本更改和 frida-server 的连接</p>
<pre><code>PYTHONsession = frida.get_device_manager().add_remote_device('10.0.0.124:56666').attach('com.example.demoso1')
</code></pre>
<p>此时就可以将 frida-server 开放到公网了;</p>
</li>
</ol>
<h1 id="hook-普通方法">Hook 普通方法</h1>
<pre><code class="language-javascript">function main(){   
Java.perform(function(){      
    var UtilsClass = Java.use("com.kevin.app.Utils");      
    UtilsClass.getCalc.implementation = function (a,b){             
      // 打印信息                
      console.log('a:' + a + ' ' + 'b:' + b);              
      // 调用原方法获取结果             
      var value = this.getCalc(a, b);                
      console.log('result:',value);            
      // 修改返回值              
      return 123456;         
    }   
})
}
setImmediate(main);
</code></pre>
<h1 id="hook-重载方法">Hook 重载方法</h1>
<pre><code class="language-javascript">function main(){   
Java.perform(function(){      
    var UtilsClass = Java.use("com.kevin.app.Utils");
    // 重载无参方法      
    UtilsClass.test.overload().implementation = function () {            
      console.log("hook overload no args");            
      return this.test();      
    }               
    // 重载有参方法 - 基础数据类型               
    UtilsClass.test.overload('int').implementation = function(num){            
      console.log("hook overload int args");            
      var myNum = 9999;            
      var oriResult = this.test(num);            
      console.log("oriResult is :" + oriResult);            
      return this.test(myNum);      
    }               
    // 重载有参方法 - 引用数据类型      
    UtilsClass.test.overload('com.kevin.app.Money').implementation = function(money){
      console.log("hook Money args");
      return this.test(money);
    }               
    // hook 指定方法的所有重载      
    var ClassName = Java.use("com.xiaojianbang.app.Utils");
    var overloadsLength = ClassName.test.overloads.length;
    for (var i = 0; i &lt; overloadsLength; i++){
      ClassName.test.overloads.implementation = function () {               
      // 遍历打印 arguments               
      for (var a = 0; a &lt; arguments.length; a++){
          console.log(a + " : " + arguments);
      }               
      // 调用原方法               
      return this.test.apply(this,arguments);            
      }      
    }   
})
}
setImmediate(main);
</code></pre>
<h1 id="hook-构造方法">Hook 构造方法</h1>
<pre><code class="language-javascript">function main(){   
Java.perform(function (){
    // hook 构造方法 $init
    var MoneyClass = Java.use("com.kevin.app.Money");
    MoneyClass.$init.overload().implementation = function(){            
      console.log("hook Money $init");            
      this.$init();      }   
})
}
setImmediate(main);
</code></pre>
<h1 id="hook-对象">Hook 对象</h1>
<pre><code class="language-javascript">function main(){   
Java.perform(function(){      
    // hook instance      
    Java.choose("com.xiaojianbang.app.Money",{            
      onMatch : function(instance){               
      console.log("find it!!", instance.getInfo());
      // something to do...         
      },onComplete: function(){
      console.log("compelete!!!");
      }      
    })   
})
}
setImmediate(main);
</code></pre>
<h1 id="hook-动静态成员属性">Hook 动静态成员属性</h1>
<pre><code class="language-javascript">function main(){   
Java.perform(function(){      
    var MoneyClass = Java.use("com.xiaojianbang.app.Money");
    // get static properties
    // need to use .value
    var ori_property = MoneyClass.flag.value;      
    console.log("ori_property: ", ori_property);
    // change static properties         
    MoneyClass.flag.value = "change the value";      
    console.log("change to : ", MoneyClass.flag.value);               
    // get dynamic properties         
    Java.choose("com.xiaojianbang.app.Money",{            
      onMatch: function(instance){               
      instance.num.value = 50000;               
      // 当对象的成员属性和成员方法名重复时,成员属性前加`_`,进行区分
      instance._name.value = "ouyuan";
      console.log(instance._name.value, instance.num.value, instance.flag.value);
      },onComplete: function(){
      console.log("complete!!")
      }      
    })   
})
}
setImmediate(main);
</code></pre>
<h1 id="hook-内部类">Hook 内部类</h1>
<pre><code class="language-javascript">function main(){   
Java.perfor(function(){
    // hook 内部类
    // 内部类使用$进行分隔 不使用.
    var InnerClass = Java.use("com.xiaojianbang.app.Money$innerClass");
    // 重写内部类的 $init 方法      
    InnerClass.$init.overload("java.lang.String","int").implementation = function(x,y){
      console.log("x: ",x);            
      console.log("y: ",y);
      this.$init(x,y);
    }   
})
}setImmediate(main)
</code></pre>
<h1 id="hook-匿名类">Hook 匿名类</h1>
<pre><code class="language-javascript">// 接口, 抽象类, 不可以被new
// 接口, 抽象类 要使用必须要实例化, 实例化不是通过new, 而是通过实现接口方法, 继承抽象类等方式
// new __接口__{} 可以理解成 new 了一个实现接口的匿名类, 在匿名类的内部(花括号内),实现了这个接口
function main(){   
Java.perform(function(){
    // hook 匿名类      
    // 匿名类在 smail中以 $1, $2 等方式存在, 需要通过 java 行号去 smail 找到准确的匿名类名称         
    var NiMingClass = Java.use("com.xiaojianbang.app.MainActivity$1");      
    NiMingClass.getInfo.implementation = function (){         
      return "kevin change 匿名类";      
    }   
})
}
setImmediate(main)
</code></pre>
<h1 id="hook-类的所有方法">Hook 类的所有方法</h1>
<ul>
<li><code>Java.enumerateLoadedClasses()</code></li>
</ul>
<pre><code class="language-javascript">function main(){   
Java.perform(function(){      
    Java.enumerateLoadedClasses({
      onMatch: function(name,handle){   
      if (name.indexOf("com.xiaojianbang.app.Money") != -1){
          console.log(name,handle);
          // 利用反射 获取类中的所有方法
          var TargetClass = Java.use(name);
          // return Method Object List
          var methodsList = TargetClass.class.getDeclaredMethods();
          for (var i = 0; i &lt; methodsList.length; i++){
            // Method Objection getName()
            console.log(methodsList.getName());
          }               
      }            
      },
      onComplete: function(){
      console.log("complete!!!")
      }
    })
})}
</code></pre>
<ul>
<li><code>Java.enumerateLoadedClassesSync()</code></li>
</ul>
<pre><code class="language-javascript">function main(){   
Java.perform(function(){
    // return String[] class name
    var classList = Java.enumerateLoadedClassesSync();
    for (var i=0; i &lt; classList.length; i++){            
      var targetClass = classList;            
      if (targetClass.indexOf("com.xiaojianbang.app.Money") != -1){
      console.log("hook the class: ", targetClass);
      var TargetClass = Java.use(targetClass);
      // 利用反射获取类中的所有方法
      var methodsList = TargetClass.class.getDeclaredMethods();
      for (var k=0; k &lt; methodsList.length; k++){
          console.log(methodsList.getName());
      }                        
      }      
    }   
})
}
setImmediate(main)
</code></pre>
<h1 id="hook-类的所有方法及重载">Hook 类的所有方法及重载</h1>
<pre><code class="language-javascript">function main(){   
Java.perform(function(){      
    // hook md5 class in app      
    // 1. iterate classes
    var classList = Java.enumerateLoadedClassesSync();
    for (var i = 0; i &lt; classList.length; i++){
      // 筛选过滤 只遍历 MD5 下面的方法
      if (classList.indexOf("com.xiaojianbang.app.MD5") != -1){
      var className = classList;
      console.log("class name is :", className);
      // 2. get methods of the class
      // 返回一个 Methods对象的数组
      var methodsList = Java.use(className).class.getDeclaredMethods();
      for (var k=0; k&lt;methodsList.length; k++){
          console.log("method is :",methodsList,typeof(methodsList));
          // 3. Method object.getName() --&gt; methodName and class to hook method
          var methodName = methodsList.getName();
          console.log('methodName',methodName);
          // 4. use apply and arguments to implementation
          var hookClass = Java.use(className);
          // 5. overloads                  
          for (var o = 0; o&lt; hookClass.overloads.length; o++){
            hookClass.overloads.implementation = function(){
            for (var a=0; a&lt;arguments.length; a++){
                console.log('argument ',a,arguments);
            }                           
            // return this.apply(this,arguments);
            return "fucking the md5"                        
            }                  
          }               
      }            
      }      
    }   
})
}
</code></pre>
<h1 id="hook-动态加载的-dex">Hook 动态加载的 dex</h1>
<pre><code class="language-javascript">function main(){   
Java.perform(function(){
    Java.enumerateClassLoaders({
      onMatch : function(loader){
      try {                  
          // loadClass or findClass
          if (loader.loadClass("com.xiaojianbang.app.Dynamic")){
            Java.classFactory.loader = loader;
            var hookClass = Java.use("com.xiaojianbang.app.Dynamic");   
            console.log("success hook it :", hookClass);
            // something to do;
          }               
      } catch (error) {
          // pass               
      }
      },
      onComplete: function () {               
      console.log("complete !!! ")
      }      
    })   
})
}
setImmediate(main);
</code></pre>
<p>经常在加壳的 app 中, 没办法正确找到正常加载 app 类的 classloader, 可以使用以下代码:</p>
<pre><code class="language-javascript">function hook() {   
Java.perform(function () {
    Java.enumerateClassLoadersSync().forEach(function (classloader) {
      try {
      console.log("classloader", classloader);
      classloader.loadClass("com.kanxue.encrypt01.MainActivity");               
      Java.classFactory.loader = classloader;               
      var mainActivityClass = Java.use("com.kanxue.encrypt01.MainActivity");
      console.log("mainActivityClass", mainActivityClass);
      } catch (error) {               
      console.log("error", error);
      }      
    });   
})
}
</code></pre>
<h1 id="hook-主动构造数组">Hook 主动构造数组</h1>
<pre><code class="language-javascript">function mainArray(){   
Java.perform(function(){
    var myCharList = Java.array("char",['一','去','二','三','里']);
    var myStringList = Java.array("java.lang.String",["一","二","三"]);
    var ArrayClass = Java.use("java.util.Arrays");
    console.log(ArrayClass.toString(myCharList));      
    console.log(ArrayClass.toString(myStringList));   
})
}
</code></pre>
<h1 id="hook-cast-强制类型转换">Hook cast 强制类型转换</h1>
<pre><code class="language-javascript">// Java.cast() 子类可以强转成父类, 父类不能转成子类
// 可以使用Java.cast()将子类强转成父类, 再调用父类的动态方法
function castDemo(){   
Java.perform(function(){      
    var JuiceHandle = null;
    // 用来存储内存中找到的Juice对象      
    var WaterClass = Java.use("com.r0ysue.a0526printout.Water");                     Java.choose("com.r0ysue.a0526printout.Juice",{       
      onComplete: function(){},            
      onMatch: function(instance){
      JuiceHandle = instance;
      console.log("instance:", instance);
      // 调用Juice对象的方法               
      console.log(JuiceHandle.fillEnergy());               
      // 子类Juice转父类Water 并调用父类的动态方法               
      var WaterInstance = Java.cast(JuiceHandle,WaterClass);
      console.log(WaterInstance.still(WaterInstance));         
      }      
    })   
})
}
</code></pre>
<h1 id="hook-打印类实现的接口">Hook 打印类实现的接口</h1>
<pre><code class="language-javascript">function searchInterface(){   
Java.perform(function(){      
    Java.enumerateLoadedClasses({            
      onComplete: function(){},            
      onMatch: function(name,handle){
      if (name.indexOf("com.r0ysue.a0526printout") &gt; -1) {
          // 使用包名进行过滤                  
          console.log("find class");
          var targetClass = Java.use(name);
          var interfaceList = targetClass.class.getInterfaces();
          // 使用反射获取类实现的接口数组
          if (interfaceList.length &gt; 0) {
            console.log(name)
            // 打印类名
            for (var i in interfaceList) {
            console.log("\t", interfaceList.toString());
            // 直接打印接口名称
            }                  
          }               
      }            
      }      
    })   
})
}
</code></pre>
<h1 id="hook-enum-枚举">Hook enum 枚举</h1>
<pre><code class="language-javascript">function enumPrint(){   
Java.perform(function(){
    Java.choose("com.r0ysue.a0526printout.Signal",{
      onComplete: function(){},
      onMatch: function(instance){
      console.log('find it ,',instance);
      console.log(instance.class.getName());
      }
    })
})
}
</code></pre>
<h1 id="hook-获取-context">Hook 获取 context</h1>
<pre><code class="language-javascript">function getContext(){   
Java.perform(function(){
    var currentApplication = Java.use("android.app.ActivityThread").currentApplication();      
    console.log(currentApplication);
    var context = currentApplication.getApplicationContext();
    console.log(context);
    var packageName = context.getPackageName();
    console.log(packageName);
    console.log(currentApplication.getPackageName());
})
}
</code></pre>
<h1 id="hook-主动调用构造方法">Hook 主动调用构造方法</h1>
<pre><code class="language-javascript">function main(){   
Java.perform(function(){      
    var StringClass = Java.use("java.lang.String");
    var MoneyClass = Java.use("com.xiaojianbang.app.Money");
    MoneyClass.$init.overload('java.lang.String','int').implementation = function(x,y){
      console.log('hook Money init');            
      var myX = StringClass.new("Hello World!");            
      var myY = 9999;            
      this.$init(myX,myY);
    }   
})
}
setImmediate(main);
</code></pre>
<h1 id="hook-主动调用静态方法">Hook 主动调用静态方法</h1>
<pre><code class="language-javascript">function main_rsa(){
Java.perform(function(){
    var RSA = Java.use("com.xiaojianbang.app.RSA");
    var StringClass = Java.use("java.lang.String");
    var base64Class = Java.use("android.util.Base64");
    var myBytes = StringClass.$new("Hello World").getBytes();
    var result = RSA.encrypt(myBytes);      
    console.log("result is :", result);      
    console.log("json result is: ",JSON.stringify(result));      
    console.log("base64 result is :", base64Class.encodeToString(result,0));
    // console.log("new String is : ", StringClass.$new(result));
    // 加密之后的内容有很多不可见字符, 不能直接 new String()   
})
}setImmediate(main_rsa);
</code></pre>
<h1 id="hook-主动调用动态方法">Hook 主动调用动态方法</h1>
<pre><code class="language-javascript">// 非静态方法的主动调用 自定义instance 并调用 非静态方法
function main_getInfo(){   
Java.perform(function(){
    var instance = Java.use("com.xiaojianbang.app.Money").$new("日元",300000);
    console.log(instance.getInfo());   
})
}
// 遍历所有的对象并调用 需要进行过滤
function main_instance_getInfo(){   
Java.perform(function(){      
    Java.choose("com.xiaojianbang.app.Money",{
      onComplete: function(){},            
      onMatch: function(instance){               
      console.log(instance.getInfo());
      }      
    })
})
}
</code></pre>
<h1 id="hook-frida-和-python-交互">Hook frida 和 python 交互</h1>
<pre><code class="language-javascript">frida 传递参数
function main(){   
Java.perform(function () {      
    console.log("enter perform");
    // 获取要hook的类
    var TextViewClass = Java.use("android.widget.TextView");
    // 要hook的方法      
    TextViewClass.setText.overload('java.lang.CharSequence').implementation = function (ori_input) {
      console.log('enter', 'java.lang.CharSequence');
      console.log('ori_input',ori_input.toString());
      // 定义用于接受python传参的data
      var receive_data;
      // 将原参数传递给python 在python中进行处理
      send(ori_input.toString());
      // recv 从python接收传递的内容 默认传过来的是个json对象
      recv(function (json_data) {
      console.log('data from python ' + json_data.data);
      receive_data = json_data.data;
      console.log(typeof (receive_data));
      }).wait();
      //wait() 等待python处理 阻塞            
      // 转java字符串
      receive_data = Java.use("java.lang.String").$new(receive_data);
      this.setText(receive_data);
    };
})
}
setImmediate(main);

</code></pre>
<p>Python代码</p>
<pre><code class="language-python">python 处理收到的参数
# -*- coding: utf-8 -*-
import sysimport time
import base64
import frida
from loguru import logger
def on_message(message,data):   
logger.info(str(message))
# dict   
logger.info(str(data) if data else "None")   
if message['type'] == 'error':
    logger.error('error:' + str(message['description']))
    logger.error('stack: ' + str(message['stack']))
    if message['type'] == 'send':      
      logger.info('get message [*] --&gt; ' + message['payload'])      
      payload = message['payload']      
      # 处理逻辑 sending to the server: YWFhOmJiYg==      
      tmp = payload.split(':')
      sts = tmp
      need_to_db64 = tmp
      user_pass = base64.b64decode(need_to_db64.encode()).decode()
      mine_str = 'admin' + ':' + user_pass.split(':')[-1]
      mine_b64_str = base64.b64encode(mine_str.encode()).decode()
      mine_b64_str = sts + mine_b64_str
      logger.info(mine_b64_str)      
      # python返回数据给js script.post      
      script.post({'data':mine_b64_str})      
      logger.info('python complete')
      device = frida.get_usb_device()
      # pid = device.spawn(['com.kevin.demo04'])
      # time.sleep(1)
      session = device.attach('com.kevin.demo02')
      with open('./hulianhutong.js','r') as f:
      script = session.create_script(f.read())
      script.on("message",on_message)
      script.load()
      input()
</code></pre>
<h1 id="hook-打印-char">Hook 打印 char</h1>
<pre><code class="language-javascript">// 打印char字符, 直接调用java.lang.Character toString()即可
function main(){   
Java.perform(function(){      
    var CharClass = Java.use("java.lang.Character");      
    CharClass.toString.overload("char").implementation = function(inputChar){         
      var result = this.toString(inputChar);
      console.log("inputChar, result: ", inputChar, result);
      return result;
    }   
})
}
</code></pre>
<h1 id="hook-打印-char-数组">Hook 打印 char 数组</h1>
<pre><code class="language-javascript">// 1. 使用 java.util.Arrays 的 toString 方法 打印 [C
// 2. 使用 js 的 JSON.stringify 打印 [C
function printCharArray(){   
Java.perform(function(){
    var ArrayClass = Java.use("java.util.Arrays");
    ArrayClass.toString.overload('[C').implementation = function(charArray){
      // 1. java.util.Arrays.toString()         
      var result = this.toString(charArray);
      // 2. javascript JSON.stringify()
      var result1 = JSON.stringify(charArray);
      console.log('charArray, result : ', charArray, result);
      console.log('charArray, result :', charArray, result1);
    }   
})
}
</code></pre>
<h1 id="hook-打印和修改-hashmap">Hook 打印和修改 HashMap</h1>
<pre><code class="language-javascript">//遍历打印
function main(){       
Java.perform(function(){
    var targetClass = Java.use("com.xiaojianbang.app.ShufferMap");
    targetClass.show.implementation = function(map){
      // 遍历 map
      var result = "";       
      var it = map.keySet().iterator();
      while (it.hasNext()){
      var keyStr = it.next();
      var valueStr = map.get(keyStr);
      result += valueStr;       
      }
      console.log("result :", result);   
      // 修改 map
      map.put("pass","fxxk");
      map.put("code","Hello World");
      console.log(JSON.stringify(map));
      this.show(map);
      return this.show(map);
    }
})   
}
setImmediate(main)
//cast打印 HashMap
function main(){   
Java.perform(function(){
    var HashMapNode = Java.use("java.util.HashMap$Node");
    var targetClass = Java.use("com.xiaojianbang.app.ShufferMap");
    var targetClass.show.implementation = function(map){
      var result = "";         
      var iterator = map.entrySet().iterator();         
      while (iterator.hasNext()) {
      console.log("entry", iterator.next());
      var entry = Java.cast(iterator.next(), HashMapNode);
      console.log(entry.getKey());
      console.log(entry.getValue());
      return += entry.getValue();
      }                        
      console.log("result is :", result);
    }   
})
}
setImmediate(main);
</code></pre>
<p><code>toString()</code>打印</p>
<pre><code class="language-javascript">function main(){   
Java.perform(function(){
    var targetClass = Java.use("com.xiaojianbang.app.ShufferMap");
    targetClass.show.implementation = function(map){
      // 直接调用 toString()
      console.log("打印hashmap: -&gt; " + map.toString());
      return this.show.apply(this,arguments);
    }
})
}
setImmediate(main)

;function printHashMap(flag, param_hm) {   
Java.perform(function () {   
    var HashMap = Java.use('java.util.HashMap');
    var args_map = Java.cast(param_hm, HashMap);
    send(flag +":" + args_map.toString());
})
}
</code></pre>
<h1 id="hook-打印-byte-数组">Hook 打印 byte 数组</h1>
<pre><code class="language-javascript">//方法 1
function main(){   
Java.perform(function(){
    var StringClass = Java.use("java.lang.String");   
    var byteArray = StringClass.$new("Hello World").getBytes();            
    // load r0gson             
    // openClassFile 返回 dex对象, dex对象.load()加载dex文件内容   
    Java.openClassFile("/data/local/tmp/r0gson.dex").load();
    var gson = Java.use("com.r0ysue.gson.Gson");
    console.log(gson.$new().toJson(byteArray));
    // // console byte[]
    // var ByteString = Java.use("com.android.okhttp.okio.ByteString");
    // console.log(ByteString.of(byteArray).hex());
    // byte转16进制字符串
    // // 创建自定义Java数组 并打印
    // var MyArray = Java.array("byte",);
    // console.log(gson.$new().toJson(MyArray));
    var TargetClass = Java.use("com.xiaojianbang.app.ShufferMap");
    TargetClass.show.implementation =function(map){               
      console.log(gson.$new().toJson(map));
      return this.show(map);         
    }
})
}
setImmediate(main);
//方法 2
// 1. 使用 java.util.Arrays.toString() 打印 [B
// 2. 使用 javascript JSON.stringify() 打印 [B
function printByteArray(){
Java.perform(function(){   
    var ArrayClass = Java.use("java.util.Arrays");
    ArrayClass.toString.overload('[B').implementation = function(byteArray){       
      // 1. 使用 java.util.Arrays.toString() 打印 [B            
      var result = this.toString(byteArray);       
      // 2. 使用 javascript JSON.stringify() 打印 [B
      var result1 = JSON.stringify(byteArray);
      console.log('byteArray,result: ', byteArray, result);   
      console.log('byteArray,result1 :', byteArray, result1);
      return result      
    }
})
}
//方法 3
function printByteArray(byteArray){
Java.perform(function(){       
    var ByteString = Java.use("com.android.okhttp.okio.ByteString");               
    console.log(ByteString.of(byteArray).hex())
})
}
</code></pre>
<h1 id="hook-打印调用栈">Hook 打印调用栈</h1>
<pre><code class="language-javascript">function printStacks(name){   
console.log("====== printStacks start ====== " + name + "==============================")
// sample 1   
var throwable = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new());
console.log(throwable);   
// sample 2   
var exception = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new());
console.log(exception);      
console.log("====== printStacks end ======== " + name + "==============================")}
</code></pre>
<h1 id="hook-gson-打印">Hook gson 打印</h1>
<pre><code class="language-javascript">function main(){   
Java.perform(function(){
    var StringClass = Java.use("java.lang.String");   
    var byteArray = StringClass.$new("Hello World").getBytes();
    // load r0gson                
    // openClassFile 返回 dex对象, dex对象.load()加载dex文件内容
    Java.openClassFile("/data/local/tmp/r0gson.dex").load();   
    var gson = Java.use("com.r0ysue.gson.Gson");
    console.log(gson.$new().toJson(byteArray));
    // // console byte[]
    // var ByteString = Java.use("com.android.okhttp.okio.ByteString");   
    // console.log(ByteString.of(byteArray).hex());
    // byte转16进制字符串   
    // // 创建自定义Java数组 并打印
    // var MyArray = Java.array("byte",);   
    // console.log(gson.$new().toJson(MyArray));
    var TargetClass = Java.use("com.xiaojianbang.app.ShufferMap");
    TargetClass.show.implementation =function(map){
      console.log(gson.$new().toJson(map));
      return this.show(map);
    }
})
}
setImmediate(main);
</code></pre>
<h1 id="hook-打印-non-ascii-和特殊字符">Hook 打印 non-ascii 和特殊字符</h1>
<p>一些特殊字符和不可见字符, 可以先通过编码再解码的方式进行 <code>hook</code></p>
<pre><code class="language-javascript">int ֏(int x) {
return x + 100;
}
</code></pre>
<p>针对上面的<code>֏</code>, 直接用<code>js</code>编码, 在通过<code>类名</code>进行<code>implementation</code></p>
<pre><code class="language-javascript">JSJava.perform(      
function x() {   
    var targetClass = "com.example.hooktest.MainActivity";   
    var hookCls = Java.use(targetClass);   
    var methods = hookCls.class.getDeclaredMethods();
    for (var i in methods) {
      console.log(methods.toString());
      console.log(encodeURIComponent(methods.toString().replace(/^.*?\.([^\s\.\(\)]+)\(.*?$/, "$1")));   
    }            
    hookCls.implementation = function (x) {   
      console.log("original call: fun(" + x + ")");
      var result = this(900);
      return result;
    }
}
)
</code></pre>
<h1 id="简易-wallbreaker-内存打印">简易 wallbreaker 内存打印</h1>
<p>内存漫游, 打印实例的字段和方法</p>
<pre><code class="language-javascript">function main(){   
Java.perform(function(){
    var Class = Java.use("java.lang.Class");
    function inspectObject(obj){
      var obj_class = Java.cast(obj.getClass(), Class);
      var fields = obj_class.getDeclaredFields();
      var methods = obj_class.getMethods();
      console.log("Inspectiong " + obj.getClass().toString());
      console.log("\t Fields:")
      for (var i in fields){
      console.log("\t\t" + fields.toString());
      }         
      console.log("\t Methods:")
      for (var i in methods){
      console.log("\t\t" + methods.toString())
      }
    }
   
    Java.choose("com.baidu.lbs.waimai.WaimaiActivity",{
      onComplete: function(){
      console.log("complete!");
      },
      onMatch: function(instance){
      console.log("find instance", instance);
      inspectObject(instance);
      }      
    })   
})}
setImmediate(main)
</code></pre>
<h1 id="hook-frida-实现-runnable">hook frida 实现 runnable</h1>
<pre><code class="language-javascript">Java.perform(function() {
// https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_SECURE
var FLAG_SECURE = 0x2000;   
var Runnable = Java.use("java.lang.Runnable");
var DisableSecureRunnable = Java.registerClass({      
    name: "me.bhamza.DisableSecureRunnable",
    implements: ,
    fields: {
      activity: "android.app.Activity",
    },
    methods: {
      $init: [{
      returnType: "void",
      argumentTypes: ["android.app.Activity"],
      implementation: function (activity) {
          this.activity.value = activity;
      }
      }],
   run: function() {
       var flags = this.activity.value.getWindow().getAttributes().flags.value;
       // get current value            
       flags &amp;= ~FLAG_SECURE;
       // toggle it
       this.activity.value.getWindow().setFlags(flags, FLAG_SECURE);
       // disable it!            
       console.log("Done disabling SECURE flag...");
   }
    }
});

Java.choose("com.example.app.FlagSecureTestActivity", {
    "onMatch": function (instance) {
      var runnable = DisableSecureRunnable.$new(instance);
      instance.runOnUiThread(runnable);
    },
    "onComplete": function () {}   
});
});
</code></pre>
<h1 id="hook-监控控件-onclick">Hook 监控控件 onClick</h1>
<pre><code class="language-javascript">var jclazz = null;
var jobj = 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));
}

function watch(obj, mtdName) {   
var listener_name = getObjClassName(obj);
var target = Java.use(listener_name);
if (!target || !mtdName in target) {
    return;
}
// send(" hooking " + mtdName + ": " + listener_name);   
target.overloads.forEach(function (overload) {      
    overload.implementation = function () {
      //send(" " + mtdName + ": " + getObjClassName(this));
      console.log(" " + mtdName + ": " + getObjClassName(this))
      return this.apply(this, arguments);      
    };
})
}

function OnClickListener() {   
Java.perform(function () {
    //以spawn启动进程的模式来attach的话   
    Java.use("android.view.View").setOnClickListener.implementation = function (listener) {   
      if (listener != null) {
      watch(listener, 'onClick');
      }
      return this.setOnClickListener(listener);
    };
    //如果frida以attach的模式进行attch的话
    Java.choose("android.view.View$ListenerInfo", {   
      onMatch: function (instance) {            
      instance = instance.mOnClickListener.value;   
      if (instance) {
          console.log("mOnClickListener name is :" + getObjClassName(instance));   
          watch(instance, 'onClick');
      }         
      },      
      onComplete: function () {   
      }
    })
})
}
setImmediate(OnClickListener);
</code></pre>
<h1 id="hook-startactivity">Hook startActivity</h1>
<pre><code class="language-javascript">Java.perform(function () {
var Activity = Java.use("android.app.Activity");
//console.log(Object.getOwnPropertyNames(Activity));
Activity.startActivity.overload('android.content.Intent').implementation=function(p1){   
    console.log("Hooking android.app.Activity.startActivity(p1) successfully,p1="+p1);   
    console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
    console.log(decodeURIComponent(p1.toUri(256)));
    this.startActivity(p1);
}   
Activity.startActivity.overload('android.content.Intent', 'android.os.Bundle').implementation=function(p1,p2){
    console.log("Hooking android.app.Activity.startActivity(p1,p2) successfully,p1="+p1+",p2="+p2);   
    console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
    console.log(decodeURIComponent(p1.toUri(256)));
    this.startActivity(p1,p2);
}   
Activity.startService.overload('android.content.Intent').implementation=function(p1){
    console.log("Hooking android.app.Activity.startService(p1) successfully,p1="+p1);   
    console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));   
    console.log(decodeURIComponent(p1.toUri(256)));   
    this.startService(p1);
}}
            )
</code></pre>
<h1 id="hook-frida-绕过-root-检测">Hook frida 绕过 root 检测</h1>
<pre><code class="language-javascript">// $ frida -l antiroot.js -U -f com.example.app --no-pause
// CHANGELOG by Pichaya Morimoto (p.morimoto@sth.sh):
//- I added extra whitelisted items to deal with the latest versions
//                                                 of RootBeer/Cordova iRoot as of August 6, 2019
//- The original one just fucked up (kill itself) if Magisk is installed lol
// Credit &amp; Originally written by: https://codeshare.frida.re/@dzonerzy/fridantiroot/
// If this isn't working in the future, check console logs, rootbeer src, or libtool-checker.so
Java.perform(function() {

    var RootPackages = ["com.noshufou.android.su", "com.noshufou.android.su.elite", "eu.chainfire.supersu",
      "com.koushikdutta.superuser", "com.thirdparty.superuser", "com.yellowes.su", "com.koushikdutta.rommanager",
      "com.koushikdutta.rommanager.license", "com.dimonvideo.luckypatcher", "com.chelpus.lackypatch",
      "com.ramdroid.appquarantine", "com.ramdroid.appquarantinepro", "com.devadvance.rootcloak", "com.devadvance.rootcloakplus",
      "de.robv.android.xposed.installer", "com.saurik.substrate", "com.zachspong.temprootremovejb", "com.amphoras.hidemyroot",
      "com.amphoras.hidemyrootadfree", "com.formyhm.hiderootPremium", "com.formyhm.hideroot", "me.phh.superuser",
      "eu.chainfire.supersu.pro", "com.kingouser.com", "com.android.vending.billing.InAppBillingService.COIN","com.topjohnwu.magisk"
    ];

    var RootBinaries = ["su", "busybox", "supersu", "Superuser.apk", "KingoUser.apk", "SuperSu.apk","magisk"];

    var RootProperties = {
      "ro.build.selinux": "1",
      "ro.debuggable": "0",
      "service.adb.root": "0",
      "ro.secure": "1"
    };

    var RootPropertiesKeys = [];

    for (var k in RootProperties) RootPropertiesKeys.push(k);

    var PackageManager = Java.use("android.app.ApplicationPackageManager");

    var Runtime = Java.use('java.lang.Runtime');

    var NativeFile = Java.use('java.io.File');

    var String = Java.use('java.lang.String');

    var SystemProperties = Java.use('android.os.SystemProperties');

    var BufferedReader = Java.use('java.io.BufferedReader');

    var ProcessBuilder = Java.use('java.lang.ProcessBuilder');

    var StringBuffer = Java.use('java.lang.StringBuffer');

    var loaded_classes = Java.enumerateLoadedClassesSync();

    send("Loaded " + loaded_classes.length + " classes!");

    var useKeyInfo = false;

    var useProcessManager = false;

    send("loaded: " + loaded_classes.indexOf('java.lang.ProcessManager'));

    if (loaded_classes.indexOf('java.lang.ProcessManager') != -1) {
      try {
            //useProcessManager = true;
            //var ProcessManager = Java.use('java.lang.ProcessManager');
      } catch (err) {
            send("ProcessManager Hook failed: " + err);
      }
    } else {
      send("ProcessManager hook not loaded");
    }

    var KeyInfo = null;

    if (loaded_classes.indexOf('android.security.keystore.KeyInfo') != -1) {
      try {
            //useKeyInfo = true;
            //var KeyInfo = Java.use('android.security.keystore.KeyInfo');
      } catch (err) {
            send("KeyInfo Hook failed: " + err);
      }
    } else {
      send("KeyInfo hook not loaded");
    }

    PackageManager.getPackageInfo.overload('java.lang.String', 'int').implementation = function(pname, flags) {
      var shouldFakePackage = (RootPackages.indexOf(pname) &gt; -1);
      if (shouldFakePackage) {
            send("Bypass root check for package: " + pname);
            pname = "set.package.name.to.a.fake.one.so.we.can.bypass.it";
      }
      return this.getPackageInfo.call(this, pname, flags);
    };

    NativeFile.exists.implementation = function() {
      var name = NativeFile.getName.call(this);
      var shouldFakeReturn = (RootBinaries.indexOf(name) &gt; -1);
      if (shouldFakeReturn) {
            send("Bypass return value for binary: " + name);
            return false;
      } else {
            return this.exists.call(this);
      }
    };

    var exec = Runtime.exec.overload('[Ljava.lang.String;');
    var exec1 = Runtime.exec.overload('java.lang.String');
    var exec2 = Runtime.exec.overload('java.lang.String', '[Ljava.lang.String;');
    var exec3 = Runtime.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;');
    var exec4 = Runtime.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;', 'java.io.File');
    var exec5 = Runtime.exec.overload('java.lang.String', '[Ljava.lang.String;', 'java.io.File');

    exec5.implementation = function(cmd, env, dir) {
      if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id" || cmd == "sh") {
            var fakeCmd = "grep";
            send("Bypass " + cmd + " command");
            return exec1.call(this, fakeCmd);
      }
      if (cmd == "su") {
            var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";
            send("Bypass " + cmd + " command");
            return exec1.call(this, fakeCmd);
      }
      if (cmd == "which") {
            var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";
            send("Bypass which command");
            return exec1.call(this, fakeCmd);
      }
      return exec5.call(this, cmd, env, dir);
    };

    exec4.implementation = function(cmdarr, env, file) {
      for (var i = 0; i &lt; cmdarr.length; i = i + 1) {
            var tmp_cmd = cmdarr;
            if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id" || tmp_cmd == "sh") {
                var fakeCmd = "grep";
                send("Bypass " + cmdarr + " command");
                return exec1.call(this, fakeCmd);
            }

            if (tmp_cmd == "su") {
                var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";
                send("Bypass " + cmdarr + " command");
                return exec1.call(this, fakeCmd);
            }
      }
      return exec4.call(this, cmdarr, env, file);
    };

    exec3.implementation = function(cmdarr, envp) {
      for (var i = 0; i &lt; cmdarr.length; i = i + 1) {
            var tmp_cmd = cmdarr;
            if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id" || tmp_cmd == "sh") {
                var fakeCmd = "grep";
                send("Bypass " + cmdarr + " command");
                return exec1.call(this, fakeCmd);
            }

            if (tmp_cmd == "su") {
                var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";
                send("Bypass " + cmdarr + " command");
                return exec1.call(this, fakeCmd);
            }
      }
      return exec3.call(this, cmdarr, envp);
    };

    exec2.implementation = function(cmd, env) {
      if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id" || cmd == "sh") {
            var fakeCmd = "grep";
            send("Bypass " + cmd + " command");
            return exec1.call(this, fakeCmd);
      }
      if (cmd == "su") {
            var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";
            send("Bypass " + cmd + " command");
            return exec1.call(this, fakeCmd);
      }
      return exec2.call(this, cmd, env);
    };

    exec.implementation = function(cmd) {
      for (var i = 0; i &lt; cmd.length; i = i + 1) {
            var tmp_cmd = cmd;
            if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id" || tmp_cmd == "sh") {
                var fakeCmd = "grep";
                send("Bypass " + cmd + " command");
                return exec1.call(this, fakeCmd);
            }

            if (tmp_cmd == "su") {
                var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";
                send("Bypass " + cmd + " command");
                return exec1.call(this, fakeCmd);
            }
      }

      return exec.call(this, cmd);
    };

    exec1.implementation = function(cmd) {
      if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id" || cmd == "sh") {
            var fakeCmd = "grep";
            send("Bypass " + cmd + " command");
            return exec1.call(this, fakeCmd);
      }
      if (cmd == "su") {
            var fakeCmd = "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled";
            send("Bypass " + cmd + " command");
            return exec1.call(this, fakeCmd);
      }
      return exec1.call(this, cmd);
    };

    String.contains.implementation = function(name) {
      if (name == "test-keys") {
            send("Bypass test-keys check");
            return false;
      }
      return this.contains.call(this, name);
    };

    var get = SystemProperties.get.overload('java.lang.String');

    get.implementation = function(name) {
      if (RootPropertiesKeys.indexOf(name) != -1) {
            send("Bypass " + name);
            return RootProperties;
      }
      return this.get.call(this, name);
    };

    Interceptor.attach(Module.findExportByName("libc.so", "fopen"), {
      onEnter: function(args) {
            var path1 = Memory.readCString(args);
            var path = path1.split("/");
            var executable = path;
            var shouldFakeReturn = (RootBinaries.indexOf(executable) &gt; -1)
            if (shouldFakeReturn) {
                Memory.writeUtf8String(args, "/ggezxxx");
                send("Bypass native fopen &gt;&gt; "+path1);
            }
      },
      onLeave: function(retval) {

      }
    });

    Interceptor.attach(Module.findExportByName("libc.so", "fopen"), {
      onEnter: function(args) {
            var path1 = Memory.readCString(args);
            var path = path1.split("/");
            var executable = path;
            var shouldFakeReturn = (RootBinaries.indexOf(executable) &gt; -1)
            if (shouldFakeReturn) {
                Memory.writeUtf8String(args, "/ggezxxx");
                send("Bypass native fopen &gt;&gt; "+path1);
            }
      },
      onLeave: function(retval) {

      }
    });

    Interceptor.attach(Module.findExportByName("libc.so", "system"), {
      onEnter: function(args) {
            var cmd = Memory.readCString(args);
            send("SYSTEM CMD: " + cmd);
            if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id") {
                send("Bypass native system: " + cmd);
                Memory.writeUtf8String(args, "grep");
            }
            if (cmd == "su") {
                send("Bypass native system: " + cmd);
                Memory.writeUtf8String(args, "justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled");
            }
      },
      onLeave: function(retval) {

      }
    });

    /*
    TO IMPLEMENT:
    Exec Family
    int execl(const char *path, const char *arg0, ..., const char *argn, (char *)0);
    int execle(const char *path, const char *arg0, ..., const char *argn, (char *)0, char *const envp[]);
    int execlp(const char *file, const char *arg0, ..., const char *argn, (char *)0);
    int execlpe(const char *file, const char *arg0, ..., const char *argn, (char *)0, char *const envp[]);
    int execv(const char *path, char *const argv[]);
    int execve(const char *path, char *const argv[], char *const envp[]);
    int execvp(const char *file, char *const argv[]);
    int execvpe(const char *file, char *const argv[], char *const envp[]);
    */


    BufferedReader.readLine.overload().implementation = function() {
      var text = this.readLine.call(this);
      if (text === null) {
            // just pass , i know it's ugly as hell but test != null won't work :(
      } else {
            var shouldFakeRead = (text.indexOf("ro.build.tags=test-keys") &gt; -1);
            if (shouldFakeRead) {
                send("Bypass build.prop file read");
                text = text.replace("ro.build.tags=test-keys", "ro.build.tags=release-keys");
            }
      }
      return text;
    };

    var executeCommand = ProcessBuilder.command.overload('java.util.List');

    ProcessBuilder.start.implementation = function() {
      var cmd = this.command.call(this);
      var shouldModifyCommand = false;
      for (var i = 0; i &lt; cmd.size(); i = i + 1) {
            var tmp_cmd = cmd.get(i).toString();
            if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd.indexOf("mount") != -1 || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd.indexOf("id") != -1) {
                shouldModifyCommand = true;
            }
      }
      if (shouldModifyCommand) {
            send("Bypass ProcessBuilder " + cmd);
            this.command.call(this, ["grep"]);
            return this.start.call(this);
      }
      if (cmd.indexOf("su") != -1) {
            send("Bypass ProcessBuilder " + cmd);
            this.command.call(this, ["justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"]);
            return this.start.call(this);
      }

      return this.start.call(this);
    };

    if (useProcessManager) {
      var ProcManExec = ProcessManager.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;', 'java.io.File', 'boolean');
      var ProcManExecVariant = ProcessManager.exec.overload('[Ljava.lang.String;', '[Ljava.lang.String;', 'java.lang.String', 'java.io.FileDescriptor', 'java.io.FileDescriptor', 'java.io.FileDescriptor', 'boolean');

      ProcManExec.implementation = function(cmd, env, workdir, redirectstderr) {
            var fake_cmd = cmd;
            for (var i = 0; i &lt; cmd.length; i = i + 1) {
                var tmp_cmd = cmd;
                if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id") {
                  var fake_cmd = ["grep"];
                  send("Bypass " + cmdarr + " command");
                }

                if (tmp_cmd == "su") {
                  var fake_cmd = ["justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"];
                  send("Bypass " + cmdarr + " command");
                }
            }
            return ProcManExec.call(this, fake_cmd, env, workdir, redirectstderr);
      };

      ProcManExecVariant.implementation = function(cmd, env, directory, stdin, stdout, stderr, redirect) {
            var fake_cmd = cmd;
            for (var i = 0; i &lt; cmd.length; i = i + 1) {
                var tmp_cmd = cmd;
                if (tmp_cmd.indexOf("getprop") != -1 || tmp_cmd == "mount" || tmp_cmd.indexOf("build.prop") != -1 || tmp_cmd == "id") {
                  var fake_cmd = ["grep"];
                  send("Bypass " + cmdarr + " command");
                }

                if (tmp_cmd == "su") {
                  var fake_cmd = ["justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"];
                  send("Bypass " + cmdarr + " command");
                }
            }
            return ProcManExecVariant.call(this, fake_cmd, env, directory, stdin, stdout, stderr, redirect);
      };
    }

    if (useKeyInfo) {
      KeyInfo.isInsideSecureHardware.implementation = function() {
            send("Bypass isInsideSecureHardware");
            return true;
      }
    }

});
</code></pre>
<h1 id="hook-frida-强制在主线程运行">Hook frida 强制在主线程运行</h1>
<p>针对使用一些方法的时候出现报错 <code>on a thread that has not called Looper.prepare()</code></p>
<p>强制让代码运行在主线程中</p>
<pre><code>JSJava.perform(function() {var Toast = Java.use('android.widget.Toast');var currentApplication = Java.use('android.app.ActivityThread').currentApplication();   var context = currentApplication.getApplicationContext();Java.scheduleOnMainThread(function() {    Toast.makeText(context, "Hello World", Toast.LENGTH_LONG.value).show();})})
</code></pre>
<h1 id="hook-frida-指定方法中过滤打印">Hook frida 指定方法中过滤打印</h1>
<pre><code>JSfunction hook_lnf() {    var activate = false;    Java.perform(function(){      var hashmapClass = Java.use("java.util.HashMap");      hashmapClass.put.implementation = function(key,value){            if (activate){                console.log("key:", key, "value:", value);            }            return this.put(key,value);      };    });    Java.perform(function () {      var lnfClazz = Java.use("tb.lnf");      lnfClazz.a.overload('java.util.HashMap', 'java.util.HashMap', 'java.lang.String',            'java.lang.String', 'boolean').implementation = function (hashmap, hashmap2, str, str2, z) {                printHashMap("hashmap", hashmap);                printHashMap("hashmap2", hashmap2);                console.log("str", str);                console.log("str2", str2);                console.log("boolean", z);                activate = true;                var result = this.a(hashmap, hashmap2, str, str2, z);                activate = false                printHashMap("result", result);                return result;            };    })}
</code></pre>
<h1 id="hook-禁止-app-退出">Hook 禁止 app 退出</h1>
<pre><code class="language-javascript">function hookExit(){
Java.perform(function(){   
    console.log("[*] Starting hook exit");
    var exitClass = Java.use("java.lang.System");
    exitClass.exit.implementation = function(){   
      console.log("[*] System.exit.called");   
    }
    console.log("[*] hooking calls to System.exit");
})
}
setImmediate(hookExit);
</code></pre>
<h1 id="hook-修改设备参数">Hook 修改设备参数</h1>
<pre><code class="language-javascript">// frida hook 修改设备参数
Java.perform(function() {       
var TelephonyManager = Java.use("android.telephony.TelephonyManager");
//IMEI hook
TelephonyManager.getDeviceId.overload().implementation = function () {
    console.log("[*]Called - getDeviceId()");
    var temp = this.getDeviceId();   
    console.log("real IMEI: "+temp);
    return "867979021642856";
};
// muti IMEI
TelephonyManager.getDeviceId.overload('int').implementation = function (p) {
    console.log("[*]Called - getDeviceId(int) param is"+p);
    var temp = this.getDeviceId(p);
    console.log("real IMEI "+p+": "+temp);
    return "867979021642856";   
};
//IMSI hook
TelephonyManager.getSimSerialNumber.overload().implementation = function () {
    console.log("[*]Called - getSimSerialNumber(String)");   
    var temp = this.getSimSerialNumber();
    console.log("real IMSI: "+temp);
    return "123456789";
};
//////////////////////////////////////   
//ANDOID_ID hook   
var Secure = Java.use("android.provider.Settings$Secure");
Secure.getString.implementation = function (p1,p2) {
    if(p2.indexOf("android_id")&lt;0) return this.getString(p1,p2);
    console.log("[*]Called - get android_ID, param is:"+p2);
    var temp = this.getString(p1,p2);
    console.log("real Android_ID: "+temp);
    return "844de23bfcf93801";
}   
//android的hidden API,需要通过反射调用
var SP = Java.use("android.os.SystemProperties");   
SP.get.overload('java.lang.String').implementation = function (p1) {           
    var tmp = this.get(p1);           
    console.log("[*]"+p1+" : "+tmp);
    return tmp;   
}   
SP.get.overload('java.lang.String', 'java.lang.String').implementation = function (p1,p2) {   
    var tmp = this.get(p1,p2)           
    console.log("[*]"+p1+","+p2+" : "+tmp);
    return tmp;
}   
// hook MAC
var wifi = Java.use("android.net.wifi.WifiInfo");
wifi.getMacAddress.implementation = function () {
    var tmp = this.getMacAddress();
    console.log("[*]real MAC: "+tmp);
    return tmp;
}
})
</code></pre>
<h1 id="hook-打印请求调用栈">Hook 打印请求调用栈</h1>
<pre><code class="language-javascript">var class_Socket = Java.use("java.net.Socket");
class_Socket.getOutputStream.overload().implementation = function(){
send("getOutputSteam");
var result = this.getOutputStream();
var bt = Java.use("android.util.Log").getStackTraceString(
    Java.use("java.lang.Exception").$new();
)
console.log("Backtrace:" + bt);
send(result);
return result;
}
</code></pre>
<h1 id="hook-ui-thread-注入">Hook UI thread 注入</h1>
<pre><code class="language-javascript">Java.perform(function() {
var Toast = Java.use('android.widget.Toast');
var currentApplication = Java.use('android.app.ActivityThread').currentApplication();
var context = currentApplication.getApplicationContext();
Java.scheduleOnMainThread(function() {
    Toast.makeText(context, "Hello World", Toast.LENGTH_LONG.value).show();

}
    )}
      )
</code></pre>
<h1 id="常用打印转换">常用打印转换</h1>
<pre><code>JS
//工具相关函数
var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
    base64DecodeChars = new Array((-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), 62, (-1), (-1), (-1), 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, (-1), (-1), (-1), (-1), (-1), (-1), (-1), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, (-1), (-1), (-1), (-1), (-1), (-1), 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, (-1), (-1), (-1), (-1), (-1));

function stringToBase64(e) {
    var r, a, c, h, o, t;
    for (c = e.length, a = 0, r = ''; a &lt; c;) {
      if (h = 255 &amp; e.charCodeAt(a++), a == c) {
            r += base64EncodeChars.charAt(h &gt;&gt; 2),
                r += base64EncodeChars.charAt((3 &amp; h) &lt;&lt; 4),
                r += '==';
            break
      }
      if (o = e.charCodeAt(a++), a == c) {
            r += base64EncodeChars.charAt(h &gt;&gt; 2),
                r += base64EncodeChars.charAt((3 &amp; h) &lt;&lt; 4 | (240 &amp; o) &gt;&gt; 4),
                r += base64EncodeChars.charAt((15 &amp; o) &lt;&lt; 2),
                r += '=';
            break
      }
      t = e.charCodeAt(a++),
            r += base64EncodeChars.charAt(h &gt;&gt; 2),
            r += base64EncodeChars.charAt((3 &amp; h) &lt;&lt; 4 | (240 &amp; o) &gt;&gt; 4),
            r += base64EncodeChars.charAt((15 &amp; o) &lt;&lt; 2 | (192 &amp; t) &gt;&gt; 6),
            r += base64EncodeChars.charAt(63 &amp; t)
    }
    return r
}

function base64ToString(e) {
    var r, a, c, h, o, t, d;
    for (t = e.length, o = 0, d = ''; o &lt; t;) {
      do
            r = base64DecodeChars;
      while (o &lt; t &amp;&amp; r == -1);
      if (r == -1)
            break;
      do
            a = base64DecodeChars;
      while (o &lt; t &amp;&amp; a == -1);
      if (a == -1)
            break;
      d += String.fromCharCode(r &lt;&lt; 2 | (48 &amp; a) &gt;&gt; 4);
      do {
            if (c = 255 &amp; e.charCodeAt(o++), 61 == c)
                return d;
            c = base64DecodeChars
      } while (o &lt; t &amp;&amp; c == -1);
      if (c == -1)
            break;
      d += String.fromCharCode((15 &amp; a) &lt;&lt; 4 | (60 &amp; c) &gt;&gt; 2);
      do {
            if (h = 255 &amp; e.charCodeAt(o++), 61 == h)
                return d;
            h = base64DecodeChars
      } while (o &lt; t &amp;&amp; h == -1);
      if (h == -1)
            break;
      d += String.fromCharCode((3 &amp; c) &lt;&lt; 6 | h)
    }
    return d
}

function hexToBase64(str) {
    return base64Encode(String.fromCharCode.apply(null, str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" ")));
}

function base64ToHex(str) {
    for (var i = 0, bin = base64Decode(str.replace(/[ \r\n]+$/, "")), hex = []; i &lt; bin.length; ++i) {
      var tmp = bin.charCodeAt(i).toString(16);
      if (tmp.length === 1)
            tmp = "0" + tmp;
      hex = tmp;
    }
    return hex.join("");
}

function hexToBytes(str) {
    var pos = 0;
    var len = str.length;
    if (len % 2 != 0) {
      return null;
    }
    len /= 2;
    var hexA = new Array();
    for (var i = 0; i &lt; len; i++) {
      var s = str.substr(pos, 2);
      var v = parseInt(s, 16);
      hexA.push(v);
      pos += 2;
    }
    return hexA;
}

function bytesToHex(arr) {
    var str = '';
    var k, j;
    for (var i = 0; i &lt; arr.length; i++) {
      k = arr;
      j = k;
      if (k &lt; 0) {
            j = k + 256;
      }
      if (j &lt; 16) {
            str += "0";
      }
      str += j.toString(16);
    }
    return str;
}

function stringToHex(str) {
    var val = "";
    for (var i = 0; i &lt; str.length; i++) {
      if (val == "")
            val = str.charCodeAt(i).toString(16);
      else
            val += str.charCodeAt(i).toString(16);
    }
    return val
}

function stringToBytes(str) {
    var ch, st, re = [];
    for (var i = 0; i &lt; str.length; i++) {
      ch = str.charCodeAt(i);
      st = [];
      do {
            st.push(ch &amp; 0xFF);
            ch = ch &gt;&gt; 8;
      }
      while (ch);
      re = re.concat(st.reverse());
    }
    return re;
}

//将byte[]转成String的方法
function bytesToString(arr) {
    var str = '';
    arr = new Uint8Array(arr);
    for (var i in arr) {
      str += String.fromCharCode(arr);
    }
    return str;
}

function bytesToBase64(e) {
    var r, a, c, h, o, t;
    for (c = e.length, a = 0, r = ''; a &lt; c;) {
      if (h = 255 &amp; e, a == c) {
            r += base64EncodeChars.charAt(h &gt;&gt; 2),
                r += base64EncodeChars.charAt((3 &amp; h) &lt;&lt; 4),
                r += '==';
            break
      }
      if (o = e, a == c) {
            r += base64EncodeChars.charAt(h &gt;&gt; 2),
                r += base64EncodeChars.charAt((3 &amp; h) &lt;&lt; 4 | (240 &amp; o) &gt;&gt; 4),
                r += base64EncodeChars.charAt((15 &amp; o) &lt;&lt; 2),
                r += '=';
            break
      }
      t = e,
            r += base64EncodeChars.charAt(h &gt;&gt; 2),
            r += base64EncodeChars.charAt((3 &amp; h) &lt;&lt; 4 | (240 &amp; o) &gt;&gt; 4),
            r += base64EncodeChars.charAt((15 &amp; o) &lt;&lt; 2 | (192 &amp; t) &gt;&gt; 6),
            r += base64EncodeChars.charAt(63 &amp; t)
    }
    return r
}

function base64ToBytes(e) {
    var r, a, c, h, o, t, d;
    for (t = e.length, o = 0, d = []; o &lt; t;) {
      do
            r = base64DecodeChars;
      while (o &lt; t &amp;&amp; r == -1);
      if (r == -1)
            break;
      do
            a = base64DecodeChars;
      while (o &lt; t &amp;&amp; a == -1);
      if (a == -1)
            break;
      d.push(r &lt;&lt; 2 | (48 &amp; a) &gt;&gt; 4);
      do {
            if (c = 255 &amp; e.charCodeAt(o++), 61 == c)
                return d;
            c = base64DecodeChars
      } while (o &lt; t &amp;&amp; c == -1);
      if (c == -1)
            break;
      d.push((15 &amp; a) &lt;&lt; 4 | (60 &amp; c) &gt;&gt; 2);
      do {
            if (h = 255 &amp; e.charCodeAt(o++), 61 == h)
                return d;
            h = base64DecodeChars
      } while (o &lt; t &amp;&amp; h == -1);
      if (h == -1)
            break;
      d.push((3 &amp; c) &lt;&lt; 6 | h)
    }
    return d
}
</code></pre>
<p>文章作者: Kevin<br>
文章链接: http://example.com/fridahookjava/<br>
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 凡墙总是门!</p><br><br>
来源:https://www.cnblogs.com/c-x-a/p/15294911.html
頁: [1]
查看完整版本: fridahookjava