gpt4 book ai didi

c++ - 使用 WinAPI 检索类指针?

转载 作者:行者123 更新时间:2023-11-30 04:20:58 26 4
gpt4 key购买 nike

在任何人问之前,这里没有恶意。该项目仅供教育和个人使用,最多被设计为“ Cheat Engine ”或 future 可能的反作弊机制。无意以任何恶意方式使用它。

我有以下 3 个项目的解决方案:

  • 32 位 MFC 应用程序,允许用户选择要注入(inject)的进程
  • 32位Win32 DLL通过VirtualAlloc + WriteProcessMemory + CreateRemoteThread + LoadLibrary技术注入(inject)目标进程
  • 32 位 Win32 控制台应用程序,用于测试何时发生本地注入(inject)

在 DLL 中,我创建了以下一组函数:

////////////////
// Deceiver.h //
////////////////
#ifdef DECEIVED_EXPORTS
# define DECEIVED_API __declspec(dllexport)
#else
# define DECEIVED_API __declspec(dllimport)
#endif

volatile class DECEIVED_API CDeceived
{
public:
CDeceived(void);
virtual HANDLE WINAPI GetRunningProcess();
virtual DWORD WINAPI GetRunningProcessId();
virtual HANDLE WINAPI GetRunningThread();
virtual DWORD WINAPI GetRunningThreadId();
virtual LPVOID WINAPI Allocate(DWORD size);
virtual BOOL WINAPI Deallocate(LPVOID address, DWORD size);
virtual BOOL WINAPI Read(LPVOID address, LPVOID buffer, DWORD size);
virtual BOOL WINAPI Write(LPVOID address, LPVOID buffer, DWORD size);
virtual BOOL WINAPI ReadEx(HANDLE hProcess, LPVOID address, LPVOID buffer, DWORD size);
virtual BOOL WINAPI WriteEx(HANDLE hProcess, LPVOID address, LPVOID buffer, DWORD size);

WCHAR m_signature[10];
};

extern DECEIVED_API CDeceived* deceiver;
LPVOID DECEIVED_API WINAPI RemoteInitialize();


//////////////////
// Deceiver.cpp //
//////////////////
#include "stdafx.h"
#include "Deceived.h"

DECEIVED_API CDeceived* deceiver = NULL;

CDeceived::CDeceived()
{
memcpy(&m_signature[0], L"Deceived?\0", 10);
}

HANDLE WINAPI CDeceived::GetRunningProcess()
{
return GetCurrentProcess();
}

DWORD WINAPI CDeceived::GetRunningProcessId()
{
return GetCurrentProcessId();
}

HANDLE WINAPI CDeceived::GetRunningThread()
{
return GetCurrentThread();
}

DWORD WINAPI CDeceived::GetRunningThreadId()
{
return GetCurrentThreadId();
}

LPVOID WINAPI CDeceived::Allocate(DWORD size)
{
return VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
}

BOOL WINAPI CDeceived::Deallocate(LPVOID address, DWORD size)
{
return VirtualFree(address, size, MEM_RELEASE);
}

BOOL WINAPI CDeceived::Read(LPVOID address, LPVOID buffer, DWORD size)
{
DWORD dwBytesRead = 0;
BOOL bRet = ReadProcessMemory(GetCurrentProcess(), address, buffer, size, &dwBytesRead);
return bRet && (dwBytesRead > 0);
}

BOOL WINAPI CDeceived::Write(LPVOID address, LPVOID buffer, DWORD size)
{
DWORD dwBytesWritten = 0;
BOOL bRet = WriteProcessMemory(GetCurrentProcess(), address, buffer, size, &dwBytesWritten);
return bRet && (dwBytesWritten > 0);
}

BOOL WINAPI CDeceived::ReadEx(HANDLE hProcess, LPVOID address, LPVOID buffer, DWORD size)
{
DWORD dwBytesRead = 0;
BOOL bRet = ReadProcessMemory(hProcess, address, buffer, size, &dwBytesRead);
return bRet && (dwBytesRead > 0);
}

BOOL WINAPI CDeceived::WriteEx(HANDLE hProcess, LPVOID address, LPVOID buffer, DWORD size)
{
DWORD dwBytesWritten = 0;
BOOL bRet = WriteProcessMemory(hProcess, address, buffer, size, &dwBytesWritten);
return bRet && (dwBytesWritten > 0);
}

LPVOID DECEIVED_API WINAPI RemoteInitialize()
{
#ifdef _DEBUG
MessageBoxA(NULL, "Please attach a debugger", "Deceived::RemoteInitialize", MB_ICONINFORMATION);
#endif

if(deceiver != NULL) delete deceiver;
deceiver = new CDeceived();
LPVOID lpReturn = deceiver->Allocate(sizeof(deceiver));

if(lpReturn) {
deceiver->Write(lpReturn, &deceiver, sizeof(deceiver));
return lpReturn;
}

return NULL;
}


MFC应用程序将DLL注入(inject)Console测试项目后...

它调用 RemoteInitialize() 来初始化远程类并返回虚拟内存空间中的地址给调用者,然后它应该被本地化到 CDeceived 类。以下是我的处理方式:

BOOL CDeceiverHook::Validate(LPVOID lpDeceivedAddress)
{
CDeceived *deceiver = new CDeceived();
BOOL bRet = deceiver->ReadEx(hProcess, lpDeceivedAddress, &m_deceived, sizeof(m_deceived));
int cmp = _wcsicmp(m_deceived->m_signature, L"Deceived?");
return bRet && (cmp == 0);
}


...但是本地化类指针似乎并不指向远程类指针,而是在它的虚拟表中包含多个 NULL 指针,如果您尝试执行其中任何一个,就会导致访问冲突。

我可能应该注意到,我已经通过 OpenThreadToken、ImpersonateSelf 和 SetPrivilege 成功地为 MFC 应用程序提供了正确的调试权限。也许我还必须以某种方式将类的地址锁定在内存中吗? volatile 关键字不够用,还是用错了?我需要做什么来检索由 DLL 分配的完全相同的指针?

提前致谢!任何有效的建议都会得到赞成票。

最佳答案

每个进程在地址空间中都有一个不同的 DLL 实例,并且可能在不同的地址上,您不能简单地强制一个进程加载一个 DLL 并期望从另一个进程使用它的地址空间。

有几种方法可以将注入(inject)的 DLL 与注入(inject)器进程相互通信:

  • 共享内存:您可以使用 MapViewOfFile 在两个或多个进程之间共享内存,请注意您应该注意存储在类实例中的指针,并且虚拟成员不能工作,因为 vtable 属于另一个地址空间。

  • RPC:可以使用Win32 RPC来进行进程间的调用和共享数据,个人认为过于复杂。

  • 命名管道/Winsock:我的首选,既简单易用又可以(几乎)做任何您想做的事。

  • Microsoft Message Queue(MSMQ):不太了解,我觉得也可以用。

  • Win32 消息:您可以使用 RegisterWindowMessage 跨系统处理 Windows 消息并共享数据,仅对共享小值(两个 DWORD)有用

如您在 MSDN 上所见,还有其他执行 IPC 的方法:http://msdn.microsoft.com/en-us/library/windows/desktop/aa365574(v=vs.85).aspx

我明确建议您使用 Named Pipes/Winsock,如果是这样,您可以使用 Google Protobuf 轻松地在进程之间共享数据结构。

关于c++ - 使用 WinAPI 检索类指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14906659/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com