PE:copyBaseRelocation2NewSection

DWORD copyBaseRelocation2NewSection(IN PVOID pFileBuffer,OUT PVOID* pNewFileBuffer)
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pPEHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;

    if(!pFileBuffer)
    {
        printf("FileBuffer無效!\n");
        free(pFileBuffer);
        return;
    }
    if(*(PWORD)pFileBuffer != IMAGE_DOS_SIGNATURE)
    {
        printf("不是有效的PE文件\n");
        free(pFileBuffer);
        return;
    }

    //新增節表
    PVOID pTemOfNewFileBuffer = NULL;
    DWORD sizeOfNewBuffer = AddNewSection(pFileBuffer, &pTemOfNewFileBuffer);
    free(pFileBuffer);
    if(!pTemOfNewFileBuffer)
    {
        printf("新節表添加失敗!\n");
        return;
    }
    if(*(PWORD)pTemOfNewFileBuffer != IMAGE_DOS_SIGNATURE)
    {
        printf("不是有效的PE文件\n");
        free(pTemOfNewFileBuffer);
        return;
    }

    pDosHeader = (PIMAGE_DOS_HEADER)pTemOfNewFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)(pDosHeader + pDosHeader->e_lfanew);
    pPEHeader = (PIMAGE_FILE_HEADER)(pNTHeader + 4);
    pOptionHeader = (PIMAGE_OPTIONAL_HEADER)(pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
    pSectionHeader = (PIMAGE_SECTION_HEADER)(pOptionHeader + pPEHeader->SizeOfOptionalHeader);
    //定位數據目錄
    PIMAGE_DATA_DIRECTORY pDataDirectory = pOptionHeader->DataDirectory;
    //獲取數據目錄數組中的第6個結構,重定位表,記錄重定位數據塊的RVA和Size(沒用)
    DWORD RVAOfBaseRelocationDataDirectory = pDataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
    //RVA轉FOA找到第一個重定位數據塊
    DWORD FOAOfBaseRelocation = RVA2FOA(pTemOfNewFileBuffer,RVAOfBaseRelocationDataDirectory);
    PIMAGE_BASE_RELOCATION pBASERELOCATION  = (PIMAGE_BASE_RELOCATION)FOAOfBaseRelocation;

    //複製
    //定義pLastSection--新節在拉伸後的內存(pTemOfNewFileBuffer)中的地址
    PDWORD pLastSection = (PDWORD)((DWORD)pTemOfNewFileBuffer + (pSectionHeader + pPEHeader->NumberOfSections)->PointerToRawData);
    //循環複製重定位數據塊到新節,結束條件是最後一個結構的VirtualAddress與SizeOfBlock都爲0
    PIMAGE_BASE_RELOCATION pTemOfBASERELOCATION = pBASERELOCATION;
    while(*(pTemOfBASERELOCATION)->VirtualAddress != 0 && *(pTemOfBASERELOCATION)->SizeOfBlock != 0)
    {
       memcpy(pLastSection,pBASERELOCATION,pTemOfBASERELOCATION->SizeOfBlock);
       pLastSection = (PDWORD)((DWORD)pLastSection + pTemOfBASERELOCATION->SizeOfBlock);
       pTemOfBASERELOCATION = (PIMAGE_BASE_RELOCATION)((DWORD)pTemOfBASERELOCATION + pTemOfBASERELOCATION->SizeOfBlock) ;
    }

    //修復,使重定位表指向的重定位數據塊的新RVA,也就是新節的RVA,要把FOA轉爲RVA
    pDataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = pOptionHeader->ImageBase + (pSectionHeader + pPEHeader->NumberOfSections)->PointerToRawData;

    //結束返回pNewFileBuffer,sizeOfNewBuffer
    pNewFileBuffer = pTemOfNewFileBuffer;
    pTemOfNewFileBuffer = NULL;
    free(pFileBuffer);
    return sizeOfNewBuffer;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章