Mercurial > hg > Members > taiki > Mach-OLoader
view mach-o-loader/loader.c @ 2:747f68297ba5 default tip
add c language mach-O loader program. this program only analize, can't still load now.
author | taiki <taiki@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 04 Mar 2014 14:41:35 +0900 |
parents | |
children |
line wrap: on
line source
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <sys/stat.h> #include <sys/mman.h> #include <mach-o/loader.h> #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; }