Skip to content

Commit

Permalink
Fix iOS 15 fishhook crash.
Browse files Browse the repository at this point in the history
  • Loading branch information
NianJi committed Sep 26, 2021
1 parent 83f28d0 commit cf99ab4
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ static id testPromise3() {
it(@"test progress promise", ^{
co_launch(^{
int progressCount = 0;
COProgressPromise *promise = progressDownloadFileFromUrl(@"http://img17.3lian.com/d/file/201701/17/9a0d018ba683b9cbdcc5a7267b90891c.jpg");
COProgressPromise *promise = progressDownloadFileFromUrl(@"https://github.com/alibaba/coobjc/archive/refs/heads/master.zip");
for(id p in promise){
double v = [p doubleValue];
NSLog(@"current progress: %f", (float)v);
Expand All @@ -380,7 +380,7 @@ static id testPromise3() {
it(@"test progress promise 50%", ^{
co_launch(^{
int progressCount = 0;
COProgressPromise *promise = progressDownloadFileFromUrl(@"http://img17.3lian.com/d/file/201701/17/9a0d018ba683b9cbdcc5a7267b90891c.jpg");
COProgressPromise *promise = progressDownloadFileFromUrl(@"https://github.com/alibaba/coobjc/archive/refs/heads/master.zip");
for(id p in promise){
double v = [p doubleValue];
if(v >= 0.5){
Expand All @@ -403,7 +403,7 @@ static id testPromise3() {
it(@"test progress promise direct", ^{
co_launch(^{
int progressCount = 0;
COProgressPromise *promise = progressDownloadFileFromUrl(@"http://img17.3lian.com/d/file/201701/17/9a0d018ba683b9cbdcc5a7267b90891c.jpg");
COProgressPromise *promise = progressDownloadFileFromUrl(@"https://github.com/alibaba/coobjc/archive/refs/heads/master.zip");
NSData *data = await(promise);
expect(data.length > 0).beTruthy();
});
Expand Down Expand Up @@ -620,7 +620,7 @@ static id testPromise3() {
[[TestThreadObject1 sharedInstance] runBlock:^{
co_launch(^{
int progressCount = 0;
COProgressPromise *promise = progressDownloadFileFromUrl(@"http://img17.3lian.com/d/file/201701/17/9a0d018ba683b9cbdcc5a7267b90891c.jpg");
COProgressPromise *promise = progressDownloadFileFromUrl(@"https://github.com/alibaba/coobjc/archive/refs/heads/master.zip");
for(id p in promise){
double v = [p doubleValue];
NSLog(@"current progress: %f", (float)v);
Expand All @@ -644,7 +644,7 @@ static id testPromise3() {
[[TestThreadObject1 sharedInstance] runBlock:^{
co_launch(^{
int progressCount = 0;
COProgressPromise *promise = progressDownloadFileFromUrl(@"http://img17.3lian.com/d/file/201701/17/9a0d018ba683b9cbdcc5a7267b90891c.jpg");
COProgressPromise *promise = progressDownloadFileFromUrl(@"https://github.com/alibaba/coobjc/archive/refs/heads/master.zip");
for(id p in promise){
double v = [p doubleValue];
if(v >= 0.5){
Expand All @@ -670,7 +670,7 @@ static id testPromise3() {
[[TestThreadObject1 sharedInstance] runBlock:^{
co_launch(^{
int progressCount = 0;
COProgressPromise *promise = progressDownloadFileFromUrl(@"http://img17.3lian.com/d/file/201701/17/9a0d018ba683b9cbdcc5a7267b90891c.jpg");
COProgressPromise *promise = progressDownloadFileFromUrl(@"https://github.com/alibaba/coobjc/archive/refs/heads/master.zip");
NSData *data = await(promise);
expect(data.length > 0).beTruthy();
});
Expand Down
77 changes: 42 additions & 35 deletions cocore/cofishhook.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
// 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.

#import "cofishhook.h"
#include "cofishhook.h"

#include <dlfcn.h>
#include <stdbool.h>
Expand Down Expand Up @@ -65,11 +65,11 @@ static struct rebindings_entry *_co_rebindings_head;
static int co_prepend_rebindings(struct rebindings_entry **rebindings_head,
struct rebinding rebindings[],
size_t nel) {
struct rebindings_entry *new_entry = malloc(sizeof(struct rebindings_entry));
struct rebindings_entry *new_entry = (struct rebindings_entry *) malloc(sizeof(struct rebindings_entry));
if (!new_entry) {
return -1;
}
new_entry->rebindings = malloc(sizeof(struct rebinding) * nel);
new_entry->rebindings = (struct rebinding *) malloc(sizeof(struct rebinding) * nel);
if (!new_entry->rebindings) {
free(new_entry);
return -1;
Expand All @@ -81,12 +81,13 @@ static int co_prepend_rebindings(struct rebindings_entry **rebindings_head,
return 0;
}

static vm_prot_t get_protection(void *sectionStart) {
#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)sectionStart;
vm_address_t address = (vm_address_t)addr;
memory_object_name_t object;
#if __LP64__
#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(
Expand All @@ -97,25 +98,28 @@ static vm_prot_t get_protection(void *sectionStart) {
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) {
return info.protection;
} else {
return VM_PROT_READ;
if (prot != NULL)
*prot = info.protection;

if (max_prot != NULL)
*max_prot = info.max_protection;

return 0;
}

return -1;
}
#endif

static void co_perform_rebinding_with_section(struct rebindings_entry *rebindings,
section_t *section,
intptr_t slide,
nlist_t *symtab,
char *strtab,
uint32_t *indirect_symtab) {
const bool isDataConst = strcmp(section->segname, "__DATA_CONST") == 0;
uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1;
void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr);
vm_prot_t oldProtection = VM_PROT_READ;
if (isDataConst) {
oldProtection = get_protection(rebindings);
mprotect(indirect_symbol_bindings, section->size, PROT_READ | PROT_WRITE);
}

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 ||
Expand All @@ -128,33 +132,36 @@ static void co_perform_rebinding_with_section(struct rebindings_entry *rebinding
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) {
if (cur->rebindings[j].replaced != NULL &&
indirect_symbol_bindings[i] != cur->rebindings[j].replacement) {
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;
}
indirect_symbol_bindings[i] = cur->rebindings[j].replacement;
goto symbol_loop;
}
}
cur = cur->next;
}
symbol_loop:;
}
if (isDataConst) {
int protection = 0;
if (oldProtection & VM_PROT_READ) {
protection |= PROT_READ;
}
if (oldProtection & VM_PROT_WRITE) {
protection |= PROT_WRITE;
}
if (oldProtection & VM_PROT_EXECUTE) {
protection |= PROT_EXEC;
}
mprotect(indirect_symbol_bindings, section->size, protection);
}
}

static void co_rebind_symbols_for_image(struct rebindings_entry *rebindings,
Expand Down Expand Up @@ -221,7 +228,7 @@ static void co_rebind_symbols_for_image(struct rebindings_entry *rebindings,

static void _co_rebind_symbols_for_image(const struct mach_header *header,
intptr_t slide) {
co_rebind_symbols_for_image(_co_rebindings_head, header, slide);
co_rebind_symbols_for_image(_co_rebindings_head, header, slide);
}

int co_rebind_symbols_image(void *header,
Expand All @@ -230,7 +237,7 @@ int co_rebind_symbols_image(void *header,
size_t rebindings_nel) {
struct rebindings_entry *rebindings_head = NULL;
int retval = co_prepend_rebindings(&rebindings_head, rebindings, rebindings_nel);
co_rebind_symbols_for_image(rebindings_head, header, slide);
co_rebind_symbols_for_image(rebindings_head, (const struct mach_header *) header, slide);
if (rebindings_head) {
free(rebindings_head->rebindings);
}
Expand Down

0 comments on commit cf99ab4

Please sign in to comment.