CENSUS / ghidra-frida-hook-gen

Frida hook generator for Ghidra
BSD 2-Clause "Simplified" License
108 stars 12 forks source link

Frida Hook generator for Ghidra

This plugin provides three new options in the right-click menu of the Listing Window in Ghidra:

Hook-demo

This extension supports both function-level hooking (when hooking the first address of a function), as well as arbitrary address hooking (when hooking inside a function).

It should be noted that the right-click should be done when hovering over the instruction address in the Listing Window. If for example it is done when hovering over a function name that the current instruction calls, the hook will be generated for that function, and not the current instruction.

Installation:

Usage:

Notes:

var module_name_vlc_exe='vlc.exe';

function start_timer_for_intercept() {
  setTimeout(
    function() {
        console.log("Registering interceptors...");

        var offset_of_FUN_00432450_00432450=0x32450;
        var dynamic_address_of_FUN_00432450_00432450=Module.findBaseAddress(module_name_vlc_exe).add(offset_of_FUN_00432450_00432450);
        Interceptor.attach(dynamic_address_of_FUN_00432450_00432450, {
                    onEnter: function(args) {
                        console.log("Entered FUN_00432450_00432450");
                        console.log('args[0]='+args[0]+' , args[1]='+args[1]+' , args[2]='+args[2]+' , args[3]='+args[3]);
                        // this.context.x0=0x1;
                    },
                    onLeave: function(retval) {
                        console.log("Exited FUN_00432450_00432450, retval:"+retval);
                        // retval.replace(0x1);
                    }
        }); 

        Interceptor.flush();
        console.log("Registered interceptors.");
    }, 2000);//milliseconds
}
start_timer_for_intercept();

If the option "Copy Frida Hook Snippet" is used, only the part in the middle will be returned (between the first console.log() and the Interceptor.flush()).
The code when hooking a random address that is not the first address in a function looks like the following:

    var offset_of_0043246c=0x3246c;
    var dynamic_address_of_0043246c=Module.findBaseAddress(module_name_vlc_exe).add(offset_of_0043246c);
    function function_to_call_when_code_reaches_0043246c(){
        console.log('Reached address 0x0043246c, which is inside function FUN_00432450');
        //this.context.x0=0x1;
    }
    Interceptor.attach(dynamic_address_of_0043246c, function_to_call_when_code_reaches_0043246c); 

The generated code that provides easy access to a struct's fields looks like the following:

class struct__time_h_timespec {
    constructor(baseaddr) {
        this.alignment = 8
        this.is_packed = true
        this.base = baseaddr
        this.total_size = 16
        this.layout = {
            tv_sec : this.base.add(0),   //__time_t, size:8 - Signed Long Integer (compiler-specific size)
            tv_nsec : this.base.add(8)   //long, size:8 - Signed Long Integer (compiler-specific size)
        }
        this.offsets = {
            tv_sec : 0,   //__time_t, size:8
            tv_nsec : 8   //long, size:8
        }
    }
}

class struct__time_h_itimerspec {
    constructor(baseaddr) {
        this.alignment = 8
        this.is_packed = true
        this.base = baseaddr
        this.total_size = 32
        this.layout = {
            it_interval : this.base.add(0),   //timespec, size:16 - 
            it_value : this.base.add(16)   //timespec, size:16 - 
        }
        this.offsets = {
            it_interval : 0,   //timespec, size:16
            it_value : 16   //timespec, size:16
        }
        this.members = {
            it_interval : new struct__time_h_timespec(this.layout.it_interval),  
            it_value : new struct__time_h_timespec(this.layout.it_value)  
        }
    }
}

Example usage videos :