SegmentBufInfo *parse_phdr(Elf64_Phdr *phdrs, int num, int *segBufNum) { printfsocket("segment num : %d\n", num); SegmentBufInfo *infos = (SegmentBufInfo *)malloc(sizeof(SegmentBufInfo) * num); int segindex = 0; for (int i = 0; i < num; i += 1) { Elf64_Phdr *phdr = &phdrs[i]; print_phdr(phdr); if (phdr->p_filesz > 0) { if ((!is_segment_in_other_segment(phdr, i, phdrs, num)) || (phdr->p_type == 0x6fffff01)) { SegmentBufInfo *info = &infos[segindex]; segindex += 1; info->index = i; info->bufsz = (phdr->p_filesz + (phdr->p_align - 1)) & (~(phdr->p_align - 1)); info->filesz = phdr->p_filesz; info->fileoff = phdr->p_offset; info->enc = (phdr->p_type != 0x6fffff01) ? TRUE : FALSE; printfsocket("seg buf info %d -->\n", segindex); printfsocket(" index : %d\n bufsz : 0x%016llX\n", info->index, info->bufsz); printfsocket(" filesz : 0x%016llX\n fileoff : 0x%016llX\n", info->filesz, info->fileoff); } } } *segBufNum = segindex; return infos; }
static void dump_phdrs(struct elf_phdr *ep, int pnum) { int i; for (i = 0; i < pnum; i++, ep++) { if ((ep->p_type == PT_LOAD) || (ep->p_type == PT_INTERP) || (ep->p_type == PT_PHDR)) print_phdr(i, ep); } }
void exec(){ uint16_t i, j; uint64_t addr; csh handle; cs_insn *insn; PHDR ph; ELF elf; SHDR sh; uint8_t *data = NULL; va_tbl* TBL = NULL; if (cs_open(CS_ARCH_PPC, CS_MODE_64+CS_MODE_BIG_ENDIAN, &handle) != CS_ERR_OK){ printf("ERROR:%s\n", get_err(&handle)); goto end; } cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON); fseek(fp, 0, SEEK_SET); fread((void*) &elf, sizeof(ELF), 1, fp); revert_elf(&elf); // because it BE on LE machine if(ELF_MAGIC != *((uint32_t*)&elf.e_ident)){ printf("Wrong ELF_MAGIC (0x%08x)\n", *((uint32_t*)&elf.e_ident)); goto end; } if(elf.e_machine != EM_PPC64){ printf("e_machine (%x) != EM_PPC64\n", elf.e_machine); goto end; } TBL = (va_tbl*) malloc(elf.e_shnum*sizeof(va_tbl)); print_elf(&elf); addr = elf.e_phoff; for(i=0; i<elf.e_phnum; i++, addr+=sizeof(PHDR)){ memset((void*)&ph, 0, sizeof(PHDR)); fseek(fp, addr, SEEK_SET); fread((void*) &ph, sizeof(PHDR), 1, fp); revert_phdr(&ph); print_phdr(&ph, i); } addr = elf.e_shoff; for(i=0; i<elf.e_shnum; i++, addr+=sizeof(SHDR)){ memset((void*)&sh, 0, sizeof(SHDR)); fseek(fp, addr, SEEK_SET); fread((void*) &sh, sizeof(SHDR), 1, fp); revert_shdr(&sh); print_shdr(&sh, i); TBL[i].off = addr; TBL[i].va = sh.sh_addr; TBL[i].used= 0; } printf("\n\n#### Disassemble ####\n"); addr = elf.e_phoff; for(i=0; i<elf.e_phnum; i++, addr+=sizeof(PHDR)){ memset((void*)&ph, 0, sizeof(PHDR)); fseek(fp, addr, SEEK_SET); fread((void*) &ph, sizeof(PHDR), 1, fp); revert_phdr(&ph); for(j=0;j<elf.e_shnum-1;j++){ if(TBL[j].used == 0 && TBL[j].va <= ph.p_vaddr){ TBL[j].used++; fseek(fp, TBL[j].off, SEEK_SET); fread((void*) &sh, sizeof(SHDR), 1, fp); revert_shdr(&sh); if(sh.sh_size != 0) data = (uint8_t*) malloc(sh.sh_size); else data = NULL; disassemble_data(&sh, data, sh.sh_size, TBL[j].va); if(sh.sh_size != 0) free(data); } } data = (uint8_t*) malloc(ph.p_filesz); if(data == NULL){ printf("Could not alloc %lu bytes\n", ph.p_filesz); break; } fseek(fp, ph.p_offset, SEEK_SET); fread((void*) data, ph.p_filesz, 1, fp); disassemble(handle, insn, data, ph.p_filesz, ph.p_vaddr); free(data); } for(j=0;j<elf.e_shnum-1;j++){ if(TBL[j].used == 0){ TBL[j].used++; fseek(fp, TBL[j].off, SEEK_SET); fread((void*) &sh, sizeof(SHDR), 1, fp); revert_shdr(&sh); if(sh.sh_size != 0) data = (uint8_t*) malloc(sh.sh_size); else data = NULL; disassemble_data(&sh, data, sh.sh_size, TBL[j].va); if(sh.sh_size != 0) free(data); } } end: if(TBL) free(TBL); cs_close(&handle); }