Skip to content

Instantly share code, notes, and snippets.

@BenjaminUrquhart
Created January 27, 2022 03:24
Show Gist options
  • Save BenjaminUrquhart/aa17b4a1370d4e3126a127af00df8ff2 to your computer and use it in GitHub Desktop.
Save BenjaminUrquhart/aa17b4a1370d4e3126a127af00df8ff2 to your computer and use it in GitHub Desktop.
Source to the GMInvoke GMS extension to comply with GPL3
#include <Windows.h>
#include <iostream>
#include <string>
#define func extern "C" __declspec(dllexport)
// Some boilerplate code
// Taken from https://github.com/Archie-osu/YYToolkit
#define TRoutine void*
#define GMI_ERROR -3
#define GMI_NOT_FOUND -4
#define ENSURE_INITIALIZED if (!EnsureInitialized()) { return GMI_ERROR; }
typedef void (*FNCodeFunctionGetTheFunction)(int id, char** bufName, void** bufRoutine, int* bufArgs, void* unused);
static FNCodeFunctionGetTheFunction GetFuncAddr = nullptr;
struct ModuleInfo_t
{
unsigned long Base;
unsigned long Size;
unsigned long EntryPoint;
};
struct FunctionInfo_t
{
int Index;
char* Name;
TRoutine Function;
int Argc;
};
ModuleInfo_t GetModuleInfo()
{
using Fn = int(__stdcall*)(HANDLE, HMODULE, ModuleInfo_t*, DWORD);
static HMODULE Module = GetModuleHandleA("kernel32.dll");
static Fn K32GetModuleInformation = (Fn)GetProcAddress(Module, "K32GetModuleInformation");
ModuleInfo_t modinfo = { 0 };
HMODULE hModule = GetModuleHandleA(NULL);
if (hModule == 0)
return modinfo;
K32GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(ModuleInfo_t));
return modinfo;
}
unsigned long FindPattern(const char* Pattern, const char* Mask, long base, unsigned size)
{
size_t PatternSize = strlen(Mask);
for (unsigned i = 0; i < size - PatternSize; i++)
{
int found = 1;
for (unsigned j = 0; j < PatternSize; j++)
{
found &= Mask[j] == '?' || Pattern[j] == *(char*)(base + i + j);
}
if (found)
return (base + i);
}
return (unsigned long)NULL;
}
bool GetFunctionByIndex(int index, FunctionInfo_t& outInfo)
{
if (index < 0)
return false;
void* pUnknown = nullptr;
GetFuncAddr(index, &outInfo.Name, (PVOID*)&outInfo.Function, &outInfo.Argc, &pUnknown);
if (!outInfo.Name)
return false;
if (!*outInfo.Name)
return false;
outInfo.Index = index;
return true;
}
bool GetFunctionByName(const char* Name, FunctionInfo_t& outInfo)
{
int Index = 0;
if (!Name)
return false;
while (GetFunctionByIndex(Index, outInfo))
{
if (outInfo.Name != nullptr && _strnicmp(Name, outInfo.Name, 64) == 0)
{
return true;
}
Index++;
}
return false;
}
bool GetCodeFunctionAddr(FNCodeFunctionGetTheFunction& outAddress)
{
ModuleInfo_t CurInfo = GetModuleInfo();
if ((outAddress = (FNCodeFunctionGetTheFunction)FindPattern("\x8B\x44\x24\x04\x3B\x05\x00\x00\x00\x00\x7F", "xxxxxx????x", CurInfo.Base, CurInfo.Size)))
return true;
return false;
}
func double EnsureInitialized() {
if (!GetFuncAddr) {
if (!GetCodeFunctionAddr(GetFuncAddr)) {
printf("[!] Failed to find GetFuncAddr\n");
std::cout.flush();
return false;
}
printf("[.] Found GetFuncAddr at %p\n", GetFuncAddr);
std::cout.flush();
}
return true;
}
func char* method_get_name(double index) {
static std::string out;
out = "";
if (EnsureInitialized()) {
FunctionInfo_t result = { 0 };
if (GetFunctionByIndex((int)index, result)) {
out = result.Name ? result.Name : "func_" + std::to_string(index);
}
}
return (char*)out.c_str();
}
func double method_get_arg_count(double index) {
ENSURE_INITIALIZED
FunctionInfo_t result = { 0 };
if (GetFunctionByIndex((int)index, result)) {
return result.Argc;
}
return GMI_NOT_FOUND;
}
func double method_by_name(char* name) {
ENSURE_INITIALIZED
FunctionInfo_t result = { 0 };
if (GetFunctionByName(name, result)) {
printf("[.] Found %s at index %d\n", name, result.Index);
std::cout.flush();
return result.Index;
}
printf("[!] Failed to find function %s\n", name);
std::cout.flush();
return GMI_NOT_FOUND;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment