当前位置: 首页 > news >正文

iOS arm64e hook MGCopyAnswer got Crash or Only Partial results got hooked

直接hook MGCopyAnswer会崩溃,按照stackoverflow的9年前的帖子说法,hook MGCopyAnswer+8仅部分生效。且hook到的都是bool类型的值。

崩溃的原因就是因为指令长度过短。
libMobileGestalt.dylib`MGCopyAnswer:
-> 0x1a483b484 <+0>: mov x1, #0x0 ; =0
0x1a483b488 <+4>: b 0x1a483af00 ; ___lldb_unnamed_symbol1060
在某些比较久(9年前)版本的ios上,libMobileGestalt的MGCopyAnswer+8对应的是MGCopyAnswer调用的内部函数。这也是原来代码+8的原因。但是新版本变成了MGGetBoolAnswer函数的开头,所以只有bool类型的MG返回值被hook到了。
方法要么是把所有类型的MGGet都改了,或者hook “b 0x1a483af00 ; ___lldb_unnamed_symbol1060”内部的长函数。

其他的例如hook opendir崩溃,也是同样的原因。

但是这里直接计算解析地址hook,还是会崩溃。怎么回事呢?

通过调试排查,发现dobby在执行完hook代码逻辑返回的时候,dobby hook框架是一个blr x8,但是lldb si单步进入之后,直接崩溃,x8变成了一个很奇怪的值:例如X8  89E3262AB23B0041 | A.;.*&.. |

这个地方解析一下就发现是高位bit set成了1,所以是pac的指针。然后就出现了EXC_BAD_ACCESS。

所以现在第二次崩溃的原因是因为:PAC指针签名的原因。

系统函数进入的时候函数开头和结尾的时候多了pac指令:例如pacibsp(pac,ib 使用key b,sp指定寄存器),retab(key b验证签名)。

解决办法:我们在hook的时候,对代码签名一下即可。

pac_helper.h

#ifndef PTRAUTH_HELPERS_H
#define PTRAUTH_HELPERS_H// Helpers for PAC archs.// If the compiler understands __arm64e__, assume it's paired with an SDK that has
// ptrauth.h. Otherwise, it'll probably error if we try to include it so don't.
#if __arm64e__
#include <ptrauth.h>
#endif#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"// Given a pointer to instructions, sign it so you can call it like a normal fptr.
static void *make_sym_callable(void *ptr) {
#if __arm64e__if (!ptr) return ptr;ptr = ptrauth_sign_unauthenticated(ptrauth_strip(ptr, ptrauth_key_function_pointer), ptrauth_key_function_pointer, 0);
#endifreturn ptr;
}// Given a function pointer, strip the PAC so you can read the instructions.
static void *make_sym_readable(void *ptr) {
#if __arm64e__if (!ptr) return ptr;ptr = ptrauth_strip(ptr, ptrauth_key_function_pointer);
#endifreturn ptr;
}#pragma clang diagnostic pop
#endif  // PTRAUTH_HELPERS_H

MyTweak.mm

#import <dlfcn.h>
#import <substrate.h>
#import <Foundation/Foundation.h>
#import <CaptainHook/CaptainHook.h>
#import "dobby.h"
#import "pac_helper.h"#define _FUNC_ADDR_(A, O) (const void *)((long)(A) + (O))
#define ABS(x) ((x) < 0 ? -(x) : (x))// 日志宏定义
#define DLog(fmt, ...) NSLog(@"[AA] " fmt, ##__VA_ARGS__)// 全局变量
static void *handle = NULL;
static void *ptrMGCopyAnswer = NULL;// 原始函数指针
static CFTypeRef (*original_MGCopyAnswer_internal)(CFStringRef key, uint32_t *status) = NULL;// 替换函数实现
static CFTypeRef replaced_MGCopyAnswer_internal(CFStringRef key, uint32_t *status)
{DLog(@"MGCopyAnswer called with key: %@", key);// 在这里可以修改返回值,例如修改设备信息/*if (CFStringCompare(key, CFSTR("DeviceClass"), 0) == kCFCompareEqualTo) {return CFRetain(CFSTR("iPhone"));}if (CFStringCompare(key, CFSTR("ProductType"), 0) == kCFCompareEqualTo) {return CFRetain(CFSTR("iPhone14,2"));}if (CFStringCompare(key, CFSTR("SerialNumber"), 0) == kCFCompareEqualTo) {return CFRetain(CFSTR("FAKE123456"));}*/// 调用原始函数CFTypeRef result = original_MGCopyAnswer_internal(key, status);if (result) {DLog(@"MGCopyAnswer result: %@", result);}return result;
}// 初始化函数
static void InitializeMGCopyAnswer()
{// 加载 libMobileGestalt.dylibhandle = dlopen("/usr/lib/libMobileGestalt.dylib", RTLD_NOW);if (!handle) {DLog(@"Failed to load libMobileGestalt.dylib: %s", dlerror());return;}// 获取 MGCopyAnswer 函数地址ptrMGCopyAnswer = dlsym(handle, "MGCopyAnswer");if (!ptrMGCopyAnswer) {DLog(@"Failed to find MGCopyAnswer: %s", dlerror());return;}DLog(@"MGCopyAnswer address: %p", ptrMGCopyAnswer);DLog(@"Handle base address: %p", handle);
}// 构造函数
CHConstructor
{@autoreleasepool {DLog(@"Initializing MGCopyAnswer hook...");// 初始化InitializeMGCopyAnswer();if (!ptrMGCopyAnswer) {DLog(@"ptrMGCopyAnswer is NULL");return;}// 读取函数开头的字节码uint8_t *readablePtr = (uint8_t *)make_sym_readable(ptrMGCopyAnswer);// 检查是否是旧版本 (mov w1, #0; b <offset>)if (memcmp(readablePtr, "\x01\x00\x80\xd2\x01\x00\x00\x14", 8) == 0){// 旧版本:直接跳转到 offset 8DobbyHook(make_sym_callable((void *)_FUNC_ADDR_(ptrMGCopyAnswer, 8)),(void *)replaced_MGCopyAnswer_internal,(void **)&original_MGCopyAnswer_internal);DLog(@"Hooked legacy MGCopyAnswer_internal");}// 检查是否是新版本 (mov w1, #0; b <offset>)else if (memcmp(readablePtr, "\x01\x00\x80\xd2", 4) == 0){// 新版本:解析 B 指令获取真实函数地址// ARM64 B 指令格式: 0x14000000 | (offset >> 2)void *bInstPtr = (void *)((uint8_t *)ptrMGCopyAnswer + 4);int32_t bInst = *((int32_t *)make_sym_readable(bInstPtr));// 检查是否是 B 指令 (opcode: 000101)if ((bInst & 0xFC000000) != 0x14000000) {DLog(@"MGCopyAnswer_internal: Invalid branch instruction: 0x%x", bInst);return;}DLog(@"B instruction: 0x%x", bInst);// 提取 26 位偏移量并进行符号扩展int32_t offset = bInst & 0x3FFFFFF;if (offset & 0x2000000) {offset |= 0xFC000000;  // 符号扩展}offset <<= 2;  // 偏移量以 4 字节为单位DLog(@"Offset: 0x%x (%d bytes)", offset, offset);// 计算真实函数地址void *mPtrMGCopyAnswer = (void *)_FUNC_ADDR_(bInstPtr, offset);DLog(@"Real MGCopyAnswer_internal address: %p", mPtrMGCopyAnswer);DLog(@"File offset of MGCopyAnswer_internal: 0x%lx",ABS((long)mPtrMGCopyAnswer - (long)handle));// Hook 真实函数DobbyHook(make_sym_callable(mPtrMGCopyAnswer),(void *)replaced_MGCopyAnswer_internal,(void **)&original_MGCopyAnswer_internal);DLog(@"Hooked modern MGCopyAnswer_internal");}else{DLog(@"Unsupported MGCopyAnswer implementation");DLog(@"First 8 bytes: %02x %02x %02x %02x %02x %02x %02x %02x",readablePtr[0], readablePtr[1], readablePtr[2], readablePtr[3],readablePtr[4], readablePtr[5], readablePtr[6], readablePtr[7]);}}
}

成功。

项目只需链接:CoreFoundation.framework, Foundation.framework, libdobby.a即可。

dobby.h libdobby.a从这里下载(github-actions released this Mar 14, 2024 latest 5dfc854):https://github.com/jmpews/Dobby/releases/download/latest/dobby-iphoneos-all.tar.gz

选取里面的universal版本即可。

http://www.dtcms.com/a/602507.html

相关文章:

  • 天津建设银行官网站首页教学督导网站建设报告
  • 网站建设行业数据手机网站静态动态
  • 初学C语言编译器选择 | 适合新手的C语言编译器推荐
  • SOME/IP协议简要介绍
  • Kettle——this connection is closed
  • 传统网站 手机网站怎么做网站的签约编辑
  • C语言编译器手机版 | 高效学习与移动编程利器
  • 做cpc不做网站可以吗怎么才能创建个人网站
  • 安徽智能网站建设推荐网站开发应该注意什么
  • 易语言反编译成源代码 | 解密易语言反编译的技术与应用
  • 易语言加密模块反编译 | 深入解析加密模块反编译技术及应用
  • c语言编译器软件下载
  • 【C++11】C++11新特性(下)
  • 免费建站并且绑定域名专业的集团网站建设
  • 接计设做的网站广西网红
  • 技术指标时空编码构建LSTM兼容的量化交易特征工程体系
  • 网站开发培训深圳高端品质网站建设
  • 自然语言编程,举个反面案例
  • Spring 框架核心技术详解:AOP、JDBC 模板与事务管理
  • 杭州做外贸网站网站编辑工具软件
  • 《C++ Primer》和《Effective C++》哪个更厚?
  • 做海报那个网站好一分钟赚50元的游戏
  • 封装了 Android 权限检查和申请功能 PermissionManager工具类,支持权限检查、申请、说明对话框显示和设置页面引导等功能。
  • 2.GPU 网络架构全栈规划与深度分析:从业务需求到落地优化(H100/H200/B200/GB200 实战视角)
  • 企业网站手机端跳转设置门户cms系统
  • 鞍山58路公交车路线苏州百度seo关键词优化
  • 大储和工商储的差异
  • Windows 终端延迟剖析:从“卡顿感”到毫秒账本
  • wordpress图片自动分页插件下载关键词排名优化工具
  • 17.PHP基础-数组