2016-09-08 200 views
2

我有一個內存緩衝區,它包含一個有效的exe文件圖像,我想從中提取一些資源。
爲此,我使用的是FindResource函數,但函數需要一個HMODULE並在提供一個帶有exe的內存緩衝區時崩潰。

有沒有辦法使它與內存緩衝區一起工作,而不是將exe寫入tempomary文件,使用LoadLibrary加載它,然後完成所需的工作?使用FindResource和內存緩衝區

+2

您可以解析PE格式並自己查找資源。 –

+1

現在,這是沒有記錄的,你不應該這樣做,但是如果你的內存塊是DWORD對齊的(因爲它應該),你應該能夠得到一個有效的資源專用'HMODULE'只需採取的起始地址和將其低位設置爲1. –

回答

3

我有一個包含一個有效的文件圖像

以何種形式

內存緩衝區?我想比在原始(如在磁盤上)。但是你需要'映射爲圖像'內存來使用FindResource。不難地圖,你自我(如果你只想要訪問的資源,而不是從內存執行它)的代碼示例原始圖像:

PVOID MapImage(PIMAGE_DOS_HEADER pvRawData, ULONG cbRawData) 
{ 
    if (cbRawData < sizeof(IMAGE_DOS_HEADER)) 
    { 
     return 0; 
    } 

    if (pvRawData->e_magic != IMAGE_DOS_SIGNATURE) 
    { 
     return 0; 
    } 

    ULONG e_lfanew = pvRawData->e_lfanew, s = e_lfanew + sizeof(IMAGE_NT_HEADERS); 

    if (e_lfanew >= s || s > cbRawData) 
    { 
     return 0; 
    } 

    PIMAGE_NT_HEADERS pinth = (PIMAGE_NT_HEADERS)RtlOffsetToPointer(pvRawData, e_lfanew); 

    if (pinth->Signature != IMAGE_NT_SIGNATURE) 
    { 
     return 0; 
    } 

    ULONG SizeOfImage = pinth->OptionalHeader.SizeOfImage, SizeOfHeaders = pinth->OptionalHeader.SizeOfHeaders; 

    s = e_lfanew + SizeOfHeaders; 

    if (SizeOfHeaders > SizeOfImage || SizeOfHeaders >= s || s > cbRawData) 
    { 
     return 0; 
    } 

    s = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + pinth->FileHeader.SizeOfOptionalHeader; 

    if (s > SizeOfHeaders) 
    { 
     return 0; 
    } 

    ULONG NumberOfSections = pinth->FileHeader.NumberOfSections; 

    PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)RtlOffsetToPointer(pinth, s); 

    ULONG Size; 

    if (NumberOfSections) 
    { 
     if (e_lfanew + s + NumberOfSections * sizeof(IMAGE_SECTION_HEADER) > SizeOfHeaders) 
     { 
      return 0; 
     } 

     do 
     { 
      if (Size = min(pish->Misc.VirtualSize, pish->SizeOfRawData)) 
      { 
       union { 
        ULONG VirtualAddress, PointerToRawData; 
       }; 

       VirtualAddress = pish->VirtualAddress, s = VirtualAddress + Size; 

       if (VirtualAddress > s || s > SizeOfImage) 
       { 
        return 0; 
       } 

       PointerToRawData = pish->PointerToRawData, s = PointerToRawData + Size; 

       if (PointerToRawData > s || s > cbRawData) 
       { 
        return 0; 
       } 
      } 

     } while (pish++, --NumberOfSections); 
    } 

    PVOID ImageBase = VirtualAlloc(0, SizeOfImage, MEM_COMMIT, PAGE_READWRITE); 

    if (!ImageBase) 
    { 
     return 0; 
    } 

    memcpy(ImageBase, pvRawData, SizeOfHeaders); 

    if (NumberOfSections = pinth->FileHeader.NumberOfSections) 
    { 
     do 
     { 
      --pish; 

      if (Size = min(pish->Misc.VirtualSize, pish->SizeOfRawData)) 
      { 
       memcpy(RtlOffsetToPointer(ImageBase, pish->VirtualAddress), 
        RtlOffsetToPointer(pvRawData, pish->PointerToRawData), Size); 
      } 

     } while (--NumberOfSections); 

    } 

    return ImageBase; 
} 

void Test(PVOID pvRawData, ULONG cbRawData, PCWSTR lpType, PCWSTR lpName) 
{ 
    if (HMODULE ImageBase = (HMODULE)MapImage((PIMAGE_DOS_HEADER)pvRawData, cbRawData)) 
    { 
     if (HRSRC hResInfo = FindResource(ImageBase, lpName, lpType)) 
     { 
      if (HGLOBAL hg = LoadResource(ImageBase, hResInfo)) 
      { 
       __nop(); 
      } 
     } 

     VirtualFree(ImageBase, 0, MEM_RELEASE); 
    } 
} 

包含檢查有效數據大小MapImage。但是如果你確信(pvRawData,cbRawData)是100%正確的 - 你可以跳過這一檢查和簡化代碼

//我編輯Test功能基於@IInspectable評論 - 刪除__try/__除了 - 這不是在這裏需要

+1

爲什麼'Test'函數中有SEH?沒有任何被調用函數被記錄來引發Win32異常。 – IInspectable

+0

@IInspectable - 因爲如果圖像數據不正確 - FindResource可能引發訪問衝突。但如果我們確信數據正確(我們將圖像作爲嵌入式資源,但不能從磁盤或網絡讀取) - 我們可以跳過__try/__除外。在MapImage中,我只檢查地圖的有效大小。但例如,如果'pinth-> OptionalHeader.DataDirectory [IMAGE_DIRECTORY_ENTRY_RESOURCE] .VirtualAddress'不正確? 'FindResource'中的例外 – RbMm

+0

@IInspectable - 但是你是正確的 - 現在我檢查 - FindResource內部句柄異常,所以我們可以刪除__try \ __,除了塊 – RbMm

0

您的選擇:

  1. 保存到臨時文件,負載LoadLibraryEx
  2. 解析PE文件並自己找到資源。
  3. 複製必要的操作以按照各種內存模塊庫之一的方式從內存加載模塊。