private static bool doMemPatch(string[] processName, string[] svals, int offset, string[] rvals) { // Get process Process proc; if (processName.Length == 3) { proc = Process.GetProcessById(int.Parse(processName[2])); } else { proc = Process.GetProcessesByName(processName[1])[0]; } IntPtr baseAddress = proc.MainModule.BaseAddress; IntPtr moduleSize = (IntPtr)proc.MainModule.ModuleMemorySize; IntPtr hProc = NativeMethods.OpenProcess(NativeMethods.ProcessAccessFlags.All, false, proc.Id); // Read bytes int bytesRead = 0; byte[] bytes = new byte[moduleSize.ToInt32()]; if (!NativeMethods.ReadProcessMemory(hProc, baseAddress, bytes, moduleSize, ref bytesRead) || bytes == null) { goto badEnding; } // Search binary data for pattern int[] locs = Patcher.BinaryPatternSearch(ref bytes, svals); // Make sure we only have 1 match if (!onlyOne(locs.Length, processName[1], String.Join(" ", svals))) { goto badEnding; } // Replace int replaced = Patcher.BinaryPatternReplace(ref bytes, locs[0], rvals, offset); if (replaced < 1) { goto badEnding; } // Write bytes int bytesWritten = 0; uint oldp = 0; uint oldp2 = 0; byte[] newbytes = new byte[rvals.Length]; IntPtr off = baseAddress + locs[0] + offset; // Get write privileges if (!NativeMethods.VirtualProtectEx(proc.Handle, off, (IntPtr)rvals.Length, (uint)NativeMethods.Protection.PAGE_EXECUTE_WRITECOPY, ref oldp)) { goto badEnding; } // Do actual write Array.Copy(bytes, locs[0] + offset, newbytes, 0, rvals.Length); NativeMethods.WriteProcessMemory(hProc, off, newbytes, (IntPtr)rvals.Length, ref bytesWritten); // Set original access rights back (we have no buisness getting errors here) NativeMethods.VirtualProtectEx(proc.Handle, off, (IntPtr)rvals.Length, oldp, ref oldp2); // Were we successful? if (bytesWritten != rvals.Length) { goto badEnding; } // Happy ending. :) NativeMethods.CloseHandle(hProc); return(true); badEnding: NativeMethods.CloseHandle(hProc); return(false); }
private static bool doPatch(string file, string search, string offset, string replace) { // Variable setup int off; if (!Int32.TryParse(offset, out off)) { return(false); } search = search.Trim(); replace = replace.Trim(); string[] svals = search.Replace(_qq, _q).Replace(_ss, _q).Split(' '); string[] rvals = replace.Replace(_qq, _q).Replace(_ss, _q).Split(' '); if (replace.Length == 0) { return(findOnly(file, ref svals)); } // MemPatch! :) (Highly experimental!) if (file.Length > 5 && file.Substring(0, 5).ToLower() == _p) { return(doMemPatch(file.Split(':'), svals, off, rvals)); } if (!File.Exists(file)) { if (isconsole == 0) { MessageBox.Show("File not found."); } else if (isconsole == 2) { Console.WriteLine(file + " not found."); } return(false); } // Get file contents byte[] bytes = File.ReadAllBytes(file); // Search binary data for pattern int[] locs = Patcher.BinaryPatternSearch(ref bytes, svals); // Make sure we only have 1 match if (!onlyOne(locs.Length, file, search)) { return(false); } // Replace int replaced = Patcher.BinaryPatternReplace(ref bytes, locs[0], rvals, off); if (replaced < 1) { return(false); } // Write new file if (!File.Exists(file + _b)) { File.Move(file, file + _b); } File.WriteAllBytes(file, bytes); return(true); }