protected PokingInformation RetrieveInformation(Process gameProcess) { #if X86 throw new InvalidOperationException("Cannot access a 64bit process with a 32bit program."); #else //verify version, and check for anticheat at the same time string version = ""; PokingInformation info = null; try { version = gameProcess.MainModule.FileVersionInfo.FileVersion; //TODO: make winstore support not horrible if (version == null) { info = _buildInfo.Poking.RetrieveLatestInfo(); } else { info = _buildInfo.Poking.RetrieveInformation(version); } if (info == null) { throw new InvalidOperationException("Game version " + version + " does not have poking information defined in the Formats folder."); } } catch (System.ComponentModel.Win32Exception) { throw new InvalidOperationException("Cannot access game process. This could be due to Anti-Cheat or lack of admin privileges."); } return(info); #endif }
/// <summary> /// Obtains a stream which can be used to read and write a cache file's meta in realtime. /// The stream will be set up such that offsets in the stream correspond to meta pointers in the cache file. /// </summary> /// <param name="cacheFile">The cache file to get a stream for.</param> /// <returns>The stream if it was opened successfully, or null otherwise.</returns> public IStream GetMetaStream(ICacheFile cacheFile) { if (string.IsNullOrEmpty(_buildInfo.PokingExecutable)) { throw new InvalidOperationException("No gameExecutable value found in Engines.xml for engine " + _buildInfo.Name + "."); } if (_buildInfo.Poking == null) { throw new InvalidOperationException("No poking definitions found in Engines.xml for engine " + _buildInfo.Name + "."); } Process gameProcess = FindGameProcess(); if (gameProcess == null) { return(null); } string version = gameProcess.MainModule.FileVersionInfo.FileVersion; PokingInformation info = _buildInfo.Poking.RetrieveInformation(version); if (info == null) { throw new InvalidOperationException("Game version " + version + " does not have poking information defined in the Formats folder."); } if (!info.HeaderAddress.HasValue) { throw new NotImplementedException("First Generation poking requires a HeaderAddress value."); } if (!info.MagicAddress.HasValue) { throw new NotImplementedException("First Generation poking requires a MagicAddress value."); } var gameMemory = new ProcessMemoryStream(gameProcess); var mapInfo = new FirstGenMapPointerReader(gameMemory, _buildInfo, info); long metaAddress = mapInfo.CurrentCacheAddress; if (mapInfo.MapName != cacheFile.InternalName) { gameMemory.Close(); return(null); } var metaStream = new OffsetStream(gameMemory, metaAddress - cacheFile.MetaArea.BasePointer); return(new EndianStream(metaStream, BitConverter.IsLittleEndian ? Endian.LittleEndian : Endian.BigEndian)); }
/// <summary> /// Obtains a stream which can be used to read and write a cache file's meta in realtime. /// The stream will be set up such that offsets in the stream correspond to meta pointers in the cache file. /// </summary> /// <param name="cacheFile">The cache file to get a stream for.</param> /// <returns>The stream if it was opened successfully, or null otherwise.</returns> public override IStream GetMetaStream(ICacheFile cacheFile = null) { if (!CheckBuildInfo()) { return(null); } Process gameProcess = FindGameProcess(); if (gameProcess == null) { return(null); } PokingInformation info = RetrieveInformation(gameProcess); if (!info.HeaderPointer.HasValue && (!info.HeaderAddress.HasValue || !info.MagicAddress.HasValue)) { throw new NotImplementedException("Poking information is missing required values."); } var gameMemory = new ProcessModuleMemoryStream(gameProcess, _buildInfo.GameModule); var mapInfo = new ThirdGenMapPointerReader(gameMemory, _buildInfo, info); long metaMagic = mapInfo.CurrentCacheAddress; if (gameMemory.BaseModule == null) { return(null); } if (mapInfo.MapName != cacheFile.InternalName) { gameMemory.Close(); return(null); } if (metaMagic == 0) { return(null); } var metaStream = new OffsetStream(gameMemory, metaMagic); return(new EndianStream(metaStream, BitConverter.IsLittleEndian ? Endian.LittleEndian : Endian.BigEndian)); }
public FirstGenMapPointerReader(ProcessModuleMemoryStream moduleStream, EngineDescription engineInfo, PokingInformation info) { _baseAddress = (long)moduleStream.BaseModule.BaseAddress; _mapHeaderAddress = _baseAddress + info.HeaderAddress.Value; _mapMagicAddress = _baseAddress + info.MagicAddress.Value; GetLayoutConstants(engineInfo); var reader = new EndianReader(moduleStream, BitConverter.IsLittleEndian ? Endian.LittleEndian : Endian.BigEndian); ReadMapPointers64(reader); ReadMapHeader(reader); ProcessMapHeader(); }
public ThirdGenMapPointerReader(ProcessModuleMemoryStream moduleStream, EngineDescription engineInfo, PokingInformation info) { _baseAddress = (long)moduleStream.BaseModule.BaseAddress; GetLayoutConstants(engineInfo); var reader = new EndianReader(moduleStream, BitConverter.IsLittleEndian ? Endian.LittleEndian : Endian.BigEndian); if (info.HeaderPointer.HasValue) { reader.SeekTo(_baseAddress + info.HeaderPointer.Value); long address = reader.ReadInt64(); _mapHeaderAddress = address + 0x10; _mapMagicAddress = address + engineInfo.HeaderSize + info.MagicOffset.Value; } else { _mapHeaderAddress = _baseAddress + info.HeaderAddress.Value; _mapMagicAddress = _baseAddress + info.MagicAddress.Value; } ReadMapPointers64(reader); ReadMapHeader(reader); ProcessMapHeader(); }
/// <summary> /// Obtains a stream which can be used to read and write a cache file's meta in realtime. /// The stream will be set up such that offsets in the stream correspond to meta pointers in the cache file. /// </summary> /// <param name="cacheFile">The cache file to get a stream for.</param> /// <returns>The stream if it was opened successfully, or null otherwise.</returns> public override IStream GetMetaStream(ICacheFile cacheFile) { if (!CheckBuildInfo()) { return(null); } Process gameProcess = FindGameProcess(); if (gameProcess == null) { return(null); } PokingInformation info = RetrieveInformation(gameProcess); if (!info.HeaderAddress.HasValue) { throw new NotImplementedException("Second Generation poking requires a HeaderAddress value."); } if (!info.MagicAddress.HasValue) { throw new NotImplementedException("Second Generation poking requires a MagicAddress value."); } if (!info.SharedMagicAddress.HasValue) { throw new NotImplementedException("Second Generation poking requires a SharedMagicAddress value."); } var gameMemory = new ProcessModuleMemoryStream(gameProcess, _buildInfo.GameModule); var mapInfo = new SecondGenMapPointerReader(gameMemory, _buildInfo, info); long metaAddress; if (cacheFile.Type != CacheFileType.Shared) { metaAddress = mapInfo.CurrentCacheAddress; // The map isn't shared, so make sure the map names match if (mapInfo.MapName != cacheFile.InternalName) { gameMemory.Close(); return(null); } } else { metaAddress = mapInfo.SharedCacheAddress; // Make sure the shared and current map pointers are different, // or that the current map is the shared map if (mapInfo.MapType != CacheFileType.Shared && mapInfo.CurrentCacheAddress == mapInfo.SharedCacheAddress) { gameMemory.Close(); return(null); } } var metaStream = new OffsetStream(gameMemory, metaAddress - cacheFile.MetaArea.BasePointer); return(new EndianStream(metaStream, BitConverter.IsLittleEndian ? Endian.LittleEndian : Endian.BigEndian)); }
public SecondGenMapPointerReader(ProcessMemoryStream processStream, EngineDescription engineInfo, PokingInformation info) { _baseAddress = (long)processStream.BaseProcess.MainModule.BaseAddress; _mapHeaderAddress = _baseAddress + info.HeaderAddress.Value; _mapMagicAddress = _baseAddress + info.MagicAddress.Value; _mapSharedMagicAddress = _baseAddress + info.SharedMagicAddress.Value; GetLayoutConstants(engineInfo); var reader = new EndianReader(processStream, BitConverter.IsLittleEndian ? Endian.LittleEndian : Endian.BigEndian); ReadMapPointers32(reader); ReadMapHeader(reader); ProcessMapHeader(); }
/// <summary> /// Obtains a stream which can be used to read and write a cache file's meta in realtime. /// The stream will be set up such that offsets in the stream correspond to meta pointers in the cache file. /// </summary> /// <param name="cacheFile">The cache file to get a stream for.</param> /// <returns>The stream if it was opened successfully, or null otherwise.</returns> public IStream GetMetaStream(ICacheFile cacheFile) { if (string.IsNullOrEmpty(_buildInfo.GameExecutable)) { throw new InvalidOperationException("No gameExecutable value found in Engines.xml for engine " + _buildInfo.Name + "."); } if (_buildInfo.Poking == null) { throw new InvalidOperationException("No poking definitions found in Engines.xml for engine " + _buildInfo.Name + "."); } Process gameProcess = FindGameProcess(); if (gameProcess == null) { return(null); } string version = gameProcess.MainModule.FileVersionInfo.FileVersion; PokingInformation info = _buildInfo.Poking.RetrieveInformation(version); if (info == null) { throw new InvalidOperationException("Game version " + version + " does not have poking information defined in the Formats folder."); } if (!info.HeaderAddress.HasValue) { throw new NotImplementedException("Second Generation poking requires a HeaderAddress value."); } if (!info.MagicAddress.HasValue) { throw new NotImplementedException("Second Generation poking requires a MagicAddress value."); } if (!info.SharedMagicAddress.HasValue) { throw new NotImplementedException("Second Generation poking requires a SharedMagicAddress value."); } long pointer = info.HeaderPointer.Value; var gameMemory = new ProcessMemoryStream(gameProcess); var mapInfo = new SecondGenMapPointerReader(gameMemory, _buildInfo, info); long metaAddress; if (cacheFile.Type != CacheFileType.Shared) { metaAddress = mapInfo.CurrentCacheAddress; // The map isn't shared, so make sure the map names match if (mapInfo.MapName != cacheFile.InternalName) { gameMemory.Close(); return(null); } } else { metaAddress = mapInfo.SharedCacheAddress; // Make sure the shared and current map pointers are different, // or that the current map is the shared map if (mapInfo.MapType != CacheFileType.Shared && mapInfo.CurrentCacheAddress == mapInfo.SharedCacheAddress) { gameMemory.Close(); return(null); } } var metaStream = new OffsetStream(gameMemory, metaAddress - cacheFile.MetaArea.BasePointer); return(new EndianStream(metaStream, BitConverter.IsLittleEndian ? Endian.LittleEndian : Endian.BigEndian)); }