我有一个生成自修改代码的程序(如果你感兴趣,请参阅https://tigress.wtf/selfModify.html )。它可以在x86、Darwin和Linux上运行。在Darwin上,我用以下命令编译
gcc -g -segprot __TEXT rwx rwx self_modifying.c -o self_modifying.exe最近,这似乎不起作用,我得到
dyld: malformed mach-o image: __TEXT segment maps start of file but is writable当我运行程序的时候。
我在MacOS 10.15.3上运行clang版本6.0.1。任何帮助都将不胜感激。
发布于 2020-03-03 18:34:51
@AlexDenisov非常接近,但该限制并不只适用于运行在最低macOS 10.15.0和更高版本的Catalina上的可执行文件。
有两种格式的Mach-O load命令指示可执行文件本身可以使用的最小MacOS:
LC_BUILD_VERSION(the新版本在10.14左右引入,如果我还记得correctly)LC_VERSION_MIN_MACOSX (传统版本)的话
即使使用LC_VERSION_MIN_MACOSX回退到较早的MacOS版本
gcc -segprot __TEXT rwx rwx -mmacosx-version-min=10.6 self_modifying.c 我们遇到了同样的问题。
为了绕过check,我发现一个有效的解决方案是完全摆脱min macos版本。不过,我不知道有什么gcc或ld标志可以做到这一点。幸运的是,在Jonathan Levin的jtool2的帮助下,我们可以在链接可执行文件之后进行处理
因此,命令链变成了:
gcc -segprot __TEXT rwx rwx self_modifying.c
jtool2 -l a.out
LC 00: LC_SEGMENT_64 Mem: 0x000000000-0x100000000 __PAGEZERO
LC 01: LC_SEGMENT_64 Mem: 0x100000000-0x100001000 __TEXT
Mem: 0x100000f60-0x100000f83 __TEXT.__text (Normal)
Mem: 0x100000f84-0x100000f8a __TEXT.__stubs (Symbol Stubs)
Mem: 0x100000f8c-0x100000fa6 __TEXT.__stub_helper (Normal)
Mem: 0x100000fa6-0x100000fb2 __TEXT.__cstring (C-String Literals)
Mem: 0x100000fb4-0x100000ffc __TEXT.__unwind_info
LC 02: LC_SEGMENT_64 Mem: 0x100001000-0x100002000 __DATA_CONST
Mem: 0x100001000-0x100001008 __DATA_CONST.__got (Non-Lazy Symbol Ptrs)
LC 03: LC_SEGMENT_64 Mem: 0x100002000-0x100003000 __DATA
Mem: 0x100002000-0x100002008 __DATA.__la_symbol_ptr (Lazy Symbol Ptrs)
Mem: 0x100002008-0x100002010 __DATA.__data
LC 04: LC_SEGMENT_64 Mem: 0x100003000-0x100004000 __LINKEDIT
LC 05: LC_DYLD_INFO
Rebase info: 8 bytes at offset 12288 (0x3000-0x3008)
Bind info: 24 bytes at offset 12296 (0x3008-0x3020)
No Weak info
Lazy info: 16 bytes at offset 12320 (0x3020-0x3030)
Export info: 48 bytes at offset 12336 (0x3030-0x3060)
LC 06: LC_SYMTAB
LC 07: LC_DYSYMTAB
1 local symbols at index 0
2 external symbols at index 1
2 undefined symbols at index 3
No TOC
No modtab
3 Indirect symbols at offset 0x30b8
LC 08: LC_LOAD_DYLINKER /usr/lib/dyld
LC 09: LC_UUID UUID: 6AE91487-DB61-3FA8-8DBE-686FEC1DA8FC
LC 10: LC_BUILD_VERSION Build Version: Platform: MacOS 10.15.0 SDK: 10
LC 11: LC_SOURCE_VERSION Source Version: 0.0.0.0.0
LC 12: LC_MAIN Entry Point: 0xf60 (Mem: 0x100000f60)
LC 13: LC_LOAD_DYLIB /usr/lib/libSystem.B.dylib
LC 14: LC_FUNCTION_STARTS Offset: 12384, Size: 8 (0x3060-0x3068)
LC 15: LC_DATA_IN_CODE Offset: 12392, Size: 0 (0x3068-0x3068)
jtool2 -rc 10 --inplace a.out现在您的a.out应该可以正确启动了:-)
发布于 2020-03-03 17:45:18
您观察到的问题是macOS Catalina的限制,与您的编译器无关。
查看dyld源代码(可以在https://opensource.apple.com/release/macos-1015.html中找到),错误消息来自以下代码:
if ( (segCmd->initprot & VM_PROT_WRITE) == VM_PROT_WRITE ) {
if ( context.strictMachORequired )
dyld::throwf("malformed mach-o image: %s segment maps start of file but is writable", segCmd->segname);
}仅当strictMachORequired (在macOS 10.15或更高版本上始终为true )基于来自dyld源代码的其他代码段时才会引发异常:
#if __MAC_OS_X_VERSION_MIN_REQUIRED
gLinkContext.strictMachORequired = false;
// <rdar://problem/22805519> be less strict about old macOS mach-o binaries
((dyld3::MachOFile*)mainExecutableMH)->forEachSupportedPlatform(^(dyld3::Platform platform, uint32_t minOS, uint32_t sdk) {
if ( (platform == dyld3::Platform::macOS) && (sdk >= DYLD_PACKED_VERSION(10,15,0)) ) {
gLinkContext.strictMachORequired = true;
}
});
if ( gLinkContext.iOSonMac )
gLinkContext.strictMachORequired = true;
#else
// simulators, iOS, tvOS, watchOS, are always strict
gLinkContext.strictMachORequired = true;
#endifhttps://stackoverflow.com/questions/60497896
复制相似问题