int pe_get_section(vm_offset_t imgbase, image_section_header *hdr, const char *name) { image_dos_header *dos_hdr; image_nt_header *nt_hdr; image_section_header *sect_hdr; int i, sections; if (imgbase == 0 || hdr == NULL) return(EINVAL); if (pe_is_nt_image(imgbase)) return (EINVAL); sections = pe_numsections(imgbase); dos_hdr = (image_dos_header *)imgbase; nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew); sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr + sizeof(image_nt_header)); for (i = 0; i < sections; i++) { if (!strcmp ((char *)§_hdr->ish_name, name)) { bcopy((char *)sect_hdr, (char *)hdr, sizeof(image_section_header)); return(0); } else sect_hdr++; } return (ENOEXEC); }
static int insert_padding(void **imgbase, int *imglen) { image_section_header *sect_hdr; image_dos_header *dos_hdr; image_nt_header *nt_hdr; image_optional_header opt_hdr; int i = 0, sections, curlen = 0; int offaccum = 0, oldraddr, oldrlen; uint8_t *newimg, *tmp; newimg = malloc(*imglen); if (newimg == NULL) return(ENOMEM); bcopy(*imgbase, newimg, *imglen); curlen = *imglen; if (pe_get_optional_header((vm_offset_t)newimg, &opt_hdr)) return(0); sections = pe_numsections((vm_offset_t)newimg); SET_HDRS(newimg); for (i = 0; i < sections; i++) { oldraddr = sect_hdr->ish_rawdataaddr; oldrlen = sect_hdr->ish_rawdatasize; sect_hdr->ish_rawdataaddr = sect_hdr->ish_vaddr; offaccum += ROUND_UP(sect_hdr->ish_vaddr - oldraddr, opt_hdr.ioh_filealign); offaccum += ROUND_UP(sect_hdr->ish_misc.ish_vsize, opt_hdr.ioh_filealign) - ROUND_UP(sect_hdr->ish_rawdatasize, opt_hdr.ioh_filealign); tmp = realloc(newimg, *imglen + offaccum); if (tmp == NULL) { free(newimg); return(ENOMEM); } newimg = tmp; SET_HDRS(newimg); sect_hdr += i; bzero(newimg + sect_hdr->ish_rawdataaddr, ROUND_UP(sect_hdr->ish_misc.ish_vsize, opt_hdr.ioh_filealign)); bcopy((uint8_t *)(*imgbase) + oldraddr, newimg + sect_hdr->ish_rawdataaddr, oldrlen); sect_hdr++; } free(*imgbase); *imgbase = newimg; *imglen += offaccum; return(0); }
static int insert_padding(void **imgbase, size_t *imglen) { struct image_section_header *sect_hdr; struct image_optional_header *opt_hdr; int ret, i, sections, curlen, offaccum = 0, oldraddr, oldrlen; uint8_t *newimg, *tmp; newimg = malloc(*imglen); if (newimg == NULL) return (ENOMEM); bcopy(*imgbase, newimg, *imglen); curlen = *imglen; if ((ret = pe_validate_header((vm_offset_t)newimg)) < 0) { free(newimg); return (ret); } sections = pe_numsections((vm_offset_t)newimg); pe_get_optional_header((vm_offset_t)newimg, &opt_hdr); pe_get_section_header((vm_offset_t)newimg, §_hdr); for (i = 0; i < sections; i++) { oldraddr = sect_hdr->pointer_to_raw_data; oldrlen = sect_hdr->size_of_raw_data; sect_hdr->pointer_to_raw_data = sect_hdr->virtual_address; offaccum += ROUND_UP(sect_hdr->virtual_address - oldraddr, opt_hdr->file_aligment); offaccum += ROUND_UP(sect_hdr->misc.virtual_size, opt_hdr->file_aligment) - ROUND_UP(sect_hdr->size_of_raw_data, opt_hdr->file_aligment); tmp = realloc(newimg, *imglen + offaccum); if (tmp == NULL) { free(newimg); return (ENOMEM); } newimg = tmp; pe_get_section_header((vm_offset_t)newimg, §_hdr); sect_hdr += i; bzero(newimg + sect_hdr->pointer_to_raw_data, ROUND_UP(sect_hdr->misc.virtual_size, opt_hdr->file_aligment)); bcopy((uint8_t *)(*imgbase) + oldraddr, newimg + sect_hdr->pointer_to_raw_data, oldrlen); sect_hdr++; } free(*imgbase); *imgbase = newimg; *imglen += offaccum; return (0); }
vm_offset_t pe_translate_addr(vm_offset_t imgbase, uint32_t rva) { image_optional_header opt_hdr; image_section_header *sect_hdr; image_dos_header *dos_hdr; image_nt_header *nt_hdr; int i = 0, sections, fixedlen; if (pe_get_optional_header(imgbase, &opt_hdr)) return(0); sections = pe_numsections(imgbase); dos_hdr = (image_dos_header *)imgbase; nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew); sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr + sizeof(image_nt_header)); /* * The test here is to see if the RVA falls somewhere * inside the section, based on the section's start RVA * and its length. However it seems sometimes the * virtual length isn't enough to cover the entire * area of the section. We fudge by taking into account * the section alignment and rounding the section length * up to a page boundary. */ while (i++ < sections) { fixedlen = sect_hdr->ish_misc.ish_vsize; fixedlen += ((opt_hdr.ioh_sectalign - 1) - sect_hdr->ish_misc.ish_vsize) & (opt_hdr.ioh_sectalign - 1); if (sect_hdr->ish_vaddr <= (u_int32_t)rva && (sect_hdr->ish_vaddr + fixedlen) > (u_int32_t)rva) break; sect_hdr++; } if (i > sections) return(0); return((vm_offset_t)(imgbase + rva - sect_hdr->ish_vaddr + sect_hdr->ish_rawdataaddr)); }