- Статус
- Оффлайн
- Регистрация
- 13 Фев 2026
- Сообщения
- 347
- Реакции
- 7
Народ, попал в руки простенький, но рабочий дампер для Раста. Ничего лишнего — чистый C#, который делает свою работу через стандартный мануальный инжект. Кто копается в материалах игры или пытается вытянуть структуру ассетов для своих нужд — вещь вполне юзабельная для быстрого сбора инфы.
Функционал:
Нюансы:
Поскольку это чистый C# Dumper, не забывайте, что инжект в игру с EAC — это всегда лотерея. Если юзаете на мейне — отлетите быстрее, чем прогрузится карта. Для легитной игры не подходит, используйте только на локалке или чистом клиенте.
Кто уже пробовал прокидывать этот дамп под актуальный билд, отпишитесь по результатам в треде?
Функционал:
- Показывает прогресс дампинга в консоли.
- Поддерживает кастомные имена файлов, что удобно для автоматизации скриптами.
- Работает через стандартный процесс инжекта (можно юзать Process Hacker или подставить свой загрузчик).
Сам инжектор реализован через стандартные WinAPI:
и
В сурсе есть логика вычисления RVA через
без резолва зависимостей, что позволяет цепляться к процессу RustClient.exe без лишних головняков.
Код:
OpenProcess
Код:
VirtualAllocEx
Код:
CreateRemoteThread
Код:
LoadLibraryExA
Код:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace RustDumperNET
{
static class Injector
{
const uint PROCESS_ALL_ACCESS = 0x001F_0FFF;
const uint MEM_COMMIT = 0x0000_1000;
const uint MEM_RESERVE = 0x0000_2000;
const uint MEM_RELEASE = 0x0000_8000;
const uint PAGE_READWRITE = 0x04;
const uint INFINITE = 0xFFFF_FFFF;
const uint DONT_RESOLVE_DLL_REFERENCES = 0x0000_0001;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(uint dwAccess, bool bInherit, int dwPid);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddr,
IntPtr dwSize, uint flType, uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddr,
IntPtr dwSize, uint dwFreeType);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddr,
byte[] lpBuffer, IntPtr nSize, out IntPtr lpWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpAttr,
IntPtr dwStackSize, IntPtr lpStartAddr, IntPtr lpParam,
uint dwFlags, out uint lpThreadId);
[DllImport("kernel32.dll", SetLastError = true)]
static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMs);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
static extern IntPtr LoadLibraryA(string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
static extern IntPtr LoadLibraryExA(string lpFileName, IntPtr hFile, uint dwFlags);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool FreeLibrary(IntPtr hModule);
public static void InjectAndRun(Process target, string dllPath,
string outputPath, bool waitForCompletion = true)
{
string fullDllPath = Path.GetFullPath(dllPath);
if (!File.Exists(fullDllPath))
throw new FileNotFoundException($"DLL not found: {fullDllPath}");
IntPtr hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, target.Id);
if (hProcess == IntPtr.Zero)
throw new InvalidOperationException(
$"OpenProcess failed (error {Marshal.GetLastWin32Error()})");
try
{
InjectDll(hProcess, fullDllPath);
IntPtr remoteStartDump = ResolveRemoteExport(target, fullDllPath, "StartDump");
byte[] pathBytes = Encoding.UTF8.GetBytes(outputPath + '\0');
IntPtr remotePath = VirtualAllocEx(hProcess, IntPtr.Zero,
(IntPtr)pathBytes.Length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (remotePath == IntPtr.Zero)
throw new InvalidOperationException(
$"VirtualAllocEx (path) failed (error {Marshal.GetLastWin32Error()})");
if (!WriteProcessMemory(hProcess, remotePath, pathBytes,
(IntPtr)pathBytes.Length, out _))
throw new InvalidOperationException(
$"WriteProcessMemory (path) failed (error {Marshal.GetLastWin32Error()})");
IntPtr hDumpThread = CreateRemoteThread(hProcess, IntPtr.Zero, IntPtr.Zero,
remoteStartDump, remotePath, 0, out _);
if (hDumpThread == IntPtr.Zero)
throw new InvalidOperationException(
$"CreateRemoteThread (StartDump) failed (error {Marshal.GetLastWin32Error()})");
if (waitForCompletion)
WaitForSingleObject(hDumpThread, INFINITE);
CloseHandle(hDumpThread);
}
finally
{
CloseHandle(hProcess);
}
}
// -------------------------------------------------------------------------
static void InjectDll(IntPtr hProcess, string fullDllPath)
{
byte[] pathBytes = Encoding.ASCII.GetBytes(fullDllPath + '\0');
IntPtr remoteDllPath = VirtualAllocEx(hProcess, IntPtr.Zero,
(IntPtr)pathBytes.Length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (remoteDllPath == IntPtr.Zero)
throw new InvalidOperationException(
$"VirtualAllocEx (DLL path) failed (error {Marshal.GetLastWin32Error()})");
try
{
if (!WriteProcessMemory(hProcess, remoteDllPath, pathBytes,
(IntPtr)pathBytes.Length, out _))
throw new InvalidOperationException(
$"WriteProcessMemory (DLL path) failed (error {Marshal.GetLastWin32Error()})");
IntPtr hKernel32 = LoadLibraryA("kernel32.dll");
IntPtr loadLibraryA = GetProcAddress(hKernel32, "LoadLibraryA");
FreeLibrary(hKernel32);
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, IntPtr.Zero,
loadLibraryA, remoteDllPath, 0, out _);
if (hThread == IntPtr.Zero)
throw new InvalidOperationException(
$"CreateRemoteThread (LoadLibraryA) failed (error {Marshal.GetLastWin32Error()})");
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
finally
{
VirtualFreeEx(hProcess, remoteDllPath, IntPtr.Zero, MEM_RELEASE);
}
}
static IntPtr ResolveRemoteExport(Process target, string fullDllPath, string exportName)
{
IntPtr hLocal = LoadLibraryExA(fullDllPath, IntPtr.Zero, DONT_RESOLVE_DLL_REFERENCES);
if (hLocal == IntPtr.Zero)
throw new InvalidOperationException(
$"Local LoadLibraryEx failed (error {Marshal.GetLastWin32Error()})");
IntPtr localExport = GetProcAddress(hLocal, exportName);
if (localExport == IntPtr.Zero)
{
FreeLibrary(hLocal);
throw new InvalidOperationException(
$"Export '{exportName}' not found in {Path.GetFileName(fullDllPath)}");
}
long exportRva = localExport.ToInt64() - hLocal.ToInt64();
FreeLibrary(hLocal);
IntPtr remoteBase = FindRemoteModuleBase(target, fullDllPath);
return new IntPtr(remoteBase.ToInt64() + exportRva);
}
static IntPtr FindRemoteModuleBase(Process target, string fullDllPath,
int retries = 15, int delayMs = 200)
{
string dllName = Path.GetFileName(fullDllPath);
for (int i = 0; i < retries; i++)
{
try
{
target.Refresh();
foreach (ProcessModule mod in target.Modules)
{
if (string.Equals(Path.GetFileName(mod.FileName), dllName,
StringComparison.OrdinalIgnoreCase))
return mod.BaseAddress;
}
}
catch (Exception) { }
Thread.Sleep(delayMs);
}
throw new InvalidOperationException(
$"Module '{dllName}' not found in target process after {retries} retries.");
}
}
}
Нюансы:
Поскольку это чистый C# Dumper, не забывайте, что инжект в игру с EAC — это всегда лотерея. Если юзаете на мейне — отлетите быстрее, чем прогрузится карта. Для легитной игры не подходит, используйте только на локалке или чистом клиенте.
Кто уже пробовал прокидывать этот дамп под актуальный билд, отпишитесь по результатам в треде?