https://opensource.apple.com/source/dyld/dyld-132.13/src/
http://turingh.github.io/2016/03/01/dyld%E4%B8%ADmacho%E5%8A%A0%E8%BD%BD%E7%9A%84%E7%AE%80%E5%8D%95%E5%88%86%E6%9E%90/
https://www.objc.io/issues/6-build-tools/mach-o-executables/
https://lowlevelbits.org/parsing-mach-o-files/
uint64_t FilegetSize(const char *file_path){
struct stat buf;
if ( stat(file_path,&buf) < 0 )
{
perror(file_path);
exit(1);
}
return buf.st_size;
}
void loadMachO()
{
char *filePath = [[[NSBundle mainBundle] pathForResource:@"MachOMethodRe" ofType:@""] UTF8String];
FILE *fp_open = fopen(filePath,"r");
uint64_t file_size = FilegetSize(filePath);
if(!fp_open){
printf("file isn't exist\n");
exit(1);
}
printf("file size is 0x%llx\n\n",file_size);
void *file_buf = malloc(file_size);
if(fread(file_buf,1,file_size,fp_open)!=file_size){
printf("fread error\n");
exit(1);
}
fclose(fp_open);
//檢查是否為Fat頭
struct fat_header* fileStartAsFat = (struct fat_header*)file_buf;
if(fileStartAsFat->magic == FAT_CIGAM || fileStartAsFat->magic == FAT_MAGIC){
printf("is fat\n");
// exit(1);
}
//檢查mach-o文件最前面幾個(gè)字節(jié)的內(nèi)容.
struct mach_header *mh = (struct mach_header*)file_buf;
int is32 = 1;
if(mh->magic==MH_MAGIC||mh->magic==MH_CIGAM){
is32 = 1;
} else if(mh->magic==MH_MAGIC_64||mh->magic==MH_CIGAM_64){
is32 = 0;
}
const uint32_t cmd_count = mh->ncmds;
const struct load_command* const startCmds = (struct load_command*)(((uint8_t*)mh) + sizeof(struct mach_header));
//獲取command段結(jié)束的地址,endCmds = mach-o地址 + mach-o頭部長度 + cmds所用的長度
const struct load_command* cmd = startCmds;
unsigned long size;
for (uint32_t i = 0; i < cmd_count; ++i) {
uint32_t cmdLength = cmd->cmdsize;
struct segment_command * segCmd;
const struct load_command* const nextCmd = (const struct load_command*)(((char*)cmd)+cmdLength);
switch (cmd->cmd) {
case LC_SEGMENT:
{
segCmd = (struct segment_command *)cmd;
NSLog(@"segname = %s",segCmd->segname);
if (strcmp(segCmd->segname, "__TEXT") == 0) {
struct section * sectionsStart = NULL;
struct section * nextSection = NULL;
for (int i = 0; i < segCmd->nsects; i++) {
if (i == 0) {
sectionsStart = (struct section *)((char *)cmd + sizeof(struct segment_command));
nextSection = sectionsStart;
} else {
nextSection = (struct section *)((char *)nextSection + sizeof(struct section));
}
if (strncmp(nextSection->sectname, "__objc_methname", strlen("__objc_methname"))==0) {
NSLog(@"***** 修改方法名 ****");
}
if (strncmp(nextSection->sectname, "__objc_classname", strlen("__objc_classname"))==0) {
NSLog(@"***** 修改類名 *****");
}
NSLog(@"sectionName = %s , segName = %s",nextSection->sectname,nextSection->segname);
}
}
}
break;
default:
break;
}
cmd = nextCmd;
}
}
unsigned int count;
const char **classes;
Dl_info info;
dladdr(&_mh_execute_header, &info);
classes = objc_copyClassNamesForImage(info.dli_fname, &count);
for (int i = 0; i < count; i++) {
NSLog(@"Class name: %s", classes[i]);
Class class = NSClassFromString ([NSString stringWithCString:classes[i] encoding:NSUTF8StringEncoding]);
// Do something with class
}