Я не могу найти память, используя функцию ReadProcessMemory () из API Win32C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Я не могу найти память, используя функцию ReadProcessMemory () из API Win32

Сообщение Anonymous »

Я пытался найти память, используя функцию ReadProcessMemory () из API Win32. Хотя это отлично работает для некоторых игр, в других поиск памяти не работает вообще из -за программы безопасности игры.
Я создаю простой макрос игры как хобби. p>
Чтобы прочитать HP, MP или координаты, я использую функцию ReadProcessMemory () < /code> из API win32. < /p>
Я успешно читаю HP , MP, и координирует в некоторых играх. Однако в определенных играх, адреса памяти вообще не найдено. < /P>
Я подозреваю, что эта проблема вызвана программой безопасности игры. Это, я попробовал несколько методов, включая: < /p>
дешифтирование /шифрование с помощью Decryptxor ()
Изменение атрибутов защиты памяти с использованием виртуальнопротекса () < /code>
Библиотека обходов
Несмотря на эти попытки, я все еще не могу сканировать память в проблемных играх.
#include
#include
#include
#include
#include
#include
#include

#include
#include // Moved after windows.h
#include
#include

#pragma comment(lib, "comctl32.lib")
#pragma comment(lib, "detours.lib")

#define ID_BUTTON_FIND_HP 101
#define ID_BUTTON_FIND_MP 102
#define ID_BUTTON_FIND_X 103
#define ID_BUTTON_FIND_Y 104
#define ID_EDIT_PID 105
#define ID_EDIT_VALUE 106
#define ID_BUTTON_SEARCH 107
#define ID_LISTVIEW 113
#define ID_EDIT_NEXT_VALUE 110
#define ID_BUTTON_NEXT 111
#define ID_TIMER 109

// 전역 변수
HWND hButtonFindHP, hButtonFindMP, hButtonFindX, hButtonFindY;
HWND hEditPID, hEditValue, hButtonSearch;
HWND hEditNextValue, hButtonNext;
HWND hListView;

DWORD targetPID = 0;
std::vector foundAddresses;
HANDLE hProcess = NULL;

// 새로운 윈도우 핸들
HWND hNewWindow = NULL;

// 메모리 캐시
std::unordered_map memoryCache;

// 스레드 풀
std::vector threadPool;
const int numThreads = std::thread::hardware_concurrency();

// XOR 암호화 키 값
BYTE xorKey = 0x5A; // 임의 값

// 함수 선언
LRESULT CALLBACK NewWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void OpenFindMeorryWindow();
void FindValueInMemory(DWORD pid, int searchValue);
void UpdateMemoryValues();
void FilterByNextValue();
void OnSearchClick();
void OnFindHPClick();
void OnFindMPClick();
void OnFindXClick();
void OnFindYClick();
void OnTimer(HWND hwnd);
void OnNextClick();

// 메모리 보호 변경 함수
BOOL ChangeMemoryProtection(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);
// XOR 복호화 함수
BYTE DecryptXOR(BYTE encryptedValue, BYTE key);

// Detours 함수 선언
BOOL(WINAPI* OriginalIsDebuggerPresent)();
BOOL WINAPI HookIsDebuggerPresent();

NTSTATUS(NTAPI* OriginalNtQueryInformationProcess)(
HANDLE hProcess,
PROCESSINFOCLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength,
PULONG ReturnLength
);
NTSTATUS NTAPI HookNtQueryInformationProcess(
HANDLE hProcess,
PROCESSINFOCLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength,
PULONG ReturnLength
);

// 스레드 풀 초기화
void InitializeThreadPool() {
for (int i = 0; i < numThreads; ++i) {
threadPool.push_back(std::thread()); // 빈 스레드 생성 (나중에 작업 할당)
}
}

// 스레드 풀 종료
void JoinThreadPool() {
for (auto& thread : threadPool) {
if (thread.joinable()) {
thread.join();
}
}
threadPool.clear();
}

// 새로운 윈도우 생성 및 관련 컨트롤 생성
void OpenFindMeorryWindow() {
if (hNewWindow == NULL) {
WNDCLASS wc = { 0 };
wc.lpfnWndProc = NewWindowProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = L"NewWindowClass";

if (!RegisterClass(&wc)) {
MessageBox(NULL, L"Window class registration failed!", L"Error", MB_OK | MB_ICONERROR);
return;
}

hNewWindow = CreateWindow(L"NewWindowClass", L"Memory Scanner", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 380, 320, NULL, NULL, wc.hInstance, NULL);

if (hNewWindow == NULL) {
MessageBox(NULL, L"Failed to create new window!", L"Error", MB_OK | MB_ICONERROR);
}
}
else {
SetForegroundWindow(hNewWindow);
}
}

// 메모리 보호 변경 함수
BOOL ChangeMemoryProtection(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect) {
return VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect, lpflOldProtect);
}

// XOR 복호화 함수
BYTE DecryptXOR(BYTE encryptedValue, BYTE key) {
return encryptedValue ^ key;
}

// 메모리 검색 함수
void FindValueInMemory(DWORD pid, int searchValue) {
if (hProcess) CloseHandle(hProcess);
hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid);
if (!hProcess) {
MessageBox(NULL, L"Failed to open process!", L"Error", MB_OK | MB_ICONERROR);
return;
}

SYSTEM_INFO si;
GetSystemInfo(&si);
BYTE* addr = (BYTE*)si.lpMinimumApplicationAddress;
BYTE* endAddr = (BYTE*)si.lpMaximumApplicationAddress;

foundAddresses.clear();
memoryCache.clear(); // 캐시 초기화

// 페이지 단위로 메모리 검색
while (addr < endAddr) {
MEMORY_BASIC_INFORMATION mbi;
if (VirtualQueryEx(hProcess, addr, &mbi, sizeof(mbi)) == 0) break;

if (mbi.State == MEM_COMMIT && (mbi.Protect & PAGE_READWRITE)) {
// 메모리 캐시 확인 및 갱신
if (memoryCache.find(addr) == memoryCache.end() || memoryCache[addr].size() != mbi.RegionSize) {
SIZE_T bytesRead;
std::vector buffer(mbi.RegionSize);
if (ReadProcessMemory(hProcess, addr, buffer.data(), mbi.RegionSize, &bytesRead)) {
memoryCache[addr] = buffer;
}
else {
// 읽기 실패 시 캐시에서 제거
memoryCache.erase(addr);
addr += mbi.RegionSize;
continue; // 다음 페이지로 이동
}
}

std::vector& buffer = memoryCache[addr];
size_t count = buffer.size() / sizeof(int);

// 검색 (SIMD, Aho-Corasick 등 적용 고려)
for (size_t i = 0; i < count; ++i) {
BYTE* valuePtr = buffer.data() + (i * sizeof(int));
int encryptedValue = *reinterpret_cast(valuePtr);
int decryptedValue = 0;

// 암호화된 값인지 확인하는 조건
// 예: 특정 비트 패턴을 확인하여 암호화된 값인지 판단
if (encryptedValue & 0x80000000) { // 예시: 상위 비트가 1이면 암호화된 값으로 간주
// XOR 복호화
for (int j = 0; j < sizeof(int); ++j) {
*((BYTE*)&decryptedValue + j) = DecryptXOR(*(valuePtr + j), xorKey);
}
}
else {
decryptedValue = encryptedValue; // 암호화되지 않은 값 그대로 사용
}

if (decryptedValue == searchValue) {
foundAddresses.push_back({ addr + (i * sizeof(int)), decryptedValue });
}
}
}
addr += mbi.RegionSize;
}
}

// ListView 항목 업데이트
void UpdateMemoryValues() {
if (!hProcess || foundAddresses.empty()) return;

ListView_DeleteAllItems(hListView);

for (auto& entry : foundAddresses) {
int currentValue = 0;
SIZE_T bytesRead;
if (ReadProcessMemory(hProcess, entry.first, &currentValue, sizeof(int), &bytesRead)) {
// 암호화 여부 확인 및 복호화
// 예시: 암호화된 값이 상위 비트가 1인 경우 복호화
if (currentValue & 0x80000000) { // 상위 비트가 1인 경우 복호화
currentValue = DecryptXOR((BYTE)currentValue, xorKey);
}
entry.second = currentValue;
wchar_t addressStr[64], valueStr[64];
swprintf(addressStr, sizeof(addressStr) / sizeof(wchar_t), L"0x%p", entry.first);
swprintf(valueStr, sizeof(valueStr) / sizeof(wchar_t), L"%d", currentValue);

LVITEM lvItem;
lvItem.mask = LVIF_TEXT;
lvItem.iItem = ListView_GetItemCount(hListView);
lvItem.iSubItem = 0;
lvItem.pszText = addressStr;
ListView_InsertItem(hListView, &lvItem);

lvItem.iSubItem = 1;
lvItem.pszText = valueStr;
ListView_SetItem(hListView, &lvItem);
}
}
}

// 다음 부분: 값으로 필터링

void FilterByNextValue() {
wchar_t nextValueStr[16];
GetWindowText(hEditNextValue, nextValueStr, sizeof(nextValueStr) / sizeof(wchar_t));

int nextValue = _wtoi(nextValueStr);
if (nextValue == 0) {
MessageBox(NULL, L"Invalid next value!", L"Error", MB_OK | MB_ICONERROR);
return;
}

std::vector filteredAddresses;

for (auto& entry : foundAddresses) {
if (entry.second == nextValue) {
filteredAddresses.push_back(entry);
}
}

foundAddresses = filteredAddresses;

// 타이머 설정: 1초마다 메모리 값 업데이트
SetTimer(hNewWindow, ID_TIMER, 1000, NULL);
}

// 검색 버튼 클릭 시 이벤트 처리
void OnSearchClick() {
wchar_t pidStr[16], valueStr[16];
GetWindowText(hEditPID, pidStr, sizeof(pidStr) / sizeof(wchar_t));
GetWindowText(hEditValue, valueStr, sizeof(valueStr) / sizeof(wchar_t));

DWORD pid = _wtoi(pidStr);
int searchValue = _wtoi(valueStr);

if (pid == 0 || searchValue == 0) {
MessageBox(NULL, L"Invalid PID or Value!", L"Error", MB_OK | MB_ICONERROR);
return;
}

targetPID = pid;
FindValueInMemory(pid, searchValue);

// 타이머 설정 제거: 실시간 업데이트 없음
UpdateMemoryValues(); // 검색 후 결과 바로 표시
}

// Find HP 버튼 클릭 시 이벤트 처리
void OnFindHPClick() {
OpenFindMeorryWindow();
}

// Find MP 버튼 클릭 시 이벤트 처리
void OnFindMPClick() {
OpenFindMeorryWindow();
}

// Find X 버튼 클릭 시 이벤트 처리
void OnFindXClick() {
OpenFindMeorryWindow();
}

// Find Y 버튼 클릭 시 이벤트 처리
void OnFindYClick() {
OpenFindMeorryWindow();
}

// WM_TIMER 메시지 처리
void OnTimer(HWND hwnd) {
UpdateMemoryValues();
}

// Next 버튼 클릭 시 이벤트 처리
void OnNextClick() {
// 메모리 보호 해제
DWORD oldProtect;
for (auto& entry : foundAddresses) {
ChangeMemoryProtection(entry.first, sizeof(int), PAGE_READWRITE, &oldProtect);
}

// 먼저 메모리 값을 업데이트한 후 필터링
UpdateMemoryValues();
FilterByNextValue();
}

// 새로운 윈도우 프로시저
LRESULT CALLBACK NewWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
static wchar_t colText1[] = L"Memory Address";
static wchar_t colText2[] = L"Value";

switch (msg) {
case WM_CREATE:
// 컨트롤 생성
hEditPID = CreateWindow(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER,
20, 20, 100, 20, hwnd, (HMENU)ID_EDIT_PID, NULL, NULL);
hEditValue = CreateWindow(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER,
140, 20, 100, 20, hwnd, (HMENU)ID_EDIT_VALUE, NULL, NULL);
hButtonSearch = CreateWindow(L"BUTTON", L"Search", WS_CHILD | WS_VISIBLE,
260, 20, 80, 25, hwnd, (HMENU)ID_BUTTON_SEARCH, NULL, NULL);
hEditNextValue = CreateWindow(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER,
20, 230, 100, 20, hwnd, (HMENU)ID_EDIT_NEXT_VALUE, NULL, NULL);
hButtonNext = CreateWindow(L"BUTTON", L"Next", WS_CHILD | WS_VISIBLE,
140, 230, 80, 25, hwnd, (HMENU)ID_BUTTON_NEXT, NULL, NULL);

// ListView 초기화 및 컬럼 추가
InitCommonControls();
hListView = CreateWindow(WC_LISTVIEW, L"", WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | WS_BORDER | WS_VSCROLL,
20, 60, 320, 160, hwnd, (HMENU)ID_LISTVIEW, NULL, NULL);

LVCOLUMN lvCol;
lvCol.mask = LVCF_TEXT | LVCF_WIDTH;
lvCol.cx = 160;

lvCol.pszText = colText1;
ListView_InsertColumn(hListView, 0, &lvCol);

lvCol.pszText = colText2;
ListView_InsertColumn(hListView, 1, &lvCol);
break;

case WM_COMMAND:
if (LOWORD(wParam) == ID_BUTTON_SEARCH) {
OnSearchClick();
}
else if (LOWORD(wParam) == ID_BUTTON_NEXT) {
OnNextClick();
}
break;

case WM_NOTIFY:
if (((LPNMHDR)lParam)->hwndFrom == hListView) {
LPNMHDR pnmh = (LPNMHDR)lParam;
if (pnmh->code == NM_CLICK) {
LPNMLISTVIEW pnmListView = (LPNMLISTVIEW)lParam;

if (pnmListView->iItem != -1) {
wchar_t addressStr[64];
wchar_t valueStr[64];

LVITEM lvItem;
lvItem.mask = LVIF_TEXT;
lvItem.iItem = pnmListView->iItem;

lvItem.iSubItem = 0;
lvItem.pszText = addressStr;
lvItem.cchTextMax = sizeof(addressStr) / sizeof(wchar_t);
ListView_GetItem(hListView, &lvItem);

lvItem.iSubItem = 1;
lvItem.pszText = valueStr;
lvItem.cchTextMax = sizeof(valueStr) / sizeof(wchar_t);
ListView_GetItem(hListView, &lvItem);
}
}
}
break;

case WM_TIMER:
OnTimer(hwnd);
break;

case WM_DESTROY:
if (hProcess) CloseHandle(hProcess);
PostQuitMessage(0);
break;

default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}

// 메인 윈도우 프로시저
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE:
// 컨트롤 생성 (레이블 및 버튼)
CreateWindow(L"STATIC", L"HP:", WS_CHILD | WS_VISIBLE, 20, 20, 40, 20, hwnd, NULL, NULL, NULL);
CreateWindow(L"STATIC", L"MP:", WS_CHILD | WS_VISIBLE, 20, 60, 40, 20, hwnd, NULL, NULL, NULL); // 수정: 100 삭제
CreateWindow(L"STATIC", L"X:", WS_CHILD | WS_VISIBLE, 20, 100, 30, 20, hwnd, NULL, NULL, NULL);
hButtonFindX = CreateWindow(L"BUTTON", L"Find X", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 60, 100, 120, 30, hwnd, (HMENU)ID_BUTTON_FIND_X, NULL, NULL);
CreateWindow(L"STATIC", L"Y:", WS_CHILD | WS_VISIBLE, 200, 100, 30, 20, hwnd, NULL, NULL, NULL);
hButtonFindY = CreateWindow(L"BUTTON", L"Find Y", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 240, 100, 120, 30, hwnd, (HMENU)ID_BUTTON_FIND_Y, NULL, NULL);

hButtonFindHP = CreateWindow(L"BUTTON", L"Find HP", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 100, 20, 120, 30, hwnd, (HMENU)ID_BUTTON_FIND_HP, NULL, NULL);
hButtonFindMP = CreateWindow(L"BUTTON", L"Find MP", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 100, 60, 120, 30, hwnd, (HMENU)ID_BUTTON_FIND_MP, NULL, NULL);
break;

case WM_COMMAND:
if (LOWORD(wParam) == ID_BUTTON_FIND_HP) {
OnFindHPClick();
}
else if (LOWORD(wParam) == ID_BUTTON_FIND_MP) {
OnFindMPClick();
}
else if (LOWORD(wParam) == ID_BUTTON_FIND_X) {
OnFindXClick();
}
else if (LOWORD(wParam) == ID_BUTTON_FIND_Y) {
OnFindYClick();
}
break;

case WM_DESTROY:
PostQuitMessage(0);
break;

default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}

// 메인 함수
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
// Detours 초기화
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());

// IsDebuggerPresent 후킹
OriginalIsDebuggerPresent = IsDebuggerPresent;
DetourAttach(&OriginalIsDebuggerPresent, HookIsDebuggerPresent);

// NtQueryInformationProcess 후킹
OriginalNtQueryInformationProcess = NtQueryInformationProcess;
DetourAttach(&OriginalNtQueryInformationProcess, HookNtQueryInformationProcess);

// Detours 트랜잭션 종료
DetourTransactionCommit();

WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.lpszClassName = L"MemoryT2Class";

if (!RegisterClass(&wc)) return 0;

HWND hwnd = CreateWindow(L"MemoryT2Class", L"MemoryT2 - Memory Manager", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 380, 220, NULL, NULL, hInstance, NULL);

MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return (int)msg.wParam;
}

// IsDebuggerPresent 후킹 함수
BOOL WINAPI HookIsDebuggerPresent() {
// 디버깅 중이 아님을 반환
return FALSE;
}

// NtQueryInformationProcess 후킹 함수 (수정됨)
NTSTATUS NTAPI HookNtQueryInformationProcess(
HANDLE hProcess,
PROCESSINFOCLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength,
PULONG ReturnLength
) {
NTSTATUS status = OriginalNtQueryInformationProcess(
hProcess,
ProcessInformationClass,
ProcessInformation,
ProcessInformationLength,
ReturnLength
);

// ProcessDebugPort만 확인 (유효한 멤버)
if (ProcessInformationClass == ProcessDebugPort) {
memset(ProcessInformation, 0, ProcessInformationLength);
}

return status;
}


Подробнее здесь: https://stackoverflow.com/questions/794 ... om-the-win
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»