Как читать память запущенного игрового процесса Mono / Unity с помощью C #? - PullRequest
0 голосов
/ 27 апреля 2018

Извините, если этот форум не подходит для этого вопроса, но я не могу найти лучшего места для него (я пытался спросить на reddit некоторое время назад, но безуспешно) вот и я.

Я создаю приложение-компаньон для игры, цель которого - предоставить игроку некоторую информацию о текущем состоянии игры. Эта информация доступна только при чтении памяти игры (кстати, она совместима с правилами игры).

Игра была построена в Unity, а мое приложение на C #. И я изо всех сил пытаюсь найти любую хорошую документацию / точку входа, чтобы достигнуть этого.
Единственные указатели, которые я получил, были о CheatEngine, но это выглядит очень хрупко по сравнению с непосредственным доступом к структуре Mono.

Редактировать: я начал создавать репозиторий GitHub для документирования моего прогресса: https://github.com/sebastientromp/unity-memory-reading-step-by-step.
Эта работа все еще находится в стадии разработки, поэтому, пожалуйста, не стесняйтесь комментировать или предлагать некоторую помощь:)

Как показано в моего основного класса , это то место, где я сегодня (комментарии удалены):

static void Main()
{
    Process process = Process.GetProcessesByName("Hearthstone").FirstOrDefault();
    Console.WriteLine("Hearthstone process: " + process);

    IntPtr processHandle = process.Handle;
    Console.WriteLine("Process Handle: " + processHandle);

    ProcessModule monoModule = process.Modules
        .OfType<ProcessModule>()
        .FirstOrDefault(module => module.ModuleName == "mono.dll");

    long monoModuleBaseAddress = monoModule.BaseAddress.ToInt64();
    Console.WriteLine("monoModuleBaseAddress: " + monoModuleBaseAddress);

    byte[] monoModuleContent = new byte[monoModule.ModuleMemorySize];
    Console.WriteLine("monoModuleContent: " + monoModuleContent);

    ReadBytes(processHandle, monoModuleBaseAddress, monoModuleContent);

    int imageDosHeaderElfanew = BitConverter.ToInt32(monoModuleContent, (int)Offsets.ImageDosHeader_e_lfanew);
    Console.WriteLine("imageDosHeaderElfanew: " + imageDosHeaderElfanew);

    int exportDirectoryAddress = BitConverter.ToInt32(
        monoModuleContent, 
        imageDosHeaderElfanew + (int)Offsets.ImageNTHeaders_ExportDirectoryAddress);
    Console.WriteLine("exportDirectoryAddress: " + exportDirectoryAddress);

    var functionAddressMap = MapAllExportFunctions(monoModuleBaseAddress, monoModuleContent, exportDirectoryAddress);

    long monoRootDomainFunctionAddress;
    functionAddressMap.TryGetValue("mono_get_root_domain", out monoRootDomainFunctionAddress);
    Console.WriteLine("Mono rot domain address: " + monoRootDomainFunctionAddress);

    var functionContent = new byte[4];
    ReadBytes(processHandle, monoRootDomainFunctionAddress, functionContent);
    Console.WriteLine("[{0}]", string.Join(", ", functionContent));

    var rootDomainPointer = BitConverter.ToInt32(functionContent, 0);
    Console.WriteLine("rootDomainPointer: " + rootDomainPointer);
    ReadBytes(processHandle, rootDomainPointer, functionContent);
    Console.WriteLine("[{0}]", string.Join(", ", functionContent)); // This gives me [0,0,0,0] -> error!
}

Эта последняя строка ясно показывает, что где-то произошла ошибка, поэтому я полагаю, что именно так я и читаю функцию по ее адресу.
Ты хоть представляешь, что мне следует делать вместо этого?

...