From: Officer Barbrady
Lol I miworded it… Lol I meant c++ lol I knew eh use java idk why i said that
Also sin what IDE is that what does it use?
Ohh.. so you're asking if you can inject into Runescape using C++?
Yes. You can. Can also inject into the JVM. An example is again, GLHook which can either be used with "SMART" or "Browsers". In order to use it in a browser, it must be injected into the Java applet that is loaded when RS loads. If you want, you can also inject into the Official RS client.
So the answer is yes, both Java & C++ can inject into RS. I believe for actually hooking the RSClient applet, its easier in Java as in C++ you'd have to read all OP codes of the JVM but I think Java has a API called "ASM" that you can download and makes it so much easier. At least, there's traces of that in Tribot so yeah.
You usually want to use C++ for the low level stuff in RS such as reading the JVM or Dx/Gl. Java is of course better for hooking RS because you can use "ASM" (Not referring to the language) and read the class fields. Again, C++ would be reading "memory" directly and Java would read
"fields" afaik.
If someone can post a nice Java example for him, that would be great.. I've added some C++ below to get you or anyone started on Inject/reverse-engineering.
Ex (NOT going to post the whole class as there's lots of
malicious code but this will certainly get you started)..
It is using Unicode:
#include <winternl.h>
#include <tchar.h>
#include <string>
#define UNICODE
#define _UNICODE
typedef struct _LDR_MODULE
{
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_MODULE, *PLDR_MODULE;
typedef struct _ProcessModuleInfo
{
std::uint32_t Size;
std::uint32_t Initialized;
HANDLE SsHandle;
LIST_ENTRY LoadOrder;
LIST_ENTRY InitOrder;
LIST_ENTRY MemoryOrder;
} ProcessModuleInfo, *pProcessModuleInfo;
typedef struct _REMOVED_MODULE
{
void* ModuleBase;
LDR_MODULE Module;
std::wstring BaseDllName;
std::wstring FullDllName;
} REMOVED_MODULE, *PREMOVED_MODULE;
#ifdef UNICODE
#define tcout std::wcout
#else
#define tcout std::cout
#endif
typedef std::basic_string<TCHAR> tstring;
typedef NTSTATUS NTAPI (*pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
class Injection
{
public:
Injection();
Injection(tstring Process, tstring File);
Injection(const Injection &I) = delete;
Injection(Injection&& I) = delete;
~Injection();
bool Inject(tstring Process, tstring File);
bool Unload(tstring Process, tstring File);
void UnlinkLocalProcessModule(LDR_MODULE* module); //Used to HIDE a module from scanners such as Wow's Warden or RS's Jaclib.
void UnlinkRemoteProcessModule(HANDLE ProcessHandle, LDR_MODULE* ModulePointer); //Same as above but out of process hooking.
void ListLocalModulesInfo();
void ListProcessModulesInfo(tstring Process);
Injection& operator = (const Injection& I) = delete;
Injection& operator = (Injection&& I) = delete;
};
PROCESSENTRY32 GetProcessInfo(const char* ProcessName)
{
void* hSnap = nullptr;
PROCESSENTRY32 Proc32 = {0};
if((hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE) return Proc32;
Proc32.dwSize = sizeof(PROCESSENTRY32);
while(Process32Next(hSnap, &Proc32))
{
if(!stricmp(ProcessName, Proc32.szExeFile))
{
CloseHandle(hSnap);
return Proc32;
}
}
CloseHandle(hSnap);
Proc32 = {0};
return Proc32;
}
bool IsProcessRunning(const TCHAR* pProcessName)
{
return (GetProcessInfo(pProcessName).th32ProcessID != 0);
}
Injection::~Injection() {}
Injection::Injection() {}
Injection::Injection(tstring Process, tstring File) {this->Inject(Process, File);}
bool Injection::Inject(tstring Process, tstring File)
{
if (IsProcessRunning(Process.c_str()))
{
HMODULE hKernel32 = nullptr;
void* RemoteAddress = nullptr;
TCHAR FilePath[MAX_PATH + 1] = {0};
HANDLE ProcessHandle, hThread = nullptr;
LPTHREAD_START_ROUTINE LoadLibraryHandle = nullptr;
PROCESSENTRY32 ProcessInfo = GetProcessInfo(Process.c_str());
_sntprintf(FilePath, MAX_PATH, File.c_str());
if ((ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, false, ProcessInfo.th32ProcessID)))
{
if (hKernel32 = GetModuleHandle(_T("Kernel32.dll")))
{
#ifndef UNICODE
LoadLibraryHandle = reinterpret_cast<LPTHREAD_START_ROUTINE>(xGetProcAddress(hKernel32, "LoadLibraryA"));
#else
LoadLibraryHandle = reinterpret_cast<LPTHREAD_START_ROUTINE>(xGetProcAddress(hKernel32, "LoadLibraryW"));
#endif
RemoteAddress = VirtualAllocEx(ProcessHandle, nullptr, File.size() * sizeof(TCHAR), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(ProcessHandle, RemoteAddress, FilePath, File.size() * sizeof(TCHAR), nullptr);
hThread = CreateRemoteThread(ProcessHandle, nullptr, 0, LoadLibraryHandle, RemoteAddress, 0, nullptr);
WaitForSingleObject(hThread, INFINITE);
VirtualFreeEx(ProcessHandle, RemoteAddress, File.size() * sizeof(TCHAR), MEM_RELEASE);
CloseHandle(ProcessHandle);
CloseHandle(hThread);
return true;
}
CloseHandle(ProcessHandle);
}
}
return false;
}
bool Injection::Unload(tstring Process, tstring File)
{
if (IsProcessRunning(Process.c_str()))
{
HMODULE hKernel32 = nullptr;
void* RemoteAddress = nullptr;
TCHAR FilePath[MAX_PATH + 1] = {0};
HANDLE ProcessHandle, hThread = nullptr;
LPTHREAD_START_ROUTINE LoadLibraryHandle = nullptr;
PrintProcessInfo(Process.c_str());
PROCESSENTRY32 ProcessInfo = GetProcessInfo(Process.c_str());
_sntprintf(FilePath, MAX_PATH, File.c_str());
if ((ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, false, ProcessInfo.th32ProcessID)))
{
if (hKernel32 = GetModuleHandle(_T("Kernel32.dll")))
{
LoadLibraryHandle = reinterpret_cast<LPTHREAD_START_ROUTINE>(xGetProcAddress(hKernel32, "FreeLibrary"));
RemoteAddress = GetModuleInfo(ProcessInfo.th32ProcessID, File).modBaseAddr;
hThread = CreateRemoteThread(ProcessHandle, nullptr, 0, LoadLibraryHandle, RemoteAddress, 0, nullptr);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(ProcessHandle);
CloseHandle(hThread);
return true;
}
CloseHandle(ProcessHandle);
}
}
return false;
}
void Injection::UnlinkLocalProcessModule(LDR_MODULE* module)
{
auto RemoveLink = [](LIST_ENTRY Link)
{
Link.Blink->Flink = Link.Flink;
Link.Flink->Blink = Link.Blink;
};
RemoveLink(module->InLoadOrderModuleList);
RemoveLink(module->InMemoryOrderModuleList);
RemoveLink(module->InInitializationOrderModuleList);
RemoveLink(module->HashTableEntry);
memset(module->BaseDllName.Buffer, 0, module->BaseDllName.Length);
memset(module->FullDllName.Buffer, 0, module->FullDllName.Length);
memset(module, 0, sizeof(LDR_MODULE));
}
void Injection::ListLocalModulesInfo()
{
/** The Offsets for the Assembly code is calculated as follows:
void* Teb = (void*)FIELD_OFFSET(NT_TIB, Self);
void* Peb = (void*)(sizeof(NT_TIB) + (3 * sizeof(void*)) + sizeof(CLIENT_ID));
int Pmi = sizeof(void*) + (2* sizeof(ULONG));
**/
ProcessModuleInfo *pmInfo = nullptr;
__asm__ volatile
(
"movl %%fs:0x18, %%eax\n\t"
"movl 0x30(%%eax), %%eax\n\t"
"movl 0x0C(%%eax), %%eax\n\t"
"movl %%eax, %0\n\t"
: "=r" (pmInfo) ::
);
LDR_MODULE* module = reinterpret_cast<LDR_MODULE*>(pmInfo->LoadOrder.Flink);
while(module->BaseAddress)
{
std::wstring BaseDllName(module->BaseDllName.Length / sizeof(WCHAR), 0);
std::wstring FullDllName(module->FullDllName.Length / sizeof(WCHAR), 0);
memcpy(&BaseDllName[0], module->BaseDllName.Buffer, module->BaseDllName.Length);
memcpy(&FullDllName[0], module->FullDllName.Buffer, module->FullDllName.Length);
tcout<<_T("BaseAddress: ")<< module->BaseAddress<<nl;
tcout<<_T("Entry-Point: ")<< module->EntryPoint<<nl;
std::wcout<<_T("Base DLL-Name: ")<< BaseDllName<<nl;
std::wcout<<_T("Full DLL-Name: ")<< FullDllName<<nl;
tcout<<_T("Reference Count: ")<< module->LoadCount<<nl;
tcout<<_T("Image Size: ")<< module->SizeOfImage<<nl;
tcout<<_T("Time Date Stamp: ")<< module->TimeDateStamp<<nl;
tcout<<nl;
module = reinterpret_cast<LDR_MODULE*>(module->InLoadOrderModuleList.Flink);
}
}
See here for the other half:
http://villavu.com/forum/showthread.php?t=100266