{"id":20639231,"url":"https://github.com/alexdremov/machobuilder","last_synced_at":"2025-09-26T18:31:41.908Z","repository":{"id":146181936,"uuid":"356869831","full_name":"alexdremov/MachOBuilder","owner":"alexdremov","description":"Mach-o simple executable and object file generator","archived":false,"fork":false,"pushed_at":"2021-05-01T13:09:47.000Z","size":437,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-11-16T15:26:36.161Z","etag":null,"topics":["generator","mach","mach-o","object","payload","relocation","symbol"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexdremov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-11T13:05:20.000Z","updated_at":"2024-11-12T20:32:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"8d27c388-2ecf-41e7-bea7-e03728e1e952","html_url":"https://github.com/alexdremov/MachOBuilder","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexdremov%2FMachOBuilder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexdremov%2FMachOBuilder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexdremov%2FMachOBuilder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexdremov%2FMachOBuilder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexdremov","download_url":"https://codeload.github.com/alexdremov/MachOBuilder/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234332702,"owners_count":18815605,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["generator","mach","mach-o","object","payload","relocation","symbol"],"created_at":"2024-11-16T15:23:05.030Z","updated_at":"2025-09-26T18:31:41.573Z","avatar_url":"https://github.com/alexdremov.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MachOBuilder\n\nExecutable and object mach-o file builder.\n\nDescription of an object file structure can be found in my blog:\n\nhttps://alexdremov.ru/mystery-of-mach-o-object-file-builders/\n\n## Install\n\n```bash\nmkdir build\ncd build\ncmake .. -DCMAKE_BUILD_TYPE=Release\nmake install\n```\n\nCheck out console output to find install directory.\n\nTo use in cmake (as an example):\n\n```cmake\nSET(CMAKE_CXX_FLAGS        \"${CMAKE_CXX_FLAGS}         -I/usr/local/include\") # check your installation directory\nSET(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS}  -L/usr/local/lib\")\n```\n\n## Mach-O format quick guide\n\nMach-O file is structured like this:\n\n\u003cimg width=\"400px\" src=\"https://github.com/AlexRoar/MachOBuilder/raw/main/assets/machostruct.png\"\u003e\n\n### Important tips: \n- Load command size must be divisible by 8. It can be padded by zeros\n- Minimal structure: PAGEZERO segment + TEXT segment(+text section) + UNIXTHREAD + code payload\n- Mach-O file must be at least one page size. Framework automatically achives that.\n- Segments virtual size nust be rounded to the page size.\n- Segments payload must be page-aligned \n- UNIXTHREAD entry point type does not require anything appart from the code itself\n- MAIN segment require: PAGEZERO + TEXT + LINKEDIT + LC_DYLD_INFO_ONLY + LC_DYSYMTAB + LC_LOAD_DYLINKER + LC_LOAD_DYLIB\n## Usage\n\nThe main interface uses ```binaryFile``` as it's code container:\n\n```java\nFILE *res = fopen(..., \"wb\");\nbinaryFile binary = {};\nbinary.init(res);\n...\nbinary.dest();\n```\n\nThe executable itself is generated using  ```MachoFileBin```\n\n```java\nMachoFileBin machoFile = {};\nmachoFile.init();\n...\nmachoFile.binWrite(\u0026binary);\nmachoFile.dest();\n```\n\n### Simple return zero executable\n\n```java\nFILE *res = fopen(\"machoRetZeroApp\", \"wb\"); // executable\nbinaryFile binary = {};\nbinary.init(res);\n\nMachoFileBin machoFile = {};\nmachoFile.init();\n\nmachoFile.header = machHeader64::executable(); // standard header\nmachoFile.loadCommands.pushBack(loadCommand::pageZero()); // add PAGEZERO load command \n\nauto codeSection = loadCommand::code();                // __TEXT segment\ncodeSection.sections.pushBack(segmentSection::code()); // push __text section to __TEXT segment\ncodeSection.payloads.pushBack(0);                      // linked to first payload\nmachoFile.loadCommands.pushBack(codeSection);\n\nmachoFile.loadCommands.pushBack(loadCommand::thread(0));           // Add UNIXTHREAD load command referencing to first section (codeSection)\n\nunsigned char asmCode[] = {\n        0x48, 0x89, 0xC7, 0xB8, 0x01, 0x00, 0x00, 0x02, 0x0F, 0x05 // asm code to execute return 0 syscall\n};\n\nbinPayload codePayload = {};\ncodePayload.payload = (char *) asmCode;\ncodePayload.size = sizeof(asmCode) / sizeof(asmCode[1]);\ncodePayload.freeable = false;             // static array asmCode, no free() required\ncodePayload.align = 1;                    // 2^1 alignment of payload block\nmachoFile.payload.pushBack(codePayload);\n\n\nmachoFile.binWrite(\u0026binary); // generate executable and write to the binary\n\nbinary.dest();\nmachoFile.dest();\n```\n\nOr as simple as this:\n\n```java\nFILE *res = fopen(\"machoRetZeroApp\", \"wb\");\nbinaryFile binary = {};\nbinary.init(res);\n\nunsigned char asmCode[] = {\n        0x48, 0x89, 0xC7, 0xB8, 0x01, 0x00, 0x00, 0x02, 0x0F, 0x05\n};\nMachoFileBin::simpleExe(binary, (char*) asmCode, sizeof(asmCode));\n\nbinary.dest();\n```\n\n### Simple object file\n\nThere is an API for creating an object file that can be linked using ld / gcc / clang\n\n```java\nFILE *res = fopen(\"machoObjectAuto.o\", \"wb\");\nbinaryFile binary = {};\nbinary.init(res);\n\nObjectMachOGen mgen = {};\nmgen.init();\n\nunsigned char asmCode[] = {\n        0x55, 0x48, 0x89, 0xE5,\n        0xE8, 0x00, 0x00, 0x00, 0x00, // call __Z8printTenv\n        0xE8, 0x00, 0x00, 0x00, 0x00, // call __Z8printTenv\n        0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, // mov eax, dword ptr [rip + offset globalVar ]\n        0x31, 0xC0, 0x5D,\n        0xE8, 0x00, 0x00, 0x00, 0x00,\n        0xC3\n};\n\nunsigned char data[] = {\n        0xDE, 0xD3, 0x2D, 0xED, 0x32, 0xDE, 0xD3, 0x2D, 0xED, 0x32,\n        0xDE, 0xD3, 0x2D, 0xED, 0x32, 0xDE, 0xD3, 0x2D, 0xED, 0x32,\n};\n\nmgen.addCode(asmCode, sizeof(asmCode));\nmgen.addData(data, sizeof(data));\n\nmgen.addInternalCodeSymbol(\"_main\", 0);\nmgen.addInternalDataSymbol(\"globalVar\", 0);\n\nmgen.bindBranchExt(\"__Z5printi\", 0x5);\nmgen.bindBranchExt(\"__Z5printi\", 0xA);\nmgen.bindSignedOffset(\"globalVar\", 16);\n\nmgen.dumpFile(binary);\n\nmgen.dest();\nbinary.dest();\n```\n\nIt will create such structure:\n\n\u003cimg width=\"400px\" src=\"https://github.com/AlexRoar/MachOBuilder/raw/main/assets/struct.png\"\u003e\n\nSeveral essential functions are used in the listing.\n\n`addInternalCodeSymbol` defines symbol at *offset* in code section\n- symbol - symbol name\n- offset - offset from the start of the section\n\n`addInternalDataSymbol` defines symbol at *offset* in data section\n- symbol - symbol name\n- offset - offset from the start of the section\n\n`bindBranchExt` defines address position for relocation for external symbol\n- symbol - symbol name\n- offset - address offset from the start of the code section\n\n`bindSignedOffset` defines address position for relocation for internal symbol\n- symbol - symbol name\n- offset - address offset from the start of the code section\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexdremov%2Fmachobuilder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexdremov%2Fmachobuilder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexdremov%2Fmachobuilder/lists"}