Skip to content

Instantly share code, notes, and snippets.

@bburky
Created August 16, 2021 04:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bburky/9abb40556bba56e745a5e78e47797733 to your computer and use it in GitHub Desktop.
Save bburky/9abb40556bba56e745a5e78e47797733 to your computer and use it in GitHub Desktop.
Inject Steam GameOverlayRenderer DLL into a game with Frida
// Inject Steam GameOverlayRenderer DLL into a game
//
// Inspired by https://gist.github.com/Andon13/d439d5334d8173e5b959f383f1c49b03
//
// Must be run during process initialization, cannot be run after the game is
// started.
//
// GameOverlayRenderer will use an appid from the SteamGameId environment
// variable. This is injected too. GameOverlayRenderer does not support
// steam_appid.txt, but this script will parse the file to discover the appid.
//
// Usage:
// cd the\game\directory
// frida -f "game.exe" -l C:\somewhere\GameOverlayRenderer.js --no-pause
function getSteamPath() {
const HKEY_LOCAL_MACHINE = ptr("0x80000002");
const ERROR_SUCCESS = 0;
const RRF_RT_REG_SZ = 0x00000002;
const reg_subkey_32 = Memory.allocUtf8String("Software\\Valve\\Steam");
const reg_subkey_64 = Memory.allocUtf8String("SOFTWARE\\WOW6432Node\\Valve\\Steam");
const reg_value = Memory.allocUtf8String("InstallPath");
const reg_data = Memory.alloc(255);
const reg_data_size = Memory.alloc(4);
reg_data_size.writeInt(255);
const RegGetValueA_ptr = Module.findExportByName("Advapi32.dll", "RegGetValueA");
const RegGetValueA = new NativeFunction(RegGetValueA_ptr, "int32", ["pointer", "pointer", "pointer", "uint32", "pointer", "pointer", "pointer"]);
if (ERROR_SUCCESS == RegGetValueA(HKEY_LOCAL_MACHINE, reg_subkey_32, reg_value, RRF_RT_REG_SZ, ptr(0), reg_data, reg_data_size)) {
return Memory.readAnsiString(reg_data);
} else if (ERROR_SUCCESS == RegGetValueA(HKEY_LOCAL_MACHINE, reg_subkey_64, reg_value, RRF_RT_REG_SZ, ptr(0), reg_data, reg_data_size)) {
return Memory.readAnsiString(reg_data);
} else {
return null;
}
}
function readSteamAppIdTxt() {
const buffer = Memory.alloc(256)
let appid;
const fopen_ptr = Module.findExportByName("msvcrt.dll", "fopen");
const fopen = new NativeFunction(fopen_ptr, "pointer", ["pointer", "pointer"]);
const fread_ptr = Module.findExportByName("msvcrt.dll", "fread");
const fread = new NativeFunction(fread_ptr, "size_t", ["pointer", "size_t", "size_t", "pointer"]);
const fclose_ptr = Module.findExportByName("msvcrt.dll", "fclose");
const fclose = new NativeFunction(fclose_ptr, "int", ["pointer"]);
const file = fopen(Memory.allocUtf8String("steam_appid.txt"), Memory.allocUtf8String("r"))
if (file.isNull()) {
return null;
}
if (fread(buffer, 1, 255, file)) {
appid = Memory.readCString(buffer);
}
if (fclose(file)) {
console.log("Failed to close steam_appid.txt file handle");
}
// Return appid cast to a number
return +appid;
}
function setEnvironmentVariable(name, value) {
const name_ptr = Memory.allocUtf8String(name);
const value_ptr = Memory.allocUtf8String(value);
const SetEnvironmentVariableA_ptr = Module.findExportByName("kernel32.dll", "SetEnvironmentVariableA");
const SetEnvironmentVariableA = new NativeFunction(SetEnvironmentVariableA_ptr, "int", ["pointer", "pointer"]);
return SetEnvironmentVariableA(name_ptr, value_ptr);
}
rpc.exports = {
init: function(stage, parameters) {
try {
console.log("Injecting GameOverlayRenderer...");
const dll_name = Process.arch == "x64" ? "GameOverlayRenderer64.dll" : "GameOverlayRenderer.dll";
const steam_path = getSteamPath();
if (!steam_path) {
console.log("Failed to find Steam install path in registry");
return;
}
const appid = readSteamAppIdTxt();
if (appid) {
if (!setEnvironmentVariable("SteamGameId", `${appid}`)) {
console.log("Failed to set SteamGameId environment variable");
}
} else {
console.log("Failed to read appid from steam_appid.txt (is the current working directory set correctly?)");
}
if (!Module.load(`${steam_path}\\${dll_name}`)) {
console.log("Failed to load GameOverlayRenderer");
return;
}
console.log("Done injecting GameOverlayRenderer.");
} catch (e) {
console.log(e)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment