VirtualProtect 中的最后一个参数是做什么用的?

What is the last parameter in VirtualProtect used for?

我想同时使用 VirtualAllocVirtualProtect 将 shellcode 注入本地进程,但我不知道最后一个参数是什么 (lpflOldProtect) 以及如何我要申报吗

void fun()
{
    size_t dwSize = 511; // size of shellcode 
    LPVOID base_add = VirtualAlloc(NULL , dwSize , MEM_RESERVE, PAGE_NOACCESS); 
    if (base_add == NULL )
    {
        cout << "Failed to allocate space " << endl;
        return ;
    }

    LPVOID end_add = base_add + dwSize; 
    // change mem protection option
    PDWORD lpflOldProtect = 0;
    bool change_protection = VirtualProtect(base_add,dwSize,PAGE_EXECUTE_READWRITE, lpflOldProtect );
    if (change_protection)
    {
        cout << "Successfully changed protection" << endl;
    }
    else
    {
        cout << " Failed" << endl;
    }
}

根据 Microsoft documentationVirtualProtect 中的最后一个参数是:

A pointer to a variable that receives the previous access protection value of the first page in the specified region of pages. If this parameter is NULL or does not point to a valid variable, the function fails.

这是什么意思?指定区域首页的值是多少?那不是基地址吗?

VirtualProtect 函数的第四个(最后一个)参数应该是 DWORD 变量的地址,在该变量中接收内存块的先前保护标志的值(或者,确切地说,是该块的第一页)。如果您愿意,可以在完成需要更改该保护的任何操作后将其用于 'reset' 该保护级别。

在您的代码中,您在 PDWORD lpflOldProtect = 0; 行中声明了一个指针并为该指针分配了一个 NULL(零)值 – 因此,根据您链接的文档,您对 VirtualProtect 会失败。

相反,您应该声明一个 actual DWORD 变量并将该变量的地址作为最后一个参数传递。在您的情况下,修改后的代码将如下所示:

DWORD flOldProtect = 0;
BOOL change_protection = VirtualProtect(base_add, dwSize, PAGE_EXECUTE_READWRITE, &flOldProtect);
                                            // Pass address of the DWORD variable ^
if (change_protection)
{
    //...

请注意,在链接文档中,最后一个参数被标记为 [out] – 这意味着它在调用之前的值未被函数使用,因此您实际上不需要对其进行初始化;然而,一些编译器 and/or 代码分析器 可能 抱怨使用未初始化的值,这就是我将其设置为零的原因。

另请注意,函数的 return 值是 BOOL 类型(在 Windows 系统头文件中声明为 typedef int BOOL;),而不是 bool;在大多数情况下,您的代码进行的隐式转换不会导致任何问题,但同样,某些编译器可能会发出有关该转换的警告。