Skip to content

Instantly share code, notes, and snippets.

@mentlerd
Created October 19, 2025 11:57
Show Gist options
  • Save mentlerd/820b004f44a40e3da6879b1a2fa2bb99 to your computer and use it in GitHub Desktop.
Save mentlerd/820b004f44a40e3da6879b1a2fa2bb99 to your computer and use it in GitHub Desktop.
Various macOS tools for mischief
#include "Tools.h"
#include <mach-o/dyld.h>
#include <mach-o/nlist.h>
#include <string_view>
namespace {
template<typename T>
auto offsetPointerTo(const void* base, ptrdiff_t offset) -> T* {
return reinterpret_cast<T*>(ptrdiff_t(base) + offset);
}
auto findImageHeader(std::string_view imageSuffix, uint64_t& slide) -> const mach_header_64* {
auto imageCount = _dyld_image_count();
for (uint32_t i = 0; i < imageCount; i++) {
auto imageName = _dyld_get_image_name(i);
if (!imageName) {
continue;
}
if (!std::string_view(imageName).ends_with(imageSuffix)) {
continue;
}
slide = _dyld_get_image_vmaddr_slide(i);
return reinterpret_cast<const mach_header_64*>(_dyld_get_image_header(i));
}
return nullptr;
}
auto findLINKEDIT(const mach_header_64& header) -> const segment_command_64* {
uint64_t offset = sizeof(mach_header_64);
for (uint32_t i = 0; i < header.ncmds; i++) {
auto command = offsetPointerTo<const load_command>(&header, offset);
if (command->cmd == LC_SEGMENT_64) {
auto segment = reinterpret_cast<const segment_command_64*>(command);
if (std::string_view(segment->segname) == SEG_LINKEDIT) {
return segment;
}
}
offset += command->cmdsize;
}
return nullptr;
}
auto findSYMTAB(const mach_header_64& header) -> const symtab_command* {
uint64_t offset = sizeof(mach_header_64);
for (uint32_t i = 0; i < header.ncmds; ++i) {
auto command = offsetPointerTo<const load_command>(&header, offset);
if (command->cmd == LC_SYMTAB) {
return reinterpret_cast<const symtab_command*>(command);
}
offset += command->cmdsize;
}
return nullptr;
}
auto findSymbol(std::string_view imageSuffix, std::string_view symbol) -> void* {
uint64_t slide = 0;
auto header = findImageHeader(imageSuffix, slide);
if (!header) {
return nullptr;
}
auto linkedit = findLINKEDIT(*header);
if (!linkedit) {
return nullptr;
}
auto symtab = findSYMTAB(*header);
if (!symtab) {
return nullptr;
}
auto base = offsetPointerTo<void>(0, linkedit->vmaddr - linkedit->fileoff + slide);
auto symbolTable = offsetPointerTo<const nlist_64>(base, symtab->symoff);
auto stringTable = offsetPointerTo<const char>(base, symtab->stroff);
for (uint32_t i = 0; i < symtab->nsyms; i++) {
auto& nlist = symbolTable[i];
auto name = &stringTable[nlist.n_un.n_strx];
if (std::string_view(name) != symbol) {
continue;
}
return offsetPointerTo<void*>(0, nlist.n_value + slide);
}
return nullptr;
}
}
void* dlsym_p(std::string_view imageSuffix, std::string_view symbol) {
return findSymbol(imageSuffix, symbol);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment