internal void ProcessInternal(Patcher p, Target target) { p.Method = p.FindMethod(target.FullName).ResolveMethodDef(); p.Instructions = p.Method.Body.Instructions; if (target.ILCodes != null && target.ILCodes.Count > 0) { ScriptEngineHelpers.ParseILCodes(p, target); } ScriptEngineHelpers.PatchTarget(p, target); ScriptEngineHelpers.WriteActionToLog(target); }
internal static void PatchTarget(Patcher p, Target target) { p.BackupExceptionHandlersIndices(); switch (target.Action) { case ActionMethod.Patch: p.Patch(target); break; case ActionMethod.Insert: p.Insert(target); break; case ActionMethod.Replace: p.Replace(target); break; case ActionMethod.Remove: p.Remove(target); break; case ActionMethod.EmptyBody: p.EmptyBody(target); break; case ActionMethod.ReturnBody: p.ReturnBody(target, Convert.ToBoolean(target.Optional)); break; default: throw new PatcherException("Invalid action method", target.FullName); } p.FixOffsets(); p.FixExceptionHandlers(); p.FixBranches(); }
internal static void ParseILCodes(Patcher p, Target target) { target.Instructions = new Instruction[target.ILCodes.Count]; for (int i = 0; i < target.Instructions.Length; i++) { string opcode = target.ILCodes[i].OpCode; if (opcode == null) { throw new PatcherException("OpCode is empty", target.FullName); } target.Instructions[i] = new Instruction(Helpers.GetOpCodeFromString(opcode.Replace('_', '.'))); } for (int i = 0; i < target.Instructions.Length; i++) { string operand = target.ILCodes[i].Operand; if (operand != null) { switch (target.Instructions[i].OpCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.ShortInlineBrTarget: if (target.Action == ActionMethod.Patch) { target.Instructions[i].Operand = p.GetInstruction(target, operand.ToInt()); } else { target.Instructions[i].Operand = p.GetInstruction(operand.ToInt()); } break; case OperandType.InlineField: target.Instructions[i].Operand = p.FindField(operand); break; case OperandType.InlineI: target.Instructions[i].Operand = operand.ToInt(); break; case OperandType.InlineI8: target.Instructions[i].Operand = operand.ToLong(); break; case OperandType.InlineMethod: target.Instructions[i].Operand = p.FindMethod(operand); break; case OperandType.InlineNone: case OperandType.InlinePhi: case OperandType.NOT_USED_8: target.Instructions[i].Operand = null; break; case OperandType.InlineR: target.Instructions[i].Operand = operand.ToDouble(); break; case OperandType.InlineSig: target.Instructions[i].Operand = p.FindMethod(operand).MethodSig; break; case OperandType.InlineString: target.Instructions[i].Operand = operand; break; case OperandType.InlineSwitch: string[] array = operand.Split(Constants.DefaultSeparator); Instruction[] instructions = new Instruction[array.Length]; for (var j = 0; j < array.Length; j++) { if (target.Action == ActionMethod.Patch) { instructions[j] = p.GetInstruction(target, array[j].ToInt()); } else { instructions[j] = p.GetInstruction(array[j].ToInt()); } } target.Instructions[i].Operand = instructions; break; case OperandType.InlineTok: target.Instructions[i].Operand = p.FindMethodFieldOrType(operand); break; case OperandType.InlineType: target.Instructions[i].Operand = p.FindType(operand); break; case OperandType.InlineVar: target.Instructions[i].Operand = p.Method.Parameters[operand.ToInt()]; break; case OperandType.ShortInlineI: target.Instructions[i].Operand = target.Instructions[i].OpCode.Code == Code.Ldc_I4_S ? (object)operand.ToSByte() : operand.ToByte(); break; case OperandType.ShortInlineR: target.Instructions[i].Operand = operand.ToFloat(); break; case OperandType.ShortInlineVar: target.Instructions[i].Operand = p.Method.Parameters[operand.ToInt()]; break; } } } target.ILCodes = null; //We don't need that anymore. }
public override void Process() { int patchedFileCount = 0; try { foreach (var patch in CurrentScript.PatchList) { foreach (string path in patch.TargetInfo.TargetFiles) { string filePath = path; if (!File.Exists(filePath)) { Logger.Error($"File not found -> {filePath}"); using (var ofd = new OpenFileDialog()) { ofd.FileName = Path.GetFileName(filePath); ofd.Filter = "Executable files (.exe;*.dll)|*.exe;*.dll|All files (*.*)|*.*"; ofd.CheckFileExists = true; string directoryName = Path.GetDirectoryName(filePath); if (Directory.Exists(directoryName)) { ofd.InitialDirectory = directoryName; } else { ofd.RestoreDirectory = true; } if (ofd.ShowDialog() == DialogResult.OK) { filePath = ofd.FileName; } else { Logger.Log("[Skipping file]"); Logger.Log(); continue; } } } bool keepOldMaxStack = patch.TargetInfo.KeepOldMaxStack; using (var p = new Patcher(filePath, keepOldMaxStack)) { Logger.Log($"[File Path] -> {filePath} {(keepOldMaxStack ? "-> KeepOldMaxStack: True" : string.Empty)}"); foreach (var target in patch.TargetList) { ProcessInternal(p, target); } p.Save(Convert.ToBoolean(CurrentScript.PatcherOptions.PatcherInfo.MakeBackup)); } patchedFileCount++; Logger.Log($"[File Patched] -> {filePath}"); Logger.Log(); } Logger.Log(); } } catch (Exception ex) { Logger.Error($"{ex.Message}{(Program.IsDebugModeEnabled ? $"\r\n{ex.StackTrace}" : string.Empty)}"); Logger.Log(); } Logger.Info(patchedFileCount > 0 ? $"Patching process finished! [{patchedFileCount} file(s) patched]" : "Nothing patched!"); }