DWORD get_hdrs_size(BYTE* payload) { if (payload == NULL) return false; bool is64b = is64bit(payload); BYTE* payload_nt_hdr = get_nt_hrds(payload); if (payload_nt_hdr == NULL) { printf("Invalid payload: %p\n", payload); return false; } IMAGE_FILE_HEADER *fileHdr = NULL; DWORD hdrsSize = 0; if (is64b) { IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr; fileHdr = &(payload_nt_hdr64->FileHeader); hdrsSize = payload_nt_hdr64->OptionalHeader.SizeOfHeaders; } else { IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr; fileHdr = &(payload_nt_hdr32->FileHeader); hdrsSize = payload_nt_hdr32->OptionalHeader.SizeOfHeaders; } return hdrsSize; }
LPVOID get_sec_ptr(BYTE* payload) { if (payload == NULL) return NULL; bool is64b = is64bit(payload); BYTE* payload_nt_hdr = get_nt_hrds(payload); if (payload_nt_hdr == NULL) { printf("Invalid payload: %p\n", payload); return NULL; } IMAGE_FILE_HEADER *fileHdr = NULL; LPVOID secptr = NULL; if (is64b) { IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr; fileHdr = &(payload_nt_hdr64->FileHeader); secptr = (LPVOID)((ULONGLONG)&(payload_nt_hdr64->OptionalHeader) + fileHdr->SizeOfOptionalHeader); } else { IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr; fileHdr = &(payload_nt_hdr32->FileHeader); secptr = (LPVOID)((ULONGLONG)&(payload_nt_hdr32->OptionalHeader) + fileHdr->SizeOfOptionalHeader); } return secptr; }
WORD get_pe_architecture(const BYTE *pe_buffer) { void *ptr = get_nt_hrds(pe_buffer); if (ptr == NULL) return 0; IMAGE_NT_HEADERS32 *inh = static_cast<IMAGE_NT_HEADERS32*>(ptr); return inh->FileHeader.Machine; }
bool is64bit(BYTE *pe_buffer) { BYTE *ptr = get_nt_hrds(pe_buffer); if (ptr == NULL) return false; IMAGE_NT_HEADERS32 *inh = (IMAGE_NT_HEADERS32*)(ptr); if (inh->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) { return true; } return false; }
IMAGE_NT_HEADERS64* get_nt_hrds64(BYTE *pe_buffer) { BYTE *ptr = get_nt_hrds(pe_buffer); if (ptr == NULL) return NULL; IMAGE_NT_HEADERS32 *inh = (IMAGE_NT_HEADERS32*)(ptr); if (inh->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) { return (IMAGE_NT_HEADERS64*)(ptr); } return NULL; }
IMAGE_NT_HEADERS32* get_nt_hrds32(BYTE *pe_buffer) { BYTE *ptr = get_nt_hrds(pe_buffer); if (ptr == NULL) return NULL; IMAGE_NT_HEADERS32 *inh = (IMAGE_NT_HEADERS32*)(ptr); if (inh->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) { return inh; } return NULL; }
DWORD get_entry_point_rva(const BYTE *pe_buffer) { WORD arch = get_pe_architecture(pe_buffer); BYTE* payload_nt_hdr = get_nt_hrds(pe_buffer); if (payload_nt_hdr == NULL) { return 0; } DWORD ep_addr = 0; if (arch == IMAGE_FILE_MACHINE_AMD64) { IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr; ep_addr = payload_nt_hdr64->OptionalHeader.AddressOfEntryPoint; } else { IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr; ep_addr = static_cast<ULONGLONG>(payload_nt_hdr32->OptionalHeader.AddressOfEntryPoint); } return ep_addr; }
bool update_image_base(BYTE* payload, PVOID destImageBase) { bool is64b = is64bit(payload); //update image base in the written content: BYTE* payload_nt_hdr = get_nt_hrds(payload); if (payload_nt_hdr == NULL) { return false; } if (is64b) { IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr; payload_nt_hdr64->OptionalHeader.ImageBase = (ULONGLONG)destImageBase; } else { IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr; payload_nt_hdr32->OptionalHeader.ImageBase = (DWORD)destImageBase; } return true; }
IMAGE_DATA_DIRECTORY* get_pe_directory(PVOID pe_buffer, DWORD dir_id) { if (dir_id >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES) return NULL; BYTE* nt_headers = get_nt_hrds((BYTE*)pe_buffer); if (nt_headers == NULL) return NULL; IMAGE_DATA_DIRECTORY* peDir = NULL; if (is64bit((BYTE*)pe_buffer)) { IMAGE_NT_HEADERS64* nt_headers64 = (IMAGE_NT_HEADERS64*)nt_headers; peDir = &(nt_headers64->OptionalHeader.DataDirectory[dir_id]); } else { IMAGE_NT_HEADERS32* nt_headers64 = (IMAGE_NT_HEADERS32*)nt_headers; peDir = &(nt_headers64->OptionalHeader.DataDirectory[dir_id]); } if (peDir->VirtualAddress == NULL) { return NULL; } return peDir; }
WORD get_sec_number(BYTE* payload) { if (payload == NULL) return 0; bool is64b = is64bit(payload); BYTE* payload_nt_hdr = get_nt_hrds(payload); if (payload_nt_hdr == NULL) { printf("Invalid payload: %p\n", payload); return 0; } IMAGE_FILE_HEADER *fileHdr = NULL; LPVOID secptr = NULL; if (is64b) { IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*)payload_nt_hdr; fileHdr = &(payload_nt_hdr64->FileHeader); } else { IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*)payload_nt_hdr; fileHdr = &(payload_nt_hdr32->FileHeader); } return fileHdr->NumberOfSections; }
bool sections_virtual_to_raw(BYTE* payload, SIZE_T payload_size, OUT BYTE* destAddress, OUT SIZE_T *raw_size_ptr) { if (payload == NULL) return false; bool is64b = is64bit(payload); BYTE* payload_nt_hdr = get_nt_hrds(payload); if (payload_nt_hdr == NULL) { printf("Invalid payload: %p\n", payload); return false; } IMAGE_FILE_HEADER *fileHdr = NULL; DWORD hdrsSize = 0; LPVOID secptr = NULL; if (is64b) { IMAGE_NT_HEADERS64* payload_nt_hdr64 = (IMAGE_NT_HEADERS64*) payload_nt_hdr; fileHdr = &(payload_nt_hdr64->FileHeader); hdrsSize = payload_nt_hdr64->OptionalHeader.SizeOfHeaders; secptr = (LPVOID)((ULONGLONG)&(payload_nt_hdr64->OptionalHeader) + fileHdr->SizeOfOptionalHeader); } else { IMAGE_NT_HEADERS32* payload_nt_hdr32 = (IMAGE_NT_HEADERS32*) payload_nt_hdr; fileHdr = &(payload_nt_hdr32->FileHeader); hdrsSize = payload_nt_hdr32->OptionalHeader.SizeOfHeaders; secptr = (LPVOID)((ULONGLONG)&(payload_nt_hdr32->OptionalHeader) + fileHdr->SizeOfOptionalHeader); } if (!validate_ptr(payload, payload_size, payload, hdrsSize)) { return false; } //copy payload's headers: memcpy(destAddress, payload, hdrsSize); //copy all the sections, one by one: printf("Coping sections:\n"); SIZE_T raw_end = 0; for (WORD i = 0; i < fileHdr->NumberOfSections; i++) { PIMAGE_SECTION_HEADER next_sec = (PIMAGE_SECTION_HEADER)((ULONGLONG)secptr + (IMAGE_SIZEOF_SECTION_HEADER * i)); if (!validate_ptr(payload, payload_size, next_sec, IMAGE_SIZEOF_SECTION_HEADER)) { return false; } LPVOID section_mapped = (BYTE*) payload + next_sec->VirtualAddress; LPVOID section_raw_ptr = destAddress + next_sec->PointerToRawData; SIZE_T sec_size = next_sec->SizeOfRawData; raw_end = next_sec->SizeOfRawData + next_sec->PointerToRawData; if (next_sec->VirtualAddress + sec_size >= payload_size) { printf("[!] Virtual section size is out ouf bounds: %lx\n", sec_size); sec_size = SIZE_T(payload_size - next_sec->VirtualAddress); printf("[!] Truncated to maximal size: %lx\n", sec_size); } if (next_sec->VirtualAddress >= payload_size && sec_size != 0) { printf("[-] VirtualAddress of section is out ouf bounds: %lx\n", static_cast<SIZE_T>(next_sec->VirtualAddress)); return false; } if (next_sec->PointerToRawData + sec_size >= payload_size) { printf("[-] Raw section size is out ouf bounds: %lx\n", sec_size); return false; } printf("[+] %s to: %p\n", next_sec->Name, section_raw_ptr); memcpy(section_raw_ptr, section_mapped, sec_size); } if (raw_end > payload_size) raw_end = payload_size; if (raw_size_ptr != NULL) { (*raw_size_ptr) = raw_end; } return true; }