Profile

youngsouk

youngsouk

코딩시작

ELF 파일 구조체에 대한 공부를 해서 ELF 섹션 정보와 GOT 정보를 얻어오는 함수들을 구현했다.

typedef struct Section{
    Elf64_Half SectionCnt;
    Elf64_Half SectionStringIndex;
    char * SectionName;
    Elf64_Shdr * SectionHeader;
}Section;

typedef struct got{
    char * name;
    unsigned long long addr;
} GOT;

typedef struct sym{
    char * name;
    unsigned long long value;
}SYM;

typedef struct elfinfo{
    int fd;
    char * filename;
    Section section;
    GOT * got;
    SYM * sym;
}ELFInfo;

Section findSectionHeader(int fd){
    Section section;
    Elf64_Off * SectionHeader = malloc(sizeof(Elf64_Off));
    Elf64_Half * SectionCnt = malloc(sizeof(Elf64_Half));
    Elf64_Half * SectionStringIndex = malloc(sizeof(Elf64_Half));
    Elf64_Shdr * SectionInformation;
    char * SectionName;
    
    //ELF 헤더
    lseek(fd, offsetof(Elf64_Ehdr, e_shnum), SEEK_SET);
    read(fd, SectionCnt, sizeof(Elf64_Half));
    section.SectionCnt = *SectionCnt;
    SectionInformation = malloc(*SectionCnt * sizeof(Elf64_Shdr));
    section.SectionHeader = SectionInformation;

    lseek(fd, offsetof(Elf64_Ehdr, e_shoff), SEEK_SET);
    read(fd, SectionHeader, sizeof(Elf64_Off));

    lseek(fd, offsetof(Elf64_Ehdr, e_shstrndx), SEEK_SET);
    read(fd, SectionStringIndex, sizeof(Elf64_Half));
    section.SectionStringIndex = *SectionStringIndex;

    //색션 정보 얻기
    lseek(fd, *SectionHeader, SEEK_SET);
    read(fd, SectionInformation, sizeof(Elf64_Shdr) * *SectionCnt);

    Elf64_Shdr * SectionString = SectionInformation + *SectionStringIndex;
    lseek(fd, SectionString -> sh_offset, SEEK_SET);
    SectionName = malloc(SectionString -> sh_size);
    read(fd, SectionName, SectionString -> sh_size);
    section.SectionName = SectionName;

    return section;
}

Elf64_Shdr * getSectionInfo(Section section, char * name){
    for(int i = 0; i < section.SectionCnt; i++){
        if(!strcmp(section.SectionName + ((section.SectionHeader + i) -> sh_name),name)) return section.SectionHeader + i;
    }
    
    return 0;
}

GOT * findGOTInfo(int fd, Section section){
    int i;

    Elf64_Shdr * PLTRelSection = getSectionInfo(section, ".rela.plt");
    if(PLTRelSection == 0) return 0;
    Elf64_Shdr * dynsymSection = getSectionInfo(section, ".dynsym");
    Elf64_Shdr * dynstrSection = getSectionInfo(section, ".dynstr");

    Elf64_Rela * PLTRel = malloc(PLTRelSection -> sh_size);
    Elf64_Sym * dynsym = malloc(dynsymSection -> sh_size);
    char * dynstr = malloc(dynstrSection -> sh_size);

    int SymOffset; // got 주소 얻는데 사용
    int NameOffset;

    int FunctionCnt = (PLTRelSection -> sh_size) / sizeof(Elf64_Rela);
    GOT * got = malloc(sizeof(GOT) * (FunctionCnt + 1)); //FunctionCnt + 1 NULL 구조체 추가

    lseek(fd, PLTRelSection -> sh_offset, SEEK_SET);
    read(fd, PLTRel, PLTRelSection -> sh_size);

    lseek(fd, dynsymSection -> sh_offset, SEEK_SET);
    read(fd, dynsym, dynsymSection -> sh_size);

    lseek(fd, dynstrSection -> sh_offset, SEEK_SET);
    read(fd, dynstr, dynstrSection -> sh_size);
    
    int idx = 0;
    for(i = 0; i < FunctionCnt; i++){
        if((PLTRel + i) -> r_offset != 0){
            (got + idx) -> addr = (PLTRel + i) -> r_offset;

            SymOffset = ELF64_R_SYM((PLTRel + i) -> r_info);
            NameOffset = (dynsym +  SymOffset) -> st_name;
            (got + idx) -> name = dynstr + NameOffset;
            idx++;
        }
    }
    
    (got + i) -> addr = 0;
    (got + i) -> name = 0;

    return got;
}

'1인 1프로젝트' 카테고리의 다른 글

코딩 중  (0) 2021.05.11
코딩 중  (0) 2021.05.10
동작방식 설계  (0) 2021.04.26
구조체 설계  (0) 2021.04.20
프로그래밍 언어 복습  (0) 2021.03.30