Frida上手和逆向三段

xiaoeryu Lv5

本章主要内容:

Frida基本操作:参数、调用栈、返回值

Frida精髓:方法重载、参数构造、动静态处理、主动调用、忽略内部细节,直接返回结果

逆向三段:(hook ・invoke)・rpc

编写代码测试hook

新建一个java类型的项目

图0
目标Demo源码
package com.xiaoeryu.lesson4_4;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        while (true){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            int m = fun(4, 5);

        }
    }

    int fun(int x, int y){
        Log.d("xiaoeryu", String.valueOf(x + y));
        return x + y;
    }

}

hook被调用的fun()函数

function main(){
    Java.perform(function(){
        Java.use("com.xiaoeryu.lesson4_4.MainActivity").fun.implementation = function(arg1, arg2){
            var result = this.fun(arg1, arg2);
            console.log("arg1, arg2, result", arg1, arg2, result);
            return result;
        }
    })
}

setImmediate(main)

方法重载hook

给源码添加一个重载函数,并调用
    int fun(int x, int y){
        Log.d("xiaoeryu", String.valueOf(x + y));
        return x + y;
    }
有重载情况下的hook
function main(){
    Java.perform(function(){
        // overloading with two parameters
        Java.use("com.xiaoeryu.lesson4_4.MainActivity").fun.overload('int', 'int').implementation = function(arg1, arg2){
            var result = this.fun(100, 200);    // parameters can be changed
            console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));	// print call stack
            console.log("arg1, arg2, result", arg1, arg2, result);
            return result;
        }
        // overloading with a one parameter
        Java.use("com.xiaoeryu.lesson4_4.MainActivity").fun.overload('java.lang.String').implementation = function(arg1){
            var result = this.fun(Java.use('java.lang.String').$new('NIHAO'));  // parameters can be changed
            console.log("arg1, result", arg1, result);
            return result;
        }
    })
}

setImmediate(main)

主动调用未被调用的函数

图一
hook方法
        Java.choose("com.xiaoeryu.lesson4_4.MainActivity",{
            onMatch:function(instance){
                console.log("found instance: ", instance)
                console.log("found instance: ", instance.secret())
            },onComplete:function(){}
        })
静态方法
图二

如果是静态方法的话,会更简单点

hook方法
var result = Java.use("com.xiaoeryu.lesson4_4.MainActivity").secret2();
        console.log(result);

实践

把各种情况分析完了,用上一章测试用的CTF题目来实践一下

在hook的时候如果是动态方法的话,我们需要去搜索实例,如果是静态方法直接调用就ok

图三
  • 用jadx可以看到我们要调用的a方法没有static修饰,是一个动态方法

  • 这样的话我们就需要在MainActivity类中去搜索它的实例去调用

上一章已经分析过了,我们要hook的是里面的getWritableDatabase函数

图四
  • 可以看到这个函数有重载,对于有重载的方法如果我们不确定应该hook哪一个就可以全部都hook
hook方法
图五
  • 可以看到报错提示有重载,修改一下脚本hook这两个重载
图六
  • 修改完就不报错了,但是因为没有调用所以我们也获取不到想要的信息
在MainActivity中搜索实例a并调用
function invoke(){
    Java.perform(function(){
        Java.choose("com.example.yaphetshan.tencentwelcome.MainActivity", {
            onMatch:function(instance){
                console.log("found instance ", instance);
                console.log("invoke instance.a ", instance.a());
            }, onComplete:function(){console.log("search completed!")}
        })
    })
}

实现完成CTRL+S保存一遍就执行了

  • 可以看到密码已经被我们成功的拿到了
  • 并且可以看到是通过参数为String的重载拿到的
  • 顺便也打印它的调用堆栈看一下

附件:

测试hook的Demo源码

hook脚本源码

  • 标题: Frida上手和逆向三段
  • 作者: xiaoeryu
  • 创建于 : 2023-11-17 17:05:39
  • 更新于 : 2023-11-24 16:18:10
  • 链接: https://github.com/xiaoeryu/2023/11/17/Frida上手和逆向三段/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论