Skip to content

Instantly share code, notes, and snippets.

@jimmy947788
Last active February 28, 2025 04:40
Show Gist options
  • Save jimmy947788/43b05c8f7c0e4e9325dc7356583a2050 to your computer and use it in GitHub Desktop.
Save jimmy947788/43b05c8f7c0e4e9325dc7356583a2050 to your computer and use it in GitHub Desktop.
frida 腳本hook so的 .init_array 區段的執行函數,再接著跑stalker
// 來源:frida hook init_array自吐新解
// https://bbs.kanxue.com/thread-280135.htm
const TARGET_SO_NAME = "libaaaaaaaa.so";
function start_stalker(tragetAddress){
const module = Process.findModuleByAddress(tragetAddress);
console.log(`[start_stalker] tragetAddress: ${tragetAddress} module: ${module.name} base: ${module.base} size: ${module.size}`);
Interceptor.attach(tragetAddress, {
onEnter: function (args) {
var curTid = Process.getCurrentThreadId();
Stalker.follow(curTid, {
transform: function (iterator) {
let instruction = iterator.next();
const baseFirstAddress = instruction.address;
//可以判读是否在当前模块内
const isModuleCode = baseFirstAddress.compare(module.base) >= 0 &&
baseFirstAddress.compare(module.base.add(module.size)) <= 0;
//const module = Process.findModuleByAddress(baseFirstAddress);
if (isModuleCode) {
if (module) {
const name = module.name;
const offset = baseFirstAddress.sub(module.base);
const base = module.base;
console.log(`[transform] start: ${baseFirstAddress} name:${name} offset: ${offset} base: ${base}`);
} else {
console.log(`[transform] start: ${baseFirstAddress}`);
}
}
do {
const curRealAddr = instruction.address;
const curOffset = curRealAddr.sub(baseFirstAddress);
const curOffsetInt = curOffset.toInt32()
const instructionStr = instruction.toString()
const realOffset = curRealAddr.sub(module.base);
if (isModuleCode){
console.log("\t" + curRealAddr + "(" + realOffset +") <+" + curOffsetInt + ">: " + instructionStr);
}
iterator.keep();
} while ((instruction = iterator.next()) !== null);
if (isModuleCode){
console.log()
}
}
})
},
onLeave: function (retval) {
console.warn("===== stalker 结束 =====");
Stalker.unfollow();
Stalker.garbageCollect();
}
})
}
let cm_include = `
#include <stdio.h>
#include <gum/gumprocess.h>
`
let cm_code = `
#if defined(__LP64__)
#define USE_RELA 1
#endif
// http://aosp.app/android-14.0.0_r1/xref/bionic/libc/include/link.h
#if defined(__LP64__)
#define ElfW(type) Elf64_ ## type
#else
#define ElfW(type) Elf32_ ## type
#endif
// http://aosp.app/android-14.0.0_r1/xref/bionic/libc/kernel/uapi/asm-generic/int-ll64.h
typedef signed char __s8;
typedef unsigned char __u8;
typedef signed short __s16;
typedef unsigned short __u16;
typedef signed int __s32;
typedef unsigned int __u32;
typedef signed long long __s64;
typedef unsigned long long __u64;
// http://aosp.app/android-14.0.0_r1/xref/bionic/libc/kernel/uapi/linux/elf.h
typedef __u32 Elf32_Addr;
typedef __u16 Elf32_Half;
typedef __u32 Elf32_Off;
typedef __s32 Elf32_Sword;
typedef __u32 Elf32_Word;
typedef __u64 Elf64_Addr;
typedef __u16 Elf64_Half;
typedef __s16 Elf64_SHalf;
typedef __u64 Elf64_Off;
typedef __s32 Elf64_Sword;
typedef __u32 Elf64_Word;
typedef __u64 Elf64_Xword;
typedef __s64 Elf64_Sxword;
typedef struct dynamic {
Elf32_Sword d_tag;
union {
Elf32_Sword d_val;
Elf32_Addr d_ptr;
} d_un;
} Elf32_Dyn;
typedef struct {
Elf64_Sxword d_tag;
union {
Elf64_Xword d_val;
Elf64_Addr d_ptr;
} d_un;
} Elf64_Dyn;
typedef struct elf32_rel {
Elf32_Addr r_offset;
Elf32_Word r_info;
} Elf32_Rel;
typedef struct elf64_rel {
Elf64_Addr r_offset;
Elf64_Xword r_info;
} Elf64_Rel;
typedef struct elf32_rela {
Elf32_Addr r_offset;
Elf32_Word r_info;
Elf32_Sword r_addend;
} Elf32_Rela;
typedef struct elf64_rela {
Elf64_Addr r_offset;
Elf64_Xword r_info;
Elf64_Sxword r_addend;
} Elf64_Rela;
typedef struct elf32_sym {
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Half st_shndx;
} Elf32_Sym;
typedef struct elf64_sym {
Elf64_Word st_name;
unsigned char st_info;
unsigned char st_other;
Elf64_Half st_shndx;
Elf64_Addr st_value;
Elf64_Xword st_size;
} Elf64_Sym;
typedef struct elf32_phdr {
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
typedef struct elf64_phdr {
Elf64_Word p_type;
Elf64_Word p_flags;
Elf64_Off p_offset;
Elf64_Addr p_vaddr;
Elf64_Addr p_paddr;
Elf64_Xword p_filesz;
Elf64_Xword p_memsz;
Elf64_Xword p_align;
} Elf64_Phdr;
// http://aosp.app/android-14.0.0_r1/xref/bionic/linker/linker_soinfo.h
typedef void (*linker_dtor_function_t)();
typedef void (*linker_ctor_function_t)(int, char**, char**);
#if defined(__work_around_b_24465209__)
#define SOINFO_NAME_LEN 128
#endif
typedef struct {
#if defined(__work_around_b_24465209__)
char old_name_[SOINFO_NAME_LEN];
#endif
const ElfW(Phdr)* phdr;
size_t phnum;
#if defined(__work_around_b_24465209__)
ElfW(Addr) unused0; // DO NOT USE, maintained for compatibility.
#endif
ElfW(Addr) base;
size_t size;
#if defined(__work_around_b_24465209__)
uint32_t unused1; // DO NOT USE, maintained for compatibility.
#endif
ElfW(Dyn)* dynamic;
#if defined(__work_around_b_24465209__)
uint32_t unused2; // DO NOT USE, maintained for compatibility
uint32_t unused3; // DO NOT USE, maintained for compatibility
#endif
void* next;
uint32_t flags_;
const char* strtab_;
ElfW(Sym)* symtab_;
size_t nbucket_;
size_t nchain_;
uint32_t* bucket_;
uint32_t* chain_;
#if !defined(__LP64__)
ElfW(Addr)** unused4; // DO NOT USE, maintained for compatibility
#endif
#if defined(USE_RELA)
ElfW(Rela)* plt_rela_;
size_t plt_rela_count_;
ElfW(Rela)* rela_;
size_t rela_count_;
#else
ElfW(Rel)* plt_rel_;
size_t plt_rel_count_;
ElfW(Rel)* rel_;
size_t rel_count_;
#endif
linker_ctor_function_t* preinit_array_;
size_t preinit_array_count_;
linker_ctor_function_t* init_array_;
size_t init_array_count_;
linker_dtor_function_t* fini_array_;
size_t fini_array_count_;
linker_ctor_function_t init_func_;
linker_dtor_function_t fini_func_;
} soinfo;
void tell_init_info(soinfo* ptr, void (*cb)(int, void*, void*)) {
cb(ptr->init_array_count_, ptr->init_array_, ptr->init_func_);
}
`
let cm = null;
let tell_init_info = null;
function setup_cmodule() {
if (Process.pointerSize == 4) {
cm_code = cm_include + "#define __work_around_b_24465209__ 1" + cm_code;
} else {
cm_code = cm_include + "#define __LP64__ 1" + cm_code;
}
cm = new CModule(cm_code, {});
tell_init_info = new NativeFunction(cm.tell_init_info, "void", ["pointer", "pointer"]);
}
function get_addr_info(addr) {
let mm = new ModuleMap();
let info = mm.find(addr);
if (info == null) return "null";
return `[${info.name} + ${addr.sub(info.base)}]`;
}
function hook_call_constructors() {
let get_soname = null;
let call_constructors_addr = null;
let hook_call_constructors_addr = true;
let linker = null;
if (Process.pointerSize == 4) {
linker = Process.findModuleByName("linker");
} else {
linker = Process.findModuleByName("linker64");
}
let symbols = linker.enumerateSymbols();
for (let index = 0; index < symbols.length; index++) {
let symbol = symbols[index];
if (symbol.name == "__dl__ZN6soinfo17call_constructorsEv") {
call_constructors_addr = symbol.address;
} else if (symbol.name == "__dl__ZNK6soinfo10get_sonameEv") {
get_soname = new NativeFunction(symbol.address, "pointer", ["pointer"]);
}
}
if (hook_call_constructors_addr && call_constructors_addr && get_soname) {
Interceptor.attach(call_constructors_addr,{
onEnter: function(args){
let soinfo = args[0];
let soname = get_soname(soinfo).readCString();
tell_init_info(soinfo, new NativeCallback((count, init_array_ptr, init_func) => {
console.log(`[call_constructors] ${soname} count:${count}`);
console.log(`[call_constructors] init_array_ptr:${init_array_ptr}`);
console.log(`[call_constructors] init_func:${init_func} -> ${get_addr_info(init_func)}`);
for (let index = 0; index < count; index++) {
let init_array_func = init_array_ptr.add(Process.pointerSize * index).readPointer();
let func_info = get_addr_info(init_array_func);
if (func_info.indexOf(TARGET_SO_NAME) >= 0) {
console.warn(`[call_constructors] init_array:${index} ${init_array_func} -> ${func_info}`);
start_stalker(init_array_func);
}else{
console.log(`[call_constructors] init_array:${index} ${init_array_func} -> ${func_info}`);
}
}
}, "void", ["int", "pointer", "pointer"]));
}
});
}
}
function main(){
setup_cmodule();
hook_call_constructors();
}
setImmediate(main);
// frida -U -f pkg_name -l hook.js -o hook.log
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment