AccessException:试图读取或写入 Protected/Corrupted 内存 -- 已知异常,未知原因?

AccessException: Attempted To Read Or Write Protected/Corrupted Memory -- Known Exception, Unknown Reason?

是的,我知道这个异常有上百万个线程,我可能已经查看了其中的 20-25 个,但是 none 的原因似乎与此相关,遗憾的是(因此标题,已知异常,未知原因)。

我最近对 ​​InfoSec 产生了兴趣。作为我的第一个 learners-project,我会创建一个基本的 DLL 注入器。到目前为止似乎进展顺利,但是,这个例外让我很沮丧,经过一些相对广泛的研究后,我感到很困惑。奇怪的是,函数完全结束后,异常也出现了。

我自己无法真正弄清楚这一点,因为外部调试器无法与我的目标应用程序一起使用,这是一个全新的无关问题。

目前建议和尝试的解决方案:

无论如何,这是我的代码块:

#pragma once

#include "pch.h"
#include "injection.h" // only specifies UserInject as an exportable proto. 

DWORD __stdcall UserInject(DWORD ProcessId, PCSTR DllPath, BOOL UseExtended) {
    DWORD length;
    CHAR* buffer;
    LPVOID memry;
    SIZE_T write;
    HANDLE hProc;
    HMODULE kr32;
    HANDLE thread;

    length = GetFullPathName(
        DllPath,
        NULL,
        NULL,
        NULL
    );
    AssertNonNull(length, INVALID_PATH);

    kr32 = GetModuleHandle("kernel32.dll");
    AssertNonNull(kr32, YOUREALLYMESSEDUP);

    buffer = new CHAR[length];

    GetFullPathName(
        DllPath,
        length,
        buffer,
        NULL
    );
    AssertNonNull(buffer, ERR_DEAD_BUFFER);

    hProc = OpenProcess(
        ADMIN,
        FALSE,
        ProcessId
    );
    AssertNonNull(hProc, INVALID_PROCID);

    memry = VirtualAllocEx(
        hProc,
        nullptr,
        sizeof buffer,
        SHELLCODE_ALLOCATION,
        PAGE_EXECUTE_READWRITE
    );
    AssertNonNull(memry, INVALID_BUFSIZE);

    WriteProcessMemory(
        hProc,
        memry,
        DllPath,
        sizeof DllPath,
        &write
    );
    AssertNonNull(write, ERR_SOLID_BUFFER);

    auto decidePrototype = [](BOOL UseExtended, HMODULE kr32) -> decltype(auto) {
        LPVOID procAddress; 

        if (!UseExtended) {
            procAddress = (LPVOID)GetProcAddress(kr32, LOADLIB_ORD);
        }
        else {
            procAddress = (LPVOID)GetProcAddress(kr32, LOADLIBX_ORD);
        };

        return (LPTHREAD_START_ROUTINE)procAddress;
    };

    auto loadLibraryAddress = decidePrototype(UseExtended, kr32);

    thread = CreateRemoteThread(
        hProc,
        NULL,
        NULL,
        loadLibraryAddress,
        memry,
        NULL,
        NULL
    );
    AssertNonNull(thread, INVALID_ROUTINE);

    WaitForSingleObject(thread, INFINITE);

    // The status stuff is quite weird; it was an attempt at debugging. The error occurs with or without this code.
    // I left it because 50% of the comments below wouldn't make sense. Just be assured this code is positively *not* the problem (sadly). 
    // LPDWORD status = (LPDWORD)1;
    // GetExitCodeThread(thread, status);

    return TRUE // *status;
}

一个晦涩的宏是“ADMIN”,它扩展为“PROCESS_ALL_ACCESS”,为了更好地适应而缩短。另一个是“AssertNonNull”:

#define AssertNonNull(o, p)      if (o == NULL) return p;

我试过调试这段代码,但它不会在任何特定点停止。除了完整性检查之外,我还对每个操作(例如分配、写入)进行了 MessageBox 测试,但没有得到任何有趣的响应。

很抱歉,我真的不能添加太多详细信息,但我真的 stone-walled 在这里,不知道该做什么,要获取什么信息,或者是否有什么要获取的。简而言之,我只是不确定要寻找什么。

这也是从 C# 调用的,1% 伪代码。

[DllImport(path, CallingConvention = CallingConvention.StdCall)]
static extern int UserInject(uint ProcId, string DllPath, bool UseExtended);

uint validProcId;    // integrity tested 
string validDllPath; // integrity tested

UserInject(validProcId, validDllPath, true);

如果您对我的测试应用程序感兴趣(用于复制)

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

static const std::string toPrint = "Hello, World!\n";

int main() 
{
    while (true) 
    {
        Sleep(1000);

        std::cout << toPrint;
    }
}

令我惊讶的是,与测试应用程序相比,这并不是代码的问题。

我使用的基本注入技术被各种漏洞利用保护和安全缓解措施阻止了 Visual Studio 2010+ 适用于任何以发布模式构建的应用程序。

如果我在调试模式下构建我的测试应用程序,没有例外。如果我使用非 VS 构建的应用程序,也不例外。

我仍然需要修复我创建线程的方式,因为没有创建线程,但我已经弄明白了,这应该很容易。