Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
        public static bool DecomposeFormatTest2()
        {
            string actualOutput = string.Empty;

            GCHandle gch = GCHandle.Alloc(Program.code2, GCHandleType.Pinned);

            // Prepare the _CodeInfo structure for decomposition.
            Distorm.CodeInfo ci = new Distorm.CodeInfo();
            ci.codeLen = Program.code2.Length;
            ci.code = gch.AddrOfPinnedObject();
            ci.codeOffset = 0xFFBAB9D0;
            ci.dt = Distorm.DecodeType.Decode64Bits;
            ci.features = Distorm.DecomposeFeatures.NONE;

            // Prepare the result instruction buffer to receive the decomposition.
            Distorm.DInst[] result = new Distorm.DInst[Program.code2.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;
            }

            Array.Resize(ref result, (int)usedInstructionsCount);

            return VerifyDecomposition2(result);
        }
Beispiel #3
0
        /// <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;
        }
Beispiel #4
0
        /// <summary>
        /// Tests the DistormSimple.distorm_decompose() function.
        /// </summary>
        /// <returns>Returns true if the test passed.</returns>
        public static bool DecomposeOnlyTest()
        {
            GCHandle gch = GCHandle.Alloc(Program.code, GCHandleType.Pinned);

            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;

            Distorm.DInst[] result = new Distorm.DInst[Program.code.Length];
            uint usedInstructionsCount = 0;

            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;
            }

            if (usedInstructionsCount < 6)
            {
                return false;
            }

            // Manually check each instruction.
            if (result[0].InstructionType != Distorm.InstructionType.PUSH ||
                result[0].ops[0].RegisterName != "ebp")
            {
                return false;
            }
            else if (result[1].InstructionType != Distorm.InstructionType.MOV ||
                result[1].ops[0].RegisterName != "ebp" ||
                result[1].ops[1].RegisterName != "esp")
            {
                return false;
            }
            else if (result[2].InstructionType != Distorm.InstructionType.MOV ||
                result[2].ops[0].RegisterName != "eax" ||
                result[2].ops[1].type != Distorm.OperandType.SMEM ||
                result[2].ops[1].RegisterName != "ebp" ||
                result[2].disp != 0x8)
            {
                return false;
            }
            else if (result[3].InstructionType != Distorm.InstructionType.ADD ||
                result[3].ops[0].RegisterName != "eax" ||
                result[3].ops[1].type != Distorm.OperandType.SMEM ||
                result[3].ops[1].RegisterName != "ebp" ||
                result[3].disp != 0xc)
            {
                return false;
            }
            else if (result[4].InstructionType != Distorm.InstructionType.LEAVE)
            {
                return false;
            }
            else if (result[5].InstructionType != Distorm.InstructionType.RET)
            {
                return false;
            }

            return true;
        }
Beispiel #5
0
        /// <summary>
        /// A wrapper for distorm_decompose(), which only takes in the code to be decomposed.
        /// </summary>
        /// <param name="code">The code to be decomposed.</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>
        /// <param name="logFilename">
        /// The name of the file to use to log important updates about the decomposition process.
        /// </param>
        /// <returns>Returns the code to be decomposed on success or an empty array upon failure.</returns>
        /// <remarks>
        /// Usage of brainpower is required to recognize that decomposing a code array of size 0 will also result in
        /// an empty array.
        /// </remarks>
        public static DInst[] Decompose(
            byte[] code,
            ulong offset = 0,
            DecodeType bitDepth = DecodeType.Decode32Bits,
            string logFilename = "Distorm3cs.log")
        {
            GCHandle gch = GCHandle.Alloc(code, GCHandleType.Pinned);

            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;

            // Most likely a gross over-estimation of how large to make the array, but it should never fail.
            Distorm.DInst[] result = new Distorm.DInst[code.Length];
            uint usedInstructionsCount = 0;

            // Decompose the data.
            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))
            {
                Logger.Log(
                    "Error decomposing data. Result was: " + r.ToString(),
                    logFilename,
                    Logger.Type.CONSOLE | Logger.Type.FILE);
                return new Distorm.DInst[0];
            }

            // Resize the array to match the actual number of instructions decoded.
            Array.Resize(ref result, (int)usedInstructionsCount);

            // Return the result.
            return result;
        }