Example #1
0
        public void Execute(IDebuggerSession session, string[] arguments, Logger output)
        {
            var process = session.GetProcesses().First();

            if (process != _process)
            {
                _process = process;
                _reader  = new ProcessMemoryReader(process)
                {
                    NegateBreakpoints = true
                };
                _disassembler = new X86Disassembler(_reader);
            }

            if (arguments.Length > 0)
            {
                _reader.Position = long.Parse(arguments[0], NumberStyles.HexNumber);
            }

            int count = 5;

            if (arguments.Length > 1)
            {
                count = int.Parse(arguments[1]);
            }

            for (int i = 0; i < count; i++)
            {
                var instruction = _disassembler.ReadNextInstruction();
                _printer.PrintInstruction(instruction, process.GetSoftwareBreakpointByAddress((IntPtr)instruction.Offset));
            }
        }
Example #2
0
        private static List <X86Instruction> ReadInstructions(int offset, int size, MemoryStreamReader reader)
        {
            List <X86Instruction> instrs = new List <X86Instruction>();
            X86Disassembler       disasm = new X86Disassembler(reader);

            while (reader.Position < offset + size)
            {
                instrs.Add(disasm.ReadNextInstruction());
            }
            return(instrs);
        }
Example #3
0
        public void SetCurrentFrame(IFrame currentFrame)
        {
            if (currentFrame == null || currentFrame.Function != _lastFunction)
            {
                instructionsListView.Items.Clear();
                _lastFunction = null;
            }

            if (currentFrame != null)
            {
                if (currentFrame.Function == _lastFunction)
                {
                    foreach (var item in instructionsListView.Items.Cast <X86InstructionListViewItem>())
                    {
                        item.UpdateItem(currentFrame);
                    }
                }
                else
                {
                    _lastFunction = currentFrame.Function;

                    var code         = ((RuntimeFunction)currentFrame.Function).NativeCode;
                    var mapping      = code.GetILToNativeMapping().ToArray();
                    var bytes        = code.GetBytes();
                    var reader       = new MemoryStreamReader(bytes);
                    var disassembler = new X86Disassembler(reader, (long)code.Address);
                    while (reader.Position < reader.StartPosition + reader.Length)
                    {
                        try
                        {
                            int start       = (int)reader.Position;
                            var instruction = disassembler.ReadNextInstruction();
                            int end         = (int)reader.Position;

                            var instructionBytes = new byte[end - start];
                            Buffer.BlockCopy(bytes, start, instructionBytes, 0, end - start);
                            var item = new X86InstructionListViewItem(instruction, instructionBytes);
                            item.RelativeOffset = start;

                            item.Mapping = mapping.FirstOrDefault(
                                x => item.RelativeOffset >= x.NativeStartOffset &&
                                item.RelativeOffset < x.NativeEndOffset);
                            item.UpdateItem(currentFrame);
                            instructionsListView.Items.Add(item);
                        }
                        catch (IndexOutOfRangeException)
                        {
                            // HACK: ignore mnemonic choosing errors in disassembler
                        }
                    }
                }
            }
        }
Example #4
0
        private static void ValidateCode(IReadOnlyList <X86Instruction> originalBody, byte[] assemblerOutput)
        {
            var formatter    = new FasmX86Formatter();
            var reader       = new MemoryStreamReader(assemblerOutput);
            var disassembler = new X86Disassembler(reader);

            for (int i = 0; i < originalBody.Count; i++)
            {
                var newInstruction = disassembler.ReadNextInstruction();
                Assert.Equal(formatter.FormatInstruction(originalBody[i]),
                             formatter.FormatInstruction(newInstruction));
            }
        }
        private static void TestSizeComputation(byte[] opcodes)
        {
            var reader       = new MemoryStreamReader(opcodes);
            var disassembler = new X86Disassembler(reader);

            while (reader.Position < reader.Length)
            {
                var instruction = disassembler.ReadNextInstruction();

                long expectedSize = reader.Position - instruction.Offset;
                long computeSize  = instruction.ComputeSize();

                Assert.Equal(expectedSize, computeSize);
            }
        }
Example #6
0
        private static void TestDisassembler(byte[] code, string source)
        {
            var reader       = new MemoryStreamReader(code);
            var disassembler = new X86Disassembler(reader);

            var sourceLines = NormalizeSource(source).Split('\n');
            var currentLine = 0;

            while (reader.Position < reader.Length)
            {
                var instruction = disassembler.ReadNextInstruction();

                var formattedInstruction = _formatter.FormatInstruction(instruction);
                Assert.AreEqual(sourceLines[currentLine], formattedInstruction);
                currentLine++;
            }
        }
Example #7
0
 public void ParseInstruction()
 {
     if (!initialized)
     {
         initialized = true;
         X86Disassembler dis = method.Executable.CreateDisassemblerFromAddress(StartAddress);
         X86Instruction  ins;
         bool            shouldBreak = false;
         do
         {
             ins = dis.ReadNextInstruction();
             ProcessPendingAddress(ins);
             instructions.Add(ins);
         }while (!ins.IsTerminator());
         EndAddress = ins.Offset;
         ProcessNextBlocks(ins);
     }
 }
Example #8
0
        private static void TestSizeComputation(byte[] opcodes)
        {
            var reader       = new MemoryStreamReader(opcodes);
            var disassembler = new X86Disassembler(reader);

            while (reader.Position < reader.Length)
            {
                var instruction = disassembler.ReadNextInstruction();

                var expectedSize = reader.Position - instruction.Offset;
                var computeSize  = instruction.ComputeSize();

                if (expectedSize != computeSize)
                {
                    Assert.Fail("The instruction {0} has size {1}, but {2} was computed.", instruction, expectedSize,
                                computeSize);
                }
            }
        }
Example #9
0
        public HookParameters Detect(HookSession session, IntPtr address)
        {
            var fixups = new List <ushort>();

            // Longest x86 instruction possible is 15 bytes. We need 5 bytes at least for a call.
            // Therefore, in the worst case scenario, we need to read 4 + 15 bytes worth of instructions.

            var reader       = new MemoryStreamReader(session.ReadMemory(address, 4 + 15));
            var disassembler = new X86Disassembler(reader, address.ToInt64());

            while (reader.Position - reader.StartPosition < 5)
            {
                var next = disassembler.ReadNextInstruction();
                if (next.OpCode.Op1 == X86OpCodes.Jmp_Rel1632.Op1 ||
                    next.OpCode.Op1 == X86OpCodes.Call_Rel1632.Op1)
                {
                    int offset = (int)(reader.Position - address.ToInt64() - 4);
                    fixups.Add((ushort)offset);
                }
            }

            return(new HookParameters((int)reader.Position, fixups));
        }
Example #10
0
        /*
         *  Byte[] asm = { 0xE8, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x00, 0xA1, 0xC0, 0x00, 0x00, 0x00 };
         *  X86Disassembler d = new X86Disassembler(new MemoryStreamReader(asm));
         *  X86Instruction i = d.ReadNextInstruction();
         *  i = d.ReadNextInstruction();
         *  i = d.ReadNextInstruction();
         */

        private static void LoadWadFiles(IntPtr function1Address, int funcOffset, IntPtr functionAddress, IntPtr ECDSA)
        {
            uint functionLength;
            uint functionLength1;
            uint ECDSALen;

            MemoryEditor.FindPattern(@"\xC2\x04\x00\xCC", "xxxx", ECDSA, out ECDSALen);
            MemoryEditor.FindPattern(@"\xC2\x08\x00\xCC", "xxxx", functionAddress, out functionLength);
            MemoryEditor.FindPattern(@"\xC3\x57\xE8\x00\x00\x00\x00\xCC", "xxx????x", function1Address, out functionLength1);
            functionLength  = (functionLength - (uint)functionAddress) + 4;
            ECDSALen        = (ECDSALen - (uint)ECDSA) + 4;
            functionLength1 = (functionLength1 - (uint)function1Address) + 8;
            //Steal the function:
            Byte[] asmECDSA;
            MemoryEditor.ReadBytes(ECDSA, (int)ECDSALen, out asmECDSA);
            Byte[] asm1;
            MemoryEditor.ReadBytes(function1Address, (int)functionLength1, out asm1);
            Byte[] asm;
            MemoryEditor.ReadBytes(functionAddress, (int)functionLength, out asm);
            //Allocate and copy the function to our new memory
            IntPtr AllocatedMemory = MemoryEditor.AllocateMemory(0x1000);
            //MemoryEditor.WriteBytes(AllocatedMemory, asm);
            //Fix the bytecode for the new offsets:
            X86Disassembler disassembler = new X86Disassembler(new MemoryStreamReader(asmECDSA));

            while (disassembler.BaseStream.Position != disassembler.BaseStream.Length)
            {
                X86Instruction instruction = disassembler.ReadNextInstruction();
                if (instruction.Mnemonic == X86Mnemonic.Je && instruction.Offset == 0x49)
                {
                    Buffer.BlockCopy(new Byte[] { 0x90, 0x90 }, 0, asmECDSA, (int)instruction.Offset, 2);
                    continue;
                }
                if (instruction.Mnemonic != X86Mnemonic.Call || (instruction.Operand1 != null && instruction.Operand1.OperandUsage == X86OperandUsage.DwordPointer))
                {
                    continue;
                }

                if (instruction.Operand1.Value.ToString() == "Eax")
                {
                    continue;
                }
                //Fix the Call:
                int offset;
                MemoryEditor.ReadInt(ECDSA + (int)instruction.Offset + 1, out offset);
                int callAddress = (5 + (int)instruction.Offset + (int)ECDSA) + offset;
                offset = callAddress - ((int)AllocatedMemory + (int)instruction.Offset + 5);
                Buffer.BlockCopy(BitConverter.GetBytes(offset), 0, asmECDSA, (int)instruction.Offset + 1, 4);
            }

            MemoryEditor.WriteBytes(AllocatedMemory, asmECDSA);
            AllocatedMemory += asmECDSA.Length;

            disassembler = new X86Disassembler(new MemoryStreamReader(asm));
            while (disassembler.BaseStream.Position != disassembler.BaseStream.Length)
            {
                X86Instruction instruction = disassembler.ReadNextInstruction();

                /*if (instruction.Mnemonic == X86Mnemonic.Jne)
                 * {
                 *  Buffer.BlockCopy(new Byte[] { 0xEB }, 0, asm, (int)instruction.Offset, 1);
                 *  continue;
                 * }*/

                if (instruction.Mnemonic != X86Mnemonic.Call || (instruction.Operand1 != null && instruction.Operand1.OperandUsage == X86OperandUsage.DwordPointer))
                {
                    continue;
                }

                if (instruction.Offset == 0x128)
                {
                    Buffer.BlockCopy(BitConverter.GetBytes(((int)AllocatedMemory - asmECDSA.Length) - ((int)AllocatedMemory + (int)instruction.Offset + 5))
                                     , 0, asm, (int)instruction.Offset + 1, 4);
                    continue;
                }
                //Fix the Call:
                int offset;
                MemoryEditor.ReadInt(functionAddress + (int)instruction.Offset + 1, out offset);
                int callAddress = (5 + (int)instruction.Offset + (int)functionAddress) + offset;
                offset = callAddress - ((int)AllocatedMemory + (int)instruction.Offset + 5);
                Buffer.BlockCopy(BitConverter.GetBytes(offset), 0, asm, (int)instruction.Offset + 1, 4);
            }

            MemoryEditor.WriteBytes(AllocatedMemory, asm);
            AllocatedMemory += asm.Length;

            disassembler = new X86Disassembler(new MemoryStreamReader(asm1));
            while (disassembler.BaseStream.Position != disassembler.BaseStream.Length)
            {
                X86Instruction instruction = disassembler.ReadNextInstruction();

                if (instruction.Mnemonic != X86Mnemonic.Call || (instruction.Operand1 != null && instruction.Operand1.OperandUsage == X86OperandUsage.DwordPointer))
                {
                    continue;
                }

                if (instruction.Offset == funcOffset)
                {
                    Buffer.BlockCopy(BitConverter.GetBytes(((int)AllocatedMemory - asm.Length) - ((int)AllocatedMemory + (int)instruction.Offset + 5))
                                     , 0, asm1, (int)instruction.Offset + 1, 4);
                    continue;
                }

                //Fix the Call:
                int offset;
                MemoryEditor.ReadInt(function1Address + (int)instruction.Offset + 1, out offset);
                int callAddress = (5 + (int)instruction.Offset + (int)function1Address) + offset;
                offset = callAddress - ((int)AllocatedMemory + (int)instruction.Offset + 5);
                Buffer.BlockCopy(BitConverter.GetBytes(offset), 0, asm1, (int)instruction.Offset + 1, 4);
            }
            MemoryEditor.WriteBytes(AllocatedMemory, asm1);
            IntPtr LoadWadFunction = AllocatedMemory;

            AllocatedMemory += asm1.Length;
            //Allocate Variables
            IntPtr StringAddress = AllocatedMemory + 0x10;

            //0x38 for failedFunctionCallback
            AllocatedMemory = StringAddress + 0x110;
            byte[] customAsm =
            {
                0x60, //pushad
                0x6A, 0x00,
                0x68, 0x00, 0x00, 0x00, 0x00,
                0xE8, 0x00, 0x00, 0x00, 0x00,
                0x5B,      //pop x2,
                0x5B,
                0x61,      //popad
                0xEB, 0xFE //Endless Loop so we know to correct the EIP
            };
            Buffer.BlockCopy(BitConverter.GetBytes((uint)StringAddress), 0, customAsm, 0x4, 4);
            Buffer.BlockCopy(BitConverter.GetBytes((uint)LoadWadFunction - ((uint)AllocatedMemory + 0xD)), 0, customAsm, 0x9, 4);
            MemoryEditor.WriteBytes(AllocatedMemory, customAsm);

            int lockedEip = (int)AllocatedMemory + customAsm.Length - 2;

            MemoryEditor.Suspend();
            MemoryEditor.Context context = MemoryEditor.GetThreadContext();
            uint originalEip             = context.Eip;

            //Load Each WADFile:
            foreach (String wadFile in WadFiles)
            {
                MemoryEditor.Suspend();
                context.Eip = (uint)AllocatedMemory;
                MemoryEditor.SetThreadContext(context);
                MemoryEditor.WriteNullTerminatedString(StringAddress, wadFile);
                MemoryEditor.Resume();
                //NOTE: THE CODE HAS TO RUN ON MAIN THREAD TO PROPERLY LOAD WADS
                //MemoryEditor.WaitForSingleObject(MemoryEditor.CreateRemoteThread(AllocatedMemory, IntPtr.Zero));
                bool loop = true;
                while (loop)
                {
                    context = MemoryEditor.GetThreadContext();
                    loop    = context.Eip != lockedEip;
                    MemoryEditor.Resume();
                }
            }
            context.Eip = originalEip;
            MemoryEditor.SetThreadContext(context);
            MemoryEditor.FreeMemory(AllocatedMemory);
        }