//http://blog.csdn.net/L173864930/article/details/40507359 int elfHook(const char *soname, const char *symbol, void *replace_func, void **old_func){ assert(old_func); assert(replace_func); assert(symbol); //从给定的so中获取基址,获取so句柄ElfHandle ElfHandle* handle = openElfBySoname(soname); ElfInfo info; //从segment视图获取elf信息(即加载到内存的so) getElfInfoBySegmentView(info, handle); Elf32_Sym *sym = NULL; int symidx = 0; //根据符号名寻找函数地址Sym findSymByName(info, symbol, &sym, &symidx); if(!sym){ LOGE("[-] Could not find symbol %s", symbol); goto fails; }else{ LOGI("[+] sym %p, symidx %d.", sym, symidx); } for (int i = 0; i < info.relpltsz; i++) { Elf32_Rel& rel = info.relplt[i]; if (ELF32_R_SYM(rel.r_info) == symidx && ELF32_R_TYPE(rel.r_info) == R_ARM_JUMP_SLOT) { void *addr = (void *) (info.elf_base + rel.r_offset); //进行一次替换relplt表函数地址操作,其中需要使用mprotect修改访问内存,然后调用系统指令 清除缓存 if (replaceFunc(addr, replace_func, old_func)) goto fails; //only once break; } } for (int i = 0; i < info.reldynsz; i++) { Elf32_Rel& rel = info.reldyn[i]; if (ELF32_R_SYM(rel.r_info) == symidx && (ELF32_R_TYPE(rel.r_info) == R_ARM_ABS32 || ELF32_R_TYPE(rel.r_info) == R_ARM_GLOB_DAT)) { void *addr = (void *) (info.elf_base + rel.r_offset); //进行一次替换reldyn表函数地址操作,其中需要使用mprotect修改访问内存,然后调用系统指令 清除缓存 if (replaceFunc(addr, replace_func, old_func)) goto fails; } } fails: closeElfBySoname(handle);//释放资源,关闭elf句柄 return 0; }
__attribute__((visibility("default"))) void hook_init( char *args ) { if( g_isInit == 1 ) { printf("i am already in!"); return; } void* soHandle = NULL; // the libapp.so is a .so of target process, and it call strcmp soHandle = dlopen( "libapp.so", RTLD_GLOBAL ); if( soHandle != NULL ) { g_realstrcmp = NULL; replaceFunc( soHandle, "strcmp", my_strcmp, (void**)&g_realstrcmp ); int ret = pthread_create( &g_hThread, NULL, my_thread, NULL ); if( ret != 0 ) { printf("create thread error:%d", ret ); } g_isInit = 1; } }
void CloexecDupCheck::check(const MatchFinder::MatchResult &Result) { const std::string &ReplacementText = (Twine("fcntl(") + getSpellingArg(Result, 0) + ", F_DUPFD_CLOEXEC)") .str(); replaceFunc(Result, "prefer fcntl() to dup() because fcntl() allows F_DUPFD_CLOEXEC", ReplacementText); }
void CloexecAcceptCheck::check(const MatchFinder::MatchResult &Result) { const std::string &ReplacementText = (Twine("accept4(") + getSpellingArg(Result, 0) + ", " + getSpellingArg(Result, 1) + ", " + getSpellingArg(Result, 2) + ", SOCK_CLOEXEC)") .str(); replaceFunc( Result, "prefer accept4() to accept() because accept4() allows SOCK_CLOEXEC", ReplacementText); }
int main(void){ char *str; char *regex = "\\w+"; regex_t reg; str = (char *)malloc(sizeof(char)*55); strcpy(str,"hello, world"); regcomp(®,regex,REG_EXTENDED); replaceFunc(str,reg,upcase,0); printf("%s\n",str); free(str); regfree(®); return 0; }