/// <summary> /// Tests both the distorm_decompose and distorm_format functions. /// </summary> /// <returns>Returns true if both tests passed.</returns> public static bool DecomposeFormatTest() { string expectedOutput = "push ebp\n" + "mov ebp, esp\n" + "mov eax, [ebp+0x8]\n" + "add eax, [ebp+0xc]\n" + "leave\n" + "ret\n"; string actualOutput = string.Empty; GCHandle gch = GCHandle.Alloc(Program.code, GCHandleType.Pinned); // Prepare the _CodeInfo structure for decomposition. Distorm.CodeInfo ci = new Distorm.CodeInfo(); ci.codeLen = Program.code.Length; ci.code = gch.AddrOfPinnedObject(); ci.codeOffset = 0; ci.dt = Distorm.DecodeType.Decode32Bits; ci.features = Distorm.DecomposeFeatures.NONE; // Prepare the result instruction buffer to receive the decomposition. Distorm.DInst[] result = new Distorm.DInst[Program.code.Length]; uint usedInstructionsCount = 0; // Perform the decomposition. Distorm.DecodeResult r = Distorm.distorm_decompose(ref ci, result, (uint)result.Length, ref usedInstructionsCount); // Release the handle pinned to the code. gch.Free(); // Return false if an error occured during decomposition. if (!r.Equals(Distorm.DecodeResult.SUCCESS)) { return false; } // Prepare a _DecodedInst structure for formatting the results. Distorm.DecodedInst inst = new Distorm.DecodedInst(); for (uint i = 0; i < usedInstructionsCount; ++i) { // Format the results of the decomposition. Distorm.distorm_format(ref ci, ref result[i], ref inst); // Add it to the buffer to be verified. if (string.IsNullOrEmpty(inst.Operands)) { actualOutput += inst.Mnemonic + "\n"; } else { actualOutput += inst.Mnemonic + " " + inst.Operands + "\n"; } } return expectedOutput.Equals(actualOutput); }
/// <summary> /// Translates opcodes into a list of strings, which each represent an instruction. /// </summary> /// <param name="code">The code to be disassembled.</param> /// <param name="offset">The offset at which the code starts in the image being disassembled.</param> /// <param name="bitDepth">The target architecture type of the code being disassembled.</param> /// <returns>Returns the disassembled instructions.</returns> public static List<string> Disassemble( byte[] code, ulong offset = 0, DecodeType bitDepth = DecodeType.Decode32Bits) { List<string> instructions = new List<string>(); GCHandle gch = GCHandle.Alloc(code, GCHandleType.Pinned); // Prepare the CodeInfo structure for decomposition. Distorm.CodeInfo ci = new Distorm.CodeInfo(); ci.codeLen = code.Length; ci.code = gch.AddrOfPinnedObject(); ci.codeOffset = offset; ci.dt = bitDepth; ci.features = Distorm.DecomposeFeatures.NONE; // Prepare the result instruction buffer to receive the decomposition. Distorm.DInst[] result = new Distorm.DInst[code.Length]; uint usedInstructionsCount = 0; // Perform the decomposition. Distorm.DecodeResult r = Distorm.distorm_decompose(ref ci, result, (uint)result.Length, ref usedInstructionsCount); // Release the handle pinned to the code. gch.Free(); // Return an empty list if an error occured during decomposition. if (!r.Equals(Distorm.DecodeResult.SUCCESS)) { return new List<string>(); } // Prepare a DecodedInst structure for formatting the results. Distorm.DecodedInst inst = new Distorm.DecodedInst(); for (uint i = 0; i < usedInstructionsCount; ++i) { // Format the results of the decomposition. Distorm.distorm_format(ref ci, ref result[i], ref inst); // Add it to the buffer to be verified. if (string.IsNullOrEmpty(inst.Operands)) { instructions.Add(inst.Mnemonic); } else { instructions.Add(inst.Mnemonic + " " + inst.Operands); } } return instructions; }