SRL Archive - Research & Development Lounge

Memory


n3ss3s

2013-01-19 19:57:17

For some things in RS you can efficiently use memory scanning instead of OCR, in some cases it might be more or less stable since things get awkwardly cached etc

Made this to copy the name of the person I'm trading on double-click, look at FindName for the relevant stuff. The idea behind this is finding the address of "Trading With: " and then reading at that loc + 14 to get the name.

(Note: probably full of bad practices etc)


#include "stdafx.h"
#include "NameGrabber.h"
#include <iostream>
#include <Windows.h>
#include <string>
#include <TlHelp32.h>
#include <conio.h>
#include <io.h>
#include <fcntl.h>
#include <fstream>
#include <sstream>

wchar_t procName[80];

DWORD timeout = 0;

int count = 0;

HHOOK hMouseHook;

HINSTANCE hInst;

BOOL busy = FALSE;

HANDLE GetProcessByName(PCWSTR name)
{
DWORD pid = 0;
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 process;
ZeroMemory(&process, sizeof(process));
process.dwSize = sizeof(process);
if (Process32First(snapshot, &process))
{
while(Process32Next(snapshot, &process))
{
if (_wcsicmp(process.szExeFile, name) == 0)
{
pid = process.th32ProcessID;
break;
}
}
}
CloseHandle(snapshot);
if (pid != 0)
return OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
return NULL;
}

BOOL EnableTokenPrivilege (LPTSTR privilege)
{
HANDLE hToken;
TOKEN_PRIVILEGES token_privileges;
DWORD dwSize;
ZeroMemory (&token_privileges, sizeof (token_privileges));
token_privileges.PrivilegeCount = 1;
if ( !OpenProcessToken (GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
return FALSE;
if (!LookupPrivilegeValue ( NULL, privilege, &token_privileges.Privileges[0].Luid))
{
CloseHandle (hToken);
return FALSE;
}
token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges ( hToken, FALSE, &token_privileges, 0, NULL, &dwSize))
{
CloseHandle (hToken);
return FALSE;
}
CloseHandle (hToken);
return TRUE;
}

// Fuck you and your faster implementations
int FindOffset(BYTE* buffer, DWORD length, BYTE* query, DWORD qlength)
{
int i = 0;
int s;
while ((i + qlength) < (length + 1))
{
s = 0;
for (int a = 0; a < qlength; a++)
{
if (buffer[i+a] == query[a])
s++;
}
if (s == qlength)
return i;
i++;
}
return -1;
}

// I just assumed that there'd be a need for this since
// I'm copying a block of 12 bytes from the memory,
// and if the name is less than 12 chars then the
// rest will probably be gibberish (also needs to be 0 terminated so)
char* TrimGibberish(char* c, DWORD len)
{
char* t = new char[len];
int z = 0;
for (int i = 0; i < len; i++)
if (isalnum((int)c[i]) || c[i] == ' ')
{
t[i] = c[i];
z++;
}
else
break;
char* r = new char[z+1];
memcpy(r, t, z);
r[z] = 0;
return r;
}

VOID SetClipboard(char* text, DWORD len)
{
if(OpenClipboard(NULL))
{
EmptyClipboard();
HGLOBAL clipbuffer;
char * buffer;
EmptyClipboard();
clipbuffer = GlobalAlloc(GMEM_DDESHARE, len + 1);
buffer = (char*)GlobalLock(clipbuffer);
strcpy(buffer, LPCSTR(text));
GlobalUnlock(clipbuffer);
SetClipboardData(CF_TEXT,clipbuffer);
CloseClipboard();
}
}

VOID FindName(char* c, DWORD len)
{
busy = TRUE;
std::cout << "FINDING \"" << c << "\"" << std::endl << std::endl;
MEMORY_BASIC_INFORMATION MemInfo;
LPVOID m_address = 0;
HANDLE hProcess = GetProcessByName(procName);
std::cout << "-- " << hProcess << std::endl;
while(VirtualQueryEx(hProcess, m_address, &MemInfo, sizeof(MemInfo) ) )
{
DWORD unusable = PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
if (MemInfo.State & MEM_COMMIT && MemInfo.Protect & unusable)
{
BYTE* buffer = new BYTE[MemInfo.RegionSize];
SIZE_T size;
ReadProcessMemory(hProcess, MemInfo.BaseAddress, buffer, MemInfo.RegionSize, &size);
int i = FindOffset(buffer, (DWORD)MemInfo.RegionSize, (BYTE*)c, len);
if (i >= 0)
{
BYTE* b = new BYTE[12];
ReadProcessMemory(hProcess, (LPVOID)((long)MemInfo.BaseAddress + i + 14), b, 12, NULL);
char* x = TrimGibberish((char*)b, 12);
if (strcmp(x, "Unknown") != 0)
{
std::cout << "FOUND TEXT AT " << std::hex << std::uppercase << ((long)MemInfo.BaseAddress + i) << std::endl << std::endl;
std::cout << "READING NAME FROM " << std::hex << std::uppercase << ((long)MemInfo.BaseAddress + i + 14) << std::endl << std::endl;
std::cout << "ADDED "<< x << " TO CLIPBOARD"<< std::endl;
std::cout << "------------------------------" << std::endl;
SetClipboard(x, strlen(x));
CloseHandle(hProcess);
busy = FALSE;
delete[] buffer;
return;
}
}
delete[] buffer;
}
m_address = reinterpret_cast<LPVOID>((unsigned long)MemInfo.BaseAddress + MemInfo.RegionSize);
}
std::cout << "COULD NOT FIND NAME" << std::endl << std::endl;
if (hProcess)
CloseHandle(hProcess);
busy = FALSE;
}

DWORD WINAPI Find(LPVOID args)
{
FindName("Trading With", 12);
return 0;
}

BOOL Scape()
{
char title[100];
GetWindowTextA(GetForegroundWindow(), title, 100);
return FindOffset((BYTE*)title, 100, (BYTE*)"RuneScape", 9) == 0;
}

LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
MOUSEHOOKSTRUCT * pMouseStruct = (MOUSEHOOKSTRUCT*)lParam;
if (pMouseStruct != NULL)
{
if(wParam == WM_LBUTTONDOWN)
{
count++;
DWORD old = timeout;
timeout = GetTickCount();
if (GetTickCount() - old < 400 && count >= 2 && Scape() && !busy)
{
DWORD threadId;
CreateThread(NULL, 0, Find, NULL, 0, &threadId);
}
}
}
return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
}

void keepAlive()
{
MSG message;
while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
}

// Credits to somebody on the interweb
void RedirectIOToConsole()
{
int hConHandle;
long lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
AllocConsole();

GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&coninfo);
coninfo.dwSize.Y = 100;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);

lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

fp = _fdopen( hConHandle, "w" );
*stdout = *fp;
setvbuf( stdout, NULL, _IONBF, 0 );

lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

fp = _fdopen( hConHandle, "r" );
*stdin = *fp;
setvbuf( stdin, NULL, _IONBF, 0 );

lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

fp = _fdopen( hConHandle, "w" );
*stderr = *fp;
setvbuf( stderr, NULL, _IONBF, 0 );

std::ios::sync_with_stdio();
}

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
RedirectIOToConsole();
EnableTokenPrivilege(SE_DEBUG_NAME);
std::cout << "Process name? (java.exe or jagexlauncher.exe)" << std::endl;
std::cout << "--";
std::wcin >> procName;
std::cout << "-- Using " << procName << std::endl;
std::cout << "-- Double-click anywhere to grab name..." << std::endl;
hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, hInstance, 0);
keepAlive();
UnhookWindowsHookEx(hMouseHook);
return 0;
}



Kevin

2013-02-04 13:10:09

This is written in C++ with DirectX (based off the word Hook and nothing else), correct?

Would this be capable of grabbing memory locations for values other than readable text? Since this is cached memory, would that mean this could be an efficient replacement for inventory/bank/ground item checking of previously seen items, or would it be capable of determining items that had not yet been recently viewed?

I apologize if I'm asking dumb questions here, I simply know nothing about hooking and what advantages it could bring us.

Although, this does look like great work! +1

n3ss3s

2013-02-09 01:37:11

From: nivek1989
This is written in C++ with DirectX (based off the word Hook and nothing else), correct?

Would this be capable of grabbing memory locations for values other than readable text? Since this is cached memory, would that mean this could be an efficient replacement for inventory/bank/ground item checking of previously seen items, or would it be capable of determining items that had not yet been recently viewed?

I apologize if I'm asking dumb questions here, I simply know nothing about hooking and what advantages it could bring us.

Although, this does look like great work! +1


No DirectX involved.

Not sure about other uses, reading text with it is feasible because you know atleast part of the text which'll give you an offset.

Echo_

2013-02-09 03:44:42

From: nivek1989
This is written in C++ with DirectX (based off the word Hook and nothing else), correct?


Nothing to do with graphics, it uses the Windows API to scan memory.

This is pretty cool, also @CynicRus was writing a plugin to bring memory scanning capabilities to Simba if you want to take a look:
http://villavu.com/forum/showthread.php?t=87444

DannyRS

2013-02-09 04:49:29

From: Echo_
Nothing to do with graphics, it uses the Windows API to scan memory.

This is pretty cool, also @CynicRus was writing a plugin to bring memory scanning capabilities to Simba if you want to take a look:
http://villavu.com/forum/newreply.php?do=postreply&t=95389


That links back here in reply mode :( just me?

Echo_

2013-02-09 13:24:16

From: DannyRS
That links back here in reply mode :( just me?


Sorry, fixed it