2013-11-30 2 views
9

Я анализирую различные модули, загруженные процессом. К сожалению, я не могу создать моментальный снимок памяти kernel32.dll, хотя функция работает правильно с другими модулями (например, ntddl.dll). Проблема с помощью следующего кода:VirtualProtect и kernel32.dll - попытка получить доступ к недопустимому адресу

/* Copy code from memory */ 
if (VirtualProtect((BYTE*)virtualAddress, sizeOfCode, PAGE_EXECUTE_READWRITE, &flags) == 0) { 
    std::cout << "VirtualProtect failed!" << std::endl; 
    std::cout << "Virtual address: " << virtualAddress << std::endl; 
    std::cout << "Size of code: " << sizeOfCode << std::endl; 
    std::cout << "Error code: " << GetLastError() << std::endl; 
} 

Результат вызова этого кода для kernel32.dll является:

Virtual address: 747d0000 
Size of code: 6a000 
Error code: 0x1e7 

Описание ошибки говорит, что:

ERROR_INVALID_ADDRESS 
487 (0x1E7) 
Attempt to access invalid address. 

Я проверил процесс карта памяти и адрес kernel32.dll верны. В чем причина?

+1

Это неправильный код, вы должны немедленно вызвать GetLastError(). Вызовы cout могут легко изменить значение, так как они также используют вызовы winapi. –

+0

Результат тот же самый, когда 'GetLastError()' вызывается сразу после 'VirtualProtect' –

+0

kernel32.dll является немного особенным. Было бы некорректно мешать вам вмешаться - например, чтобы предотвратить различные инъекции. –

ответ

6

Довольно сложно проверить правильность адреса, это необычно низко. Я просто написал еще одну программу, чтобы проверить это. Он перечисляет регионы в kernel32.dll и вызывает VirtualProtect() на них:

#include <Windows.h> 
#include <assert.h> 
#include <iostream> 


int main() 
{ 
    HMODULE hmod = GetModuleHandle(L"kernel32.dll"); 
    MEMORY_BASIC_INFORMATION info; 
    // Start at PE32 header 
    SIZE_T len = VirtualQuery(hmod, &info, sizeof(info)); 
    assert(len > 0); 
    BYTE* dllBase = (BYTE*)info.AllocationBase; 
    BYTE* address = dllBase; 
    for (;;) { 
     len = VirtualQuery(address, &info, sizeof(info)); 
     assert(len > 0); 
     if (info.AllocationBase != dllBase) break; 
     std::cout << "Address: " << std::hex << info.BaseAddress; 
     std::cout << " (" << std::hex << info.RegionSize << ") "; 
     std::cout << " protect = " << std::hex << info.Protect; 
     DWORD oldprotect; 
     if (info.Protect == 0) std::cout << ", VirtualProtect skipped" << std::endl; 
     else { 
      BOOL ok = VirtualProtect(info.BaseAddress, info.RegionSize, PAGE_EXECUTE_READWRITE, &oldprotect); 
      std::cout << ", VirtualProtect = " << (ok ? "okay" : "Failed!") << std::endl; 
     } 
     address = (BYTE*)info.BaseAddress + info.RegionSize; 
    } 
    return 0; 
} 

Вывод этой программы на моем компьютере, работающем под управлением Windows 8.1 x64:

Address: 77470000 (1000) protect = 2, VirtualProtect = okay 
Address: 77471000 (f000) protect = 0, VirtualProtect skipped 
Address: 77480000 (62000) protect = 20, VirtualProtect = okay 
Address: 774E2000 (e000) protect = 0, VirtualProtect skipped 
Address: 774F0000 (7e000) protect = 2, VirtualProtect = okay 
Address: 7756E000 (2000) protect = 0, VirtualProtect skipped 
Address: 77570000 (1000) protect = 4, VirtualProtect = okay 
Address: 77571000 (f000) protect = 0, VirtualProtect skipped 
Address: 77580000 (1000) protect = 2, VirtualProtect = okay 
Address: 77581000 (f000) protect = 0, VirtualProtect skipped 
Address: 77590000 (1a000) protect = 2, VirtualProtect = okay 
Address: 775AA000 (6000) protect = 0, VirtualProtect skipped 

Запуск его в 64-битном режиме :

Address: 00007FFC4F870000 (1000) protect = 2, VirtualProtect = okay 
Address: 00007FFC4F871000 (112000) protect = 20, VirtualProtect = okay 
Address: 00007FFC4F983000 (1000) protect = 4, VirtualProtect = okay 
Address: 00007FFC4F984000 (1000) protect = 8, VirtualProtect = okay 
Address: 00007FFC4F985000 (24000) protect = 2, VirtualProtect = okay 

Очевидно, что у вас есть другая версия Windows, поэтому не забудьте запустить эту программу на своем компьютере, чтобы получить сопоставимые результаты.

Вывод, который я рисую, не является основополагающей причиной отказа этого кода. И если это произойдет на вашей машине, то это, скорее всего, будет экологичным. С очень очевидным кандидатом, чтобы быть вашим программным обеспечением для защиты от вредоносных программ, которое, конечно же, имеет большую заинтересованность в предотвращении проникновения кода с kernel32.dll. Я использую минимальную защиту на своей машине.

Смежные вопросы