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;
}