view loader.c @ 1:1b796d0dd763

display segment command and section in Mach-O executable.
author taiki
date Tue, 05 Feb 2013 15:26:25 +0900
parents 075d70197fc2
children
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <mach-o/loader.h>

#define NAME_MAX_LENGTH 256
#define MAX_SEGMENT_NUM 256

struct mach_o_data {
    int mh64_size;
    int sc64_size;
    int sect64_size;
};

struct data_count {
    int nsects_count;
    int sc_count;
};

/* prototype */

__code analyze_mach_o(struct mach_o_data md, struct mach_header_64 *mh64, struct segment_command_64 *sc64, struct section_64 *sect64, struct data_count dc, char *head, int fp, int j);

/* end  */

__code finish(int fp, struct segment_command_64 *sc64, struct section_64 *sect64)
{
    close(fp);
    free(sc64);
    free(sect64);
    printf("close \n");
}

__code make_section(
    struct mach_o_data md,
    struct mach_header_64 *mh64,
    struct segment_command_64 *sc64, 
    struct section_64 *sect64, 
    struct data_count dc, 
    char *head, 
    char *c_sect64, 
    int fp, 
    int scsect_count, 
    int sectsize_count,
    int cmd_count)
{
    if(scsect_count < sc64->nsects) {
        if(sectsize_count < md.sect64_size) {
            c_sect64[sectsize_count] = head[md.mh64_size + md.sc64_size * dc.sc_count + (dc.nsects_count + scsect_count) * md.sect64_size + sectsize_count];
            sectsize_count++;
            goto make_section(md, mh64, sc64, sect64, dc, head, c_sect64, fp, scsect_count, sectsize_count, cmd_count);
        }
        sect64 = (struct section_64 *)c_sect64;
        printf("%s %s \n", sect64->segname, sect64->sectname);
        sect64 = NULL;
        scsect_count++;
        sectsize_count = 0;
        goto make_section(md, mh64, sc64, sect64, dc, head, c_sect64, fp, scsect_count, sectsize_count, cmd_count);
    }
    free(c_sect64);
    dc.nsects_count += sc64->nsects;
    cmd_count++;
    goto analyze_mach_o(md, mh64, sc64, sect64, dc, head, fp, cmd_count);
}

__code check_segment(
    struct mach_o_data md,
    struct mach_header_64 *mh64,
    struct segment_command_64 *sc64,
    struct section_64 *sect64,
    struct data_count dc,
    char *head,
    int fp,
    int scsect_count,
    int cmd_count)
{
    if (LC_SEGMENT_64 == sc64->cmd) {
        printf("segment command :LC_SEGMENT_64");
        printf("\tsegname :%s \n", sc64->segname);
        printf("\tvmaddr :%#llx \n", sc64->vmaddr);
        printf("\tvmsize :%lld \n", sc64->vmsize);
        printf("\tfileoff :%#llx \n", sc64->fileoff);
        printf("\tnumber of section :%d\n", sc64->nsects);
        dc.sc_count++;
        char *c_sect64 = (char *)malloc(sizeof(struct section_64 *));
        int sectsize_count = 0;
        goto make_section(md, mh64, sc64, sect64, dc, head, c_sect64, fp, scsect_count , sectsize_count, cmd_count);
    }
    goto finish(fp, sc64, sect64);
}

__code make_segment_command(
    struct mach_o_data md, 
    struct mach_header_64 *mh64,
    struct segment_command_64 *sc64,
    struct section_64 *sect64,
    struct data_count dc,
    char *head,
    char *c_sc64,
    int fp,
    int scsize_count,
    int cmd_count)
{
    if (cmd_count < mh64->ncmds) {
        if (scsize_count < md.sc64_size) {
            c_sc64[scsize_count] = head[md.mh64_size + md.sc64_size * dc.sc_count + dc.nsects_count * md.sect64_size + scsize_count];
            scsize_count++;
            goto make_segment_command(md, mh64, sc64, sect64, dc, head, c_sc64,fp, scsize_count, cmd_count);
        } 
        sc64 = (struct segment_command_64 *)c_sc64;
        int scsect_count = 0;
        goto check_segment(md, mh64, sc64, sect64, dc, head, fp, scsect_count ,cmd_count);
    } else {
        free(c_sc64);
        goto finish(fp, sc64, sect64);
    }
}


__code analyze_mach_o(
    struct mach_o_data md,
    struct mach_header_64 *mh64,
    struct segment_command_64 *sc64,
    struct section_64 *sect64,
    struct data_count dc,
    char *head,
    int fp,
    int cmd_count)
{
    int scsize_count = 0;
    char *c_sc64 = (char *)malloc(sizeof(struct segment_command_64));
    goto make_segment_command(md, mh64, sc64, sect64, dc, head, c_sc64, fp, scsize_count, cmd_count);
}

__code ready_analyzing(struct mach_header_64 *mh64, char *head, int fp)
{
    struct mach_o_data md;
    md.mh64_size = sizeof(struct mach_header_64);
    md.sc64_size = sizeof(struct segment_command_64);
    md.sect64_size = sizeof(struct section_64);

    struct segment_command_64 *sc64 = (struct segment_command_64 *)malloc(sizeof(struct segment_command_64));
    struct section_64 *sect64 = (struct section_64 *)malloc(sizeof(struct section_64));
    
    struct data_count dc;
    dc.nsects_count = 0;
    dc.sc_count = 0;
    int cmd_count = 0;
    goto analyze_mach_o(md, mh64, sc64, sect64, dc, head,fp, cmd_count);
}

__code judge_mach_o_file(struct mach_header_64 *mh64, char *head, char *filename, int fp)
{
    printf("%s is executable file.\n", filename);
    printf("number of load commands : %d\n", mh64->ncmds);
    printf("size of cmds : %d\n", mh64->sizeofcmds);

    free(filename);

    if (CPU_TYPE_X86_64 == mh64->cputype) printf("CPU : x86_64\n"); 
    goto ready_analyzing(mh64, head, fp);
}

__code judge_filetype(struct mach_header_64 *mh64 , char *head, char *filename, int fp)
{
    if (MH_EXECUTE != mh64->filetype) {
        fprintf(stderr, "This is not executable file.\n");
        return;
    }
    goto judge_mach_o_file(mh64, head, filename, fp);
}

__code judge_header(int fp, struct stat sb, char *head, char *filename)
{
    struct mach_header_64 *mh64 = (struct mach_header_64 *)head;

    if (MH_MAGIC_64 != mh64->magic) {
        fprintf(stderr, "This is not mach header 64.\n");
        return; 
    }
    if (MH_MAGIC_64 == mh64->magic)
        printf("%s is 64bit Mach-O file.\n", filename);

    goto judge_filetype(mh64, head, filename, fp);
}

__code file_map(int fp, struct stat sb, char *filename)
{
    char *head = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fp, 0);
    goto judge_header(fp, sb, head, filename);
}

__code get_fstat(int fp, char *filename)
{
    struct stat sb;
    fstat(fp, &sb);
    goto file_map(fp, sb, filename);
}

__code file_open(char *filename)
{
    int fp;
    if ((fp = open(filename, O_RDONLY)) < 0) {
        fprintf(stderr, "can not open file\t: %s\n", filename);
        exit(1);
    }
    goto get_fstat(fp, filename);
}

__code option_reader(int argc, char *argv[], char filename[NAME_MAX_LENGTH], int i)
{
    if (i < argc) {
        if(argv[i][0] == '-') {
            if(strcmp(argv[i], "-name")==0) {
                strncpy(filename, argv[i], NAME_MAX_LENGTH);
            }
        } else {
            strncpy(filename, argv[i], NAME_MAX_LENGTH);
        }
        printf("read %s\n", filename);
        i++;
        goto option_reader(argc, argv, filename, i);
    }
    printf("use %s \n", filename);
    goto file_open(filename);
}

void mach_o_loader(int argc, char *argv[])
{
    int argv_count = 0;
    char *filename = (char *)malloc(sizeof(char)*NAME_MAX_LENGTH);
    goto option_reader(argc, argv, filename, argv_count);
}

int main(int argc, char*argv[])
{
    mach_o_loader(argc, argv);
    return 0;
}