diff --git a/COFFLoader.c b/COFFLoader.c index 8773692..eb6fe2d 100644 --- a/COFFLoader.c +++ b/COFFLoader.c @@ -5,10 +5,12 @@ * it's meant to provide functional example of loading a COFF file in memory * and maybe be useful. */ +#include #include #include #include #include +#include #if defined(_WIN32) #include @@ -173,6 +175,15 @@ void* process_symbol(char* symbolstring) { return functionaddress; } +static bool coff_symbol_is_defined(struct coff_sym *symbol) { + return symbol->SectionNumber > 0; +} + +static bool coff_symbol_is_external(struct coff_sym *symbol) { + return symbol->StorageClass == IMAGE_SYM_CLASS_EXTERNAL + || symbol->StorageClass == IMAGE_SYM_CLASS_EXTERNAL_DEF; +} + /* Just a generic runner for testing, this is pretty much just a reference * implementation, return values will need to be checked, more relocation * types need to be handled, and needs to have different arguments for use @@ -184,7 +195,7 @@ int RunCOFF(char* functionname, unsigned char* coff_data, uint32_t filesize, uns int counter = 0; int reloccount = 0; unsigned int tempcounter = 0; - uint32_t symptr = 0; + char *symbol_name = NULL; COFFLOADER_RETURN_VAL_IF(functionname == NULL, 1, "Function name is NULL\n"); COFFLOADER_RETURN_VAL_IF(coff_data == NULL, 1, "Can't execute NULL\n"); @@ -243,10 +254,12 @@ int RunCOFF(char* functionname, unsigned char* coff_data, uint32_t filesize, uns int *sectionSize = NULL; #endif void(*foo)(char* in, unsigned long datalen); - char* functionMapping = NULL; + void **functionMapping = NULL; int functionMappingCount = 0; int relocationCount = 0; #endif + /* Buffer to hold the symbol short name if the symbol has no trailing NULL byte */ + char symbol_shortname_buffer[9] = {0}; DEBUG_PRINT("Machine 0x%X\n", coff_header_ptr->Machine); DEBUG_PRINT("Number of sections: %d\n", coff_header_ptr->NumberOfSections); @@ -310,9 +323,9 @@ int RunCOFF(char* functionname, unsigned char* coff_data, uint32_t filesize, uns /* Actually allocate enough for worst case every relocation, may not be needed, but hey better safe than sorry */ #ifdef _WIN32 #ifdef _WIN64 - functionMapping = VirtualAlloc(NULL, relocationCount*8, MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE); + functionMapping = (void **)VirtualAlloc(NULL, relocationCount*8, MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE); #else - functionMapping = VirtualAlloc(NULL, relocationCount*8, MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE); + functionMapping = (void **)VirtualAlloc(NULL, relocationCount*8, MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE); #endif if (functionMapping == NULL){ DEBUG_PRINT("Failed to allocate functionMapping\n"); @@ -329,262 +342,219 @@ int RunCOFF(char* functionname, unsigned char* coff_data, uint32_t filesize, uns DEBUG_PRINT("\tVirtualAddress: 0x%X\n", coff_reloc_ptr->VirtualAddress); DEBUG_PRINT("\tSymbolTableIndex: 0x%X\n", coff_reloc_ptr->SymbolTableIndex); DEBUG_PRINT("\tType: 0x%X\n", coff_reloc_ptr->Type); - if (coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].first.Name[0] != 0) { - symptr = coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].first.value[1]; - DEBUG_PRINT("\tSymPtr: 0x%X\n", symptr); - DEBUG_PRINT("\tSymName: %s\n", coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].first.Name); - DEBUG_PRINT("\tSectionNumber: 0x%X\n", coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber); - /* This is the code for relative offsets in other sections of the COFF file. */ -#ifdef _WIN32 -#ifdef _WIN64 - /* Type == 1 relocation is the 64-bit VA of the relocation target */ - if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_ADDR64) { - memcpy(&longoffsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(uint64_t)); - DEBUG_PRINT("\tReadin longOffsetValue : 0x%llX\n", longoffsetvalue); - longoffsetvalue = (uint64_t)(sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] + (uint64_t)longoffsetvalue); - longoffsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - DEBUG_PRINT("\tModified longOffsetValue : 0x%llX Base Address: %p\n", longoffsetvalue, sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1]); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &longoffsetvalue, sizeof(uint64_t)); - } - /* This is Type == 3 relocation code */ - else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_ADDR32NB) { - memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); - DEBUG_PRINT("\tReadin OffsetValue : 0x%0X\n", offsetvalue); - DEBUG_PRINT("\t\tReferenced Section: 0x%X\n", sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] + offsetvalue); - DEBUG_PRINT("\t\tEnd of Relocation Bytes: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4); - if (((char*)(sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] + offsetvalue) - (char*)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)) > 0xffffffff) { - DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); - retcode = 1; - goto cleanup; - } - offsetvalue = ((char*)(sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] + offsetvalue) - (char*)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); - offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - DEBUG_PRINT("\tSetting 0x%p to OffsetValue: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - } - /* This is Type == 4 relocation code, needed to make global variables to work correctly */ - else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_REL32) { - memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); - DEBUG_PRINT("\t\tReadin offset value: 0x%X\n", offsetvalue); - if ((sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)) > 0xffffffff) { - DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); - retcode = 1; - goto cleanup; - } - offsetvalue += (sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); - offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - DEBUG_PRINT("\t\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - } - else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_REL32_1) { - memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); - DEBUG_PRINT("\t\tReadin offset value: 0x%X\n", offsetvalue); - if ((sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)) > 0xffffffff) { - DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); - retcode = 1; - goto cleanup; - } - offsetvalue += (sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); - offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - offsetvalue += 1; - DEBUG_PRINT("\t\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - } + /* Check if the symbol name is a long symbol name */ + if (coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].first.value[0] == 0) { + /* Long symbol name from the string table */ - else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_REL32_2) { - memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); - DEBUG_PRINT("\t\tReadin offset value: 0x%X\n", offsetvalue); - if ((sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)) > 0xffffffff) { - DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); - retcode = 1; - goto cleanup; - } - offsetvalue += (sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); - offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - offsetvalue += 2; - DEBUG_PRINT("\t\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - } + symbol_name = ((char*)(coff_sym_ptr + coff_header_ptr->NumberOfSymbols)) + + coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].first.value[1]; - else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_REL32_3) { - memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); - DEBUG_PRINT("\t\tReadin offset value: 0x%X\n", offsetvalue); - if ((sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)) > 0xffffffff) { - DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); - retcode = 1; - goto cleanup; - } - offsetvalue += (sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); - offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - offsetvalue += 3; - DEBUG_PRINT("\t\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - } + } else { + /* Short symbol name */ - else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_REL32_4) { - memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); - DEBUG_PRINT("\t\tReadin offset value: 0x%X\n", offsetvalue); - if ((sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)) > 0xffffffff) { - DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); - retcode = 1; - goto cleanup; - } - offsetvalue += (sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); - offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - offsetvalue += 4; - DEBUG_PRINT("\t\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - } - else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_REL32_5) { - memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); - DEBUG_PRINT("\t\tReadin offset value: 0x%X\n", offsetvalue); - if ((sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)) > 0xffffffff) { - DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); - retcode = 1; - goto cleanup; - } - offsetvalue += (sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); - offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - offsetvalue += 5; - DEBUG_PRINT("\t\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - } + /* If the short symbol name is 8 bytes in length, it is not NULL + * terminated. Copy it to a temporary buffer to add the NULL terminator. */ + if (coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].first.Name[7] != '\0') { + strncpy_s( + symbol_shortname_buffer, + sizeof(symbol_shortname_buffer), + &coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].first.Name[0], + sizeof(coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].first.Name) + ); - else { - DEBUG_PRINT("No code for relocation type: %d\n", coff_reloc_ptr->Type); + symbol_name = symbol_shortname_buffer; + } else { + symbol_name = &coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].first.Name[0]; } -#else - /* This is Type == IMAGE_REL_I386_DIR32 relocation code */ - if (coff_reloc_ptr->Type == IMAGE_REL_I386_DIR32){ - memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); - DEBUG_PRINT("\tReadin OffsetValue : 0x%0X\n", offsetvalue); - offsetvalue = (uint32_t)(sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1]) + offsetvalue; - offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - DEBUG_PRINT("\tSetting 0x%p to: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - } - else if (coff_reloc_ptr->Type == IMAGE_REL_I386_REL32){ - memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); - DEBUG_PRINT("\tReadin OffsetValue : 0x%0X\n", offsetvalue); - offsetvalue += (sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); - offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - DEBUG_PRINT("\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - - } -#endif //WIN64 statement close -#endif //WIN32 statement close } - else { - symptr = coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].first.value[1]; - DEBUG_PRINT("\tSymPtr: 0x%X\n", symptr); - DEBUG_PRINT("\tSymVal: %s\n", ((char*)(coff_sym_ptr + coff_header_ptr->NumberOfSymbols)) + symptr); - DEBUG_PRINT("\tSectionNumber: 0x%X\n", coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber); - /* This is the code to handle functions themselves, so using a makeshift Global Offset Table for it */ -#ifdef _WIN32 - funcptrlocation = process_symbol(((char*)(coff_sym_ptr + coff_header_ptr->NumberOfSymbols)) + symptr); - if (funcptrlocation == NULL && coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber == 0) { - DEBUG_PRINT("Failed to resolve symbol\n"); + DEBUG_PRINT("\tSymNamePtr: %p\n", symbol_name); + DEBUG_PRINT("\tSymName: %s\n", symbol_name); + DEBUG_PRINT("\tSectionNumber: 0x%X\n", coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber); + + /* Check if the target symbol is a local symbol or an external undefined symbol + * and resolve it */ + if (coff_symbol_is_defined(&coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex])) { + /* Locally defined symbol. Find the mapped address. */ + funcptrlocation = sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1]; + + funcptrlocation = (void *)((char *)funcptrlocation + coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value); + } else if (coff_symbol_is_external(&coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex]) + && coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value == 0) { + /* Imported symbol. Resolve it and map it in */ + funcptrlocation = process_symbol(symbol_name); + if (funcptrlocation == NULL) { + DEBUG_PRINT("Failed resolving imported symbol '%s'\n", symbol_name); retcode = 1; goto cleanup; } + + /* Map the imported symbol address to the local import table */ + functionMapping[functionMappingCount] = funcptrlocation; + + /* Get the address of the imported symbol mapped in the local import + * table for the relocation target */ + funcptrlocation = &functionMapping[functionMappingCount]; + + /* Increment the number of mapped imported functions */ + functionMappingCount += 1; + + } else { + /* Relocation to an undefined symbol */ + DEBUG_PRINT("Relocation %d in section index %d references undefined symbol %s\n", reloccount, counter, symbol_name); + retcode = 1; + goto cleanup; + } + +#ifdef _WIN32 #ifdef _WIN64 - if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_ADDR64) { - memcpy(&longoffsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(uint64_t)); - DEBUG_PRINT("\tReadin longOffsetValue : 0x%llX\n", longoffsetvalue); - longoffsetvalue = (uint64_t)(sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] + (uint64_t)longoffsetvalue); - longoffsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - DEBUG_PRINT("\tModified longOffsetValue : 0x%llX Base Address: %p\n", longoffsetvalue, sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1]); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &longoffsetvalue, sizeof(uint64_t)); + /* Type == 1 relocation is the 64-bit VA of the relocation target */ + if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_ADDR64) { + memcpy(&longoffsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(uint64_t)); + DEBUG_PRINT("\tReadin longOffsetValue : 0x%llX\n", longoffsetvalue); + longoffsetvalue += (uint64_t)funcptrlocation; + DEBUG_PRINT("\tModified longOffsetValue : 0x%llX Base Address: %p\n", longoffsetvalue, funcptrlocation); + memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &longoffsetvalue, sizeof(uint64_t)); + } + /* This is Type == 3 relocation code */ + else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_ADDR32NB) { + memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); + DEBUG_PRINT("\tReadin OffsetValue : 0x%0X\n", offsetvalue); + DEBUG_PRINT("\t\tReferenced Section: 0x%X\n", sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] + offsetvalue); + DEBUG_PRINT("\t\tEnd of Relocation Bytes: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4); + if (((char*)(sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] + offsetvalue) - (char*)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)) > 0xffffffff) { + DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); + retcode = 1; + goto cleanup; + } + offsetvalue = ((char*)(sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] + offsetvalue) - (char*)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); + offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; + DEBUG_PRINT("\tSetting 0x%p to OffsetValue: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); + memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); + } + /* This is Type == 4 relocation code, this is either a relocation to a global + * or imported symbol */ + else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_REL32) { + offsetvalue = 0; + memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); + DEBUG_PRINT("\t\tReadin offset value: 0x%X\n", offsetvalue); + + if (llabs((long long)funcptrlocation - (long long)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)) > UINT_MAX) { + DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); + goto cleanup; } - else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_REL32 && funcptrlocation != NULL) { - /* This is Type == 4 relocation code */ - DEBUG_PRINT("Doing function relocation\n"); - if (((functionMapping + (functionMappingCount * 8)) - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)) > 0xffffffff) { - DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); - retcode = 1; - goto cleanup; - } - memcpy(functionMapping + (functionMappingCount * 8), &funcptrlocation, sizeof(uint64_t)); - offsetvalue = (int32_t)((functionMapping + (functionMappingCount * 8)) - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); - offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - DEBUG_PRINT("\t\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - functionMappingCount++; - } - else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_REL32) { - /* This shouldn't be needed here, but incase there's a defined symbol - * that somehow doesn't have a function, try to resolve it here.*/ - memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); - if ((sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)) > 0xffffffff) { - DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); - retcode = 1; - goto cleanup; - } - DEBUG_PRINT("\t\tReferenced Section: 0x%X\n", sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] + offsetvalue); - DEBUG_PRINT("\t\tReadin offset value: 0x%X\n", offsetvalue); - DEBUG_PRINT("\t\tVirtualAddressOffset: 0x%X\n", (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); - offsetvalue += (sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); - offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - DEBUG_PRINT("\t\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - } - else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_ADDR32NB) { - memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); - DEBUG_PRINT("\tReadin OffsetValue : 0x%0X\n", offsetvalue); - DEBUG_PRINT("\t\tReferenced Section: 0x%X\n", sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] + offsetvalue); - DEBUG_PRINT("\t\tEnd of Relocation Bytes: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4); - if (((char*)(sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] + offsetvalue) - (char*)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)) > 0xffffffff) { - DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); - retcode = 1; - goto cleanup; - } - offsetvalue = ((char*)(sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] + offsetvalue) - (char*)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); - offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - DEBUG_PRINT("\tSetting 0x%p to OffsetValue: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - } - else { - DEBUG_PRINT("No code for relocation type: %d\n", coff_reloc_ptr->Type); - } -#else - if (coff_reloc_ptr->Type == IMAGE_REL_I386_DIR32 && funcptrlocation != NULL){ - /* This is Type == IMAGE_REL_I386_DIR32 relocation code */ - memcpy(functionMapping + (functionMappingCount * 4), &funcptrlocation, sizeof(uint32_t)); - offsetvalue = (int32_t)(functionMapping + (functionMappingCount * 4)); - DEBUG_PRINT("\tSetting 0x%p to virtual address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - functionMappingCount++; - } - else if (coff_reloc_ptr->Type == IMAGE_REL_I386_DIR32) { - memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); - DEBUG_PRINT("\tReadin OffsetValue : 0x%0X\n", offsetvalue); - offsetvalue = (uint32_t)(sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1]) + offsetvalue; - offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - DEBUG_PRINT("\tSetting 0x%p to virtual address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - } - else if (coff_reloc_ptr->Type == IMAGE_REL_I386_REL32){ - memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); - DEBUG_PRINT("\tReadin OffsetValue : 0x%0X\n", offsetvalue); - offsetvalue += (sectionMapping[coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber - 1] - (sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); - offsetvalue += coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value; - DEBUG_PRINT("\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); - memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); - - } - else { - DEBUG_PRINT("No code for relocation type: %d\n", coff_reloc_ptr->Type); - } -#endif -#endif + offsetvalue += ((size_t)funcptrlocation - ((size_t)sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4)); + DEBUG_PRINT("\t\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); + memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); } + else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_REL32_1) { + offsetvalue = 0; + memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); + DEBUG_PRINT("\t\tReadin offset value: 0x%X\n", offsetvalue); + + if (llabs((long long)funcptrlocation - (long long)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4 + 1)) > UINT_MAX) { + DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); + retcode = 1; + goto cleanup; + } + + offsetvalue += (size_t)funcptrlocation - ((size_t)sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4 + 1); + DEBUG_PRINT("\t\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); + memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); + } + + else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_REL32_2) { + offsetvalue = 0; + memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); + DEBUG_PRINT("\t\tReadin offset value: 0x%X\n", offsetvalue); + + if (llabs((long long)funcptrlocation - (long long)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4 + 2)) > UINT_MAX) { + DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); + retcode = 1; + goto cleanup; + } + + offsetvalue += (size_t)funcptrlocation - ((size_t)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4 + 2)); + DEBUG_PRINT("\t\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); + memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); + } + + else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_REL32_3) { + offsetvalue = 0; + memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); + DEBUG_PRINT("\t\tReadin offset value: 0x%X\n", offsetvalue); + + if (llabs((long long)funcptrlocation - (long long)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4 + 3)) > UINT_MAX) { + DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); + retcode = 1; + goto cleanup; + } + + offsetvalue += (size_t)funcptrlocation - ((size_t)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4 + 3)); + DEBUG_PRINT("\t\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); + memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); + } + + else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_REL32_4) { + offsetvalue = 0; + memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); + DEBUG_PRINT("\t\tReadin offset value: 0x%X\n", offsetvalue); + + if (llabs((long long)funcptrlocation - (long long)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4 + 4)) > UINT_MAX) { + DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); + retcode = 1; + goto cleanup; + } + + offsetvalue += (size_t)funcptrlocation - ((size_t)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4 + 4)); + DEBUG_PRINT("\t\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); + memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); + } + else if (coff_reloc_ptr->Type == IMAGE_REL_AMD64_REL32_5) { + offsetvalue = 0; + memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); + DEBUG_PRINT("\t\tReadin offset value: 0x%X\n", offsetvalue); + + if (llabs((long long)funcptrlocation - (long long)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4 + 5)) > UINT_MAX) { + DEBUG_PRINT("Relocations > 4 gigs away, exiting\n"); + retcode = 1; + goto cleanup; + } + + offsetvalue += (size_t)funcptrlocation - ((size_t)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4 + 5)); + DEBUG_PRINT("\t\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); + memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); + } + + else { + DEBUG_PRINT("No code for relocation type: %d\n", coff_reloc_ptr->Type); + } +#else + /* This is Type == IMAGE_REL_I386_DIR32 relocation code */ + if (coff_reloc_ptr->Type == IMAGE_REL_I386_DIR32){ + offsetvalue = 0; + memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); + DEBUG_PRINT("\tReadin OffsetValue : 0x%0X\n", offsetvalue); + offsetvalue = (uint32_t)funcptrlocation + offsetvalue; + DEBUG_PRINT("\tSetting 0x%p to: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); + memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); + } + else if (coff_reloc_ptr->Type == IMAGE_REL_I386_REL32){ + offsetvalue = 0; + memcpy(&offsetvalue, sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, sizeof(int32_t)); + DEBUG_PRINT("\tReadin OffsetValue : 0x%0X\n", offsetvalue); + offsetvalue += (uint32_t)funcptrlocation - (uint32_t)(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress + 4); + DEBUG_PRINT("\tSetting 0x%p to relative address: 0x%X\n", sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, offsetvalue); + memcpy(sectionMapping[counter] + coff_reloc_ptr->VirtualAddress, &offsetvalue, sizeof(uint32_t)); + } +#endif //WIN64 statement close +#endif //WIN32 statement close + DEBUG_PRINT("\tValueNumber: 0x%X\n", coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].Value); DEBUG_PRINT("\tSectionNumber: 0x%X\n", coff_sym_ptr[coff_reloc_ptr->SymbolTableIndex].SectionNumber); - coff_reloc_ptr = (coff_reloc_t*)(((char*)coff_reloc_ptr) + sizeof(coff_reloc_t)); + coff_reloc_ptr += 1; DEBUG_PRINT("\n"); } DEBUG_PRINT("\n");