Skip to content

Instantly share code, notes, and snippets.

@just-ero
Created January 23, 2022 15:18
Show Gist options
  • Save just-ero/3b07dc98802ba3652cb13ff8313bbfee to your computer and use it in GitHub Desktop.
Save just-ero/3b07dc98802ba3652cb13ff8313bbfee to your computer and use it in GitHub Desktop.

ReadValue<T>, ReadString, ReadPointer: https://github.com/LiveSplit/LiveSplit/blob/master/LiveSplit/LiveSplit.Core/ComponentUtil/ProcessExtensions.cs

// "address" is an IntPtr to an int value
int intValue = game.ReadValue<int>(address);

// "address" is an IntPtr to a string, "64" is the maximum amount of bytes to read
string strValue = game.ReadString(address, 64);

// "address" is an IntPtr to another address (for example a class)
IntPtr ptrValue = game.ReadPointer(address);

DeepPointer: https://github.com/LiveSplit/LiveSplit/blob/master/LiveSplit/LiveSplit.Core/ComponentUtil/DeepPointer.cs

var deepPointer = new DeepPointer("Celeste.exe", 0x4A03598, 0xAC, 0x18);

int intValue = deepPointer.Deref<int>(game);
string strValue = deepPointer.DerefString(game, 64);
IntPtr ptrValue = IntPtr.Zero;
bool success = deepPointer.DerefOffsets(game, out ptrValue);

MemoryWatcher<T>, StringWatcher: https://github.com/LiveSplit/LiveSplit/blob/master/LiveSplit/LiveSplit.Core/ComponentUtil/MemoryWatcher.cs

// initializes a list of MemoryWatchers
vars.Watchers = new MemoryWatcherList
{
	// adds a Watcher to the list; additionally use of vars.Watchers.Add(MemoryWatcher) is possible
	new MemoryWatcher<int>(new DeepPointer("Celeste.exe", 0x4A03598, 0xAC, 0x18)) { Name = "intWatcher" },
	new MemoryWatcher<float>(address) { Name = "floatWatcher" },
	new StringWatcher(deepPointer, 64) { Name = "stringWatcher" }
};

// updates all Watchers in the list (use this in update {})
vars.Watchers.UpdateAll(game);

// access a Watcher's values
vars.Watchers["intWatcher"].Current; // retrieves the value at this Watcher's address on the current update
vars.Watchers["intWatcher"].Old; // retrieves the value at this Watcher's address on the previous update
vars.Watchers["intWatcher"].Changed; // checks whether .Current and .Old are not equal

SignatureScanner, SigScanTarget, MemoryPages: https://github.com/LiveSplit/LiveSplit/blob/master/LiveSplit/LiveSplit.Core/ComponentUtil/SignatureScanner.cs

var mainModule = modules.First();

// initializes a new scanner with the target process, the start address, and the amount of bytes to search
var scanner = new SignatureScanner(game, mainModule.BaseAddress, mainModule.ModuleMemorySize);

// initializes a new signature target with the offset (added to the address when found) and the pattern
var target = new SigScanTarget(10, "13 37 13 ?? ?? 37 13 37");

// optionally, some code which gets executed upon a successful find can be defined:
// this code returns the address relative to another one in a 64-bit process
target.OnFound = (proc, scanner, address) =>
{
	return address + 0x4 + proc.ReadValue<int>(address);
};

// scans the bytes in the scanner for the target and returns the first address at which it was found
IntPtr result = scanner.Scan(target);

// returns all addresses which matched the target
var results = scanner.ScanAll(target);

// scans all of the game's memory pages to search for a successful scan
foreach (var page in game.MemoryPages(false))
{
	var scanner = new SignatureScanner(game, page.BaseAddress, (int)(page.RegionSize));
	result = scanner.Scan(target);
	if (result != IntPtr.Zero)
		break;
}
@mitchell-merry
Copy link

Super helpful. Thanks Ero.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment