Hacking Framework MacOS versions

We recently got bitten by a version of the bug mentioned in my last post here. That’s an issue where codesign uses sha256 hashes instead of sha1, causing crashes on launch on MacOS 10.10.5. In this case however, the framework was a third-party binary, which we couldn’t just recompile. Instead, we needed to hack the MacOS version to trick codesign. To check the version of a framework, you can use otool:

otool -l <framework> | grep -A 3 LC_VERSION_MIN_MACOSX

In this case, it was reporting 10.12. We need 10.10. The nice thing about values like this is that they tend to follow a really specific layout in the binary, since the loader needs to find it. The header for the MacOS loader is pretty readable, and tells us where to look. LC_VERSION_MIN_MACOSX starts with a value of 0x24, and has this structure: `\

struct version_min_command {

uint32_t    cmd;        /* LC_VERSION_MIN_MACOSX or
               LC_VERSION_MIN_IPHONEOS  */
uint32_t    cmdsize;    /* sizeof(struct min_version_command) */
uint32_t    version;    /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
uint32_t    sdk;        /* X.Y.Z is encoded in nibbles xxxx.yy.zz */

Pop open your hex editor and search for the first 0x24. The first “12” we find is the MacOS version, and the second is the SDK version. So we just change our 0x0C to a 0x0A and save it. Then we can run the otool command again to confirm the versions. Now, codesign will apply both sha1 and sha256 hashes when we build. Hoorah!

Leave a Reply