我有一個內存緩衝區,它包含一個有效的exe文件圖像,我想從中提取一些資源。
爲此,我使用的是FindResource
函數,但函數需要一個HMODULE並在提供一個帶有exe的內存緩衝區時崩潰。
有沒有辦法使它與內存緩衝區一起工作,而不是將exe寫入tempomary文件,使用LoadLibrary
加載它,然後完成所需的工作?使用FindResource和內存緩衝區
回答
以何種形式我有一個包含一個有效的文件圖像
內存緩衝區?我想比在原始(如在磁盤上)。但是你需要'映射爲圖像'內存來使用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/__除了 - 這不是在這裏需要
爲什麼'Test'函數中有SEH?沒有任何被調用函數被記錄來引發Win32異常。 – IInspectable
@IInspectable - 因爲如果圖像數據不正確 - FindResource可能引發訪問衝突。但如果我們確信數據正確(我們將圖像作爲嵌入式資源,但不能從磁盤或網絡讀取) - 我們可以跳過__try/__除外。在MapImage中,我只檢查地圖的有效大小。但例如,如果'pinth-> OptionalHeader.DataDirectory [IMAGE_DIRECTORY_ENTRY_RESOURCE] .VirtualAddress'不正確? 'FindResource'中的例外 – RbMm
@IInspectable - 但是你是正確的 - 現在我檢查 - FindResource內部句柄異常,所以我們可以刪除__try \ __,除了塊 – RbMm
您的選擇:
- 保存到臨時文件,負載
LoadLibraryEx
。 - 解析PE文件並自己找到資源。
- 複製必要的操作以按照各種內存模塊庫之一的方式從內存加載模塊。
- 1. GStreamer內存緩衝區的使用
- 2. 緩衝區內存分配
- 3. 比較內存緩衝區
- 4. 內存緩衝區和IO操作
- 5. 內存池和緩衝區C++
- 6. C++雙緩衝區和內存
- 7. 緩衝區和緩存區別?
- 8. SQL Server緩衝區緩存內容
- 9. MPI內部緩衝區內存問題
- 10. pread/pwrite,緩衝區和磁盤緩存
- 11. 估計PostgreSQL緩衝區緩存中有多少內存可用?
- 12. 限制緩衝區緩存
- 13. 發送緩衝區和接收緩衝區的使用和區別(txb&rxb)
- 14. 將ID3D11Texture2D轉換爲內存緩衝區
- 15. C緩衝區內存分配
- 16. nodejs內存緩衝區同步.pipe()
- 17. SimpleFramework:OutOfMemoryError:直接緩衝區內存
- 18. 在緩衝區中存儲內容
- 19. fread後訪問內存緩衝區()
- 20. 來自內存緩衝區的CreateProcess
- 21. 獲取與c + +的內存緩衝區
- 22. 緩衝區NULL!:無法分配內存
- 23. DataOutputStream內部保存整個緩衝區?
- 24. OpenCL - 緩衝區和全局內存之間的區別
- 25. 使用setvbuf使內存緩衝區行爲像FILE *
- 26. BufferedWriter緩衝區大小和佔用內存
- 27. Pyopencl:to_device和緩衝區
- 28. AVAudioPCMBuffer - 讀取(進入緩衝區:AVAudioPCMBuffer)內存崩潰? (緩衝區溢出)
- 29. 用臨時緩衝區使用ofstream寫入臨時緩衝區
- 30. 使用minizip從內存緩衝區打開文件
您可以解析PE格式並自己查找資源。 –
現在,這是沒有記錄的,你不應該這樣做,但是如果你的內存塊是DWORD對齊的(因爲它應該),你應該能夠得到一個有效的資源專用'HMODULE'只需採取的起始地址和將其低位設置爲1. –