diff --git a/Memory/Memory.csproj b/Memory/Memory.csproj index c662c14..a0bf854 100644 --- a/Memory/Memory.csproj +++ b/Memory/Memory.csproj @@ -13,7 +13,7 @@ Read and Write to process memory. Make PC cheat trainers easily! icon.png LICENSE - 1.2.21 + 1.2.22 x64;x86 app.manifest @@ -34,10 +34,6 @@ true - - - - @@ -51,4 +47,8 @@ + + + + diff --git a/Memory/Methods/AoB.cs b/Memory/Methods/AoB.cs new file mode 100644 index 0000000..f608b93 --- /dev/null +++ b/Memory/Methods/AoB.cs @@ -0,0 +1,319 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using static Memory.Imps; + +namespace Memory +{ + public partial class Mem + { + /// + /// Array of byte scan. + /// + /// array of bytes to search for, OR your ini code label. + /// Include writable addresses in scan + /// Include executable addresses in scan + /// ini file (OPTIONAL) + /// IEnumerable of all addresses found. + public Task> AoBScan(string search, bool writable = false, bool executable = true, string file = "") + { + return AoBScan(0, long.MaxValue, search, writable, executable, file); + } + + /// + /// Array of byte scan. + /// + /// array of bytes to search for, OR your ini code label. + /// Include readable addresses in scan + /// Include writable addresses in scan + /// Include executable addresses in scan + /// ini file (OPTIONAL) + /// IEnumerable of all addresses found. + public Task> AoBScan(string search, bool readable, bool writable, bool executable, string file = "") + { + return AoBScan(0, long.MaxValue, search, readable, writable, executable, file); + } + + + /// + /// Array of Byte scan. + /// + /// Your starting address. + /// ending address + /// array of bytes to search for, OR your ini code label. + /// ini file (OPTIONAL) + /// Include writable addresses in scan + /// Include executable addresses in scan + /// IEnumerable of all addresses found. + public Task> AoBScan(long start, long end, string search, bool writable = false, bool executable = true, string file = "") + { + // Not including read only memory was scan behavior prior. + return AoBScan(start, end, search, false, writable, executable, file); + } + + /// + /// Array of Byte scan. + /// + /// Your starting address. + /// ending address + /// array of bytes to search for, OR your ini code label. + /// ini file (OPTIONAL) + /// Include readable addresses in scan + /// Include writable addresses in scan + /// Include executable addresses in scan + /// IEnumerable of all addresses found. + public Task> AoBScan(long start, long end, string search, bool readable, bool writable, bool executable, string file = "") + { + return Task.Run(() => + { + var memRegionList = new List(); + + string memCode = LoadCode(search, file); + + string[] stringByteArray = memCode.Split(' '); + + byte[] aobPattern = new byte[stringByteArray.Length]; + byte[] mask = new byte[stringByteArray.Length]; + + for (var i = 0; i < stringByteArray.Length; i++) + { + string ba = stringByteArray[i]; + + if (ba == "??" || (ba.Length == 1 && ba == "?")) + { + mask[i] = 0x00; + stringByteArray[i] = "0x00"; + } + else if (Char.IsLetterOrDigit(ba[0]) && ba[1] == '?') + { + mask[i] = 0xF0; + stringByteArray[i] = ba[0] + "0"; + } + else if (Char.IsLetterOrDigit(ba[1]) && ba[0] == '?') + { + mask[i] = 0x0F; + stringByteArray[i] = "0" + ba[1]; + } + else + mask[i] = 0xFF; + } + + + for (int i = 0; i < stringByteArray.Length; i++) + aobPattern[i] = (byte)(Convert.ToByte(stringByteArray[i], 16) & mask[i]); + + SYSTEM_INFO sys_info = new SYSTEM_INFO(); + GetSystemInfo(out sys_info); + + UIntPtr proc_min_address = sys_info.minimumApplicationAddress; + UIntPtr proc_max_address = sys_info.maximumApplicationAddress; + + if (start < (long)proc_min_address.ToUInt64()) + start = (long)proc_min_address.ToUInt64(); + + if (end > (long)proc_max_address.ToUInt64()) + end = (long)proc_max_address.ToUInt64(); + + Debug.WriteLine("[DEBUG] memory scan starting... (start:0x" + start.ToString(MSize()) + " end:0x" + end.ToString(MSize()) + " time:" + DateTime.Now.ToString("h:mm:ss tt") + ")"); + UIntPtr currentBaseAddress = new UIntPtr((ulong)start); + + MEMORY_BASIC_INFORMATION memInfo = new MEMORY_BASIC_INFORMATION(); + + //Debug.WriteLine("[DEBUG] start:0x" + start.ToString("X8") + " curBase:0x" + currentBaseAddress.ToUInt64().ToString("X8") + " end:0x" + end.ToString("X8") + " size:0x" + memInfo.RegionSize.ToString("X8") + " vAloc:" + VirtualQueryEx(mProc.Handle, currentBaseAddress, out memInfo).ToUInt64().ToString()); + + while (VirtualQueryEx(mProc.Handle, currentBaseAddress, out memInfo).ToUInt64() != 0 && + currentBaseAddress.ToUInt64() < (ulong)end && + currentBaseAddress.ToUInt64() + (ulong)memInfo.RegionSize > + currentBaseAddress.ToUInt64()) + { + bool isValid = memInfo.State == MEM_COMMIT; + isValid &= memInfo.BaseAddress.ToUInt64() < (ulong)proc_max_address.ToUInt64(); + isValid &= ((memInfo.Protect & PAGE_GUARD) == 0); + isValid &= ((memInfo.Protect & PAGE_NOACCESS) == 0); + isValid &= (memInfo.Type == MEM_PRIVATE) || (memInfo.Type == MEM_IMAGE); + + if (isValid) + { + bool isReadable = (memInfo.Protect & PAGE_READONLY) > 0; + + bool isWritable = ((memInfo.Protect & PAGE_READWRITE) > 0) || + ((memInfo.Protect & PAGE_WRITECOPY) > 0) || + ((memInfo.Protect & PAGE_EXECUTE_READWRITE) > 0) || + ((memInfo.Protect & PAGE_EXECUTE_WRITECOPY) > 0); + + bool isExecutable = ((memInfo.Protect & PAGE_EXECUTE) > 0) || + ((memInfo.Protect & PAGE_EXECUTE_READ) > 0) || + ((memInfo.Protect & PAGE_EXECUTE_READWRITE) > 0) || + ((memInfo.Protect & PAGE_EXECUTE_WRITECOPY) > 0); + + isReadable &= readable; + isWritable &= writable; + isExecutable &= executable; + + isValid &= isReadable || isWritable || isExecutable; + } + + if (!isValid) + { + currentBaseAddress = new UIntPtr(memInfo.BaseAddress.ToUInt64() + (ulong)memInfo.RegionSize); + continue; + } + + MemoryRegionResult memRegion = new MemoryRegionResult + { + CurrentBaseAddress = currentBaseAddress, + RegionSize = memInfo.RegionSize, + RegionBase = memInfo.BaseAddress + }; + + currentBaseAddress = new UIntPtr(memInfo.BaseAddress.ToUInt64() + (ulong)memInfo.RegionSize); + + //Console.WriteLine("SCAN start:" + memRegion.RegionBase.ToString() + " end:" + currentBaseAddress.ToString()); + + if (memRegionList.Count > 0) + { + var previousRegion = memRegionList[memRegionList.Count - 1]; + + if ((long)previousRegion.RegionBase + previousRegion.RegionSize == (long)memInfo.BaseAddress) + { + memRegionList[memRegionList.Count - 1] = new MemoryRegionResult + { + CurrentBaseAddress = previousRegion.CurrentBaseAddress, + RegionBase = previousRegion.RegionBase, + RegionSize = previousRegion.RegionSize + memInfo.RegionSize + }; + + continue; + } + } + + memRegionList.Add(memRegion); + } + + ConcurrentBag bagResult = new ConcurrentBag(); + + Parallel.ForEach(memRegionList, + (item, parallelLoopState, index) => + { + long[] compareResults = CompareScan(item, aobPattern, mask); + + foreach (long result in compareResults) + bagResult.Add(result); + }); + + Debug.WriteLine("[DEBUG] memory scan completed. (time:" + DateTime.Now.ToString("h:mm:ss tt") + ")"); + + return bagResult.ToList().OrderBy(c => c).AsEnumerable(); + }); + } + + /// + /// Array of bytes scan + /// + /// Starting address or ini label + /// ending address + /// array of bytes to search for or your ini code label + /// ini file + /// First address found + public async Task AoBScan(string code, long end, string search, string file = "") + { + long start = (long)GetCode(code, file).ToUInt64(); + + return (await AoBScan(start, end, search, true, true, true, file)).FirstOrDefault(); + } + + private long[] CompareScan(MemoryRegionResult item, byte[] aobPattern, byte[] mask) + { + if (mask.Length != aobPattern.Length) + throw new ArgumentException($"{nameof(aobPattern)}.Length != {nameof(mask)}.Length"); + + IntPtr buffer = Marshal.AllocHGlobal((int)item.RegionSize); + + ReadProcessMemory(mProc.Handle, item.CurrentBaseAddress, buffer, (UIntPtr)item.RegionSize, out ulong bytesRead); + + int result = 0 - aobPattern.Length; + List ret = new List(); + unsafe + { + do + { + + result = FindPattern((byte*)buffer.ToPointer(), (int)bytesRead, aobPattern, mask, result + aobPattern.Length); + + if (result >= 0) + ret.Add((long)item.CurrentBaseAddress + result); + + } while (result != -1); + } + + Marshal.FreeHGlobal(buffer); + + return ret.ToArray(); + } + + private int FindPattern(byte[] body, byte[] pattern, byte[] masks, int start = 0) + { + int foundIndex = -1; + + if (body.Length <= 0 || pattern.Length <= 0 || start > body.Length - pattern.Length || + pattern.Length > body.Length) return foundIndex; + + for (int index = start; index <= body.Length - pattern.Length; index++) + { + if (((body[index] & masks[0]) == (pattern[0] & masks[0]))) + { + var match = true; + for (int index2 = 1; index2 <= pattern.Length - 1; index2++) + { + if ((body[index + index2] & masks[index2]) == (pattern[index2] & masks[index2])) continue; + match = false; + break; + + } + + if (!match) continue; + + foundIndex = index; + break; + } + } + + return foundIndex; + } + + private unsafe int FindPattern(byte* body, int bodyLength, byte[] pattern, byte[] masks, int start = 0) + { + int foundIndex = -1; + + if (bodyLength <= 0 || pattern.Length <= 0 || start > bodyLength - pattern.Length || + pattern.Length > bodyLength) return foundIndex; + + for (int index = start; index <= bodyLength - pattern.Length; index++) + { + if (((body[index] & masks[0]) == (pattern[0] & masks[0]))) + { + var match = true; + for (int index2 = 1; index2 <= pattern.Length - 1; index2++) + { + if ((body[index + index2] & masks[index2]) == (pattern[index2] & masks[index2])) continue; + match = false; + break; + + } + + if (!match) continue; + + foundIndex = index; + break; + } + } + + return foundIndex; + } + } +} \ No newline at end of file diff --git a/Memory/Methods/Read.cs b/Memory/Methods/Read.cs new file mode 100644 index 0000000..f1b01d2 --- /dev/null +++ b/Memory/Methods/Read.cs @@ -0,0 +1,369 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using static Memory.Imps; + +namespace Memory +{ + public partial class Mem + { + /// + /// Cut a string that goes on for too long or one that is possibly merged with another string. + /// + /// The string you want to cut. + /// + public string CutString(string str) + { + StringBuilder sb = new StringBuilder(); + foreach (char c in str) + { + if (c >= ' ' && c <= '~') + sb.Append(c); + else + break; + } + return sb.ToString(); + } + + /// + /// Reads up to `length ` bytes from an address. + /// + /// address, module + pointer + offset, module + offset OR label in .ini file. + /// The maximum bytes to read. + /// path and name of ini file. + /// The bytes read or null + public byte[] ReadBytes(string code, long length, string file = "") + { + byte[] memory = new byte[length]; + UIntPtr theCode = GetCode(code, file); + + if (!ReadProcessMemory(mProc.Handle, theCode, memory, (UIntPtr)length, IntPtr.Zero)) + return null; + + return memory; + } + + /// + /// Read a float value from an address. + /// + /// address, module + pointer + offset, module + offset OR label in .ini file. + /// path and name of ini file. (OPTIONAL) + /// Round the value to 2 decimal places + /// + public float ReadFloat(string code, string file = "", bool round = true) + { + byte[] memory = new byte[4]; + + UIntPtr theCode; + theCode = GetCode(code, file); + try + { + if (ReadProcessMemory(mProc.Handle, theCode, memory, (UIntPtr)4, IntPtr.Zero)) + { + float address = BitConverter.ToSingle(memory, 0); + float returnValue = (float)address; + if (round) + returnValue = (float)Math.Round(address, 2); + return returnValue; + } + else + return 0; + } + catch + { + return 0; + } + } + + /// + /// Read a string value from an address. + /// + /// address, module + pointer + offset, module + offset OR label in .ini file. + /// path and name of ini file. (OPTIONAL) + /// length of bytes to read (OPTIONAL) + /// terminate string at null char + /// System.Text.Encoding.UTF8 (DEFAULT). Other options: ascii, unicode, utf32, utf7 + /// + public string ReadString(string code, string file = "", int length = 32, bool zeroTerminated = true, System.Text.Encoding stringEncoding = null) + { + if (stringEncoding == null) + stringEncoding = System.Text.Encoding.UTF8; + + byte[] memoryNormal = new byte[length]; + UIntPtr theCode; + theCode = GetCode(code, file); + + if (ReadProcessMemory(mProc.Handle, theCode, memoryNormal, (UIntPtr)length, IntPtr.Zero)) + return (zeroTerminated) ? stringEncoding.GetString(memoryNormal).Split('\0')[0] : stringEncoding.GetString(memoryNormal); + else + return ""; + } + + /// + /// Read a double value + /// + /// address, module + pointer + offset, module + offset OR label in .ini file. + /// path and name of ini file. (OPTIONAL) + /// Round the value to 2 decimal places + /// + public double ReadDouble(string code, string file = "", bool round = true) + { + byte[] memory = new byte[8]; + + UIntPtr theCode; + theCode = GetCode(code, file); + try + { + if (ReadProcessMemory(mProc.Handle, theCode, memory, (UIntPtr)8, IntPtr.Zero)) + { + double address = BitConverter.ToDouble(memory, 0); + double returnValue = (double)address; + if (round) + returnValue = (double)Math.Round(address, 2); + return returnValue; + } + else + return 0; + } + catch + { + return 0; + } + } + + public int ReadUIntPtr(UIntPtr code) + { + byte[] memory = new byte[4]; + if (ReadProcessMemory(mProc.Handle, code, memory, (UIntPtr)4, IntPtr.Zero)) + return BitConverter.ToInt32(memory, 0); + else + return 0; + } + + /// + /// Read an integer from an address. + /// + /// address, module + pointer + offset, module + offset OR label in .ini file. + /// path and name of ini file. (OPTIONAL) + /// + public int ReadInt(string code, string file = "") + { + byte[] memory = new byte[4]; + UIntPtr theCode; + theCode = GetCode(code, file); + if (ReadProcessMemory(mProc.Handle, theCode, memory, (UIntPtr)4, IntPtr.Zero)) + return BitConverter.ToInt32(memory, 0); + else + return 0; + } + + /// + /// Read a long value from an address. + /// + /// address, module + pointer + offset, module + offset OR label in .ini file. + /// path and name of ini file. (OPTIONAL) + /// + public long ReadLong(string code, string file = "") + { + byte[] memory = new byte[16]; + UIntPtr theCode; + + theCode = GetCode(code, file); + + if (ReadProcessMemory(mProc.Handle, theCode, memory, (UIntPtr)8, IntPtr.Zero)) + return BitConverter.ToInt64(memory, 0); + else + return 0; + } + + /// + /// Read a UInt value from address. + /// + /// address, module + pointer + offset, module + offset OR label in .ini file. + /// path and name of ini file. (OPTIONAL) + /// + public UInt32 ReadUInt(string code, string file = "") + { + byte[] memory = new byte[4]; + UIntPtr theCode; + theCode = GetCode(code, file); + + if (ReadProcessMemory(mProc.Handle, theCode, memory, (UIntPtr)4, IntPtr.Zero)) + return BitConverter.ToUInt32(memory, 0); + else + return 0; + } + + /// + /// Reads a 2 byte value from an address and moves the address. + /// + /// address, module + pointer + offset, module + offset OR label in .ini file. + /// Quantity to move. + /// path and name of ini file (OPTIONAL) + /// + public int Read2ByteMove(string code, int moveQty, string file = "") + { + byte[] memory = new byte[4]; + UIntPtr theCode; + theCode = GetCode(code, file); + + UIntPtr newCode = UIntPtr.Add(theCode, moveQty); + + if (ReadProcessMemory(mProc.Handle, newCode, memory, (UIntPtr)2, IntPtr.Zero)) + return BitConverter.ToInt32(memory, 0); + else + return 0; + } + + /// + /// Reads an integer value from address and moves the address. + /// + /// address, module + pointer + offset, module + offset OR label in .ini file. + /// Quantity to move. + /// path and name of ini file (OPTIONAL) + /// + public int ReadIntMove(string code, int moveQty, string file = "") + { + byte[] memory = new byte[4]; + UIntPtr theCode; + theCode = GetCode(code, file); + + UIntPtr newCode = UIntPtr.Add(theCode, moveQty); + + if (ReadProcessMemory(mProc.Handle, newCode, memory, (UIntPtr)4, IntPtr.Zero)) + return BitConverter.ToInt32(memory, 0); + else + return 0; + } + + /// + /// Get UInt and move to another address by moveQty. Use in a for loop. + /// + /// address, module + pointer + offset, module + offset OR label in .ini file. + /// Quantity to move. + /// path and name of ini file (OPTIONAL) + /// + public ulong ReadUIntMove(string code, int moveQty, string file = "") + { + byte[] memory = new byte[8]; + UIntPtr theCode; + theCode = GetCode(code, file, 8); + + UIntPtr newCode = UIntPtr.Add(theCode, moveQty); + + if (ReadProcessMemory(mProc.Handle, newCode, memory, (UIntPtr)8, IntPtr.Zero)) + return BitConverter.ToUInt64(memory, 0); + else + return 0; + } + + /// + /// Read a 2 byte value from an address. Returns an integer. + /// + /// address, module + pointer + offset, module + offset OR label in .ini file. + /// path and file name to ini file. (OPTIONAL) + /// + public int Read2Byte(string code, string file = "") + { + byte[] memoryTiny = new byte[4]; + + UIntPtr theCode; + theCode = GetCode(code, file); + + if (ReadProcessMemory(mProc.Handle, theCode, memoryTiny, (UIntPtr)2, IntPtr.Zero)) + return BitConverter.ToInt32(memoryTiny, 0); + else + return 0; + } + + /// + /// Read 1 byte from address. + /// + /// address, module + pointer + offset, module + offset OR label in .ini file. + /// path and file name of ini file. (OPTIONAL) + /// + public int ReadByte(string code, string file = "") + { + byte[] memoryTiny = new byte[1]; + + UIntPtr theCode = GetCode(code, file); + + if (ReadProcessMemory(mProc.Handle, theCode, memoryTiny, (UIntPtr)1, IntPtr.Zero)) + return memoryTiny[0]; + + return 0; + } + + /// + /// Reads a byte from memory and splits it into bits + /// + /// address, module + pointer + offset, module + offset OR label in .ini file. + /// path and file name of ini file. (OPTIONAL) + /// Array of 8 booleans representing each bit of the byte read + public bool[] ReadBits(string code, string file = "") + { + byte[] buf = new byte[1]; + + UIntPtr theCode = GetCode(code, file); + + bool[] ret = new bool[8]; + + if (!ReadProcessMemory(mProc.Handle, theCode, buf, (UIntPtr)1, IntPtr.Zero)) + return ret; + + + if (!BitConverter.IsLittleEndian) + throw new Exception("Should be little endian"); + + for (var i = 0; i < 8; i++) + ret[i] = Convert.ToBoolean(buf[0] & (1 << i)); + + return ret; + + } + + public int ReadPByte(UIntPtr address, string code, string file = "") + { + byte[] memory = new byte[4]; + if (ReadProcessMemory(mProc.Handle, address + LoadIntCode(code, file), memory, (UIntPtr)1, IntPtr.Zero)) + return BitConverter.ToInt32(memory, 0); + else + return 0; + } + + public float ReadPFloat(UIntPtr address, string code, string file = "") + { + byte[] memory = new byte[4]; + if (ReadProcessMemory(mProc.Handle, address + LoadIntCode(code, file), memory, (UIntPtr)4, IntPtr.Zero)) + { + float spawn = BitConverter.ToSingle(memory, 0); + return (float)Math.Round(spawn, 2); + } + else + return 0; + } + + public int ReadPInt(UIntPtr address, string code, string file = "") + { + byte[] memory = new byte[4]; + if (ReadProcessMemory(mProc.Handle, address + LoadIntCode(code, file), memory, (UIntPtr)4, IntPtr.Zero)) + return BitConverter.ToInt32(memory, 0); + else + return 0; + } + + public string ReadPString(UIntPtr address, string code, string file = "") + { + byte[] memoryNormal = new byte[32]; + if (ReadProcessMemory(mProc.Handle, address + LoadIntCode(code, file), memoryNormal, (UIntPtr)32, IntPtr.Zero)) + return CutString(System.Text.Encoding.ASCII.GetString(memoryNormal)); + else + return ""; + } + } +} diff --git a/Memory/Methods/Write.cs b/Memory/Methods/Write.cs new file mode 100644 index 0000000..49124ef --- /dev/null +++ b/Memory/Methods/Write.cs @@ -0,0 +1,284 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using static Memory.Imps; + +namespace Memory +{ + public partial class Mem + { + Dictionary FreezeTokenSrcs = new Dictionary(); + + /// + /// Freeze a value to an address. + /// + /// Your address + /// byte, 2bytes, bytes, float, int, string, double or long. + /// Value to freeze + /// ini file to read address from (OPTIONAL) + public void FreezeValue(string address, string type, string value, string file = "") + { + CancellationTokenSource cts = new CancellationTokenSource(); + + lock (FreezeTokenSrcs) + { + if (FreezeTokenSrcs.ContainsKey(address)) + { + Debug.WriteLine("Changing Freezing Address " + address + " Value " + value); + try + { + FreezeTokenSrcs[address].Cancel(); + FreezeTokenSrcs.Remove(address); + } + catch + { + Debug.WriteLine("ERROR: Avoided a crash. Address " + address + " was not frozen."); + } + } + else + Debug.WriteLine("Adding Freezing Address " + address + " Value " + value); + + FreezeTokenSrcs.Add(address, cts); + } + + Task.Factory.StartNew(() => + { + while (!cts.Token.IsCancellationRequested) + { + WriteMemory(address, type, value, file); + Thread.Sleep(25); + } + }, + cts.Token); + } + + /// + /// Unfreeze a frozen value at an address + /// + /// address where frozen value is stored + public void UnfreezeValue(string address) + { + Debug.WriteLine("Un-Freezing Address " + address); + try + { + lock (FreezeTokenSrcs) + { + FreezeTokenSrcs[address].Cancel(); + FreezeTokenSrcs.Remove(address); + } + } + catch + { + Debug.WriteLine("ERROR: Address " + address + " was not frozen."); + } + } + + /// + ///Write to memory address. See https://github.com/erfg12/memory.dll/wiki/writeMemory() for more information. + /// + ///address, module + pointer + offset, module + offset OR label in .ini file. + ///byte, 2bytes, bytes, float, int, string, double or long. + ///value to write to address. + ///path and name of .ini file (OPTIONAL) + ///System.Text.Encoding.UTF8 (DEFAULT). Other options: ascii, unicode, utf32, utf7 + ///If building a trainer on an emulator (Ex: RPCS3) you'll want to set this to false + public bool WriteMemory(string code, string type, string write, string file = "", System.Text.Encoding stringEncoding = null, bool RemoveWriteProtection = true) + { + byte[] memory = new byte[4]; + int size = 4; + + UIntPtr theCode; + theCode = GetCode(code, file); + + if (type.ToLower() == "float") + { + write = Convert.ToString(float.Parse(write, CultureInfo.InvariantCulture)); + memory = BitConverter.GetBytes(Convert.ToSingle(write)); + size = 4; + } + else if (type.ToLower() == "int") + { + memory = BitConverter.GetBytes(Convert.ToInt32(write)); + size = 4; + } + else if (type.ToLower() == "byte") + { + memory = new byte[1]; + memory[0] = Convert.ToByte(write, 16); + size = 1; + } + else if (type.ToLower() == "2bytes") + { + memory = new byte[2]; + memory[0] = (byte)(Convert.ToInt32(write) % 256); + memory[1] = (byte)(Convert.ToInt32(write) / 256); + size = 2; + } + else if (type.ToLower() == "bytes") + { + if (write.Contains(",") || write.Contains(" ")) //check if it's a proper array + { + string[] stringBytes; + if (write.Contains(",")) + stringBytes = write.Split(','); + else + stringBytes = write.Split(' '); + //Debug.WriteLine("write:" + write + " stringBytes:" + stringBytes); + + int c = stringBytes.Count(); + memory = new byte[c]; + for (int i = 0; i < c; i++) + { + memory[i] = Convert.ToByte(stringBytes[i], 16); + } + size = stringBytes.Count(); + } + else //wasnt array, only 1 byte + { + memory = new byte[1]; + memory[0] = Convert.ToByte(write, 16); + size = 1; + } + } + else if (type.ToLower() == "double") + { + memory = BitConverter.GetBytes(Convert.ToDouble(write)); + size = 8; + } + else if (type.ToLower() == "long") + { + memory = BitConverter.GetBytes(Convert.ToInt64(write)); + size = 8; + } + else if (type.ToLower() == "string") + { + if (stringEncoding == null) + memory = System.Text.Encoding.UTF8.GetBytes(write); + else + memory = stringEncoding.GetBytes(write); + size = memory.Length; + } + + //Debug.Write("DEBUG: Writing bytes [TYPE:" + type + " ADDR:" + theCode + "] " + String.Join(",", memory) + Environment.NewLine); + MemoryProtection OldMemProt = 0x00; + bool WriteProcMem = false; + if (RemoveWriteProtection) + ChangeProtection(code, MemoryProtection.ExecuteReadWrite, out OldMemProt); // change protection + WriteProcMem = WriteProcessMemory(mProc.Handle, theCode, memory, (UIntPtr)size, IntPtr.Zero); + if (RemoveWriteProtection) + ChangeProtection(code, OldMemProt, out _); // restore + return WriteProcMem; + } + + /// + /// Write to address and move by moveQty. Good for byte arrays. See https://github.com/erfg12/memory.dll/wiki/Writing-a-Byte-Array for more information. + /// + ///address, module + pointer + offset, module + offset OR label in .ini file. + ///byte, bytes, float, int, string or long. + /// byte to write + /// quantity to move + /// path and name of .ini file (OPTIONAL) + /// milliseconds to sleep between each byte + /// + public bool WriteMove(string code, string type, string write, int MoveQty, string file = "", int SlowDown = 0) + { + byte[] memory = new byte[4]; + int size = 4; + + UIntPtr theCode; + theCode = GetCode(code, file); + + if (type == "float") + { + memory = new byte[write.Length]; + memory = BitConverter.GetBytes(Convert.ToSingle(write)); + size = write.Length; + } + else if (type == "int") + { + memory = BitConverter.GetBytes(Convert.ToInt32(write)); + size = 4; + } + else if (type == "double") + { + memory = BitConverter.GetBytes(Convert.ToDouble(write)); + size = 8; + } + else if (type == "long") + { + memory = BitConverter.GetBytes(Convert.ToInt64(write)); + size = 8; + } + else if (type == "byte") + { + memory = new byte[1]; + memory[0] = Convert.ToByte(write, 16); + size = 1; + } + else if (type == "string") + { + memory = new byte[write.Length]; + memory = System.Text.Encoding.UTF8.GetBytes(write); + size = write.Length; + } + + UIntPtr newCode = UIntPtr.Add(theCode, MoveQty); + + //Debug.Write("DEBUG: Writing bytes [TYPE:" + type + " ADDR:[O]" + theCode + " [N]" + newCode + " MQTY:" + MoveQty + "] " + String.Join(",", memory) + Environment.NewLine); + Thread.Sleep(SlowDown); + return WriteProcessMemory(mProc.Handle, newCode, memory, (UIntPtr)size, IntPtr.Zero); + } + + /// + /// Write byte array to addresses. + /// + /// address to write to + /// byte array to write + /// path and name of ini file. (OPTIONAL) + public void WriteBytes(string code, byte[] write, string file = "") + { + UIntPtr theCode; + theCode = GetCode(code, file); + WriteProcessMemory(mProc.Handle, theCode, write, (UIntPtr)write.Length, IntPtr.Zero); + } + + /// + /// Takes an array of 8 booleans and writes to a single byte + /// + /// address to write to + /// Array of 8 booleans to write + /// path and name of ini file. (OPTIONAL) + public void WriteBits(string code, bool[] bits, string file = "") + { + if (bits.Length != 8) + throw new ArgumentException("Not enough bits for a whole byte", nameof(bits)); + + byte[] buf = new byte[1]; + + UIntPtr theCode = GetCode(code, file); + + for (var i = 0; i < 8; i++) + { + if (bits[i]) + buf[0] |= (byte)(1 << i); + } + + WriteProcessMemory(mProc.Handle, theCode, buf, (UIntPtr)1, IntPtr.Zero); + } + + /// + /// Write byte array to address + /// + /// Address to write to + /// Byte array to write to + public void WriteBytes(UIntPtr address, byte[] write) + { + WriteProcessMemory(mProc.Handle, address, write, (UIntPtr)write.Length, out IntPtr bytesRead); + } + } +} diff --git a/Memory/README.txt b/Memory/README.txt index 2e55a72..395eeda 100644 --- a/Memory/README.txt +++ b/Memory/README.txt @@ -1,4 +1,4 @@ -Thank you for choosing Memory.dll! Created by NeWaGe and hollow87 at New Age Software. +Thank you for choosing Memory.dll! BEFORE YOU START diff --git a/Memory/Structures/Imports.cs b/Memory/Structures/Imports.cs new file mode 100644 index 0000000..b46050f --- /dev/null +++ b/Memory/Structures/Imports.cs @@ -0,0 +1,354 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace Memory +{ + public class Imps + { + [DllImport("kernel32.dll")] + public static extern IntPtr OpenProcess( + UInt32 dwDesiredAccess, + bool bInheritHandle, + Int32 dwProcessId + ); + +#if WINXP +#else + [DllImport("kernel32.dll", EntryPoint = "VirtualQueryEx")] + public static extern UIntPtr Native_VirtualQueryEx(IntPtr hProcess, UIntPtr lpAddress, + out MEMORY_BASIC_INFORMATION32 lpBuffer, UIntPtr dwLength); + + [DllImport("kernel32.dll", EntryPoint = "VirtualQueryEx")] + public static extern UIntPtr Native_VirtualQueryEx(IntPtr hProcess, UIntPtr lpAddress, + out MEMORY_BASIC_INFORMATION64 lpBuffer, UIntPtr dwLength); + + [DllImport("kernel32.dll")] + static extern uint GetLastError(); + + + + [DllImport("kernel32.dll")] + public static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo); +#endif + + [DllImport("kernel32.dll")] + public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); + [DllImport("kernel32.dll")] + public static extern uint SuspendThread(IntPtr hThread); + [DllImport("kernel32.dll")] + public static extern int ResumeThread(IntPtr hThread); + + [DllImport("dbghelp.dll")] + static extern bool MiniDumpWriteDump( + IntPtr hProcess, + Int32 ProcessId, + IntPtr hFile, + MINIDUMP_TYPE DumpType, + IntPtr ExceptionParam, + IntPtr UserStreamParam, + IntPtr CallackParam); + + [DllImport("user32.dll", SetLastError = true)] + public static extern int GetWindowLong(IntPtr hWnd, int nIndex); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] + public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr w, IntPtr l); + + [DllImport("kernel32.dll")] + public static extern bool WriteProcessMemory( + IntPtr hProcess, + UIntPtr lpBaseAddress, + string lpBuffer, + UIntPtr nSize, + out IntPtr lpNumberOfBytesWritten + ); + + [DllImport("kernel32.dll")] + public static extern int GetProcessId(IntPtr handle); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + public static extern uint GetPrivateProfileString( + string lpAppName, + string lpKeyName, + string lpDefault, + StringBuilder lpReturnedString, + uint nSize, + string lpFileName); + + [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] + public static extern bool VirtualFreeEx( + IntPtr hProcess, + UIntPtr lpAddress, + UIntPtr dwSize, + uint dwFreeType + ); + + [DllImport("psapi.dll")] + static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, [In][MarshalAs(UnmanagedType.U4)] int nSize); + [DllImport("psapi.dll", SetLastError = true)] + public static extern bool EnumProcessModules(IntPtr hProcess, + [Out] IntPtr lphModule, + uint cb, + [MarshalAs(UnmanagedType.U4)] out uint lpcbNeeded); + + [DllImport("kernel32.dll")] + public static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr lpBaseAddress, [Out] byte[] lpBuffer, UIntPtr nSize, IntPtr lpNumberOfBytesRead); + + [DllImport("kernel32.dll")] + public static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr lpBaseAddress, [Out] byte[] lpBuffer, UIntPtr nSize, out ulong lpNumberOfBytesRead); + + [DllImport("kernel32.dll")] + public static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr lpBaseAddress, [Out] IntPtr lpBuffer, UIntPtr nSize, out ulong lpNumberOfBytesRead); + + [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] + public static extern UIntPtr VirtualAllocEx( + IntPtr hProcess, + UIntPtr lpAddress, + uint dwSize, + uint flAllocationType, + uint flProtect + ); + + [DllImport("kernel32.dll")] + public static extern bool VirtualProtectEx(IntPtr hProcess, UIntPtr lpAddress, + IntPtr dwSize, MemoryProtection flNewProtect, out MemoryProtection lpflOldProtect); + + [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true)] + public static extern UIntPtr GetProcAddress( + IntPtr hModule, + string procName + ); + + [DllImport("kernel32.dll", EntryPoint = "CloseHandle")] + private static extern bool _CloseHandle(IntPtr hObject); + + [DllImport("kernel32.dll")] + public static extern Int32 CloseHandle( + IntPtr hObject + ); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto)] + public static extern IntPtr GetModuleHandle( + string lpModuleName + ); + + [DllImport("kernel32", SetLastError = true, ExactSpelling = true)] + internal static extern Int32 WaitForSingleObject( + IntPtr handle, + Int32 milliseconds + ); + + [DllImport("kernel32.dll")] + public static extern bool WriteProcessMemory(IntPtr hProcess, UIntPtr lpBaseAddress, byte[] lpBuffer, UIntPtr nSize, IntPtr lpNumberOfBytesWritten); + + // Added to avoid casting to UIntPtr + [DllImport("kernel32.dll")] + public static extern bool WriteProcessMemory(IntPtr hProcess, UIntPtr lpBaseAddress, byte[] lpBuffer, UIntPtr nSize, out IntPtr lpNumberOfBytesWritten); + + [DllImport("kernel32")] + public static extern IntPtr CreateRemoteThread( + IntPtr hProcess, + IntPtr lpThreadAttributes, + uint dwStackSize, + UIntPtr lpStartAddress, // raw Pointer into remote process + UIntPtr lpParameter, + uint dwCreationFlags, + out IntPtr lpThreadId + ); + + [DllImport("kernel32")] + public static extern bool IsWow64Process(IntPtr hProcess, out bool lpSystemInfo); + + [DllImport("user32.dll")] + public static extern bool SetForegroundWindow(IntPtr hWnd); + + [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern IntPtr CreateToolhelp32Snapshot([In] UInt32 dwFlags, [In] UInt32 th32ProcessID); + + [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + static extern bool Process32First([In] IntPtr hSnapshot, ref PROCESSENTRY32 lppe); + [DllImport("kernel32.dll")] + public static extern bool Module32First(IntPtr hSnapshot, ref MODULEENTRY32 lpme); + [DllImport("kernel32.dll")] + public static extern bool Module32Next(IntPtr hSnapshot, ref MODULEENTRY32 lpme); + + [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + static extern bool Process32Next([In] IntPtr hSnapshot, ref PROCESSENTRY32 lppe); + + // privileges + public const int PROCESS_CREATE_THREAD = 0x0002; + public const int PROCESS_QUERY_INFORMATION = 0x0400; + public const int PROCESS_VM_OPERATION = 0x0008; + public const int PROCESS_VM_WRITE = 0x0020; + public const int PROCESS_VM_READ = 0x0010; + + // used for memory allocation + public const uint MEM_FREE = 0x10000; + public const uint MEM_COMMIT = 0x00001000; + public const uint MEM_RESERVE = 0x00002000; + + public const uint PAGE_READONLY = 0x02; + public const uint PAGE_READWRITE = 0x04; + public const uint PAGE_WRITECOPY = 0x08; + public const uint PAGE_EXECUTE_READWRITE = 0x40; + public const uint PAGE_EXECUTE_WRITECOPY = 0x80; + public const uint PAGE_EXECUTE = 0x10; + public const uint PAGE_EXECUTE_READ = 0x20; + + public const uint PAGE_GUARD = 0x100; + public const uint PAGE_NOACCESS = 0x01; + + public const uint MEM_PRIVATE = 0x20000; + public const uint MEM_IMAGE = 0x1000000; + + internal enum MINIDUMP_TYPE + { + MiniDumpNormal = 0x00000000, + MiniDumpWithDataSegs = 0x00000001, + MiniDumpWithFullMemory = 0x00000002, + MiniDumpWithHandleData = 0x00000004, + MiniDumpFilterMemory = 0x00000008, + MiniDumpScanMemory = 0x00000010, + MiniDumpWithUnloadedModules = 0x00000020, + MiniDumpWithIndirectlyReferencedMemory = 0x00000040, + MiniDumpFilterModulePaths = 0x00000080, + MiniDumpWithProcessThreadData = 0x00000100, + MiniDumpWithPrivateReadWriteMemory = 0x00000200, + MiniDumpWithoutOptionalData = 0x00000400, + MiniDumpWithFullMemoryInfo = 0x00000800, + MiniDumpWithThreadInfo = 0x00001000, + MiniDumpWithCodeSegs = 0x00002000 + } + + public struct SYSTEM_INFO + { + public ushort processorArchitecture; + ushort reserved; + public uint pageSize; + public UIntPtr minimumApplicationAddress; + public UIntPtr maximumApplicationAddress; + public IntPtr activeProcessorMask; + public uint numberOfProcessors; + public uint processorType; + public uint allocationGranularity; + public ushort processorLevel; + public ushort processorRevision; + } + + public struct MEMORY_BASIC_INFORMATION32 + { + public UIntPtr BaseAddress; + public UIntPtr AllocationBase; + public uint AllocationProtect; + public uint RegionSize; + public uint State; + public uint Protect; + public uint Type; + } + + public struct MEMORY_BASIC_INFORMATION64 + { + public UIntPtr BaseAddress; + public UIntPtr AllocationBase; + public uint AllocationProtect; + public uint __alignment1; + public ulong RegionSize; + public uint State; + public uint Protect; + public uint Type; + public uint __alignment2; + } + + public struct MEMORY_BASIC_INFORMATION + { + public UIntPtr BaseAddress; + public UIntPtr AllocationBase; + public uint AllocationProtect; + public long RegionSize; + public uint State; + public uint Protect; + public uint Type; + } + + private enum SnapshotFlags : uint + { + HeapList = 0x00000001, + Process = 0x00000002, + Thread = 0x00000004, + Module = 0x00000008, + Module32 = 0x00000010, + Inherit = 0x80000000, + All = 0x0000001F, + NoHeaps = 0x40000000 + } + + [Flags] + public enum ThreadAccess : int + { + TERMINATE = (0x0001), + SUSPEND_RESUME = (0x0002), + GET_CONTEXT = (0x0008), + SET_CONTEXT = (0x0010), + SET_INFORMATION = (0x0020), + QUERY_INFORMATION = (0x0040), + SET_THREAD_TOKEN = (0x0080), + IMPERSONATE = (0x0100), + DIRECT_IMPERSONATION = (0x0200) + } + + [Flags] + public enum MemoryProtection : uint + { + Execute = 0x10, + ExecuteRead = 0x20, + ExecuteReadWrite = 0x40, + ExecuteWriteCopy = 0x80, + NoAccess = 0x01, + ReadOnly = 0x02, + ReadWrite = 0x04, + WriteCopy = 0x08, + GuardModifierflag = 0x100, + NoCacheModifierflag = 0x200, + WriteCombineModifierflag = 0x400 + } + + //inner struct used only internally + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + private struct PROCESSENTRY32 + { + const int MAX_PATH = 260; + internal UInt32 dwSize; + internal UInt32 cntUsage; + internal UInt32 th32ProcessID; + internal IntPtr th32DefaultHeapID; + internal UInt32 th32ModuleID; + internal UInt32 cntThreads; + internal UInt32 th32ParentProcessID; + internal Int32 pcPriClassBase; + internal UInt32 dwFlags; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] + internal string szExeFile; + } + + [StructLayout(LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public struct MODULEENTRY32 + { + internal uint dwSize; + internal uint th32ModuleID; + internal uint th32ProcessID; + internal uint GlblcntUsage; + internal uint ProccntUsage; + internal IntPtr modBaseAddr; + internal uint modBaseSize; + internal IntPtr hModule; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + internal string szModule; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] + internal string szExePath; + } + + + } +} \ No newline at end of file diff --git a/Memory/MemoryRegionResult.cs b/Memory/Structures/MemoryRegionResult.cs similarity index 83% rename from Memory/MemoryRegionResult.cs rename to Memory/Structures/MemoryRegionResult.cs index 1d04e25..e137a2a 100644 --- a/Memory/MemoryRegionResult.cs +++ b/Memory/Structures/MemoryRegionResult.cs @@ -6,6 +6,9 @@ namespace Memory { + /// + /// AoB scan information. + /// struct MemoryRegionResult { public UIntPtr CurrentBaseAddress { get; set; } diff --git a/Memory/Structures/Process.cs b/Memory/Structures/Process.cs new file mode 100644 index 0000000..a20f6f9 --- /dev/null +++ b/Memory/Structures/Process.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace Memory +{ + /// + /// Information about the opened process. + /// + public class Proc + { + public Process Process { get; set; } + public IntPtr Handle { get; set; } + public bool Is64Bit { get; set; } + public Dictionary Modules { get; set; } + public ProcessModule MainModule { get; set; } + } +} diff --git a/Memory/memory.cs b/Memory/memory.cs index 83303f2..05da64d 100644 --- a/Memory/memory.cs +++ b/Memory/memory.cs @@ -6,50 +6,27 @@ using System.Text; using System.Runtime.InteropServices; using System.Diagnostics; -using System.Threading; using System.Globalization; -//using System.Windows.Forms; using System.Security.Principal; using System.Threading.Tasks; -using System.Collections.Concurrent; -using System.Reflection; using System.ComponentModel; +using static Memory.Imps; namespace Memory { /// /// Memory.dll class. Full documentation at https://github.com/erfg12/memory.dll/wiki /// - public class Mem + public partial class Mem { - #region DllImports - [DllImport("kernel32.dll")] - public static extern IntPtr OpenProcess( - UInt32 dwDesiredAccess, - bool bInheritHandle, - Int32 dwProcessId - ); + public Proc mProc = new Proc(); -#if WINXP -#else - [DllImport("kernel32.dll", EntryPoint = "VirtualQueryEx")] - public static extern UIntPtr Native_VirtualQueryEx(IntPtr hProcess, UIntPtr lpAddress, - out MEMORY_BASIC_INFORMATION32 lpBuffer, UIntPtr dwLength); - - [DllImport("kernel32.dll", EntryPoint = "VirtualQueryEx")] - public static extern UIntPtr Native_VirtualQueryEx(IntPtr hProcess, UIntPtr lpAddress, - out MEMORY_BASIC_INFORMATION64 lpBuffer, UIntPtr dwLength); - - [DllImport("kernel32.dll")] - static extern uint GetLastError(); - - public UIntPtr VirtualQueryEx(IntPtr hProcess, UIntPtr lpAddress, - out MEMORY_BASIC_INFORMATION lpBuffer) + public UIntPtr VirtualQueryEx(IntPtr hProcess, UIntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer) { UIntPtr retVal; // TODO: Need to change this to only check once. - if (Is64Bit || IntPtr.Size == 8) + if (mProc.Is64Bit || IntPtr.Size == 8) { // 64 bit MEMORY_BASIC_INFORMATION64 tmp64 = new MEMORY_BASIC_INFORMATION64(); @@ -65,7 +42,6 @@ public UIntPtr VirtualQueryEx(IntPtr hProcess, UIntPtr lpAddress, return retVal; } - MEMORY_BASIC_INFORMATION32 tmp32 = new MEMORY_BASIC_INFORMATION32(); retVal = Native_VirtualQueryEx(hProcess, lpAddress, out tmp32, new UIntPtr((uint)Marshal.SizeOf(tmp32))); @@ -81,333 +57,11 @@ public UIntPtr VirtualQueryEx(IntPtr hProcess, UIntPtr lpAddress, return retVal; } - [DllImport("kernel32.dll")] - static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo); -#endif - - [DllImport("kernel32.dll")] - static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); - [DllImport("kernel32.dll")] - static extern uint SuspendThread(IntPtr hThread); - [DllImport("kernel32.dll")] - static extern int ResumeThread(IntPtr hThread); - - [DllImport("dbghelp.dll")] - static extern bool MiniDumpWriteDump( - IntPtr hProcess, - Int32 ProcessId, - IntPtr hFile, - MINIDUMP_TYPE DumpType, - IntPtr ExceptionParam, - IntPtr UserStreamParam, - IntPtr CallackParam); - - [DllImport("user32.dll", SetLastError = true)] - static extern int GetWindowLong(IntPtr hWnd, int nIndex); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] - public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr w, IntPtr l); - - [DllImport("kernel32.dll")] - static extern bool WriteProcessMemory( - IntPtr hProcess, - UIntPtr lpBaseAddress, - string lpBuffer, - UIntPtr nSize, - out IntPtr lpNumberOfBytesWritten - ); - - [DllImport("kernel32.dll")] - static extern int GetProcessId(IntPtr handle); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - static extern uint GetPrivateProfileString( - string lpAppName, - string lpKeyName, - string lpDefault, - StringBuilder lpReturnedString, - uint nSize, - string lpFileName); - - [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] - static extern bool VirtualFreeEx( - IntPtr hProcess, - UIntPtr lpAddress, - UIntPtr dwSize, - uint dwFreeType - ); - - [DllImport("psapi.dll")] - static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, [In][MarshalAs(UnmanagedType.U4)] int nSize); - [DllImport("psapi.dll", SetLastError = true)] - public static extern bool EnumProcessModules(IntPtr hProcess, - [Out] IntPtr lphModule, - uint cb, - [MarshalAs(UnmanagedType.U4)] out uint lpcbNeeded); - - [DllImport("kernel32.dll")] - private static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr lpBaseAddress, [Out] byte[] lpBuffer, UIntPtr nSize, IntPtr lpNumberOfBytesRead); - - [DllImport("kernel32.dll")] - private static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr lpBaseAddress, [Out] byte[] lpBuffer, UIntPtr nSize, out ulong lpNumberOfBytesRead); - - [DllImport("kernel32.dll")] - private static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr lpBaseAddress, [Out] IntPtr lpBuffer, UIntPtr nSize, out ulong lpNumberOfBytesRead); - - [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] - static extern UIntPtr VirtualAllocEx( - IntPtr hProcess, - UIntPtr lpAddress, - uint dwSize, - uint flAllocationType, - uint flProtect - ); - - [DllImport("kernel32.dll")] - static extern bool VirtualProtectEx(IntPtr hProcess, UIntPtr lpAddress, - IntPtr dwSize, MemoryProtection flNewProtect, out MemoryProtection lpflOldProtect); - - [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true)] - public static extern UIntPtr GetProcAddress( - IntPtr hModule, - string procName - ); - - [DllImport("kernel32.dll", EntryPoint = "CloseHandle")] - private static extern bool _CloseHandle(IntPtr hObject); - - [DllImport("kernel32.dll")] - public static extern Int32 CloseHandle( - IntPtr hObject - ); - - [DllImport("kernel32.dll", CharSet = CharSet.Auto)] - public static extern IntPtr GetModuleHandle( - string lpModuleName - ); - - [DllImport("kernel32", SetLastError = true, ExactSpelling = true)] - internal static extern Int32 WaitForSingleObject( - IntPtr handle, - Int32 milliseconds - ); - - [DllImport("kernel32.dll")] - private static extern bool WriteProcessMemory(IntPtr hProcess, UIntPtr lpBaseAddress, byte[] lpBuffer, UIntPtr nSize, IntPtr lpNumberOfBytesWritten); - - // Added to avoid casting to UIntPtr - [DllImport("kernel32.dll")] - private static extern bool WriteProcessMemory(IntPtr hProcess, UIntPtr lpBaseAddress, byte[] lpBuffer, UIntPtr nSize, out IntPtr lpNumberOfBytesWritten); - - [DllImport("kernel32")] - public static extern IntPtr CreateRemoteThread( - IntPtr hProcess, - IntPtr lpThreadAttributes, - uint dwStackSize, - UIntPtr lpStartAddress, // raw Pointer into remote process - UIntPtr lpParameter, - uint dwCreationFlags, - out IntPtr lpThreadId - ); - - [DllImport("kernel32")] - public static extern bool IsWow64Process(IntPtr hProcess, out bool lpSystemInfo); - - [DllImport("user32.dll")] - static extern bool SetForegroundWindow(IntPtr hWnd); - - private enum SnapshotFlags : uint - { - HeapList = 0x00000001, - Process = 0x00000002, - Thread = 0x00000004, - Module = 0x00000008, - Module32 = 0x00000010, - Inherit = 0x80000000, - All = 0x0000001F, - NoHeaps = 0x40000000 - } - //inner struct used only internally - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - private struct PROCESSENTRY32 - { - const int MAX_PATH = 260; - internal UInt32 dwSize; - internal UInt32 cntUsage; - internal UInt32 th32ProcessID; - internal IntPtr th32DefaultHeapID; - internal UInt32 th32ModuleID; - internal UInt32 cntThreads; - internal UInt32 th32ParentProcessID; - internal Int32 pcPriClassBase; - internal UInt32 dwFlags; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - internal string szExeFile; - } - - [StructLayout(LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Auto)] - public struct MODULEENTRY32 - { - internal uint dwSize; - internal uint th32ModuleID; - internal uint th32ProcessID; - internal uint GlblcntUsage; - internal uint ProccntUsage; - internal IntPtr modBaseAddr; - internal uint modBaseSize; - internal IntPtr hModule; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] - internal string szModule; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - internal string szExePath; - } - - [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] - static extern IntPtr CreateToolhelp32Snapshot([In] UInt32 dwFlags, [In] UInt32 th32ProcessID); - - [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] - static extern bool Process32First([In] IntPtr hSnapshot, ref PROCESSENTRY32 lppe); - [DllImport("kernel32.dll")] - static extern bool Module32First(IntPtr hSnapshot, ref MODULEENTRY32 lpme); - [DllImport("kernel32.dll")] - static extern bool Module32Next(IntPtr hSnapshot, ref MODULEENTRY32 lpme); - - [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] - static extern bool Process32Next([In] IntPtr hSnapshot, ref PROCESSENTRY32 lppe); - - // privileges - const int PROCESS_CREATE_THREAD = 0x0002; - const int PROCESS_QUERY_INFORMATION = 0x0400; - const int PROCESS_VM_OPERATION = 0x0008; - const int PROCESS_VM_WRITE = 0x0020; - const int PROCESS_VM_READ = 0x0010; - - // used for memory allocation - const uint MEM_FREE = 0x10000; - const uint MEM_COMMIT = 0x00001000; - const uint MEM_RESERVE = 0x00002000; - - private const uint PAGE_READONLY = 0x02; - const uint PAGE_READWRITE = 0x04; - const uint PAGE_WRITECOPY = 0x08; - private const uint PAGE_EXECUTE_READWRITE = 0x40; - private const uint PAGE_EXECUTE_WRITECOPY = 0x80; - private const uint PAGE_EXECUTE = 0x10; - private const uint PAGE_EXECUTE_READ = 0x20; - - private const uint PAGE_GUARD = 0x100; - private const uint PAGE_NOACCESS = 0x01; - - private uint MEM_PRIVATE = 0x20000; - private uint MEM_IMAGE = 0x1000000; - - #endregion - - /// - /// The process handle that was opened. (Use OpenProcess function to populate this variable) - /// - public IntPtr pHandle; - Dictionary FreezeTokenSrcs = new Dictionary(); - public Process theProc = null; - - internal enum MINIDUMP_TYPE - { - MiniDumpNormal = 0x00000000, - MiniDumpWithDataSegs = 0x00000001, - MiniDumpWithFullMemory = 0x00000002, - MiniDumpWithHandleData = 0x00000004, - MiniDumpFilterMemory = 0x00000008, - MiniDumpScanMemory = 0x00000010, - MiniDumpWithUnloadedModules = 0x00000020, - MiniDumpWithIndirectlyReferencedMemory = 0x00000040, - MiniDumpFilterModulePaths = 0x00000080, - MiniDumpWithProcessThreadData = 0x00000100, - MiniDumpWithPrivateReadWriteMemory = 0x00000200, - MiniDumpWithoutOptionalData = 0x00000400, - MiniDumpWithFullMemoryInfo = 0x00000800, - MiniDumpWithThreadInfo = 0x00001000, - MiniDumpWithCodeSegs = 0x00002000 - } - - bool IsDigitsOnly(string str) - { - foreach (char c in str) - { - if (c < '0' || c > '9') - return false; - } - return true; - } - - /// - /// Freeze a value to an address. - /// - /// Your address - /// byte, 2bytes, bytes, float, int, string, double or long. - /// Value to freeze - /// ini file to read address from (OPTIONAL) - public void FreezeValue(string address, string type, string value, string file = "") - { - CancellationTokenSource cts = new CancellationTokenSource(); - - lock (FreezeTokenSrcs) - { - if (FreezeTokenSrcs.ContainsKey(address)) - { - Debug.WriteLine("Changing Freezing Address " + address + " Value " + value); - try - { - FreezeTokenSrcs[address].Cancel(); - FreezeTokenSrcs.Remove(address); - } - catch - { - Debug.WriteLine("ERROR: Avoided a crash. Address " + address + " was not frozen."); - } - } - else - Debug.WriteLine("Adding Freezing Address " + address + " Value " + value); - - FreezeTokenSrcs.Add(address, cts); - } - - Task.Factory.StartNew(() => - { - while (!cts.Token.IsCancellationRequested) - { - WriteMemory(address, type, value, file); - Thread.Sleep(25); - } - }, - cts.Token); - } - - /// - /// Unfreeze a frozen value at an address - /// - /// address where frozen value is stored - public void UnfreezeValue(string address) - { - Debug.WriteLine("Un-Freezing Address " + address); - try - { - lock (FreezeTokenSrcs) - { - FreezeTokenSrcs[address].Cancel(); - FreezeTokenSrcs.Remove(address); - } - } - catch - { - Debug.WriteLine("ERROR: Address " + address + " was not frozen."); - } - } - /// /// Open the PC game process with all security and access rights. /// /// Use process name or process ID here. - /// + /// Process opened successfully or failed. public bool OpenProcess(int pid) { if (!IsAdmin()) @@ -422,44 +76,44 @@ public bool OpenProcess(int pid) } - if (theProc != null && theProc.Id == pid) + if (mProc.Process != null && mProc.Process.Id == pid) return true; try { - theProc = Process.GetProcessById(pid); + mProc.Process = System.Diagnostics.Process.GetProcessById(pid); - if (theProc != null && !theProc.Responding) + if (mProc.Process != null && !mProc.Process.Responding) { Debug.WriteLine("ERROR: OpenProcess: Process is not responding or null."); return false; } - pHandle = OpenProcess(0x1F0FFF, true, pid); + mProc.Handle = Imps.OpenProcess(0x1F0FFF, true, pid); - try { - Process.EnterDebugMode(); + try { + System.Diagnostics.Process.EnterDebugMode(); } catch (Win32Exception) { //Debug.WriteLine("WARNING: You are not running with raised privileges! Visit https://github.com/erfg12/memory.dll/wiki/Administrative-Privileges"); } - if (pHandle == IntPtr.Zero) + if (mProc.Handle == IntPtr.Zero) { var eCode = Marshal.GetLastWin32Error(); Debug.WriteLine("ERROR: OpenProcess has failed opening a handle to the target process (GetLastWin32ErrorCode: " + eCode + ")"); - Process.LeaveDebugMode(); - theProc = null; + System.Diagnostics.Process.LeaveDebugMode(); + mProc = null; return false; } // Lets set the process to 64bit or not here (cuts down on api calls) - Is64Bit = Environment.Is64BitOperatingSystem && (IsWow64Process(pHandle, out bool retVal) && !retVal); + mProc.Is64Bit = Environment.Is64BitOperatingSystem && (IsWow64Process(mProc.Handle, out bool retVal) && !retVal); - mainModule = theProc.MainModule; + mProc.MainModule = mProc.Process.MainModule; GetModules(); - Debug.WriteLine("Process #" + theProc + " is now open."); + Debug.WriteLine("Process #" + mProc.Process + " is now open."); return true; } @@ -501,43 +155,32 @@ public bool IsAdmin() } } - /// - /// Check if opened process is 64bit. Used primarily for getCode(). - /// - /// True if 64bit false if 32bit. - private bool _is64Bit; - public bool Is64Bit - { - get { return _is64Bit; } - private set { _is64Bit = value; } - } - /// /// Builds the process modules dictionary (names with addresses). /// public void GetModules() { - if (theProc == null) + if (mProc.Process == null) return; - if (_is64Bit && IntPtr.Size != 8) + if (mProc.Is64Bit && IntPtr.Size != 8) { Debug.WriteLine("WARNING: Game is x64, but your Trainer is x86! You will be missing some modules, change your Trainer's Solution Platform."); } - else if (!_is64Bit && IntPtr.Size == 8) + else if (!mProc.Is64Bit && IntPtr.Size == 8) { Debug.WriteLine("WARNING: Game is x86, but your Trainer is x64! You will be missing some modules, change your Trainer's Solution Platform."); } - modules.Clear(); + mProc.Modules.Clear(); - foreach (ProcessModule Module in theProc.Modules) + foreach (ProcessModule Module in mProc.Process.Modules) { - if (!string.IsNullOrEmpty(Module.ModuleName) && !modules.ContainsKey(Module.ModuleName)) - modules.Add(Module.ModuleName, Module.BaseAddress); + if (!string.IsNullOrEmpty(Module.ModuleName) && !mProc.Modules.ContainsKey(Module.ModuleName)) + mProc.Modules.Add(Module.ModuleName, Module.BaseAddress); } - Debug.WriteLine("Found " + modules.Count() + " process modules."); + Debug.WriteLine("Found " + mProc.Modules.Count() + " process modules."); } public void SetFocus() @@ -545,7 +188,7 @@ public void SetFocus() //int style = GetWindowLong(procs.MainWindowHandle, -16); //if ((style & 0x20000000) == 0x20000000) //minimized // SendMessage(procs.Handle, 0x0112, (IntPtr)0xF120, IntPtr.Zero); - SetForegroundWindow(theProc.MainWindowHandle); + SetForegroundWindow(mProc.Process.MainWindowHandle); } /// @@ -562,7 +205,7 @@ public int GetProcIdFromName(string name) //new 1.0.2 function if (name.ToLower().Contains(".bin")) // test name = name.Replace(".bin", ""); - foreach (Process theprocess in processlist) + foreach (System.Diagnostics.Process theprocess in processlist) { if (theprocess.ProcessName.Equals(name, StringComparison.CurrentCultureIgnoreCase)) //find (name).exe in the process list (use task manager to find the name) return theprocess.Id; @@ -613,11 +256,6 @@ private int LoadIntCode(string name, string path) } } - /// - /// Dictionary with our opened process module names with addresses. - /// - public Dictionary modules = new Dictionary(); - /// /// Make a named pipe (if not already made) and call to a remote function. /// @@ -639,617 +277,22 @@ public void ThreadStartClient(string func, string name) sw.WriteLine(func); } } - } - - private ProcessModule mainModule; - - /// - /// Cut a string that goes on for too long or one that is possibly merged with another string. - /// - /// The string you want to cut. - /// - public string CutString(string str) - { - StringBuilder sb = new StringBuilder(); - foreach (char c in str) - { - if (c >= ' ' && c <= '~') - sb.Append(c); - else - break; - } - return sb.ToString(); - } - - /// - /// Clean up a string that has bad characters in it. - /// - /// The string you want to sanitize. - /// - public string SanitizeString(string str) - { - StringBuilder sb = new StringBuilder(); - foreach (char c in str) - { - if (c >= ' ' && c <= '~') - sb.Append(c); - } - return sb.ToString(); - } + } #region protection - [Flags] - public enum MemoryProtection : uint - { - Execute = 0x10, - ExecuteRead = 0x20, - ExecuteReadWrite = 0x40, - ExecuteWriteCopy = 0x80, - NoAccess = 0x01, - ReadOnly = 0x02, - ReadWrite = 0x04, - WriteCopy = 0x08, - GuardModifierflag = 0x100, - NoCacheModifierflag = 0x200, - WriteCombineModifierflag = 0x400 - } public bool ChangeProtection(string code, MemoryProtection newProtection, out MemoryProtection oldProtection, string file = "") { UIntPtr theCode = GetCode(code, file); if (theCode == UIntPtr.Zero - || pHandle == IntPtr.Zero) + || mProc.Handle == IntPtr.Zero) { oldProtection = default; return false; } - return VirtualProtectEx(pHandle, theCode, (IntPtr)(Is64Bit ? 8 : 4), newProtection, out oldProtection); - } - #endregion - - #region readMemory - /// - /// Reads up to `length ` bytes from an address. - /// - /// address, module + pointer + offset, module + offset OR label in .ini file. - /// The maximum bytes to read. - /// path and name of ini file. - /// The bytes read or null - public byte[] ReadBytes(string code, long length, string file = "") - { - byte[] memory = new byte[length]; - UIntPtr theCode = GetCode(code, file); - - if (!ReadProcessMemory(pHandle, theCode, memory, (UIntPtr)length, IntPtr.Zero)) - return null; - - return memory; - } - - /// - /// Read a float value from an address. - /// - /// address, module + pointer + offset, module + offset OR label in .ini file. - /// path and name of ini file. (OPTIONAL) - /// Round the value to 2 decimal places - /// - public float ReadFloat(string code, string file = "", bool round = true) - { - byte[] memory = new byte[4]; - - UIntPtr theCode; - theCode = GetCode(code, file); - try - { - if (ReadProcessMemory(pHandle, theCode, memory, (UIntPtr)4, IntPtr.Zero)) - { - float address = BitConverter.ToSingle(memory, 0); - float returnValue = (float)address; - if (round) - returnValue = (float)Math.Round(address, 2); - return returnValue; - } - else - return 0; - } - catch - { - return 0; - } - } - - /// - /// Read a string value from an address. - /// - /// address, module + pointer + offset, module + offset OR label in .ini file. - /// path and name of ini file. (OPTIONAL) - /// length of bytes to read (OPTIONAL) - /// terminate string at null char - /// System.Text.Encoding.UTF8 (DEFAULT). Other options: ascii, unicode, utf32, utf7 - /// - public string ReadString(string code, string file = "", int length = 32, bool zeroTerminated = true, System.Text.Encoding stringEncoding = null) - { - if (stringEncoding == null) - stringEncoding = System.Text.Encoding.UTF8; - - byte[] memoryNormal = new byte[length]; - UIntPtr theCode; - theCode = GetCode(code, file); - - if (ReadProcessMemory(pHandle, theCode, memoryNormal, (UIntPtr)length, IntPtr.Zero)) - return (zeroTerminated) ? stringEncoding.GetString(memoryNormal).Split('\0')[0] : stringEncoding.GetString(memoryNormal); - else - return ""; - } - - /// - /// Read a double value - /// - /// address, module + pointer + offset, module + offset OR label in .ini file. - /// path and name of ini file. (OPTIONAL) - /// Round the value to 2 decimal places - /// - public double ReadDouble(string code, string file = "", bool round = true) - { - byte[] memory = new byte[8]; - - UIntPtr theCode; - theCode = GetCode(code, file); - try - { - if (ReadProcessMemory(pHandle, theCode, memory, (UIntPtr)8, IntPtr.Zero)) - { - double address = BitConverter.ToDouble(memory, 0); - double returnValue = (double)address; - if (round) - returnValue = (double)Math.Round(address, 2); - return returnValue; - } - else - return 0; - } - catch - { - return 0; - } - } - - public int ReadUIntPtr(UIntPtr code) - { - byte[] memory = new byte[4]; - if (ReadProcessMemory(pHandle, code, memory, (UIntPtr)4, IntPtr.Zero)) - return BitConverter.ToInt32(memory, 0); - else - return 0; - } - - /// - /// Read an integer from an address. - /// - /// address, module + pointer + offset, module + offset OR label in .ini file. - /// path and name of ini file. (OPTIONAL) - /// - public int ReadInt(string code, string file = "") - { - byte[] memory = new byte[4]; - UIntPtr theCode; - theCode = GetCode(code, file); - if (ReadProcessMemory(pHandle, theCode, memory, (UIntPtr)4, IntPtr.Zero)) - return BitConverter.ToInt32(memory, 0); - else - return 0; - } - - /// - /// Read a long value from an address. - /// - /// address, module + pointer + offset, module + offset OR label in .ini file. - /// path and name of ini file. (OPTIONAL) - /// - public long ReadLong(string code, string file = "") - { - byte[] memory = new byte[16]; - UIntPtr theCode; - - theCode = GetCode(code, file); - - if (ReadProcessMemory(pHandle, theCode, memory, (UIntPtr)8, IntPtr.Zero)) - return BitConverter.ToInt64(memory, 0); - else - return 0; - } - - /// - /// Read a UInt value from address. - /// - /// address, module + pointer + offset, module + offset OR label in .ini file. - /// path and name of ini file. (OPTIONAL) - /// - public UInt32 ReadUInt(string code, string file = "") - { - byte[] memory = new byte[4]; - UIntPtr theCode; - theCode = GetCode(code, file); - - if (ReadProcessMemory(pHandle, theCode, memory, (UIntPtr)4, IntPtr.Zero)) - return BitConverter.ToUInt32(memory, 0); - else - return 0; - } - - /// - /// Reads a 2 byte value from an address and moves the address. - /// - /// address, module + pointer + offset, module + offset OR label in .ini file. - /// Quantity to move. - /// path and name of ini file (OPTIONAL) - /// - public int Read2ByteMove(string code, int moveQty, string file = "") - { - byte[] memory = new byte[4]; - UIntPtr theCode; - theCode = GetCode(code, file); - - UIntPtr newCode = UIntPtr.Add(theCode, moveQty); - - if (ReadProcessMemory(pHandle, newCode, memory, (UIntPtr)2, IntPtr.Zero)) - return BitConverter.ToInt32(memory, 0); - else - return 0; - } - - /// - /// Reads an integer value from address and moves the address. - /// - /// address, module + pointer + offset, module + offset OR label in .ini file. - /// Quantity to move. - /// path and name of ini file (OPTIONAL) - /// - public int ReadIntMove(string code, int moveQty, string file = "") - { - byte[] memory = new byte[4]; - UIntPtr theCode; - theCode = GetCode(code, file); - - UIntPtr newCode = UIntPtr.Add(theCode, moveQty); - - if (ReadProcessMemory(pHandle, newCode, memory, (UIntPtr)4, IntPtr.Zero)) - return BitConverter.ToInt32(memory, 0); - else - return 0; - } - - /// - /// Get UInt and move to another address by moveQty. Use in a for loop. - /// - /// address, module + pointer + offset, module + offset OR label in .ini file. - /// Quantity to move. - /// path and name of ini file (OPTIONAL) - /// - public ulong ReadUIntMove(string code, int moveQty, string file = "") - { - byte[] memory = new byte[8]; - UIntPtr theCode; - theCode = GetCode(code, file, 8); - - UIntPtr newCode = UIntPtr.Add(theCode, moveQty); - - if (ReadProcessMemory(pHandle, newCode, memory, (UIntPtr)8, IntPtr.Zero)) - return BitConverter.ToUInt64(memory, 0); - else - return 0; - } - - /// - /// Read a 2 byte value from an address. Returns an integer. - /// - /// address, module + pointer + offset, module + offset OR label in .ini file. - /// path and file name to ini file. (OPTIONAL) - /// - public int Read2Byte(string code, string file = "") - { - byte[] memoryTiny = new byte[4]; - - UIntPtr theCode; - theCode = GetCode(code, file); - - if (ReadProcessMemory(pHandle, theCode, memoryTiny, (UIntPtr)2, IntPtr.Zero)) - return BitConverter.ToInt32(memoryTiny, 0); - else - return 0; - } - - /// - /// Read 1 byte from address. - /// - /// address, module + pointer + offset, module + offset OR label in .ini file. - /// path and file name of ini file. (OPTIONAL) - /// - public int ReadByte(string code, string file = "") - { - byte[] memoryTiny = new byte[1]; - - UIntPtr theCode = GetCode(code, file); - - if (ReadProcessMemory(pHandle, theCode, memoryTiny, (UIntPtr) 1, IntPtr.Zero)) - return memoryTiny[0]; - - return 0; - } - - /// - /// Reads a byte from memory and splits it into bits - /// - /// address, module + pointer + offset, module + offset OR label in .ini file. - /// path and file name of ini file. (OPTIONAL) - /// Array of 8 booleans representing each bit of the byte read - public bool[] ReadBits(string code, string file = "") - { - byte[] buf = new byte[1]; - - UIntPtr theCode = GetCode(code, file); - - bool[] ret = new bool[8]; - - if (!ReadProcessMemory(pHandle, theCode, buf, (UIntPtr) 1, IntPtr.Zero)) - return ret; - - - if (!BitConverter.IsLittleEndian) - throw new Exception("Should be little endian"); - - for (var i = 0; i < 8; i++) - ret[i] = Convert.ToBoolean(buf[0] & (1 << i)); - - return ret; - - } - - public int ReadPByte(UIntPtr address, string code, string file = "") - { - byte[] memory = new byte[4]; - if (ReadProcessMemory(pHandle, address + LoadIntCode(code, file), memory, (UIntPtr)1, IntPtr.Zero)) - return BitConverter.ToInt32(memory, 0); - else - return 0; - } - - public float ReadPFloat(UIntPtr address, string code, string file = "") - { - byte[] memory = new byte[4]; - if (ReadProcessMemory(pHandle, address + LoadIntCode(code, file), memory, (UIntPtr)4, IntPtr.Zero)) - { - float spawn = BitConverter.ToSingle(memory, 0); - return (float)Math.Round(spawn, 2); - } - else - return 0; - } - - public int ReadPInt(UIntPtr address, string code, string file = "") - { - byte[] memory = new byte[4]; - if (ReadProcessMemory(pHandle, address + LoadIntCode(code, file), memory, (UIntPtr)4, IntPtr.Zero)) - return BitConverter.ToInt32(memory, 0); - else - return 0; - } - - public string ReadPString(UIntPtr address, string code, string file = "") - { - byte[] memoryNormal = new byte[32]; - if (ReadProcessMemory(pHandle, address + LoadIntCode(code, file), memoryNormal, (UIntPtr)32, IntPtr.Zero)) - return CutString(System.Text.Encoding.ASCII.GetString(memoryNormal)); - else - return ""; - } - #endregion - - #region writeMemory - /// - ///Write to memory address. See https://github.com/erfg12/memory.dll/wiki/writeMemory() for more information. - /// - ///address, module + pointer + offset, module + offset OR label in .ini file. - ///byte, 2bytes, bytes, float, int, string, double or long. - ///value to write to address. - ///path and name of .ini file (OPTIONAL) - ///System.Text.Encoding.UTF8 (DEFAULT). Other options: ascii, unicode, utf32, utf7 - ///If building a trainer on an emulator (Ex: RPCS3) you'll want to set this to false - public bool WriteMemory(string code, string type, string write, string file = "", System.Text.Encoding stringEncoding = null, bool RemoveWriteProtection = true) - { - byte[] memory = new byte[4]; - int size = 4; - - UIntPtr theCode; - theCode = GetCode(code, file); - - if (type.ToLower() == "float") - { - write = Convert.ToString(float.Parse(write, CultureInfo.InvariantCulture)); - memory = BitConverter.GetBytes(Convert.ToSingle(write)); - size = 4; - } - else if (type.ToLower() == "int") - { - memory = BitConverter.GetBytes(Convert.ToInt32(write)); - size = 4; - } - else if (type.ToLower() == "byte") - { - memory = new byte[1]; - memory[0] = Convert.ToByte(write, 16); - size = 1; - } - else if (type.ToLower() == "2bytes") - { - memory = new byte[2]; - memory[0] = (byte)(Convert.ToInt32(write) % 256); - memory[1] = (byte)(Convert.ToInt32(write) / 256); - size = 2; - } - else if (type.ToLower() == "bytes") - { - if (write.Contains(",") || write.Contains(" ")) //check if it's a proper array - { - string[] stringBytes; - if (write.Contains(",")) - stringBytes = write.Split(','); - else - stringBytes = write.Split(' '); - //Debug.WriteLine("write:" + write + " stringBytes:" + stringBytes); - - int c = stringBytes.Count(); - memory = new byte[c]; - for (int i = 0; i < c; i++) - { - memory[i] = Convert.ToByte(stringBytes[i], 16); - } - size = stringBytes.Count(); - } - else //wasnt array, only 1 byte - { - memory = new byte[1]; - memory[0] = Convert.ToByte(write, 16); - size = 1; - } - } - else if (type.ToLower() == "double") - { - memory = BitConverter.GetBytes(Convert.ToDouble(write)); - size = 8; - } - else if (type.ToLower() == "long") - { - memory = BitConverter.GetBytes(Convert.ToInt64(write)); - size = 8; - } - else if (type.ToLower() == "string") - { - if (stringEncoding == null) - memory = System.Text.Encoding.UTF8.GetBytes(write); - else - memory = stringEncoding.GetBytes(write); - size = memory.Length; - } - - //Debug.Write("DEBUG: Writing bytes [TYPE:" + type + " ADDR:" + theCode + "] " + String.Join(",", memory) + Environment.NewLine); - MemoryProtection OldMemProt = 0x00; - bool WriteProcMem = false; - if (RemoveWriteProtection) - ChangeProtection(code, MemoryProtection.ExecuteReadWrite, out OldMemProt); // change protection - WriteProcMem = WriteProcessMemory(pHandle, theCode, memory, (UIntPtr)size, IntPtr.Zero); - if (RemoveWriteProtection) - ChangeProtection(code, OldMemProt, out _); // restore - return WriteProcMem; - } - - /// - /// Write to address and move by moveQty. Good for byte arrays. See https://github.com/erfg12/memory.dll/wiki/Writing-a-Byte-Array for more information. - /// - ///address, module + pointer + offset, module + offset OR label in .ini file. - ///byte, bytes, float, int, string or long. - /// byte to write - /// quantity to move - /// path and name of .ini file (OPTIONAL) - /// milliseconds to sleep between each byte - /// - public bool WriteMove(string code, string type, string write, int MoveQty, string file = "", int SlowDown = 0) - { - byte[] memory = new byte[4]; - int size = 4; - - UIntPtr theCode; - theCode = GetCode(code, file); - - if (type == "float") - { - memory = new byte[write.Length]; - memory = BitConverter.GetBytes(Convert.ToSingle(write)); - size = write.Length; - } - else if (type == "int") - { - memory = BitConverter.GetBytes(Convert.ToInt32(write)); - size = 4; - } - else if (type == "double") - { - memory = BitConverter.GetBytes(Convert.ToDouble(write)); - size = 8; - } - else if (type == "long") - { - memory = BitConverter.GetBytes(Convert.ToInt64(write)); - size = 8; - } - else if (type == "byte") - { - memory = new byte[1]; - memory[0] = Convert.ToByte(write, 16); - size = 1; - } - else if (type == "string") - { - memory = new byte[write.Length]; - memory = System.Text.Encoding.UTF8.GetBytes(write); - size = write.Length; - } - - UIntPtr newCode = UIntPtr.Add(theCode, MoveQty); - - //Debug.Write("DEBUG: Writing bytes [TYPE:" + type + " ADDR:[O]" + theCode + " [N]" + newCode + " MQTY:" + MoveQty + "] " + String.Join(",", memory) + Environment.NewLine); - Thread.Sleep(SlowDown); - return WriteProcessMemory(pHandle, newCode, memory, (UIntPtr)size, IntPtr.Zero); - } - - /// - /// Write byte array to addresses. - /// - /// address to write to - /// byte array to write - /// path and name of ini file. (OPTIONAL) - public void WriteBytes(string code, byte[] write, string file = "") - { - UIntPtr theCode; - theCode = GetCode(code, file); - WriteProcessMemory(pHandle, theCode, write, (UIntPtr)write.Length, IntPtr.Zero); - } - - /// - /// Takes an array of 8 booleans and writes to a single byte - /// - /// address to write to - /// Array of 8 booleans to write - /// path and name of ini file. (OPTIONAL) - public void WriteBits(string code, bool[] bits, string file = "") - { - if(bits.Length != 8) - throw new ArgumentException("Not enough bits for a whole byte", nameof(bits)); - - byte[] buf = new byte[1]; - - UIntPtr theCode = GetCode(code, file); - - for (var i = 0; i < 8; i++) - { - if (bits[i]) - buf[0] |= (byte)(1 << i); - } - - WriteProcessMemory(pHandle, theCode, buf, (UIntPtr) 1, IntPtr.Zero); - } - - /// - /// Write byte array to address - /// - /// Address to write to - /// Byte array to write to - public void WriteBytes(UIntPtr address, byte[] write) - { - WriteProcessMemory(pHandle, address, write, (UIntPtr)write.Length, out IntPtr bytesRead); + return VirtualProtectEx(mProc.Handle, theCode, (IntPtr)(mProc.Is64Bit ? 8 : 4), newProtection, out oldProtection); } - #endregion /// @@ -1262,7 +305,7 @@ public void WriteBytes(UIntPtr address, byte[] write) public UIntPtr GetCode(string name, string path = "", int size = 8) { string theCode = ""; - if (Is64Bit) + if (mProc.Is64Bit) { //Debug.WriteLine("Changing to 64bit code..."); if (size == 8) size = 16; //change to 64bit @@ -1320,7 +363,7 @@ public UIntPtr GetCode(string name, string path = "", int size = 8) int[] offsets = offsetsList.ToArray(); if (theCode.Contains("base") || theCode.Contains("main")) - ReadProcessMemory(pHandle, (UIntPtr)((int)mainModule.BaseAddress + offsets[0]), memoryAddress, (UIntPtr)size, IntPtr.Zero); + ReadProcessMemory(mProc.Handle, (UIntPtr)((int)mProc.MainModule.BaseAddress + offsets[0]), memoryAddress, (UIntPtr)size, IntPtr.Zero); else if (!theCode.Contains("base") && !theCode.Contains("main") && theCode.Contains("+")) { string[] moduleName = theCode.Split('+'); @@ -1335,18 +378,18 @@ public UIntPtr GetCode(string name, string path = "", int size = 8) { try { - altModule = modules[moduleName[0]]; + altModule = mProc.Modules[moduleName[0]]; } catch { Debug.WriteLine("Module " + moduleName[0] + " was not found in module list!"); - Debug.WriteLine("Modules: " + string.Join(",", modules)); + Debug.WriteLine("Modules: " + string.Join(",", mProc.Modules)); } } - ReadProcessMemory(pHandle, (UIntPtr)((int)altModule + offsets[0]), memoryAddress, (UIntPtr)size, IntPtr.Zero); + ReadProcessMemory(mProc.Handle, (UIntPtr)((int)altModule + offsets[0]), memoryAddress, (UIntPtr)size, IntPtr.Zero); } else - ReadProcessMemory(pHandle, (UIntPtr)(offsets[0]), memoryAddress, (UIntPtr)size, IntPtr.Zero); + ReadProcessMemory(mProc.Handle, (UIntPtr)(offsets[0]), memoryAddress, (UIntPtr)size, IntPtr.Zero); uint num1 = BitConverter.ToUInt32(memoryAddress, 0); //ToUInt64 causes arithmetic overflow. @@ -1355,7 +398,7 @@ public UIntPtr GetCode(string name, string path = "", int size = 8) for (int i = 1; i < offsets.Length; i++) { base1 = new UIntPtr(Convert.ToUInt32(num1 + offsets[i])); - ReadProcessMemory(pHandle, base1, memoryAddress, (UIntPtr)size, IntPtr.Zero); + ReadProcessMemory(mProc.Handle, base1, memoryAddress, (UIntPtr)size, IntPtr.Zero); num1 = BitConverter.ToUInt32(memoryAddress, 0); //ToUInt64 causes arithmetic overflow. } return base1; @@ -1366,7 +409,7 @@ public UIntPtr GetCode(string name, string path = "", int size = 8) IntPtr altModule = IntPtr.Zero; //Debug.WriteLine("newOffsets=" + newOffsets); if (theCode.ToLower().Contains("base") || theCode.ToLower().Contains("main")) - altModule = mainModule.BaseAddress; + altModule = mProc.MainModule.BaseAddress; else if (!theCode.ToLower().Contains("base") && !theCode.ToLower().Contains("main") && theCode.Contains("+")) { string[] moduleName = theCode.Split('+'); @@ -1380,17 +423,17 @@ public UIntPtr GetCode(string name, string path = "", int size = 8) { try { - altModule = modules[moduleName[0]]; + altModule = mProc.Modules[moduleName[0]]; } catch { Debug.WriteLine("Module " + moduleName[0] + " was not found in module list!"); - Debug.WriteLine("Modules: " + string.Join(",", modules)); + Debug.WriteLine("Modules: " + string.Join(",", mProc.Modules)); } } } else - altModule = modules[theCode.Split('+')[0]]; + altModule = mProc.Modules[theCode.Split('+')[0]]; return (UIntPtr)((int)altModule + trueCode); } } @@ -1448,7 +491,7 @@ public UIntPtr Get64BitCode(string name, string path = "", int size = 16) Int64[] offsets = offsetsList.ToArray(); if (theCode.Contains("base") || theCode.Contains("main")) - ReadProcessMemory(pHandle, (UIntPtr)((Int64)mainModule.BaseAddress + offsets[0]), memoryAddress, (UIntPtr)size, IntPtr.Zero); + ReadProcessMemory(mProc.Handle, (UIntPtr)((Int64)mProc.MainModule.BaseAddress + offsets[0]), memoryAddress, (UIntPtr)size, IntPtr.Zero); else if (!theCode.Contains("base") && !theCode.Contains("main") && theCode.Contains("+")) { string[] moduleName = theCode.Split('+'); @@ -1459,18 +502,18 @@ public UIntPtr Get64BitCode(string name, string path = "", int size = 16) { try { - altModule = modules[moduleName[0]]; + altModule = mProc.Modules[moduleName[0]]; } catch { Debug.WriteLine("Module " + moduleName[0] + " was not found in module list!"); - Debug.WriteLine("Modules: " + string.Join(",", modules)); + Debug.WriteLine("Modules: " + string.Join(",", mProc.Modules)); } } - ReadProcessMemory(pHandle, (UIntPtr)((Int64)altModule + offsets[0]), memoryAddress, (UIntPtr)size, IntPtr.Zero); + ReadProcessMemory(mProc.Handle, (UIntPtr)((Int64)altModule + offsets[0]), memoryAddress, (UIntPtr)size, IntPtr.Zero); } else // no offsets - ReadProcessMemory(pHandle, (UIntPtr)(offsets[0]), memoryAddress, (UIntPtr)size, IntPtr.Zero); + ReadProcessMemory(mProc.Handle, (UIntPtr)(offsets[0]), memoryAddress, (UIntPtr)size, IntPtr.Zero); Int64 num1 = BitConverter.ToInt64(memoryAddress, 0); @@ -1479,7 +522,7 @@ public UIntPtr Get64BitCode(string name, string path = "", int size = 16) for (int i = 1; i < offsets.Length; i++) { base1 = new UIntPtr(Convert.ToUInt64(num1 + offsets[i])); - ReadProcessMemory(pHandle, base1, memoryAddress, (UIntPtr)size, IntPtr.Zero); + ReadProcessMemory(mProc.Handle, base1, memoryAddress, (UIntPtr)size, IntPtr.Zero); num1 = BitConverter.ToInt64(memoryAddress, 0); } return base1; @@ -1489,7 +532,7 @@ public UIntPtr Get64BitCode(string name, string path = "", int size = 16) Int64 trueCode = Convert.ToInt64(newOffsets, 16); IntPtr altModule = IntPtr.Zero; if (theCode.Contains("base") || theCode.Contains("main")) - altModule = mainModule.BaseAddress; + altModule = mProc.MainModule.BaseAddress; else if (!theCode.Contains("base") && !theCode.Contains("main") && theCode.Contains("+")) { string[] moduleName = theCode.Split('+'); @@ -1503,17 +546,17 @@ public UIntPtr Get64BitCode(string name, string path = "", int size = 16) { try { - altModule = modules[moduleName[0]]; + altModule = mProc.Modules[moduleName[0]]; } catch { Debug.WriteLine("Module " + moduleName[0] + " was not found in module list!"); - Debug.WriteLine("Modules: " + string.Join(",", modules)); + Debug.WriteLine("Modules: " + string.Join(",", mProc.Modules)); } } } else - altModule = modules[theCode.Split('+')[0]]; + altModule = mProc.Modules[theCode.Split('+')[0]]; return (UIntPtr)((Int64)altModule + trueCode); } } @@ -1523,11 +566,11 @@ public UIntPtr Get64BitCode(string name, string path = "", int size = 16) /// public void CloseProcess() { - if (pHandle == null) + if (mProc.Handle == null) return; - CloseHandle(pHandle); - theProc = null; + CloseHandle(mProc.Handle); + mProc = null; } /// @@ -1538,25 +581,25 @@ public bool InjectDll(String strDllName) { IntPtr bytesout; - foreach (ProcessModule pm in theProc.Modules) + foreach (ProcessModule pm in mProc.Process.Modules) { if (pm.ModuleName.StartsWith("inject", StringComparison.InvariantCultureIgnoreCase)) return false; } - if (!theProc.Responding) + if (!mProc.Process.Responding) return false; int lenWrite = strDllName.Length + 1; - UIntPtr allocMem = VirtualAllocEx(pHandle, (UIntPtr)null, (uint)lenWrite, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + UIntPtr allocMem = VirtualAllocEx(mProc.Handle, (UIntPtr)null, (uint)lenWrite, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - WriteProcessMemory(pHandle, allocMem, strDllName, (UIntPtr)lenWrite, out bytesout); + WriteProcessMemory(mProc.Handle, allocMem, strDllName, (UIntPtr)lenWrite, out bytesout); UIntPtr injector = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); if (injector == null) return false; - IntPtr hThread = CreateRemoteThread(pHandle, (IntPtr)null, 0, injector, allocMem, 0, out bytesout); + IntPtr hThread = CreateRemoteThread(mProc.Handle, (IntPtr)null, 0, injector, allocMem, 0, out bytesout); if (hThread == null) return false; @@ -1567,7 +610,7 @@ public bool InjectDll(String strDllName) CloseHandle(hThread); return false; } - VirtualFreeEx(pHandle, allocMem, (UIntPtr)0, 0x8000); + VirtualFreeEx(mProc.Handle, allocMem, (UIntPtr)0, 0x8000); if (hThread != null) CloseHandle(hThread); @@ -1605,8 +648,7 @@ public UIntPtr CreateCodeCave(string code, byte[] newBytes, int replaceCount, in for(var i = 0; i < 10 && caveAddress == UIntPtr.Zero; i++) { - caveAddress = VirtualAllocEx(pHandle, FindFreeBlockForRegion(prefered, (uint)size), - (uint)size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + caveAddress = VirtualAllocEx(mProc.Handle, FindFreeBlockForRegion(prefered, (uint)size), (uint)size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (caveAddress == UIntPtr.Zero) prefered = UIntPtr.Add(prefered, 0x10000); @@ -1614,7 +656,7 @@ public UIntPtr CreateCodeCave(string code, byte[] newBytes, int replaceCount, in // Failed to allocate memory around the address we wanted let windows handle it and hope for the best? if (caveAddress == UIntPtr.Zero) - caveAddress = VirtualAllocEx(pHandle, UIntPtr.Zero, (uint)size, MEM_COMMIT | MEM_RESERVE, + caveAddress = VirtualAllocEx(mProc.Handle, UIntPtr.Zero, (uint)size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); int nopsNeeded = replaceCount > 5 ? replaceCount - 5 : 0; @@ -1654,7 +696,7 @@ private UIntPtr FindFreeBlockForRegion(UIntPtr baseAddress, uint size) GetSystemInfo(out SYSTEM_INFO si); - if (Is64Bit) + if (mProc.Is64Bit) { if ((long)minAddress > (long)si.maximumApplicationAddress || (long)minAddress < (long)si.minimumApplicationAddress) @@ -1675,7 +717,7 @@ private UIntPtr FindFreeBlockForRegion(UIntPtr baseAddress, uint size) UIntPtr current = minAddress; UIntPtr previous = current; - while (VirtualQueryEx(pHandle, current, out mbi).ToUInt64() != 0) + while (VirtualQueryEx(mProc.Handle, current, out mbi).ToUInt64() != 0) { if ((long)mbi.BaseAddress > (long)maxAddress) return UIntPtr.Zero; // No memory found, let windows handle @@ -1751,23 +793,9 @@ private UIntPtr FindFreeBlockForRegion(UIntPtr baseAddress, uint size) } #endif - [Flags] - public enum ThreadAccess : int - { - TERMINATE = (0x0001), - SUSPEND_RESUME = (0x0002), - GET_CONTEXT = (0x0008), - SET_CONTEXT = (0x0010), - SET_INFORMATION = (0x0020), - QUERY_INFORMATION = (0x0040), - SET_THREAD_TOKEN = (0x0080), - IMPERSONATE = (0x0100), - DIRECT_IMPERSONATION = (0x0200) - } - public static void SuspendProcess(int pid) { - var process = Process.GetProcessById(pid); + var process = System.Diagnostics.Process.GetProcessById(pid); if (process.ProcessName == string.Empty) return; @@ -1785,7 +813,7 @@ public static void SuspendProcess(int pid) public static void ResumeProcess(int pid) { - var process = Process.GetProcessById(pid); + var process = System.Diagnostics.Process.GetProcessById(pid); if (process.ProcessName == string.Empty) return; @@ -1829,7 +857,7 @@ public byte[] FileToBytes(string path, bool dontDelete = false) { public string MSize() { - if (Is64Bit) + if (mProc.Is64Bit) return ("x16"); else return ("x8"); @@ -1868,59 +896,6 @@ public static string ByteArrayToString(byte[] ba) return hex.ToString(); } -#if WINXP -#else - - public struct SYSTEM_INFO - { - public ushort processorArchitecture; - ushort reserved; - public uint pageSize; - public UIntPtr minimumApplicationAddress; - public UIntPtr maximumApplicationAddress; - public IntPtr activeProcessorMask; - public uint numberOfProcessors; - public uint processorType; - public uint allocationGranularity; - public ushort processorLevel; - public ushort processorRevision; - } - - public struct MEMORY_BASIC_INFORMATION32 - { - public UIntPtr BaseAddress; - public UIntPtr AllocationBase; - public uint AllocationProtect; - public uint RegionSize; - public uint State; - public uint Protect; - public uint Type; - } - - public struct MEMORY_BASIC_INFORMATION64 - { - public UIntPtr BaseAddress; - public UIntPtr AllocationBase; - public uint AllocationProtect; - public uint __alignment1; - public ulong RegionSize; - public uint State; - public uint Protect; - public uint Type; - public uint __alignment2; - } - - public struct MEMORY_BASIC_INFORMATION - { - public UIntPtr BaseAddress; - public UIntPtr AllocationBase; - public uint AllocationProtect; - public long RegionSize; - public uint State; - public uint Protect; - public uint Type; - } - public ulong GetMinAddress() { SYSTEM_INFO SI; @@ -1942,7 +917,7 @@ public bool DumpMemory(string file = "dump.dmp") // saving the values as long ints so I won't have to do a lot of casts later Int64 proc_min_address_l = (Int64)proc_min_address; //(Int64)procs.MainModule.BaseAddress; - Int64 proc_max_address_l = (Int64)theProc.VirtualMemorySize64 + proc_min_address_l; + Int64 proc_max_address_l = (Int64)mProc.Process.VirtualMemorySize64 + proc_min_address_l; //int arrLength = 0; if (File.Exists(file)) @@ -1952,12 +927,12 @@ public bool DumpMemory(string file = "dump.dmp") MEMORY_BASIC_INFORMATION memInfo = new MEMORY_BASIC_INFORMATION(); while (proc_min_address_l < proc_max_address_l) { - VirtualQueryEx(pHandle, proc_min_address, out memInfo); + VirtualQueryEx(mProc.Handle, proc_min_address, out memInfo); byte[] buffer = new byte[(Int64)memInfo.RegionSize]; UIntPtr test = (UIntPtr)((Int64)memInfo.RegionSize); UIntPtr test2 = (UIntPtr)((Int64)memInfo.BaseAddress); - ReadProcessMemory(pHandle, test2, buffer, test, IntPtr.Zero); + ReadProcessMemory(mProc.Handle, test2, buffer, test, IntPtr.Zero); AppendAllBytes(file, buffer); //due to memory limits, we have to dump it then store it in an array. //arrLength += buffer.Length; @@ -1971,310 +946,7 @@ public bool DumpMemory(string file = "dump.dmp") return true; } - /// - /// Array of byte scan. - /// - /// array of bytes to search for, OR your ini code label. - /// Include writable addresses in scan - /// Include executable addresses in scan - /// ini file (OPTIONAL) - /// IEnumerable of all addresses found. - public Task> AoBScan(string search, bool writable = false, bool executable = true, string file = "") - { - return AoBScan(0, long.MaxValue, search, writable, executable, file); - } - - /// - /// Array of byte scan. - /// - /// array of bytes to search for, OR your ini code label. - /// Include readable addresses in scan - /// Include writable addresses in scan - /// Include executable addresses in scan - /// ini file (OPTIONAL) - /// IEnumerable of all addresses found. - public Task> AoBScan(string search, bool readable, bool writable, bool executable, string file = "") - { - return AoBScan(0, long.MaxValue, search, readable, writable, executable, file); - } - - - /// - /// Array of Byte scan. - /// - /// Your starting address. - /// ending address - /// array of bytes to search for, OR your ini code label. - /// ini file (OPTIONAL) - /// Include writable addresses in scan - /// Include executable addresses in scan - /// IEnumerable of all addresses found. - public Task> AoBScan(long start, long end, string search, bool writable = false, bool executable = true, string file = "") - { - // Not including read only memory was scan behavior prior. - return AoBScan(start, end, search, false, writable, executable, file); - } - - /// - /// Array of Byte scan. - /// - /// Your starting address. - /// ending address - /// array of bytes to search for, OR your ini code label. - /// ini file (OPTIONAL) - /// Include readable addresses in scan - /// Include writable addresses in scan - /// Include executable addresses in scan - /// IEnumerable of all addresses found. - public Task> AoBScan(long start, long end, string search, bool readable, bool writable, bool executable, string file = "") - { - return Task.Run(() => - { - var memRegionList = new List(); - - string memCode = LoadCode(search, file); - - string[] stringByteArray = memCode.Split(' '); - - byte[] aobPattern = new byte[stringByteArray.Length]; - byte[] mask = new byte[stringByteArray.Length]; - - for (var i = 0; i < stringByteArray.Length; i++) - { - string ba = stringByteArray[i]; - - if (ba == "??" || (ba.Length == 1 && ba == "?")) - { - mask[i] = 0x00; - stringByteArray[i] = "0x00"; - } - else if (Char.IsLetterOrDigit(ba[0]) && ba[1] == '?') - { - mask[i] = 0xF0; - stringByteArray[i] = ba[0] + "0"; - } - else if (Char.IsLetterOrDigit(ba[1]) && ba[0] == '?') - { - mask[i] = 0x0F; - stringByteArray[i] = "0" + ba[1]; - } - else - mask[i] = 0xFF; - } - - - for (int i = 0; i < stringByteArray.Length; i++) - aobPattern[i] = (byte)(Convert.ToByte(stringByteArray[i], 16) & mask[i]); - - SYSTEM_INFO sys_info = new SYSTEM_INFO(); - GetSystemInfo(out sys_info); - - UIntPtr proc_min_address = sys_info.minimumApplicationAddress; - UIntPtr proc_max_address = sys_info.maximumApplicationAddress; - - if (start < (long)proc_min_address.ToUInt64()) - start = (long)proc_min_address.ToUInt64(); - - if (end > (long)proc_max_address.ToUInt64()) - end = (long)proc_max_address.ToUInt64(); - - Debug.WriteLine("[DEBUG] memory scan starting... (start:0x" + start.ToString(MSize()) + " end:0x" + end.ToString(MSize()) + " time:" + DateTime.Now.ToString("h:mm:ss tt") + ")"); - UIntPtr currentBaseAddress = new UIntPtr((ulong)start); - - MEMORY_BASIC_INFORMATION memInfo = new MEMORY_BASIC_INFORMATION(); - - //Debug.WriteLine("[DEBUG] start:0x" + start.ToString("X8") + " curBase:0x" + currentBaseAddress.ToUInt64().ToString("X8") + " end:0x" + end.ToString("X8") + " size:0x" + memInfo.RegionSize.ToString("X8") + " vAloc:" + VirtualQueryEx(pHandle, currentBaseAddress, out memInfo).ToUInt64().ToString()); - - while (VirtualQueryEx(pHandle, currentBaseAddress, out memInfo).ToUInt64() != 0 && - currentBaseAddress.ToUInt64() < (ulong)end && - currentBaseAddress.ToUInt64() + (ulong)memInfo.RegionSize > - currentBaseAddress.ToUInt64()) - { - bool isValid = memInfo.State == MEM_COMMIT; - isValid &= memInfo.BaseAddress.ToUInt64() < (ulong)proc_max_address.ToUInt64(); - isValid &= ((memInfo.Protect & PAGE_GUARD) == 0); - isValid &= ((memInfo.Protect & PAGE_NOACCESS) == 0); - isValid &= (memInfo.Type == MEM_PRIVATE) || (memInfo.Type == MEM_IMAGE); - - if (isValid) - { - bool isReadable = (memInfo.Protect & PAGE_READONLY) > 0; - - bool isWritable = ((memInfo.Protect & PAGE_READWRITE) > 0) || - ((memInfo.Protect & PAGE_WRITECOPY) > 0) || - ((memInfo.Protect & PAGE_EXECUTE_READWRITE) > 0) || - ((memInfo.Protect & PAGE_EXECUTE_WRITECOPY) > 0); - - bool isExecutable = ((memInfo.Protect & PAGE_EXECUTE) > 0) || - ((memInfo.Protect & PAGE_EXECUTE_READ) > 0) || - ((memInfo.Protect & PAGE_EXECUTE_READWRITE) > 0) || - ((memInfo.Protect & PAGE_EXECUTE_WRITECOPY) > 0); - - isReadable &= readable; - isWritable &= writable; - isExecutable &= executable; - - isValid &= isReadable || isWritable || isExecutable; - } - - if (!isValid) - { - currentBaseAddress = new UIntPtr(memInfo.BaseAddress.ToUInt64() + (ulong)memInfo.RegionSize); - continue; - } - - MemoryRegionResult memRegion = new MemoryRegionResult - { - CurrentBaseAddress = currentBaseAddress, - RegionSize = memInfo.RegionSize, - RegionBase = memInfo.BaseAddress - }; - - currentBaseAddress = new UIntPtr(memInfo.BaseAddress.ToUInt64() + (ulong)memInfo.RegionSize); - - //Console.WriteLine("SCAN start:" + memRegion.RegionBase.ToString() + " end:" + currentBaseAddress.ToString()); - - if (memRegionList.Count > 0) - { - var previousRegion = memRegionList[memRegionList.Count - 1]; - - if ((long)previousRegion.RegionBase + previousRegion.RegionSize == (long)memInfo.BaseAddress) - { - memRegionList[memRegionList.Count - 1] = new MemoryRegionResult - { - CurrentBaseAddress = previousRegion.CurrentBaseAddress, - RegionBase = previousRegion.RegionBase, - RegionSize = previousRegion.RegionSize + memInfo.RegionSize - }; - - continue; - } - } - - memRegionList.Add(memRegion); - } - - ConcurrentBag bagResult = new ConcurrentBag(); - - Parallel.ForEach(memRegionList, - (item, parallelLoopState, index) => - { - long[] compareResults = CompareScan(item, aobPattern, mask); - - foreach (long result in compareResults) - bagResult.Add(result); - }); - - Debug.WriteLine("[DEBUG] memory scan completed. (time:" + DateTime.Now.ToString("h:mm:ss tt") + ")"); - - return bagResult.ToList().OrderBy(c => c).AsEnumerable(); - }); - } - - /// - /// Array of bytes scan - /// - /// Starting address or ini label - /// ending address - /// array of bytes to search for or your ini code label - /// ini file - /// First address found - public async Task AoBScan(string code, long end, string search, string file ="") - { - long start = (long)GetCode(code, file).ToUInt64(); - - return (await AoBScan(start, end, search, true, true, true, file)).FirstOrDefault(); - } - - private long[] CompareScan(MemoryRegionResult item, byte[] aobPattern, byte[] mask) - { - if (mask.Length != aobPattern.Length) - throw new ArgumentException($"{nameof(aobPattern)}.Length != {nameof(mask)}.Length"); - - IntPtr buffer = Marshal.AllocHGlobal((int)item.RegionSize); - - ReadProcessMemory(pHandle, item.CurrentBaseAddress, buffer, (UIntPtr)item.RegionSize, out ulong bytesRead); - - int result = 0 - aobPattern.Length; - List ret = new List(); - unsafe - { - do - { - - result = FindPattern((byte*)buffer.ToPointer(), (int)bytesRead, aobPattern, mask, result + aobPattern.Length); - - if (result >= 0) - ret.Add((long) item.CurrentBaseAddress + result); - - } while (result != -1); - } - - Marshal.FreeHGlobal(buffer); - - return ret.ToArray(); - } - - private int FindPattern(byte[] body, byte[] pattern, byte[] masks, int start = 0) - { - int foundIndex = -1; - - if (body.Length <= 0 || pattern.Length <= 0 || start > body.Length - pattern.Length || - pattern.Length > body.Length) return foundIndex; - - for (int index = start; index <= body.Length - pattern.Length; index++) - { - if (((body[index] & masks[0]) == (pattern[0] & masks[0]))) - { - var match = true; - for (int index2 = 1; index2 <= pattern.Length - 1; index2++) - { - if ((body[index + index2] & masks[index2]) == (pattern[index2] & masks[index2])) continue; - match = false; - break; - - } - - if (!match) continue; - - foundIndex = index; - break; - } - } - - return foundIndex; - } - - private unsafe int FindPattern(byte* body, int bodyLength, byte[] pattern, byte[] masks, int start = 0) - { - int foundIndex = -1; - - if (bodyLength <= 0 || pattern.Length <= 0 || start > bodyLength - pattern.Length || - pattern.Length > bodyLength) return foundIndex; - - for (int index = start; index <= bodyLength - pattern.Length; index++) - { - if (((body[index] & masks[0]) == (pattern[0] & masks[0]))) - { - var match = true; - for (int index2 = 1; index2 <= pattern.Length - 1; index2++) - { - if ((body[index + index2] & masks[index2]) == (pattern[index2] & masks[index2])) continue; - match = false; - break; - - } - - if (!match) continue; - - foundIndex = index; - break; - } - } - - return foundIndex; - } + -#endif } } diff --git a/Test/TestApp/MemoryTestApp.sln b/Test/TestApp/MemoryTestApp.sln index 34d5665..b0f90c5 100644 --- a/Test/TestApp/MemoryTestApp.sln +++ b/Test/TestApp/MemoryTestApp.sln @@ -23,8 +23,8 @@ Global {75D0CEA2-0444-4959-B797-91ADD7FD3A4A}.Release|Any CPU.Build.0 = Release|Any CPU {75D0CEA2-0444-4959-B797-91ADD7FD3A4A}.Release|x64.ActiveCfg = Release|x64 {75D0CEA2-0444-4959-B797-91ADD7FD3A4A}.Release|x64.Build.0 = Release|x64 - {D506F6CE-1A4C-4655-809E-928893D45005}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D506F6CE-1A4C-4655-809E-928893D45005}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D506F6CE-1A4C-4655-809E-928893D45005}.Debug|Any CPU.ActiveCfg = Debug|x64 + {D506F6CE-1A4C-4655-809E-928893D45005}.Debug|Any CPU.Build.0 = Debug|x64 {D506F6CE-1A4C-4655-809E-928893D45005}.Debug|x64.ActiveCfg = Debug|Any CPU {D506F6CE-1A4C-4655-809E-928893D45005}.Debug|x64.Build.0 = Debug|Any CPU {D506F6CE-1A4C-4655-809E-928893D45005}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/Test/TestApp/MemoryTestApp/Classes/Processing.cs b/Test/TestApp/MemoryTestApp/Classes/Processing.cs index 498e060..35c7c00 100644 --- a/Test/TestApp/MemoryTestApp/Classes/Processing.cs +++ b/Test/TestApp/MemoryTestApp/Classes/Processing.cs @@ -15,70 +15,45 @@ public partial class TrainerForm : Form public bool ProcOpen = false; /// - /// Process opening code. Generates a list of modules too. + /// After process opens, update UI. Generates a list of modules too. /// - public void OpenTheProc() + public void ProcUIUpdate() { - ProcTypeBox.Invoke((MethodInvoker)delegate - { - if (String.Compare(ProcTypeBox.Text, "Name") == 0) // if combobox set to Name, use string - ProcOpen = m.OpenProcess(ProcTextBox.Text); - else // if combobox set to ID, use integer - ProcOpen = m.OpenProcess(Convert.ToInt32(ProcTextBox.Text)); - }); - if (ProcOpen) // if process opens successfully { - OpenProcessBtn.Invoke((MethodInvoker)delegate - { - OpenProcessBtn.Text = "Close Process"; - OpenProcessBtn.ForeColor = Color.Red; - }); + OpenProcessBtn.Text = "Close Process"; + OpenProcessBtn.ForeColor = Color.Red; - ModuleList.Invoke((MethodInvoker)delegate - { - if (ModuleList.Items.Count <= 0) - GetModuleList(); - }); + if (ModuleList.Items.Count <= 0) + GetModuleList(); } else // on process open fail, show error message { //MessageBox.Show("ERROR: Process open failed!"); - ProcStatus.Invoke((MethodInvoker)delegate - { - ProcStatus.Text = "Closed"; - ProcStatus.ForeColor = Color.Red; - }); - ModuleList.Invoke((MethodInvoker)delegate - { - if (ModuleList.Items.Count > 0) - ModuleList.Items.Clear(); - }); + ProcStatus.Text = "Closed"; + ProcStatus.ForeColor = Color.Red; + + if (ModuleList.Items.Count > 0) + ModuleList.Items.Clear(); StopWorker = true; } } public void GetModuleList() { - ModuleList.Invoke((MethodInvoker)delegate + ModuleList.Items.Clear(); + foreach (KeyValuePair kvp in m.mProc.Modules) // iterate through process module list { - ModuleList.Items.Clear(); - foreach (KeyValuePair kvp in m.modules) // iterate through process module list - { - string[] arr = new string[4]; - ListViewItem itm; - arr[0] = "0x" + kvp.Value.ToString("x8"); - arr[1] = kvp.Key; - itm = new ListViewItem(arr); - ModuleList.Items.Add(itm); - } - }); + string[] arr = new string[4]; + ListViewItem itm; + arr[0] = "0x" + kvp.Value.ToString("x8"); + arr[1] = kvp.Key; + itm = new ListViewItem(arr); + ModuleList.Items.Add(itm); + } - ProcStatus.Invoke((MethodInvoker)delegate - { - ProcStatus.Text = "Open"; - ProcStatus.ForeColor = Color.Green; - }); + ProcStatus.Text = "Open"; + ProcStatus.ForeColor = Color.Green; } /// diff --git a/Test/TestApp/MemoryTestApp/Forms/TrainerForm.Designer.cs b/Test/TestApp/MemoryTestApp/Forms/TrainerForm.Designer.cs index fe58da2..9c8f1d1 100644 --- a/Test/TestApp/MemoryTestApp/Forms/TrainerForm.Designer.cs +++ b/Test/TestApp/MemoryTestApp/Forms/TrainerForm.Designer.cs @@ -91,6 +91,7 @@ private void InitializeComponent() this.ProcTextBox.Size = new System.Drawing.Size(120, 20); this.ProcTextBox.TabIndex = 0; this.ProcTextBox.Text = "Xae\'s Quest"; + this.ProcTextBox.TextChanged += new System.EventHandler(this.ProcTextBox_TextChanged); // // label1 // @@ -601,8 +602,11 @@ private void InitializeComponent() // // BackgroundWork // + this.BackgroundWork.WorkerReportsProgress = true; this.BackgroundWork.WorkerSupportsCancellation = true; this.BackgroundWork.DoWork += new System.ComponentModel.DoWorkEventHandler(this.BackgroundWork_DoWork); + this.BackgroundWork.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.BackgroundWork_ProgressChanged); + this.BackgroundWork.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.BackgroundWork_RunWorkerCompleted); // // TrainerForm // diff --git a/Test/TestApp/MemoryTestApp/Forms/TrainerForm.cs b/Test/TestApp/MemoryTestApp/Forms/TrainerForm.cs index bcd2bfd..a32f7f9 100644 --- a/Test/TestApp/MemoryTestApp/Forms/TrainerForm.cs +++ b/Test/TestApp/MemoryTestApp/Forms/TrainerForm.cs @@ -30,6 +30,7 @@ public TrainerForm() Mem m = new Mem(); // Declare m as our Memory.dll function reference variable. bool StopWorker = false; + string ProcNameOrID; private void TrainerForm_Shown(object sender, EventArgs e) { @@ -41,6 +42,8 @@ private void TrainerForm_Shown(object sender, EventArgs e) private void OpenProcessBtn_Click(object sender, EventArgs e) { + ProcNameOrID = ProcTextBox.Text; + // start BG worker if not already started if (!BackgroundWork.IsBusy) { BackgroundWork.RunWorkerAsync(); @@ -102,18 +105,13 @@ private void BackgroundWork_DoWork(object sender, DoWorkEventArgs e) // infinite loop that checks if the process is available and open, if not, modify the UI. while (true) { - OpenTheProc(); - System.Threading.Thread.Sleep(1000); - if (StopWorker) - { - StopWorker = false; - OpenProcessBtn.Invoke((MethodInvoker)delegate - { - OpenProcessBtn.Text = "Close Process"; - OpenProcessBtn.ForeColor = Color.Red; - }); - break; - } + if (String.Compare(ProcTypeBox.Text, "Name") == 0) // if combobox set to Name, use string + ProcOpen = m.OpenProcess(ProcNameOrID); + else // if combobox set to ID, use integer + ProcOpen = m.OpenProcess(Convert.ToInt32(ProcNameOrID)); + + BackgroundWork.ReportProgress(0); // do UI thread stuff + Thread.Sleep(1000); } } @@ -122,5 +120,25 @@ private void UpdateModulesButton_Click(object sender, EventArgs e) if (ProcOpen) GetModuleList(); } + + private void BackgroundWork_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) + { + if (StopWorker) + { + StopWorker = false; + OpenProcessBtn.Text = "Open Process"; + OpenProcessBtn.ForeColor = Color.Black; + } + } + + private void BackgroundWork_ProgressChanged(object sender, ProgressChangedEventArgs e) + { + ProcUIUpdate(); + } + + private void ProcTextBox_TextChanged(object sender, EventArgs e) + { + StopWorker = true; // stop worker if we're changing process name + } } }