macOS自定义malloc/free使用DYLD_INSERT_库,加载时间不够早
我正试图编写自己的malloc/free包装来捕获缓冲区溢出。原因:Guard Malloc不够激进,因为它无法捕获溢出,除非它们接近页面边界。我不介意稍后(当内存被释放时)检测溢出,但我不介意检测它 我使用了插入和macOS自定义malloc/free使用DYLD_INSERT_库,加载时间不够早,c,macos,debugging,memory,malloc,C,Macos,Debugging,Memory,Malloc,我正试图编写自己的malloc/free包装来捕获缓冲区溢出。原因:Guard Malloc不够激进,因为它无法捕获溢出,除非它们接近页面边界。我不介意稍后(当内存被释放时)检测溢出,但我不介意检测它 我使用了插入和DYLD\u INSERT\u库来注入malloc和free的实现。问题是,在加载动态库之前,似乎有对malloc的调用。当这些对象被释放时,我的free()认为它们已损坏,因为我要添加的序言和尾声不存在 我的代码如下所示: #define DYLD_INTERPOSE(_repla
DYLD\u INSERT\u库
来注入malloc和free的实现。问题是,在加载动态库之前,似乎有对malloc的调用。当这些对象被释放时,我的free()
认为它们已损坏,因为我要添加的序言和尾声不存在
我的代码如下所示:
#define DYLD_INTERPOSE(_replacment,_replacee) \
__attribute__((used)) static struct{ const void* replacment; const void* replacee; } _interpose_##_replacee \
__attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacment, (const void*)(unsigned long)&_replacee };
static const char *premagic = "abcdefgh";
static const char *postmagic = "zyxwvuts";
static const size_t prologueLength = 16;
static const size_t sizeOffset = 8;
static const size_t preMagicOffset = 0;
static const size_t epilogueLength = 8;
static const size_t totalOverhead = prologueLength + epilogueLength;
static void WriteMetadata(void *p, size_t size) {
memmove(p + preMagicOffset, premagic, 8);
memmove(p + sizeOffset, &size, sizeof(size));
memmove(p + prologueLength + size, postmagic, 8);
}
static void CheckMemory(void *ptr) {
void *realP = ptr - prologueLength;
// Get size
size_t size;
memmove(&size, realP + sizeOffset, sizeof(size_t));
// Check premagic
if (memcmp(realP + preMagicOffset, premagic, 8)) {
while (1);
}
// Check postmagic
void *post = ptr + size;
if (memcmp(post, postmagic, 8)) {
while (1);
}
}
void *ITMalloc(size_t size) {
void *p = malloc(size + totalOverhead);
if (p == 0) {
return p;
}
WriteMetadata(p, size);
return p + prologueLength;
}
DYLD_INTERPOSE(ITMalloc, malloc);
void ITFree(void *ptr) {
CheckMemory(ptr);
void *realP = ptr - prologueLength;
free(realP);
}
DYLD_INTERPOSE(ITFree, free);
... and more for calloc, realloc, etc. ...
下面是我如何运行它的:
DYLD_INSERT_LIBRARIES=libitmalloc.dylib ./helloworld
问题是,我的ITFree
函数被调用时使用的ptr
从未由ITMalloc
分配。使用MallocStackLogging
我可以看到,它是在boostapping期间由动态加载程序的一部分分配的。以下是第一次此类分配的堆栈跟踪:
0x10261d036 (dyld) _dyld_start
0x10261d503 (dyld) dyldbootstrap::start(macho_header const*, int, char const**, long, macho_header const*, unsigned long*)
0x102623709 (dyld) dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*)
0x10261e71f (dyld) dyld::initializeMainExecutable()
0x10262ee05 (dyld) ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&)
0x10262ed73 (dyld) ImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&)
0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&)
0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&)
0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&)
0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&)
0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&)
0x10262fbea (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&)
0x102634798 (dyld) ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&)
0x102634592 (dyld) ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&)
0x7fff76ad49c5 (libSystem.B.dylib) libSystem_initializer
0x7fff79cccad2 (libdispatch.dylib) libdispatch_init
0x7fff79cc0e36 (libdispatch.dylib) _os_object_init
0x7fff784ce234 (libobjc.A.dylib) _objc_init
0x7fff79cf9a27 (libdyld.dylib) _dyld_objc_notify_register
0x10262162e (dyld) dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*))
0x10262147b (dyld) dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool)
0x7fff784e1560 (libobjc.A.dylib) map_images
0x7fff784cea50 (libobjc.A.dylib) map_images_nolock
0x7fff784cfa92 (libobjc.A.dylib) _read_images
0x7fff784d0847 (libobjc.A.dylib) NXCreateMapTable
0x7fff784d089d (libobjc.A.dylib) NXCreateMapTableFromZone
0x7fff784d09c0 (libobjc.A.dylib) NXCreateHashTable
0x7fff784d0aff (libobjc.A.dylib) NXCreateHashTableFromZone
0x7fff784d0de4 (libobjc.A.dylib) NXHashInsert
0x7fff79ebb1b0 (libsystem_malloc.dylib) malloc_zone_calloc
我是否得出结论,唯一的解决方案是维护一个“已知指针”的副表,我知道它有我的开场白/尾声,并且不依赖于在任何其他用户之前挂钩
malloc
?或者,有没有一种方法可以让我的代码更早地加载到我还没有找到的地方?dyld需要在dyld_INSERT_库插入的库之前运行初始化器libSystem,这是有道理的,因为它不能告诉这些初始化器通常会做什么。正如回溯所示,初始化libSystem确实需要分配。因此,您可能会被这样一个事实所困扰,即您的库无法看到某些分配。dyld需要在dyld_INSERT_库插入库的分配之前运行初始值设定项libSystem,这是有道理的,因为它无法告诉这些初始值设定项通常会做什么。正如回溯所示,初始化libSystem确实需要分配。因此,您可能会被这样一个事实所困扰,即您的库无法看到分配。