Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

convert MH_EXECUTE to MH_DYLIB (mach-o)

The problem:

I have 2 MH_EXECUTE iOS binary files (compiled, no source code).
Lets name them binary1 and binary2.
I try to switch between them before UIApplicationMain is called!

1 try

I successfully do this with binary1 and one dylib. So I try to convert MH_EXECUTE to MH_DYLIB.


step 1
creating iOS Application binary1

#import <dlfcn.h>

int main(int argc, char * argv[])
{
    NSLog(@"binary1 -> Hello, World!");

    void *handle = dlopen([[[NSBundle mainBundle] pathForResource:@"binary2" ofType:nil] cStringUsingEncoding:NSUTF8StringEncoding], RTLD_NOW);

    if (handle)
    {
        NSLog(@"DLOPEN is OK!");
    }
    else
    {
        NSLog(@"!OK ... --> %s", dlerror());

    }

    return 0;
}

creating iOS Application binary2

int main(int argc, char * argv[])
{
    NSLog(@"binary2 -> Hello, World!");

    return 0;
}

When I run binary1 I get:

enter image description here

step 2


Lets see the difference MH_EXECUTE vs MH_DYLIB

fullscreen enter image description here

  • as we can see the main difference here is File Type: MH_EXECUTE vs MH_DYLIB

Lets change them and run binary1 again.
After change the result was out of address space

step 3


Lets see Load Commands
fullscreen enter image description here
* in dylib there is NO __PAGEZERO segment
* dylib __TEXT segment VM address == 0 but in binary2 == 0000000100000000

So lets patch them too ... (patched: __TEXT, ___DATA and __LINKEDIT)
After run binary1 i get malformed mach-o image: segment __PAGEZERO overlaps load commands

step 4


I successfully removed __PAGEZERO from Load Commands now binary looks like dylib:
fullscreen enter image description here

But on start binary1 I get BAD_ACCESS

Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Exception Subtype: KERN_PROTECTION_FAILURE at 0x00000001019e0010
Triggered by Thread:  0

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   dyld                            0x0000000120016d78 ImageLoaderMachOCompressed::rebase(ImageLoader::LinkContext const&) + 892
1   dyld                            0x0000000120016c24 ImageLoaderMachOCompressed::rebase(ImageLoader::LinkContext const&) + 552
2   dyld                            0x0000000120010c8c ImageLoader::recursiveRebase(ImageLoader::LinkContext const&) + 132
3   dyld                            0x000000012001039c ImageLoader::link(ImageLoader::LinkContext const&, bool, bool, bool, ImageLoader::RPathChain const&) + 176
4   dyld                            0x00000001200088e0 dyld::link(ImageLoader*, bool, bool, ImageLoader::RPathChain const&) + 180
5   dyld                            0x000000012000df68 dlopen + 684
6   libdyld.dylib                   0x0000000194e65b94 dlopen + 68
7   binary1                         0x00000001000b7e18 main (main.m:16)
8   libdyld.dylib                   0x0000000194e66a04 start + 0

Any idea ???

like image 805
unstable Avatar asked May 01 '15 13:05

unstable


1 Answers

You're getting BAD_ACCESS because you removed __PAGEZERO and thus invalidated the rebasing opcodes. Keep __PAGEZERO but nullify it. I similarly converted an executable into a shared library and it's loading fine on iOS and macOS.

like image 81
John Coates Avatar answered Nov 06 '22 22:11

John Coates