非越狱app下能否根据地址hook指定的地址的c代码库?

需求:
采用monkey dev 新建了一个monkey app,导入自有的一个demo app。

其中demo app中吸入了一个c函数,

void testFunction() {
    NSLog(@"这是测试函数");
}

随后在Monkey app,中导入这个app的文件,并使用MSFunctionHook,发现,c函数地址寻找到了并且正确。只是hook无法生效。

请问MonkeyApp 中如何hook这种已知内存地址的c语言函数?

1 个赞

非越狱不可以

是否是这种只知道地址的函数,无法进行修改了?

可以,改二进制,重签

https://github.com/jmpews/HookZz/tree/dev/Plugins/MachOStaticPatcher

1 个赞

这个可以,我star下,然后研究下

大佬,这个真是太好用了。:smiling_face_with_three_hearts::smiling_face_with_three_hearts::smiling_face_with_three_hearts::smiling_face_with_three_hearts:

另外有一个小问题,现在这个MachOStaticPatcher是不是还不支持多架构模式啊?

按理说随便加的. 但是…

错误出现在rebase_stub,*entry->trampoline_target_stub = entry->relocated_origin_function;出现Exec Bad Access

估计是访问到了空指针,这部分rebase出错

调用方式:ZzReplaceStatic(“MachOStaitcPatcherExample”, 0x100006ad8, runReplace, runMainFunction);

不知这样做是否是正确调用呢?

大家遇到相同的情况,可以暂时这样处理:注视掉下面这句代码,还不懂这句的作用,但hook是成功的

*origin_call = (void *)entry->relocated_origin_function;

主要原因是指针越界了,待读懂大佬的代码后,再看看要如何使用吧

以下提供正确的使用方式:

ZzReplaceStatic(char *image_name, void *function_virtual_address, void *replace_call, void **origin_call)

ZzReplaceStatic(“image名称,可用dyld函数查看”, 需要hook的函数的虚存地址, 替换的函数的函数指针, 这个参数是获取回调原函数的指针[所以可以自己创建个指针传参])

经过了几天的时间,本小白才勉强看懂了作者的代码,代码真的是非常地强,赞叹!

我在代码中是采用宏方式进行替换的,因为发现每次想hook的函数写法都是相当类似。

// 我这里因为多数时间hook的是c++代码,所以无论hook的是有参还是无参均会携带一个self参数
#define CrackOldFunctionDefine(functionReturnType, functionName, args...) \
functionReturnType (*old_##functionName)(__int64_t self, args)
#define CrackNewFunctionDefine(functionReturnType, functionName, args...)\
static functionReturnType new_##functionName(__int64_t self, args)

#define CrackFunction(functionReturnType, functionName, functionOriginAddress, args...) \
CrackOldFunctionDefine(functionReturnType, functionName, ##args);\
\
CrackNewFunctionDefine(functionReturnType, functionName, ##args);\
\
static void crack_##functionName() {\
long long address = functionOriginAddress;\
ZzReplaceStatic((char *)"这里修改成需要hook的image名称", (void *)address, (void *)new_##functionName,(void**)&old_##functionName);\
}\
\
CrackNewFunctionDefine(functionReturnType, functionName, ##args)

这里是我自己的用法

// 宏的参数依次是 出参类型 hook函数名称 hook函数地址 hook的其他入参
CrackFunction(float, test, 0x1000000) {
    // 这里的old_test就是原有参数了
    return old_test(self);
}
// 剩下的就是调用修改了,放在入口函数中进行
crack_test();

我觉得用宏包一层后能减少些重复代码的工作量,如果有更好的使用方案,还望讨论

1 个赞

感谢你提供的解答,可惜没赶上,我这两天完整地看了MachOStaticPatcher的代码
使用都是差不多,通过ZzReplaceStatic这个函数接口
只是打算加上自动识别寻找对应的image和虚存地址,再封装一层

任何建议都可以提 or PR 欢迎联系我

好的,感谢大大,代码是读了,但某些原理的操作还是不太明白,我还是先去补逆向的知识吧

请问MachOStaticPatcher支持短函数吗?
还有回调原函数时,原函数的前5个指令直接没了

1 个赞

这个短函数是几条指令?

3个,少于5个指令应该就很难操作了吧

请问一下,回写被覆盖的原函数的前几条指令是不是还没写完整?
某些函数crash了,像_sqlite3VdbeFreeCursor开头指令是cbz、ldrb

回写是什么意思, 写什么东西