AccessException:试图读取或写入 Protected/Corrupted 内存 -- 已知异常,未知原因?
AccessException: Attempted To Read Or Write Protected/Corrupted Memory -- Known Exception, Unknown Reason?
是的,我知道这个异常有上百万个线程,我可能已经查看了其中的 20-25 个,但是 none 的原因似乎与此相关,遗憾的是(因此标题,已知异常,未知原因)。
我最近对 InfoSec 产生了兴趣。作为我的第一个 learners-project,我会创建一个基本的 DLL 注入器。到目前为止似乎进展顺利,但是,这个例外让我很沮丧,经过一些相对广泛的研究后,我感到很困惑。奇怪的是,函数完全结束后,异常也出现了。
我自己无法真正弄清楚这一点,因为外部调试器无法与我的目标应用程序一起使用,这是一个全新的无关问题。
目前建议和尝试的解决方案:
- Fix/Remove线程状态检查(错误)
- 确保正在分配 DllPath ptr 后面的值,而不是 ptr
- 封送 C# 互操作参数
无论如何,这是我的代码块:
#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 构建的应用程序,也不例外。
我仍然需要修复我创建线程的方式,因为没有创建线程,但我已经弄明白了,这应该很容易。
是的,我知道这个异常有上百万个线程,我可能已经查看了其中的 20-25 个,但是 none 的原因似乎与此相关,遗憾的是(因此标题,已知异常,未知原因)。
我最近对 InfoSec 产生了兴趣。作为我的第一个 learners-project,我会创建一个基本的 DLL 注入器。到目前为止似乎进展顺利,但是,这个例外让我很沮丧,经过一些相对广泛的研究后,我感到很困惑。奇怪的是,函数完全结束后,异常也出现了。
我自己无法真正弄清楚这一点,因为外部调试器无法与我的目标应用程序一起使用,这是一个全新的无关问题。
目前建议和尝试的解决方案:
- Fix/Remove线程状态检查(错误)
- 确保正在分配 DllPath ptr 后面的值,而不是 ptr
- 封送 C# 互操作参数
无论如何,这是我的代码块:
#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 构建的应用程序,也不例外。
我仍然需要修复我创建线程的方式,因为没有创建线程,但我已经弄明白了,这应该很容易。