2016-09-08 4 views
2

У меня есть буфер памяти, который содержит действительное изображение файла exe, и я хочу извлечь из него некоторые ресурсы.
Для этого я использую функцию FindResource, но функция ожидает HMODULE и сбой при подаче буфера памяти с помощью exe.

Есть ли способ заставить его работать с буфером памяти вместо того, чтобы писать exe во временный файл, загружая его с помощью 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

Почему существует SEH в функции 'Test'? Ни одна из вызываемых функций не документирована для получения исключений Win32. – IInspectable

+0

@Inspectable - потому что, если данные изображения неверны - 'FindResource' может вызвать нарушение прав доступа. но если мы уверены, что данные верны (у нас есть изображение как внедренный ресурс, но он не читается с диска или сети), мы можем пропустить __try/__ except. в MapImage я проверяю только допустимые размеры для карты. но, например, что будет, если 'pinth-> НеобязательныйHeader.DataDirectory [IMAGE_DIRECTORY_ENTRY_RESOURCE] .VirtualAddress' некорректный? exception в 'FindResource' – RbMm

+0

@IInspectable - однако вы правы - теперь я проверяю - исключение внутреннего дескриптора FindResource, поэтому мы можем удалить __try \ __ except block – RbMm

0

Ваши варианты:

  1. Сохранить временный файл и загрузки с LoadLibraryEx.
  2. Разберите файл PE и найдите ресурс самостоятельно.
  3. Повторите необходимые действия для загрузки модуля из памяти в виде одной из библиотек модулей памяти.
Смежные вопросы