# HG changeset patch # User taiki # Date 1393911695 -32400 # Node ID 747f68297ba58665ac026a314d31a19bf80358ae # Parent 1b796d0dd763566ca60b9f46a79720324de3c8e4 add c language mach-O loader program. this program only analize, can't still load now. diff -r 1b796d0dd763 -r 747f68297ba5 Makefile --- a/Makefile Tue Feb 05 15:26:25 2013 +0900 +++ b/Makefile Tue Mar 04 14:41:35 2014 +0900 @@ -2,7 +2,7 @@ TARGET = loader -CFLAGES = -Wall -O0 -g -std=c99 -o +CFLAGES = -Wall -O5 -std=c99 -o $(TARGET): loader.c $(CC) $(CFLAGES) $(TARGET) loader.c diff -r 1b796d0dd763 -r 747f68297ba5 mach-o-loader/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mach-o-loader/Makefile Tue Mar 04 14:41:35 2014 +0900 @@ -0,0 +1,12 @@ +TARGET = loader + +CC = clang + +CFLAGS = -g -O2 -Wall + + +$(TARGET): loader.c + $(CC) $(CFLAGS) -o $@ $^ + +clean: + rm $(TARGET) *.o diff -r 1b796d0dd763 -r 747f68297ba5 mach-o-loader/loader.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mach-o-loader/loader.c Tue Mar 04 14:41:35 2014 +0900 @@ -0,0 +1,282 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "loader.h" + +#define MAX_COMMAND_LEN 10000 +#define MAX_SECTION_LEN 10000 + +int analyze(char* head) +{ + struct mach_header_64 *mh64 = (struct mach_header_64 *)head; + + // mach header is 32 bytes + int com_index = sizeof(struct mach_header_64); + + for (int cmds = 0; cmds < mh64->ncmds; cmds++) { + + struct load_command *com = (struct load_command *) (head + com_index); + + switch(com->cmd) { + case LC_SEGMENT_64: + { + struct segment_command_64 *sc = + (struct segment_command_64 *) (head + com_index); + com_index += sizeof(struct segment_command_64); + + printf("segment command:\n"); + printf("\tcmd :%0xd \n", sc->cmd); + printf("\tcmdsize :%d \n", sc->cmdsize); + printf("\tsegname :%s \n", sc->segname); + printf("\tvmaddr :%0llx \n", sc->vmaddr); + printf("\tnsects :%d \n", sc->nsects); + + int nsects = sc->nsects; + printf("sections:\n"); + for (int sects = 0; sects < nsects; sects++) { + struct section_64 *sc64 = (struct section_64*) (head + com_index); + printf("\t%s\n", sc64->sectname); + com_index += sizeof(struct section_64); + } + break; + } + case LC_UUID: + { + struct uuid_command *uc = + (struct uuid_command*) (head + com_index); + com_index += sizeof(struct uuid_command); + + printf("uuid command\n"); + for(int i = 0; i < 16; i++) { + printf("%u", uc->uuid[i]); + } + printf("\n"); + break; + } + case LC_SYMTAB: + { + struct symtab_command *syt = + (struct symtab_command*) (head + com_index); + com_index += sizeof(struct symtab_command); + + printf("symtab_command\n"); + printf("\tsymoff %d\n", syt->symoff); + printf("\tnsyms %d\n", syt->nsyms); + break; + } + case LC_DYSYMTAB: + { + struct dysymtab_command *dysyt = + (struct dysymtab_command*) (head + com_index); + com_index += sizeof(struct dysymtab_command); + + printf("dysymtab_command\n"); + printf("symtab_command\n"); + printf("\tsymoff %d\n", dysyt->cmd); + printf("\tnsyms %d\n", dysyt->cmdsize); + break; + } + case LC_THREAD: + { + printf("thread\n"); + break; + } + case LC_UNIXTHREAD: + { + printf("unix thread\n"); + break; + } + case LC_ID_DYLIB: + { + printf("unix thread\n"); + break; + } + case LC_PREBOUND_DYLIB: + { + printf("unix thread\n"); + break; + } + case LC_LOAD_DYLINKER: + { + struct dylinker_command *dylc = (struct dylinker_command *) (head + com_index); + printf("load dylinker\n"); + printf("\tcmdsize: %d\n", dylc->cmdsize); + printf("\tdylc->name.offset: %d\n", dylc->name.offset); + char *name = (head + com_index) + sizeof(struct dylinker_command); + printf("\tname: %s\n", name); + com_index = com_index + dylc->cmdsize; + break; + } + case LC_ID_DYLINKER: + { + printf("id dylinker\n"); + break; + } + case LC_ROUTINES: + { + printf("routines\n"); + break; + } + case LC_ROUTINES_64: + { + printf("iroutines 64\n"); + break; + } + case LC_TWOLEVEL_HINTS: + { + printf("two level hints\n"); + break; + } + case LC_SUB_FRAMEWORK: + { + printf("sub framework\n"); + break; + } + case LC_SUB_UMBRELLA: + { + printf("sub umbrella\n"); + break; + } + case LC_SUB_LIBRARY: + { + printf("sub library\n"); + break; + } + case LC_SUB_CLIENT: + { + + printf("sub client\n"); + break; + } + case LC_DYLD_INFO_ONLY: + { + struct dyld_info_command *dyldi_com = (struct dyld_info_command *) (head + com_index); + com_index += sizeof(struct dyld_info_command); + printf("dyld info only\n"); + printf("\tcmdsize: %d\n", dyldi_com->cmdsize); + break; + } + case LC_VERSION_MIN_MACOSX: + { + struct version_min_command *vm_com = (struct version_min_command *) (head + com_index); + com_index += sizeof(struct version_min_command); + printf("version min macosx\n"); + break; + } + case LC_SOURCE_VERSION: + { + struct source_version_command *sv_com = (struct source_version_command *) (head + com_index); + com_index += sizeof(struct source_version_command); + printf("source version\n"); + break; + } + case LC_DATA_IN_CODE: + { + struct linkedit_data_command *ld_com = (struct linkedit_data_command*) (head + com_index); + com_index += sizeof(struct linkedit_data_command); + printf("data in code\n"); + break; + } + case LC_DYLIB_CODE_SIGN_DRS: + { + printf("cylib code sign drs\n"); + break; + } + case LC_LOAD_DYLIB: + { + struct dylib_command *dl_com = (struct dylib_command *) (head + com_index); + printf("lc load dylib\n"); + int offset = dl_com->dylib.name.offset; + printf("\tname offset: %d\n",offset); + char *name = (head + com_index) + sizeof(struct dylib_command); + printf("\tname: %s\n", name); + com_index = com_index + dl_com->cmdsize; + break; + } + case LC_MAIN: + { + struct entry_point_command *ep_com = (struct entry_point_command *) (head + com_index); + com_index += sizeof(struct entry_point_command); + printf("lc main\n"); + break; + } + case LC_FUNCTION_STARTS: + { + struct linkedit_data_command *ld_com = (struct linkedit_data_command*) (head + com_index); + com_index += sizeof(struct linkedit_data_command); + printf("lc functions starts\n"); + break; + } + default: + printf("no suitable cmd:%d\n", com->cmd); + break; + } + } + + return 0; +} + +int check_header(int fp, struct stat sb, char* head) +{ + struct mach_header_64 *mh64 = (struct mach_header_64 *)head; + if (MH_MAGIC_64 != mh64->magic) { + fprintf(stderr, "This is no mach header 64.\n"); + return -1; + } + + if (MH_EXECUTE != mh64->filetype) { + fprintf(stderr, "This isn't executable file.\n"); + return -1; + } + + if (CPU_TYPE_X86_64 != mh64->cputype) { + fprintf(stderr, "No suitable cpu type.\n"); + return -1; + } + + printf("numbler of load commands : %d\n", mh64->ncmds); + printf("size of cmds : %d\n", mh64->sizeofcmds); + + return 0; +} + +int main(int argc, char *argv[]) +{ + + char *filename = argv[1]; + int fp = 0; + + if ((fp = open(filename, O_RDONLY)) < 0) { + fprintf(stderr, "can not open file\t: %s\n", filename); + return -1; + } + + struct stat sb; + if (fstat(fp, &sb) < 0) { + fprintf(stderr, "can not get stat\t: %s\n", filename); + return -1; + } + + char *head = (char *)mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fp, 0); + if ((int)head < 0) { + fprintf(stderr, "can't map memory.\n"); + return -1; + } + + if (check_header(fp, sb, head) < 0) { + return -1; + } + + analyze(head); + + close(fp); /* close file */ + + return 0; +} diff -r 1b796d0dd763 -r 747f68297ba5 mach-o-loader/loader.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mach-o-loader/loader.h Tue Mar 04 14:41:35 2014 +0900 @@ -0,0 +1,10 @@ +#ifndef LOADER +#define LOADER + +struct mach_o_data { + int mh64_size; + int sc64_size; + int sect64_size; +}; + +#endif /* LOADER */ diff -r 1b796d0dd763 -r 747f68297ba5 sample/sample.c --- a/sample/sample.c Tue Feb 05 15:26:25 2013 +0900 +++ b/sample/sample.c Tue Mar 04 14:41:35 2014 +0900 @@ -5,4 +5,5 @@ int c = 3; a = b + c; + a += c; }