繁体   English   中英

无法将我的 C++ PELoader 从 x86 转换为 x64

[英]Can't convert my C++ PELoader from x86 to x64

我有这个 PELoader 项目,它基本上将一个 PE 加载到 memory 中。它在 x86 PE 上工作正常,但是当我试图让它在 x64 上工作时我被卡住了。

我试过的是:

  • 我用 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM