public static OpCode DecodeOpCode(IMemoryManager memory, ulong address, ExecutionMode mode) { int opCode = memory.Read <int>(address); InstDescriptor inst; OpCodeTable.MakeOp makeOp; if (mode == ExecutionMode.Aarch64) { (inst, makeOp) = OpCodeTable.GetInstA64(opCode); } else { if (mode == ExecutionMode.Aarch32Arm) { (inst, makeOp) = OpCodeTable.GetInstA32(opCode); } else /* if (mode == ExecutionMode.Aarch32Thumb) */ { (inst, makeOp) = OpCodeTable.GetInstT32(opCode); } } if (makeOp != null) { return((OpCode)makeOp(inst, address, opCode)); } else { return(new OpCode(inst, address, opCode)); } }
public static OpCode64 DecodeOpCode(MemoryManager memory, long position, ExecutionMode mode) { int opCode = memory.ReadInt32(position); Inst inst; if (mode == ExecutionMode.Aarch64) { inst = OpCodeTable.GetInstA64(opCode); } else { if (mode == ExecutionMode.Aarch32Arm) { inst = OpCodeTable.GetInstA32(opCode); } else /* if (mode == ExecutionMode.Aarch32Thumb) */ { inst = OpCodeTable.GetInstT32(opCode); } } OpCode64 decodedOpCode = new OpCode64(Inst.Undefined, position, opCode); if (inst.Type != null) { decodedOpCode = MakeOpCode(inst.Type, inst, position, opCode); } return(decodedOpCode); }
public override Instruction ReadInstruction(Function function) { var instr = new Instruction(); var instruction = Reader.ReadBEInt32(); var opcode = (instruction & 0xFF000000) >> 25; var a = instruction & 0xFF; int c = (int)(instruction & 0x1FF00) >> 8; int b = (int)(instruction & 0x1FE0000) >> 17; bool szero = false; if (c >= 256) { c -= 256; szero = true; } instr.A = (uint)a; instr.B = (uint)b; instr.C = (uint)c; instr.Bx = (uint)((instruction & 0x1FFFF00) >> 8); instr.SBx = (int)(instr.Bx - 65536 + 1); instr.ExtraCBit = szero; instr.OpCode = LuaOpCode.HKS_OPCODE_UNK; if (OpCodeTable.TryGetValue((int)opcode, out LuaOpCode opCode)) { instr.OpCode = opCode; } return(instr); }
public static OpCode64 DecodeOpCode(CpuThreadState state, MemoryManager memory, long position) { int opCode = memory.ReadInt32(position); Inst inst; if (state.ExecutionMode == ExecutionMode.AArch64) { inst = OpCodeTable.GetInstA64(opCode); } else { //TODO: Thumb support. inst = OpCodeTable.GetInstA32(opCode); } OpCode64 decodedOpCode = new OpCode64(Inst.Undefined, position, opCode); if (inst.Type != null) { decodedOpCode = MakeOpCode(inst.Type, inst, position, opCode); } return(decodedOpCode); }
public static OpCode DecodeOpCode(MemoryManager memory, ulong address, ExecutionMode mode) { int opCode = memory.ReadInt32((long)address); InstDescriptor inst; Type type; if (mode == ExecutionMode.Aarch64) { (inst, type) = OpCodeTable.GetInstA64(opCode); } else { if (mode == ExecutionMode.Aarch32Arm) { (inst, type) = OpCodeTable.GetInstA32(opCode); } else /* if (mode == ExecutionMode.Aarch32Thumb) */ { (inst, type) = OpCodeTable.GetInstT32(opCode); } } if (type != null) { return(MakeOpCode(inst, type, address, opCode)); } else { return(new OpCode(inst, address, opCode)); } }
public OpArray(OpCodeTable table) { List <Op> ops = new List <Op>(); foreach (string opName in table.NameToOpCode.Keys) { ops.Add(new Op(opName, true)); } _ops = ops.ToArray(); _length = _ops.Length; }
public VexHandler(uint dword1, uint dword2, uint dword3) : base(GetCode(dword1), GetOpCode(dword1), GetGroupIndex(dword2), (Encodable)((dword2 >> (int)VexFlags.EncodableShift) & (int)VexFlags.EncodableMask), OperandSize.None, AddressSize.None, null, CreateOps(dword3)) { opCodeTable = (OpCodeTable)((dword2 >> (int)VexFlags.OpCodeTableShift) & (int)VexFlags.OpCodeTableMask); mandatoryPrefix = (MandatoryPrefix)((dword2 >> (int)VexFlags.MandatoryPrefixShift) & (int)VexFlags.MandatoryPrefixMask); W1 = (dword2 & (uint)VexFlags.VEX_W1) != 0; lastByte = (dword2 >> ((int)VexFlags.VEX_LShift - 2)) & 4; if (W1) { lastByte |= 0x80; } }
public void AddOpTable(OpCodeTable table) { Action action = () => { _ops = new OpArray(table); //string[] uck = new string[] { "BALLOON", "LOCATION", "DOOR", "SHUTTLE", "SPAWN", "S_SOCIAL" }; //foreach (string filter in uck) //{ // foreach (Op op in _ops.GetByFilter(filter)) _ops[op.Name].Checked = false; //} }; Invoke(action); }
public EvexHandler(uint dword1, uint dword2, uint dword3) : base(GetCode(dword1), GetOpCode(dword1), GetGroupIndex(dword2), (Encodable)((dword2 >> (int)EvexFlags.EncodableShift) & (int)EvexFlags.EncodableMask), OperandSize.None, AddressSize.None, tryConvertToDisp8N, CreateOps(dword3)) { flags = (EvexFlags)dword2; tupleType = (TupleType)((dword2 >> (int)EvexFlags.TupleTypeShift) & (uint)EvexFlags.TupleTypeMask); opCodeTable = (OpCodeTable)((dword2 >> (int)EvexFlags.OpCodeTableShift) & (int)EvexFlags.OpCodeTableMask); Debug.Assert((int)MandatoryPrefix.None == 0); Debug.Assert((int)MandatoryPrefix.P66 == 1); Debug.Assert((int)MandatoryPrefix.PF3 == 2); Debug.Assert((int)MandatoryPrefix.PF2 == 3); p1Bits = 4 | ((dword2 >> (int)EvexFlags.MandatoryPrefixShift) & (int)EvexFlags.MandatoryPrefixMask); if ((dword2 & (uint)EvexFlags.EVEX_W1) != 0) { p1Bits |= 0x80; } llBits = (dword2 >> ((int)EvexFlags.EVEX_LShift - 5)) & 0x60; }
private static void LinkNode(IGraphNode node, IDictionary <ushort, CallGraphNode> nodes, ushort targetIP) { CallGraphNode targetNode; if (nodes.TryGetValue(targetIP, out targetNode)) { node.OutEdges.Add(targetNode); targetNode.InEdges.Add(node); } else { // Create a new empty node at the IP IList <IInstruction> instructions = new List <IInstruction>(); instructions.Add(OpCodeTable.GetInstruction(OpCodes.Nop, targetIP, null)); CallGraphNode emptyNode = new CallGraphNode(instructions); nodes.Add(targetIP, emptyNode); node.OutEdges.Add(emptyNode); emptyNode.InEdges.Add(node); } }
protected override Instruction ReadInstruction() { var instruction = new HavokInstruction(); // Reading the values attached to the instruction // A = 8 bits // C = 9 bits // B = 8 bits // OpCode = 7 bits instruction.A = Reader.ReadByte(); int cValue = Reader.ReadByte(); byte bValue = Reader.ReadByte(); if (GetBit(bValue, 0) == 1) { instruction.ExtraCBit = true; } instruction.C = (uint)cValue; instruction.B = (uint)(bValue >> 1); byte flagsB = Reader.ReadByte(); if (GetBit(flagsB, 0) == 1) { instruction.B += 128; } instruction.HavokOpCode = LuaHavokOpCode.HKS_OPCODE_UNK; if (OpCodeTable.TryGetValue(flagsB >> 1, out var opCode)) { instruction.HavokOpCode = opCode; } instruction.Bx = (uint)(instruction.B * 512 + instruction.C + (instruction.ExtraCBit ? 256 : 0)); instruction.SBx = (int)(instruction.Bx - 65536 + 1); return(instruction); }
private void Test(String methodName) { MethodInfo method = typeof(ExceptionHandlerTest).GetMethod(methodName); MethodBody body = method.GetMethodBody(); IMethodReference methodReference = AssemblyManager.FindMethod(method); ushort ip = 0; byte[] il = body.GetILAsByteArray(); SortedList <ushort, IInstruction> instructions = new SortedList <ushort, IInstruction>(); while (ip < il.Length) { instructions.Add(ip, OpCodeTable.GetInstruction(il, ref ip, (NDecompile.Model.Impl.Module)methodReference.Resolve().DeclaringType.Resolve().Module, new Type[0], new Type[0])); } foreach (ExceptionHandlingClause clause in body.ExceptionHandlingClauses) { Console.WriteLine(clause.Flags); Console.WriteLine(clause.TryOffset + " " + (clause.TryOffset + clause.TryLength)); Console.WriteLine(clause.HandlerOffset + " " + (clause.HandlerOffset + clause.HandlerLength)); Console.WriteLine(); } Node rootNode = new Node(); rootNode.StartIP = 0; rootNode.EndIP = (ushort)body.GetILAsByteArray().Length; rootNode.Type = "Return"; rootNode.Instructions.AddRange(instructions.Values); List <Node> nodes = new List <Node>(); nodes.Add(rootNode); // Add the exception information - build a sorted tree of clauses SortedList <int, TryHandler> clauses = new SortedList <int, TryHandler>(); foreach (ExceptionHandlingClause clause in body.ExceptionHandlingClauses) { Add(new TryHandler(clause), clauses); } Print(clauses, 0); Console.WriteLine(); foreach (TryHandler tryHandler in clauses.Values) { TraverseExceptionTree(tryHandler, nodes); } foreach (Node node in nodes) { Console.Write(node.StartIP + " " + node.EndIP + " " + node.Type); if (node.Type == "Try") { //Console.Write(" - Handler Node " + node.OutEdges[1].StartIP + " - Follow Node " + node.OutEdges[2].StartIP); Console.Write(" - Handler Node " + node.HandlerNode.StartIP + " - Follow Node " + node.FollowNode.StartIP); } ; Console.WriteLine(); foreach (IInstruction instruction in node.Instructions) { Console.WriteLine(" " + instruction.IP + " " + instruction.OpCode.Name); } } }
public Instruction(NetOpCode opCode, ushort ip, Object argument) { _opCode = OpCodeTable.Get(opCode.Value); _ip = ip; _argument = argument; }
public void generateOpcodeTable(int key) { if (key == 0) { byte[] opcodes = new byte[0xd1]; // d0 + 1 for (int i = 0; i < opcodes.Length; i++) { opcodes[i] = (byte)i; } short[] exOpcodes = new short[0x4e]; for (int i = 0; i < exOpcodes.Length; i++) { exOpcodes[i] = (byte)i; } _table = new OpCodeTable(opcodes, exOpcodes); } else { _table = OpcodeObfuscator.getObfuscatedTable(key); } }
public static void AddTable(OpCodeTable table) => Instance.AddOpTable(table);
public ControlFlowGraph(NetMethodBody body, Module module, Type[] genericTypeArguments, Type[] genericMethodArguments) { // Convert the byte code into instruction objects ushort ip = 0; byte[] il = body.GetILAsByteArray(); List <IInstruction> instructions = new List <IInstruction>(); while (ip < il.Length) { instructions.Add(OpCodeTable.GetInstruction(il, ref ip, module, genericTypeArguments, genericMethodArguments)); } // Iterate the instructions building a list of call graph nodes SortedList <ushort, CallGraphNode> nodes = new SortedList <ushort, CallGraphNode>(); CallGraphNode node = new CallGraphNode(0); nodes.Add(0, node); int index = 0; IInstruction instruction = instructions[index]; do { Console.Write(instruction); // Create the nodes that this instruction branches to switch (instruction.OpCode.FlowControl) { case FlowControl.Branch: { if ((instruction.OpCode != OpCodes.Leave) && (instruction.OpCode != OpCodes.Leave_S)) { // Direct branch to a new instruction that is not a leave instruction from a try-catch block. // Create a call graph node for the target of the branch. MakeNode((ushort)instruction.Argument, nodes); Console.Write(" <-- Branch {0:x4}", instruction.Argument); } break; } case FlowControl.Cond_Branch: { if (instruction.OpCode.Value == OpCodes.Switch.Value) { // Conditional branch to n-blocks foreach (ushort switchTargetIp in (ushort[])instruction.Argument) { MakeNode(switchTargetIp, nodes); } } else { // Conditional branch to two blocks MakeNode((ushort)instruction.Argument, nodes); Console.WriteLine("Making " + instruction.Argument); } // Set the next instruction of a branch to also be a target MakeNode(instructions[index + 1].IP, nodes); Console.Write(" <-- If Node {0:x4}", instruction.Argument); break; } case FlowControl.Return: // Set the next instruction of a branch to also be a target Console.Write(" <-- Exit Node"); break; case FlowControl.Throw: // End of graph Console.Write(" <-- Throw Node"); break; case FlowControl.Break: case FlowControl.Call: case FlowControl.Meta: case FlowControl.Next: #pragma warning disable 612,618 case FlowControl.Phi: #pragma warning restore 612,618 // Add the continuation link //node.NodeType = NodeType.FallThrough; //MakeNode(ip, node, nodes); break; } Console.WriteLine(); // Get the next instruction index++; if (index < instructions.Count) { instruction = instructions[index]; // Find the node to add the next instruction to CallGraphNode nextNode; if (nodes.TryGetValue(instruction.IP, out nextNode)) { /*if (node.NodeType == NodeType.FallThrough) * { * Console.Write("added fall through link "); * node.OutEdges.Add(nextNode); * nextNode.InEdges.Add(node); * }*/ node = nextNode; Console.Write("New Node --> "); } } } while (index < instructions.Count); Console.WriteLine(); // Iterate the instructions a second time adding them to the correct nodes //CallGraphNode node; node = nodes[0]; for (index = 0; index < instructions.Count; index++) { instruction = instructions[index]; if (index > 0) { CallGraphNode nextNode; if (nodes.TryGetValue(instruction.IP, out nextNode)) { if (node.OutEdges.Count == 0) { Console.WriteLine("ff"); node.NodeType = NodeType.FallThrough; LinkNode(node, nextNode); } Console.Write("--" + node.OutEdges.Count + "--"); node = nextNode; Console.Write("new node "); } } Console.WriteLine(instruction); node.Instructions.Add(instruction); // Create the nodes that this instruction branches to switch (instruction.OpCode.FlowControl) { case FlowControl.Branch: { if ((instruction.OpCode != OpCodes.Leave) && (instruction.OpCode != OpCodes.Leave_S)) { // Direct branch to a new instruction that is not a leave instruction from a try-catch block. // Create a call graph node for the target of the branch. node.NodeType = NodeType.OneBranch; LinkNode(node, nodes[(ushort)instruction.Argument]); Console.Write(" <-- Branch {0:x4}", instruction.Argument); } break; } case FlowControl.Cond_Branch: { if (instruction.OpCode.Value == OpCodes.Switch.Value) { // Conditional branch to n-blocks node.NodeType = NodeType.MultiBranch; foreach (ushort switchTargetIp in (ushort[])instruction.Argument) { LinkNode(node, nodes[switchTargetIp]); } } else { // Conditional branch to two blocks node.NodeType = NodeType.TwoBranch; LinkNode(node, nodes[(ushort)instruction.Argument]); Console.Write("Linking " + instruction.Argument); } // Set the next instruction of a branch to also be a target LinkNode(node, nodes[instructions[index + 1].IP]); Console.Write(" <-- If Node {0:x4}", instruction.Argument); break; } case FlowControl.Return: // Set the next instruction of a branch to also be a target node.NodeType = NodeType.Exit; Console.Write(" <-- Exit Node"); break; case FlowControl.Throw: // End of graph node.NodeType = NodeType.Throw; Console.Write(" <-- Throw Node"); break; } } // Copy the nodes to a simple list _nodes.AddRange(nodes.Values); Console.WriteLine(); Console.WriteLine(_nodes.Count); foreach (CallGraphNode n in _nodes) { Console.WriteLine(n.StartIP + " " + n.NodeType + " " + n.OutEdges.Count); } CheckGraph(); // Add the exception information - build a sorted tree of clauses SortedList <int, TryHandler> clauses = new SortedList <int, TryHandler>(); foreach (ExceptionHandlingClause clause in body.ExceptionHandlingClauses) { Add(new TryHandler(clause), clauses); } foreach (TryHandler clause in clauses.Values) { TraverseExceptionTree(clause); } // Find the root node -- This fails when there are multiple try statements on the first instruction for (int i = 0; i < _nodes.Count; i++) { if (_nodes[i].StartIP == 0) { _rootNode = _nodes[i]; break; } } if (_rootNode == null) { throw new ApplicationException("Unable to find a root node"); } CheckGraph(); // Remove redundancies and add in-edge information Optimize(); CheckGraph(); // Visit the graph in depth first order and label the nodes _depthFirstSearchLast = new CallGraphNode[_nodes.Count]; int last = _nodes.Count - 1; DepthFirstTraverse(_rootNode, ref last); // Find the immediate dominators of each node FindImmediateDominators(); // Check the graph for reducibility FindDerivedSequence(); // Work out the graphs back edges DetermineBackEdges(); ResetTraversal(); StructureCases(); StructureLoops(); StructureIfs(); ResetTraversal(); }
protected override Instruction ReadInstruction() { var instr = new LuaJitInstruction(); var codeword = Reader.ReadUInt32(); instr.OpCode = LuaJitOpCode.UNKNW; if (OpCodeTable.TryGetValue((int)(codeword & 0xFF), out var opCode)) { instr.OpCode = opCode; } dynamic ProcessOperand(LuaJitArgumentType type, dynamic operand) { if (type is LuaJitArgumentType.Str or LuaJitArgumentType.Tab or LuaJitArgumentType.Fun or LuaJitArgumentType.Cdt) { return(((long)((LuaJitFunctionHeader)Header).ComplexConstantsCount) - operand - 1); } if (type == LuaJitArgumentType.Jmp) { return(operand - 0x8000); } if (type == LuaJitArgumentType.Slit || type == LuaJitArgumentType.Num) { return(BitConverter.ToInt16(BitConverter.GetBytes(operand))); } return(operand); } var a = (codeword >> 8) & 0xFF; uint b = 0; long cd; if (instr.OpCode.ArgumentsCount == 3) { cd = (codeword >> 16) & 0xFF; b = (codeword >> 24) & 0xFF; } else { cd = (codeword >> 16) & 0xFFFF; } if (instr.OpCode.AType != LuaJitArgumentType.None) { instr.A = ProcessOperand(instr.OpCode.AType, a); } if (instr.OpCode.BType != LuaJitArgumentType.None) { instr.B = ProcessOperand(instr.OpCode.BType, b); } if (instr.OpCode.CDType != LuaJitArgumentType.None) { instr.CD = ProcessOperand(instr.OpCode.CDType, cd); } return(instr); }