Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plthook issues on MacOS #48

Open
tomrus88 opened this issue Aug 14, 2024 · 6 comments
Open

plthook issues on MacOS #48

tomrus88 opened this issue Aug 14, 2024 · 6 comments

Comments

@tomrus88
Copy link

tomrus88 commented Aug 14, 2024

I've come across multiple issues with hooking imported functions on MacOS, resulting hook either not working at all or hooking wrong function (after "fixing" issue with hook not working at all).

So here is what I found out after many many hours of debugging:

  • in read_chained_fixups function value of
    const uint8_t *ptr
    is calculated incorrectly, making that pointer off by
    linkedit->vmaddr - linkedit->fileoff
    bytes, which results in rest of the things to be read incorrectly and ends up with "unknown imports format 0" error message in my case. I've changed code a bit and it fixed that error for me:
    //const uint8_t *ptr = (const uint8_t *)mh + d->chained_fixups->dataoff;
    struct segment_command_64* linkedit = d->segments[d->linkedit_segment_idx];
    const uint8_t* ptr = (uint8_t*)(linkedit->vmaddr - linkedit->fileoff + d->slide + d->chained_fixups->dataoff);
  • after "fixing" above error another one surfaced which results in plthook hooking incorrect functions, which results in app crashing when that hooked function is called, more specifically it is hooking functions that are located at address that is 0x30 bytes lower than intended (in my case), for example if target function's __got entry is located at 0x4BF2C8, plthook hooks function with __got entry at 0x4BF298 instead... At this point calculated addr already has incorrect value:
        void **addr = (void**)(d->got_addr + i * sizeof(void*));
        DEBUG_FIXUPS("  lib_ordinal %u, weak_import %u, name_offset %u (%s), addr %p, addend %llu\n",
                     imp.lib_ordinal, imp.weak_import, imp.name_offset, name, addr, imp.addend);
        d->plthook->entries[i].name = name;
        d->plthook->entries[i].addr = addr;
lib_base 0x10d9a7000

lib_ordinal 1, weak_import 0, name_offset 1387 (_dlopen), addr 0x10de66298, addend 0

dlopen=0x10de66298-0x10d9a7000=0x4BF298 while real dlopen is at 0x4BF2C8 if you look at IDA

image_2024-08-14_204020586

Rough code I'm using:

void* dlopen_hook(const char* filename, int flags)
{
    // stuff
}

void* dlsym_hook(void* handle, const char* symbol)
{
    // stuff
}

bool hook_stuff()
{
    plthook_t* plthook;

    if (plthook_open(&plthook, "libname.dylib") != 0) {
        return false;
    }

    if (plthook_replace(plthook, "dlopen", (void*)dlopen_hook, nullptr) != 0) {
        plthook_close(plthook);
        return false;
    }
    if (plthook_replace(plthook, "dlsym", (void*)dlsym_hook, nullptr) != 0) {
        plthook_close(plthook);
        return false;
    }
}
@tomrus88
Copy link
Author

tomrus88 commented Aug 14, 2024

I think I found why this offset of 0x30 error happens, but I don't know how to fix it...

There's some __got entries in the library i'm hooking that are followed by 8+8+8 (0x18) bytes more data that should be skipped, but your code doesn't skip it and that causes rest of the functions to have invalid addresses that is shifted by 8 bytes per each entry that should be skipped

void **addr = (void**)(d->got_addr + i * sizeof(void*));

image
image

Here you can see __Unwind_Resume and __ZSt9terminatev are 8 bytes structs followed by 8+8+8 more bytes which shifts all __got entries after them by 0x18+0x18=0x30 bytes, which is exactly the error I encountered and it breaks everything...

@tomrus88
Copy link
Author

tomrus88 commented Aug 14, 2024

After more digging it seems like some __got entries must be skipped, specifically those that have dyld_chained_ptr_64_rebase::bind value equal to 0, that should make things work again... And from looks of it that data is only available in file on disk, but not in memory?

        dyld_chained_ptr_64_bind __Unwind_Resume
          ordinal  19
          addend   0
          reserved 0
          next     2
          bind     1
        dyld_chained_ptr_64_rebase must skip
          target   3912432
          high8    0
          reserved 0
          next     2
          bind     0
        dyld_chained_ptr_64_rebase must skip
          target   431472
          high8    0
          reserved 0
          next     2
          bind     0
        dyld_chained_ptr_64_rebase must skip
          target   383136
          high8    0
          reserved 0
          next     2
          bind     0
        dyld_chained_ptr_64_bind __ZSt9terminatev
          ordinal  29
          addend   0
          reserved 0
          next     2
          bind     1
        dyld_chained_ptr_64_rebase must skip
          target   5070584
          high8    0
          reserved 0
          next     2
          bind     0
        dyld_chained_ptr_64_rebase must skip
          target   5060176
          high8    0
          reserved 0
          next     2
          bind     0
        dyld_chained_ptr_64_rebase must skip
          target   5026720
          high8    0
          reserved 0
          next     2
          bind     0

@kubo
Copy link
Owner

kubo commented Aug 15, 2024

Thanks for your report.

@kubo
Copy link
Owner

kubo commented Sep 2, 2024

@tomrus88
I updated plthook.h and plthook_osx.c. Could you check whether it works for you?

@tomrus88
Copy link
Author

tomrus88 commented Sep 3, 2024

Sure, i'll check it out soon and report back.

@tomrus88
Copy link
Author

tomrus88 commented Sep 4, 2024

Tested your fixes and it seems to work fine now. No more crash and hooked functions being called correctly in my case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants