9

プロセスによってロードされたさまざまなモジュールを分析しています。残念ながら、kernel32.dllメモリ スナップショットを作成することはできませんが、関数は他のモジュール (たとえばntddl.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 アドレスが正しいことがわかりました。原因は何ですか?

4

1 に答える 1

6

Pretty hard to verify that you got the address correct, it is unusually low. I just wrote another program to test this. It enumerates the regions in kernel32.dll and calls VirtualProtect() on them:

#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;
}

Output of this program on my machine, running 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

Running it in 64-bit mode:

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

Clearly you have a different Windows version so be sure to run this program on your machine to get comparable results.

The conclusion I draw is there is no fundamental reason for this kind of code to fail. And if it does on your machine then that's likely to be environmental. With a very obvious candidate to be your anti-malware software, which of course has a great stake in preventing code from messing with kernel32.dll. I'm running minimal protection on my machine.

于 2013-12-03T11:41:58.093 に答える