转: https://blog.51cto.com/u_15318120/4309633
记录下:didFinishLaunchingWithOptions没有进去直接闪退,崩溃日志如下
Incident Identifier: 2722EB09-28C2-485E-8F
CrashReporter Key: 2b0889363d8e8ab6d0da6c2cf2d1e334cd4dab4b
Hardware Model: iPhone10,2
Process: ********** [359]
Path: /private/var/containers/Bundle/Application/39DDF82D-54D8-4827-867F-9BC016F7D3DA/**********.app/**********
Identifier: com.aliyun.rtc.demo
Version: 1.0 (1)
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: com.aliyun.rtc.demo [468]
Date/Time: 2022-06-22 09:42:29.4855 +0800
Launch Time: 2022-06-22 09:42:28.7947 +0800
OS Version: iPhone OS 15.2.1 (19C63)
Release Type: User
Baseband Version: 7.02.00
Report Version: 104
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Subtype: KERN_PROTECTION_FAILURE at 0x00000001ec92e0c8
Exception Codes: 0x0000000000000002, 0x00000001ec92e0c8
VM Region Info: 0x1ec92e0c8 is in 0x1ec92d968-0x1ec92fb40; bytes after start: 1888 bytes before end: 6775
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
__DATA_CONST 1ec92c550-1ec92d968 [ 5K] r--/rw- SM=COW ...em_info.dylib
---> __DATA_CONST 1ec92d968-1ec92fb40 [ 8K] r--/rw- SM=COW ...ystem_c.dylib
__DATA_CONST 1ec92fb40-1ec947a28 [ 96K] r--/rw- SM=COW ...BoardServices
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: SIGNAL; [10]
Terminating Process: exc handler [359]
Terminating Process: exc handler [359]
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 ********** 0x10506c198 perform_rebinding_with_section + 600
1 ********** 0x10506c0f0 perform_rebinding_with_section + 432
2 ********** 0x10506be00 rebind_symbols_for_image + 636
3 ********** 0x10506bf34 _rebind_symbols_for_image + 40
4 dyld 0x10750ee88 invocation function for block in dyld4::APIs::_dyld_register_func_for_add_image(void (*)(mach_header const*, long)) + 164
5 dyld 0x1075082a4 dyld4::RuntimeState::withLoadersReadLock(void () block_pointer) + 60
6 dyld 0x10752e790 dyld4::APIs::_dyld_register_func_for_add_image(void (*)(mach_header const*, long)) + 124
7 ********** 0x10506bea4 rebind_symbols + 96
8 ********** 0x105077f1c HookAPIEngineInitialize + 100
9 ********** 0x105040bc8 main + 172
10 dyld 0x10751c250 start + 444
Thread 1:
0 libsystem_pthread.dylib 0x1dd6f29e8 start_wqthread + 0
Thread 2:
0 libsystem_pthread.dylib 0x1dd6f29e8 start_wqthread + 0
Thread 3:
0 libsystem_pthread.dylib 0x1dd6f29e8 start_wqthread + 0
Thread 4:
0 libsystem_pthread.dylib 0x1dd6f29e8 start_wqthread + 0
Thread 5:
0 libsystem_pthread.dylib 0x1dd6f29e8 start_wqthread + 0
Thread 6:
0 libsystem_kernel.dylib 0x1bd246088 __semwait_signal + 8
1 libsystem_c.dylib 0x18d62b8e0 nanosleep + 212
2 libsystem_c.dylib 0x18d62c5a8 usleep + 64
3 ********** 0x1050052b4 CAsyncLog::DoLog() + 260
4 ********** 0x1050051a0 CAsyncLog::LogProc(void*) + 32
5 libsystem_pthread.dylib 0x1dd6f43a4 _pthread_start + 116
6 libsystem_pthread.dylib 0x1dd6f29fc thread_start + 8
Thread 7:
0 libsystem_kernel.dylib 0x1bd246088 __semwait_signal + 8
1 libsystem_c.dylib 0x18d62b8e0 nanosleep + 212
2 libsystem_c.dylib 0x18d62c5a8 usleep + 64
3 ********** 0x10503c3d8 NetModuleHook::Process() + 84
4 ********** 0x10503c274 NetModuleHook::NetModuleFunc(void*) + 32
5 libsystem_pthread.dylib 0x1dd6f43a4 _pthread_start + 116
6 libsystem_pthread.dylib 0x1dd6f29fc thread_start + 8
Thread 0 crashed with ARM Thread State (64-bit):
x0: 0x0000000000000000 x1: 0x0000000105fcda3c x2: 0x0000000000000003 x3: 0xfffffffffffffff0
x4: 0x0000000000000000 x5: 0x0000000000000000 x6: 0x0000000000000000 x7: 0x00000000000005d0
x8: 0x0000000105078838 x9: 0x00000001ec92e0c8 x10: 0x00000000000000ec x11: 0x0000000000000018
x12: 0x000000010a198000 x13: 0x0000000105fcda47 x14: 0x0000000105078b3c x15: 0x000000010650bac0
x16: 0x00000001dd6e2f90 x17: 0x0000000000000000 x18: 0x0000000000000000 x19: 0x000000016ae1b530
x20: 0x00000001075a8060 x21: 0x00000001075519b9 x22: 0x000000018d627000 x23: 0x00000001075ae5f0
x24: 0x0000000000001308 x25: 0x000000010506bf0c x26: 0x0000000000000000 x27: 0x0000000000000000
x28: 0x0000000000000000 fp: 0x000000016ae1b390 lr: 0x000000010506c0f0
sp: 0x000000016ae1b310 pc: 0x000000010506c198 cpsr: 0x20000000
far: 0x00000001ec92e0c8 esr: 0x9200004f (Data Abort) byte write Permission fault
Binary Images:
0x104fe4000 - 0x1063b3fff ********** arm64 /private/var/containers/Bundle/Application/39DDF82D-54D8-4827-867F-9BC016F7D3DA/**********.app/**********
0x107504000 - 0x107557fff dyld arm64 <0b12aec1caef38ad8fb73cab3da30489> /usr/lib/dyld
0x1dd6ee000 - 0x1dd701fff libsystem_pthread.dylib arm64 <263a2eadc4f33ef5bc4b7a61e6698c8b> /usr/lib/system/libsystem_pthread.dylib
0x1bd245000 - 0x1bd276fff libsystem_kernel.dylib arm64 <8f5f208de1bd3eb2994023b6d21843c5> /usr/lib/system/libsystem_kernel.dylib
0x18d627000 - 0x18d6a1fff libsystem_c.dylib arm64 /usr/lib/system/libsystem_c.dylib
0x0 - 0xffffffffffffffff ??? unknown-arch <00000000000000000000000000000000> ???
EOF
解决方法:fishhook.c代码替换
// Copyright (c) 2013, Facebook, Inc.
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name Facebook nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific
// prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "fishhook.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef __LP64__
typedef struct mach_header_64 mach_header_t;
typedef struct segment_command_64 segment_command_t;
typedef struct section_64 section_t;
typedef struct nlist_64 nlist_t;
#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64
#else
typedef struct mach_header mach_header_t;
typedef struct segment_command segment_command_t;
typedef struct section section_t;
typedef struct nlist nlist_t;
#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT
#endif
#ifndef SEG_DATA_CONST
#define SEG_DATA_CONST "__DATA_CONST"
#endif
struct rebindings_entry {
struct rebinding *rebindings;
size_t rebindings_nel;
struct rebindings_entry *next;
};
static struct rebindings_entry *_rebindings_head;
static int prepend_rebindings(struct rebindings_entry **rebindings_head,
struct rebinding rebindings[],
size_t nel) {
struct rebindings_entry *new_entry = (struct rebindings_entry *) malloc(sizeof(struct rebindings_entry));
if (!new_entry) {
return -1;
}
new_entry->rebindings = (struct rebinding *) malloc(sizeof(struct rebinding) * nel);
if (!new_entry->rebindings) {
free(new_entry);
return -1;
}
memcpy(new_entry->rebindings, rebindings, sizeof(struct rebinding) * nel);
new_entry->rebindings_nel = nel;
new_entry->next = *rebindings_head;
*rebindings_head = new_entry;
return 0;
}
#if 0
static int get_protection(void *addr, vm_prot_t *prot, vm_prot_t *max_prot) {
mach_port_t task = mach_task_self();
vm_size_t size = 0;
vm_address_t address = (vm_address_t)addr;
memory_object_name_t object;
#ifdef __LP64__
mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64;
vm_region_basic_info_data_64_t info;
kern_return_t info_ret = vm_region_64(
task, &address, &size, VM_REGION_BASIC_INFO_64, (vm_region_info_64_t)&info, &count, &object);
#else
mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT;
vm_region_basic_info_data_t info;
kern_return_t info_ret = vm_region(task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)&info, &count, &object);
#endif
if (info_ret == KERN_SUCCESS) {
if (prot != NULL)
*prot = info.protection;
if (max_prot != NULL)
*max_prot = info.max_protection;
return 0;
}
return -1;
}
#endif
static void perform_rebinding_with_section(struct rebindings_entry *rebindings,
section_t *section,
intptr_t slide,
nlist_t *symtab,
char *strtab,
uint32_t *indirect_symtab) {
uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1;
void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr);
for (uint i = 0; i < section->size / sizeof(void *); i++) {
uint32_t symtab_index = indirect_symbol_indices[i];
if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL ||
symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) {
continue;
}
uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx;
char *symbol_name = strtab + strtab_offset;
bool symbol_name_longer_than_1 = symbol_name[0] && symbol_name[1];
struct rebindings_entry *cur = rebindings;
while (cur) {
for (uint j = 0; j < cur->rebindings_nel; j++) {
if (symbol_name_longer_than_1 && strcmp(&symbol_name[1], cur->rebindings[j].name) == 0) {
kern_return_t err;
if (cur->rebindings[j].replaced != NULL && indirect_symbol_bindings[i] != cur->rebindings[j].replacement)
*(cur->rebindings[j].replaced) = indirect_symbol_bindings[i];
/**
* 1. Moved the vm protection modifying codes to here to reduce the
* changing scope.
* 2. Adding VM_PROT_WRITE mode unconditionally because vm_region
* API on some iOS/Mac reports mismatch vm protection attributes.
* -- Lianfu Hao Jun 16th, 2021
**/
err = vm_protect (mach_task_self (), (uintptr_t)indirect_symbol_bindings, section->size, 0, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY);
if (err == KERN_SUCCESS) {
/**
* Once we failed to change the vm protection, we
* MUST NOT continue the following write actions!
* iOS 15 has corrected the const segments prot.
* -- Lionfore Hao Jun 11th, 2021
**/
indirect_symbol_bindings[i] = cur->rebindings[j].replacement;
}
goto symbol_loop;
}
}
cur = cur->next;
}
symbol_loop:;
}
}
static void rebind_symbols_for_image(struct rebindings_entry *rebindings,
const struct mach_header *header,
intptr_t slide) {
Dl_info info;
if (dladdr(header, &info) == 0) {
return;
}
segment_command_t *cur_seg_cmd;
segment_command_t *linkedit_segment = NULL;
struct symtab_command* symtab_cmd = NULL;
struct dysymtab_command* dysymtab_cmd = NULL;
uintptr_t cur = (uintptr_t)header + sizeof(mach_header_t);
for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) {
cur_seg_cmd = (segment_command_t *)cur;
if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) {
if (strcmp(cur_seg_cmd->segname, SEG_LINKEDIT) == 0) {
linkedit_segment = cur_seg_cmd;
}
} else if (cur_seg_cmd->cmd == LC_SYMTAB) {
symtab_cmd = (struct symtab_command*)cur_seg_cmd;
} else if (cur_seg_cmd->cmd == LC_DYSYMTAB) {
dysymtab_cmd = (struct dysymtab_command*)cur_seg_cmd;
}
}
if (!symtab_cmd || !dysymtab_cmd || !linkedit_segment ||
!dysymtab_cmd->nindirectsyms) {
return;
}
// Find base symbol/string table addresses
uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff;
nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff);
char *strtab = (char *)(linkedit_base + symtab_cmd->stroff);
// Get indirect symbol table (array of uint32_t indices into symbol table)
uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff);
cur = (uintptr_t)header + sizeof(mach_header_t);
for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) {
cur_seg_cmd = (segment_command_t *)cur;
if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) {
if (strcmp(cur_seg_cmd->segname, SEG_DATA) != 0 &&
strcmp(cur_seg_cmd->segname, SEG_DATA_CONST) != 0) {
continue;
}
for (uint j = 0; j < cur_seg_cmd->nsects; j++) {
section_t *sect =
(section_t *)(cur + sizeof(segment_command_t)) + j;
if ((sect->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS) {
perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab);
}
if ((sect->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS) {
perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab);
}
}
}
}
}
static void _rebind_symbols_for_image(const struct mach_header *header,
intptr_t slide) {
rebind_symbols_for_image(_rebindings_head, header, slide);
}
int rebind_symbols_image(void *header,
intptr_t slide,
struct rebinding rebindings[],
size_t rebindings_nel) {
struct rebindings_entry *rebindings_head = NULL;
int retval = prepend_rebindings(&rebindings_head, rebindings, rebindings_nel);
rebind_symbols_for_image(rebindings_head, (const struct mach_header *) header, slide);
if (rebindings_head) {
free(rebindings_head->rebindings);
}
free(rebindings_head);
return retval;
}
int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel) {
int retval = prepend_rebindings(&_rebindings_head, rebindings, rebindings_nel);
if (retval < 0) {
return retval;
}
// If this was the first call, register callback for image additions (which is also invoked for
// existing images, otherwise, just run on existing images
if (!_rebindings_head->next) {
_dyld_register_func_for_add_image(_rebind_symbols_for_image);
} else {
uint32_t c = _dyld_image_count();
for (uint32_t i = 0; i < c; i++) {
_rebind_symbols_for_image(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i));
}
}
return retval;
}