主动调用函数,尤其在函数参数构造,内部依赖比较好修复的情况下,可以加速我们的动态调试。可以快速的触发逻辑,触发断点,进行调试。
直接上代码。
主动调用C函数 NSString *__fastcall sub_100099999():
//
// hook_test_captain.mm
// hook_test_captain
//
//
#if TARGET_OS_SIMULATOR
#error Do not support the simulator, please use the real iPhone Device.
#endif
#import <Foundation/Foundation.h>
#import "CaptainHook/CaptainHook.h"
#import <mach-o/dyld.h>
#import <mach-o/getsect.h>
CHConstructor
{
@autoreleasepool
{
// 获取主可执行文件的正确ASLR偏移量
uint32_t imageCount = _dyld_image_count();
NSLog(@"Image count: %d", imageCount);
// 打印所有镜像的信息,找到主可执行文件
intptr_t slide = 0;
for (uint32_t i = 0; i < imageCount; i++) {
const char* imageName = _dyld_get_image_name(i);
intptr_t currentSlide = _dyld_get_image_vmaddr_slide(i);
NSLog(@"[%d] Image: %s, Slide: 0x%lx", i, imageName, (unsigned long)currentSlide);
// 检查是否为主可执行文件
NSString *imagePath = [NSString stringWithUTF8String:imageName];
if ([imagePath isEqualToString:[[NSBundle mainBundle] executablePath]]) {
slide = currentSlide;
NSLog(@"Found main executable at index %d with slide: 0x%lx", i, (unsigned long)slide);
break;
}
}
// 如果没有找到主可执行文件,尝试使用另一种方法
if (slide == 0) {
// 获取TEXT段的实际加载地址
const struct mach_header* header = _dyld_get_image_header(0);
uintptr_t textSegmentCmd = (uintptr_t)(header + 1);
uintptr_t textVmaddr = 0;
// 遍历所有load commands找到__TEXT段
for (uint32_t i = 0; i < header->ncmds; i++) {
const struct load_command* loadCmd = (struct load_command*)textSegmentCmd;
if (loadCmd->cmd == LC_SEGMENT || loadCmd->cmd == LC_SEGMENT_64) {
const struct segment_command_64* segmentCmd = (struct segment_command_64*)loadCmd;
if (strncmp(segmentCmd->segname, "__TEXT", 16) == 0) {
textVmaddr = segmentCmd->vmaddr;
break;
}
}
textSegmentCmd += loadCmd->cmdsize;
}
if (textVmaddr != 0) {
// 计算slide = 实际加载地址 - 预期加载地址
slide = (intptr_t)header - textVmaddr;
NSLog(@"Calculated slide using TEXT segment: 0x%lx", (unsigned long)slide);
}
}
// 计算函数的实际地址
// 主动调用 NSString *__fastcall sub_100099999()
void *functionAddress = (void *)(0x100099999 + slide);
NSLog(@"Static function address: 0x100099999");
NSLog(@"Calculated runtime function address: %p", functionAddress);
// 定义函数指针类型并调用
NSString * (*targetFunction)(void) = (NSString * (*)(void))functionAddress;
// 调用函数并打印返回值
NSString *result = targetFunction();
NSLog(@"Function at 0x100099999 returned: %@", result);
}
}
主动调用OC函数:
CHConstructor // code block that runs immediately upon load
{
@autoreleasepool
{
// 主动调用这个函数 +[ClazzTarget calcKeyStr]
Class ClazzTargetClass = NSClassFromString(@"ClazzTarget");
if (ClazzTargetClass) {
SEL calcKeyStrSelector = NSSelectorFromString(@"calcKeyStr");
if ([ClazzTargetClass respondsToSelector:calcKeyStrSelector]) {
NSString *result14 = [ClazzTargetClass performSelector:calcKeyStrSelector];
NSLog(@"[htest] calcKeyStr返回值: %@", result14);
} else {
NSLog(@"[htest] Error: calcKeyStr method not found in ClazzTarget class");
}
} else {
NSLog(@"[htest] Error: ClazzTarget class not found");
}
// 主动调用这个函数 +[ClazzTarget calcKeyStr2]
if (ClazzTargetClass) {
SEL calcKeyStr2Selector = NSSelectorFromString(@"calcKeyStr2");
if ([ClazzTargetClass respondsToSelector:calcKeyStr2Selector]) {
NSString *result15 = [ClazzTargetClass performSelector:calcKeyStr2Selector];
NSLog(@"[htest] calcKeyStr2返回值: %@", result15);
} else {
NSLog(@"[htest] Error: calcKeyStr2 method not found in ClazzTarget class");
}
} else {
NSLog(@"[htest] Error: ClazzTarget class not found");
}
}
}