Open
Description
Problem description
On the macOS ARM64 platform, when a dynamic library is injected into a binary using the insert_dylib tool, Frida mistakenly identifies a normal ARM64 program as an ARM64E architecture, causing the hook function to not work properly.
Reason analysis
Source code analysis reveals that the problem is in the ARM64 Darwin implementation of the gum_do_query_cpu_features function:
static GumCpuFeatures
gum_do_query_cpu_features (void)
{
GumCpuFeatures features = 0;
GumDarwinAllImageInfos infos;
GumDarwinCpuSubtype subtype;
gum_darwin_query_all_image_infos (mach_task_self (), &infos);
subtype = *((GumDarwinCpuSubtype *) (infos.dyld_image_load_address + 8));
if ((subtype & GUM_DARWIN_CPU_SUBTYPE_MASK) == GUM_DARWIN_CPU_SUBTYPE_ARM64E)
features |= GUM_CPU_PTRAUTH;
return features;
}
Instead of reading the CPU subtype of the Mach-O header directly, Frida detects it by:
- Call gum_darwin_query_all_image_infos to obtain dyld information
- Read the CPU subtype from the dyld load address offset by 8 bytes
- Check whether the subtype is ARM64E
When the insert_dylib tool is used to inject the dynamic library, it may modify parts of the binary, causing the layout of the dyld in memory to change after it loads, causing Frida to read the CPU subtype information from the wrong place.
Repeat step
- Create a normal ARM64 binary file
- Use the insert_dylib tool to inject dynamic libraries
- Use Frida to try the binary after hook injection
- Observed that Frida incorrectly identified the program as the ARM64E architecture (confirmed by the CPU attribute value of 0x40)
Solution suggestion
It is recommended to modify the gum_do_query_cpu_features function to use a more reliable method to detect CPU subtypes:
static GumCpuFeatures
gum_do_query_cpu_features (void)
{
GumCpuFeatures features = 0;
// 使用 Mach-O 头部直接检测 CPU 子类型
const struct mach_header_64 *header = NULL;
header = (const struct mach_header_64 *)_dyld_get_image_header(0);
if (header != NULL) {
// 直接从 Mach-O 头部读取 CPU 类型和子类型
if (header->magic == MH_MAGIC_64 &&
header->cputype == CPU_TYPE_ARM64 &&
(header->cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_ARM64E) {
features |= GUM_CPU_PTRAUTH;
}
} else {
// 如果无法获取头部,回退到原来的方法
GumDarwinAllImageInfos infos;
GumDarwinCpuSubtype subtype;
gum_darwin_query_all_image_infos (mach_task_self (), &infos);
subtype = *((GumDarwinCpuSubtype *) (infos.dyld_image_load_address + 8));
if ((subtype & GUM_DARWIN_CPU_SUBTYPE_MASK) == GUM_DARWIN_CPU_SUBTYPE_ARM64E)
features |= GUM_CPU_PTRAUTH;
}
return features;
}
Metadata
Metadata
Assignees
Labels
No labels