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!
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:

Lets see the difference MH_EXECUTE vs MH_DYLIB
fullscreen

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

* 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
I successfully removed __PAGEZERO from Load Commands now binary looks like dylib:
fullscreen

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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With