ElfHook的代码参考boyliang的AllHookInOne
-
.dynmaic节中没有DT_HAST,使用DT_GNU_HASH的情况下.
-
计算动态库加载的base_addr是错误的,应该使用bias_addr来计算出ehdr、phdr和shdr之外的所有地址。
-
替换函数时,修改page的读写权限时,在SEAndroid上PROT_EXEC和PROT_WRITE同时设置可能会导致异常,
-
在dlopen返回时,通过返回值获得动态库加载的base_addr
-
elfhook 支持 aarch64 (arm64-v8a),soinfo的处理暂不支持
-
android 6以下系统使用/proc/self/maps来检索进程内动态库,android 7以上使用soinfo_list
ref:
AllHookInOne : [https://github.com/boyliang/AllHookInOne.git]
AllHookInOne说明 : [http://bbs.pediy.com/showthread.php?p=1328038]
bionic : [https://android.googlesource.com/platform/bionic]
export -p PATH=$PATH:$ANDROID_NDK
./build.sh arm // 构建arm32 target
./build.sh arm64 // 构建arm64 target
./build.sh both // 构建arm32和arm64 targets
elf_file用于解析文件形式的elf文件, elf_module用于解析加载到内存中的elf文件, elf_hooker 封装linker中解析出来的私有方法和对象,例如dlopen_ext、soinfo_list等
- bool elf_hooker::load()
elf_hooker初始化,解析出linker中在hook过程中需要使用到的变量和方法的地址。
- void elf_hooker::dump_module_list()
打印在android 6以下版本,使用/proc/self/maps中解析出来当前已经加载的所有动态库的名字和基地址
- void elf_hooker::dump_soinfo_list()
打印在android 7以上版本,soinfo_list链表中所有soinfo对象的动态库文件路径和内存中的基地址
- void elf_hooker::set_prehook_cb( prehook_cb ):
设置回调函数,用于检查该动态库是否hook
bool prehook_cb(const char* module_name);
参数:
module_name: 动态库路径
返回值:
true: 可以hook
false: 不需要hook
- void elf_hooker::hook_all_modules(struct elf_rebinds * rebinds)
劫持elf_hooker中解析出来当前已加载所有动态库
struct elf_rebinds {
const char * func_name;
void * pfn_new;
void ** ppfn_old;
};
func_name: 要劫持的函数名.
pfn_new: 新函数地址
ppfn_old: 返回的劫持前原函数地址, ppfn_old非空
- elf_module::elf_module(ElfW(Addr) base_addr, const char* module_name)
elf_module构造函数,传入elf内存基地址和文件路径作为参数,如果使用无参数的默认构造函数,则在调用get_segment_view前需要调用set_base_addr()和 set_module_name()设置基地址和路径。
- bool elf_module::get_segment_view()
解析elf格式
- bool elf_module:hook(const char * symbol, void * replace_func, void ** old_func);
劫持当前模块中的symbol函数,
symbol: 要劫持的函数名.
replace_func: 新函数地址
old_func: 返回的劫持前原函数地址, old_func非空