[英]Can't convert my C++ PELoader from x86 to x64
我有这个 PELoader 项目,它基本上将一个 PE 加载到 memory 中。它在 x86 PE 上工作正常,但是当我试图让它在 x64 上工作时我被卡住了。
我试过的是:
IMAGE_NT_HEADERS*
和IMAGE_NT_HEADERS64*
(DWORD)
替换为reinterpret_cast<DWORD_PTR>
并且异常已更改。 我想这是必要的,但还不够。更新 2
我刚刚发现问题出在重新分配上。 (检查代码)
在我发现这个错误之前,我已经修复了一个错误,它在存储可选 header 的基地址的数据类型中。
它存储在 DWORD 中,但我已将其更改为 char* 并解决了问题。
所以我认为错误出在某些值的转换或某些数据类型中。
这是搬迁代码:
/** Handle relocations **/
//this is how much we shifted the ImageBase
DWORD_PTR delta_VA_reloc = (reinterpret_cast<DWORD_PTR>(ImageBase)) - p_NT_HDR->OptionalHeader.ImageBase;
// if there is a relocation table, and we actually shitfted the ImageBase
if (data_directory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0 && delta_VA_reloc != 0) {
printf("\n[*] The allocated address is not the prefered address, started relocating\n");
//calculate the relocation table address
IMAGE_BASE_RELOCATION* p_reloc = (IMAGE_BASE_RELOCATION*)(ImageBase + data_directory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
//once again, a null terminated array
while (p_reloc->VirtualAddress != 0) {
// how many relocations in this block
// ie the total size, minus the size of the "header", divided by 2 (those are words, so 2 bytes for each)
//std::cout << sizeof(WORD) << "\n"; sizeof word is 2
DWORD size = (p_reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
// the first relocation element in the block, right after the header (using pointer arithmetic again)
WORD* reloc = (WORD*)(p_reloc + 1);
for (int i = 0; i < size; ++i) {
//type is the first 4 bits of the relocation word
int type = reloc[i] >> 12;
// offset is the last 12 bits
unsigned long long int offset = reloc[i] & 0x0fff;
//printf("--------------- %#llx\n", offset);
//this is the address we are going to change
DWORD* change_addr = (DWORD*)(ImageBase + p_reloc->VirtualAddress + offset);
// there is only one type used that needs to make a change
// When you relocate you should look if the flag HIGHT_LOW is active for PE32 and DIR64 for PE32+
switch (type) {
case IMAGE_REL_BASED_HIGHLOW://for x86
*change_addr += delta_VA_reloc;
break;
case IMAGE_REL_BASED_DIR64://for x64
*change_addr += delta_VA_reloc;
break;
default:
break;
}
}
// switch to the next relocation block, based on the size
p_reloc = (IMAGE_BASE_RELOCATION*)((reinterpret_cast<DWORD_PTR>(p_reloc)) + p_reloc->SizeOfBlock);
}
}
我发现了问题:
我不太清楚,但是在这一行中使用 DWORD* 时:
DWORD* change_addr = (DWORD*)(ImageBase + p_reloc->VirtualAddress + offset);
我在 x86 中打印了 chnage_addr,它打印了代表地址的整个 6 个字节。
但在 x64 中它只打印 4 个字节。 我认为 windows DWORD* 在 x64 中较小。
所以我找到的解决方案是使用长数据类型
unsigned long long int* change_addr = (unsigned long long int*)(ImageBase + p_reloc->VirtualAddress + offset);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.