首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

PE Loader 核心邏輯:將檔案映射至虛擬位址空間

     編輯:關於C

設計考量

早期版本將記憶體配置寫在函式內部,嚴重降低復用性(如驅動層無法直接呼叫)。改良後將「系統相關的記憶體配置」移至呼叫端,LdrLayoutPe 僅負責依 PE 結構將檔案內容複製到指定基址,職責單一、易於移植。

核心實作

BOOL LdrLayoutPe(
    char *pImage,          // 檔案緩衝區
    DWORD FileSize,        // 檔案大小
    char *pRealImageBase,  // 目標映射基址(由呼叫端配置)
    DWORD SizeOfImage      // 映射總大小(來自 OptionalHeader)
) {
    PIMAGE_FILE_HEADER     pFileHeader;
    PIMAGE_SECTION_HEADER  pSectionHeader;
    char *pSrc, *pDst;
    DWORD CopySize, i;

    if (!LdrValidateImage(pImage, FileSize)) return FALSE;

    pFileHeader   = _GetFileHeaderFromPe(pImage);
    pSectionHeader = _GetSectionHeaderFromPe(pFileHeader);

    // 1. 複製 DOS Header + NT Headers + Section Table
    pDst = pRealImageBase;
    pSrc = pImage;
    CopySize = (char*)pSectionHeader - pImage
             + pFileHeader->NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
    if (pDst + CopySize >= pRealImageBase + SizeOfImage) return FALSE;
    RtlCopyMemory(pDst, pSrc, CopySize);

    // 2. 逐區段複製 Raw Data 至 VirtualAddress
    for (i = 0; i < pFileHeader->NumberOfSections; ++i) {
        if (!pSectionHeader[i].PointerToRawData) continue; // 僅保留虛擬空間的區段(如 .bss)

        pDst = pRealImageBase + pSectionHeader[i].VirtualAddress;
        pSrc = pImage + pSectionHeader[i].PointerToRawData;
        CopySize = pSectionHeader[i].SizeOfRawData;
        if (pDst + CopySize >= pRealImageBase + SizeOfImage) return FALSE;
        RtlCopyMemory(pDst, pSrc, CopySize);
    }
    return TRUE;
}

關鍵點說明

  • 邊界檢查:每次複製前皆檢查 pDst + CopySize 是否超出 SizeOfImage,防止緩衝區溢位。
  • 區段對齊:呼叫端需確保 pRealImageBase 符合 SectionAlignment 對齊需求。
  • 無重定位/導入表處理:此函式僅完成「映射」,重定位修正、IAT 解析、TLS 回呼等留給上層 Loader 流程。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved