Exemplo n.º 1
0
        private void btnDisAsm_Click(object sender, EventArgs e)
        {
            rtbHexDump.Clear();

            //Console.WriteLine("Version: " + BeaEngine.Version);
            //Console.WriteLine("Revision: " + BeaEngine.Revision);

            //UnmanagedBuffer buffer = new UnmanagedBuffer(File.ReadAllBytes("BeaEngine.dll"));

            uint address  = Convert.ToUInt32(tbOffsetToWatch.Text, 16);
            uint naddress = address + (uint)baseAddressModule;

            UnmanagedBuffer buffer = new UnmanagedBuffer(procTools.Memory.ReadBytes(naddress, 1120));

            var disasm = new Disasm();

            //disasm.EIP = new IntPtr(buffer.Ptr.ToInt64() + 0x400);
            disasm.EIP = new IntPtr(buffer.Ptr.ToInt64());

            for (int counter = 0; counter < 100; ++counter)
            {
                int result = BeaEngine.Disasm(disasm);

                if (result == (int)BeaConstants.SpecialInfo.UNKNOWN_OPCODE)
                {
                    break;
                }

                //rtbHexDump.AppendText("0x" + disasm.EIP.ToString("X") + " " + disasm.CompleteInstr+"\r\n");
                rtbHexDump.AppendText("0x" + address.ToString("X") + "\t" + disasm.CompleteInstr + "\r\n");
                disasm.EIP = new IntPtr(disasm.EIP.ToInt64() + result);
                address   += (uint)result;
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Disassembles the given code
        /// </summary>
        /// <param name="generatedCode">The generated code</param>
        public string Disassemble(IList <byte> generatedCode)
        {
            var output = new StringBuilder();
            var buffer = new UnmanagedBuffer(generatedCode.ToArray());

            var disasm = new Disasm()
            {
                Archi = 64
            };

            int offset = 0;

            while (offset < generatedCode.Count)
            {
                disasm.EIP = new IntPtr(buffer.Ptr.ToInt64() + offset);
                int result = BeaEngine64.Disasm(disasm);

                if (result == (int)BeaConstants.SpecialInfo.UNKNOWN_OPCODE)
                {
                    break;
                }

                //strBuffer.AppendLine("0x" + offset.ToString("X") + " " + disasm.CompleteInstr);
                output.AppendLine(disasm.CompleteInstr);
                offset += result;
            }

            return(output.ToString());
        }
Exemplo n.º 3
0
 public X86IMUL(Disasm rawInstruction) : base()
 {
     Operands    = new IX86Operand[3];
     Operands[0] = GetOperand(rawInstruction.Argument1);
     Operands[1] = GetOperand(rawInstruction.Argument2);
     Operands[2] = GetOperand(rawInstruction.Argument3);
 }
Exemplo n.º 4
0
        /// <summary>
        /// Creates a new disassembler
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        public Disassembler(AbstractCompilationData compilationData)
        {
            this.compilationData = compilationData;

            this.codeBuffer   = new UnmanagedBuffer(compilationData.Function.GeneratedCode.ToArray());
            this.disassembler = new Disasm()
            {
                Archi = 64,
                EIP   = new IntPtr(this.codeBuffer.Ptr.ToInt64())
            };
        }
Exemplo n.º 5
0
        /// <summary>
        /// Disassemble a given piece of shellcode. 
        /// </summary>
        /// <param name="disasmBytes">The byte array to disassemble</param>
        /// <param name="architecture">The architecture to target. Either 32 or 64 bit Windows</param>
        /// <param name="disasmBox">The listbox to place the disassembly</param>
        /// <param name="showOffsets">Boolean to determine whether or not to display address offsets in the disassembly listing.</param>
        public void disassembleSC(byte[] disasmBytes, uint architecture, System.Windows.Forms.RichTextBox disasmBox, bool showOffsets)
        {
            var disasm = new Disasm();
            disasm.Options = 0x200;//display in NASM syntax

            if (architecture == 32)
            {
                disasm.Archi = 32;
            }
            else if (architecture == 64)
            {
                disasm.Archi = 64;
            }

            int size = disasmBytes.Length;
            IntPtr executionPointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(size);
            System.Runtime.InteropServices.Marshal.Copy(disasmBytes, 0, executionPointer, size);
            disasm.EIP = new IntPtr(executionPointer.ToInt64());

            int result;
            var disasmPtr = Marshal.AllocHGlobal(Marshal.SizeOf(disasm));
            disasmBox.AppendText("Disassembled shellcode with " + architecture + "bit\n");
            var EIPrange = (executionPointer.ToInt64() + size/2);

            try
            {
                while (disasm.EIP.ToInt64()  < EIPrange)
                {
                    System.Runtime.InteropServices.Marshal.StructureToPtr(disasm, disasmPtr, false);
                    result = BeaEngine.Disasm(disasmPtr);
                    Marshal.PtrToStructure(disasmPtr, disasm);
                    if (result == (int)BeaConstants.SpecialInfo.UNKNOWN_OPCODE)
                    {
                        disasmBox.AppendText("Unknown opcode error @ " + disasm.EIP.ToString("X") + "\n");
                        break;
                    }

                    if (showOffsets)
                        disasmBox.AppendText(disasm.EIP.ToString("X") + "h : " + disasm.CompleteInstr.ToString() + "\n");
                    else
                        disasmBox.AppendText(disasm.CompleteInstr.ToString() + "\n");

                    if (disasm.Instruction.Opcode.ToString("X") == "C3")
                        break;
                    disasm.EIP = new IntPtr(disasm.EIP.ToInt64() + result);

                }
            }
            catch
            {
                disasmBox.AppendText("Something went wrong with disassembly\n");
            }
        }
Exemplo n.º 6
0
 public DisassemblyInstruction(Disasm disasm, int length, byte[] instructionData)
 {
     Length              = length;
     InstructionData     = instructionData;
     CompleteInstruction = disasm.CompleteInstr;
     Architecture        = disasm.Archi;
     Options             = disasm.Options;
     Instruction         = disasm.Instruction;
     Argument1           = disasm.Argument1;
     Argument2           = disasm.Argument2;
     Argument3           = disasm.Argument3;
     Prefix              = disasm.Prefix;
 }
Exemplo n.º 7
0
 public static Disasm Clone(Disasm disasm)
 {
     return(new Disasm
     {
         Archi = disasm.Archi,
         Argument1 = disasm.Argument1,
         Argument2 = disasm.Argument2,
         Argument3 = disasm.Argument3,
         CompleteInstr = disasm.CompleteInstr,
         EIP = disasm.EIP,
         Instruction = disasm.Instruction,
         Options = disasm.Options,
         Prefix = disasm.Prefix,
         SecurityBlock = disasm.SecurityBlock,
         VirtualAddr = disasm.VirtualAddr
     });
 }
Exemplo n.º 8
0
        public void Execute(uint offset, UnmanagedBuffer buffer, bool followCalls = false)
        {
            try
            {
                Esp.Value -= 4; // Assume we are calling from the beginning of a function. return address is on the stack

                Disasm disasm = new Disasm();
                disasm.EIP = new IntPtr(buffer.Ptr.ToInt64() + offset); // new IntPtr(buffer.Ptr.ToInt64()/* + offset*/);
                while (true)
                {
                    var result = BeaEngine.Disassemble(disasm);
                    if (result == BeaConstants.SpecialInfo.UNKNOWN_OPCODE)
                    {
                        return;
                    }

                    // Returns true if jumped or following calls
                    var jumped = ExecuteASM(disasm, buffer, followCalls);
                    if ((disasm.CompleteInstr.Contains("leave") || disasm.CompleteInstr.Contains("ret")) && !jumped)
                    {
                        break;
                    }

                    Debugger.TryTrigger(this, BreakpointType.InstructionName, disasm.Instruction.Mnemonic);

                    if (!jumped)
                    {
                        disasm.EIP = new IntPtr(disasm.EIP.ToInt64() + (int)result);
                    }
                }
                for (var i = 0; i < CallOffsets.Count; ++i)
                {
                    CallOffsets[i] += 0x400C00;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
Exemplo n.º 9
0
        static void Main(string[] args)
        {
            Console.WriteLine("Version: " + BeaEngine.Version);
            Console.WriteLine("Revision: " + BeaEngine.Revision);

            UnmanagedBuffer buffer = new UnmanagedBuffer(File.ReadAllBytes("BeaEngine.dll"));

            var disasm = new Disasm();

            disasm.EIP = new IntPtr(buffer.Ptr.ToInt64() + 0x400);

            for (int counter = 0; counter < 100; ++counter)
            {
                int result = BeaEngine.Disasm(disasm);

                if (result == (int)BeaConstants.SpecialInfo.UNKNOWN_OPCODE)
                {
                    break;
                }

                Console.WriteLine("0x" + disasm.EIP.ToString("X") + " " + disasm.CompleteInstr);
                disasm.EIP = new IntPtr(disasm.EIP.ToInt64() + result);
            }
        }
Exemplo n.º 10
0
        public static IEnumerable<DisassemblyInstruction> Disassemble(IntPtr pAddr, int maxInstructionCount = 0)
        {
            if (pAddr == IntPtr.Zero)
                 throw new ArgumentNullException("pAddr");

             const int maxInstructionSize = 15;
             const int maxBufferSize = 4096;

             // default buffer of 100 x maxInstructionSize bytes (1500 bytes)
             // unless maxInstructionCount is specified
             var bufferSize = (maxInstructionCount == 0 ? 100 : maxInstructionCount)*maxInstructionSize;
             // ensure we don't allocate too large a buffer if a huge instruction count is specified
             bufferSize = Math.Min(bufferSize, maxBufferSize);

             // allocate an unmanaged buffer (instead of reading into managed byte array)
             var pBuffer = IntPtr.Zero;
             try
             {
                 pBuffer = Process.GetCurrentProcess().Allocate(IntPtr.Zero, (uint) bufferSize);

                 // TODO: this is probably horribly inefficient
                 Marshal.Copy(pAddr.ReadArray<byte>(bufferSize), 0, pBuffer, bufferSize);

                 var pDisasmLoc = pBuffer;
                 var virtualAddr = (uint) pAddr; // TODO: currently doesnt support x64
                 var disasm = new Disasm {EIP = pDisasmLoc, VirtualAddr = virtualAddr};

                 int length;
                 var instructionsRead = 0;
                 var bufferOffset = 0;
                 while ((length = BeaEngine.Disasm(disasm)) != (int) BeaConstants.SpecialInfo.UNKNOWN_OPCODE)
                 {
                     instructionsRead++;

                     var disasmInstr = new DisassemblyInstruction(disasm, length,
                                                                  virtualAddr.ReadArray<byte>(length));
                     yield return disasmInstr;

                     pDisasmLoc += length;
                     virtualAddr += (uint) length;
                     bufferOffset += length;

                     if (maxInstructionCount > 0 && instructionsRead >= maxInstructionCount)
                         break;

                     // if we don't have an instruction limit and we're less than maxInstructionSize away
                     // from the end of the buffer, reread buffer data from current location
                     if ((bufferSize - bufferOffset) < maxInstructionSize)
                     {
                         // Copy new bytes to buffer from current location
                         Marshal.Copy(virtualAddr.ReadArray<byte>(bufferSize), 0, pBuffer, bufferSize);
                         // reset pointers etc
                         pDisasmLoc = pBuffer;
                         bufferOffset = 0;
                     }

                     disasm.EIP = pDisasmLoc;
                     disasm.VirtualAddr = virtualAddr;
                 }
             }
             finally
             {
                 if (pBuffer != IntPtr.Zero)
                     Process.GetCurrentProcess().Free(pBuffer);
             }
        }
Exemplo n.º 11
0
        public static IEnumerable <DisassemblyInstruction> Disassemble(IntPtr pAddr, int maxInstructionCount = 0)
        {
            if (pAddr == IntPtr.Zero)
            {
                throw new ArgumentNullException("pAddr");
            }

            const int maxInstructionSize = 15;
            const int maxBufferSize      = 4096;

            // default buffer of 100 x maxInstructionSize bytes (1500 bytes)
            // unless maxInstructionCount is specified
            var bufferSize = (maxInstructionCount == 0 ? 100 : maxInstructionCount) * maxInstructionSize;

            // ensure we don't allocate too large a buffer if a huge instruction count is specified
            bufferSize = Math.Min(bufferSize, maxBufferSize);

            // allocate an unmanaged buffer (instead of reading into managed byte array)
            var pBuffer = IntPtr.Zero;

            try
            {
                pBuffer = Process.GetCurrentProcess().Allocate(IntPtr.Zero, (uint)bufferSize);

                // TODO: this is probably horribly inefficient
                Marshal.Copy(pAddr.ReadArray <byte>(bufferSize), 0, pBuffer, bufferSize);

                var pDisasmLoc  = pBuffer;
                var virtualAddr = (uint)pAddr;   // TODO: currently doesnt support x64
                var disasm      = new Disasm {
                    EIP = pDisasmLoc, VirtualAddr = virtualAddr
                };

                int length;
                var instructionsRead = 0;
                var bufferOffset     = 0;
                while ((length = BeaEngine.Disasm(disasm)) != (int)BeaConstants.SpecialInfo.UNKNOWN_OPCODE)
                {
                    instructionsRead++;

                    var disasmInstr = new DisassemblyInstruction(disasm, length,
                                                                 virtualAddr.ReadArray <byte>(length));
                    yield return(disasmInstr);

                    pDisasmLoc   += length;
                    virtualAddr  += (uint)length;
                    bufferOffset += length;

                    if (maxInstructionCount > 0 && instructionsRead >= maxInstructionCount)
                    {
                        break;
                    }

                    // if we don't have an instruction limit and we're less than maxInstructionSize away
                    // from the end of the buffer, reread buffer data from current location
                    if ((bufferSize - bufferOffset) < maxInstructionSize)
                    {
                        // Copy new bytes to buffer from current location
                        Marshal.Copy(virtualAddr.ReadArray <byte>(bufferSize), 0, pBuffer, bufferSize);
                        // reset pointers etc
                        pDisasmLoc   = pBuffer;
                        bufferOffset = 0;
                    }

                    disasm.EIP         = pDisasmLoc;
                    disasm.VirtualAddr = virtualAddr;
                }
            }
            finally
            {
                if (pBuffer != IntPtr.Zero)
                {
                    Process.GetCurrentProcess().Free(pBuffer);
                }
            }
        }
Exemplo n.º 12
0
        private void ParseInstructions(MethodDef method)
        {
            var rawInstructions = new List <Disasm>();

            while (true)
            {
                byte[] bytes = ReadChunk(method, _module);

                var disasm = new Disasm();
                var buff   = new UnmanagedBuffer(bytes);

                disasm.EIP = new IntPtr(buff.Ptr.ToInt32());

                var instruction = BeaEngine.Disasm(disasm);
                _readOffset -= 8 - instruction; // revert offset back for each byte that was not a part of this instruction
                var mnemonic = disasm.Instruction.Mnemonic.Trim();

                if (mnemonic == "ret") //TODO: Check if this is the only return in function, e.g. check for jumps that go beyond this address
                {
                    Marshal.FreeHGlobal(buff.Ptr);
                    break;
                }

                rawInstructions.Add(Clone(disasm));
                //disasm.EIP = new IntPtr(disasm.EIP.ToInt32() + instruction);

                Marshal.FreeHGlobal(buff.Ptr);
            }

            //while(rawInstructions.First().Instruction.Mnemonic.Trim() == "pop")
            //    rawInstructions.Remove(rawInstructions.First());

            while (rawInstructions.Last().Instruction.Mnemonic.Trim() == "pop")
            {
                rawInstructions.Remove(rawInstructions.Last());
            }


            foreach (var instr in rawInstructions)
            {
                switch (instr.Instruction.Mnemonic.Trim())
                {
                case "mov":
                    Instructions.Add(new X86MOV(instr));
                    break;

                case "add":
                    Instructions.Add(new X86ADD(instr));
                    break;

                case "sub":
                    Instructions.Add(new X86SUB(instr));
                    break;

                case "imul":
                    Instructions.Add(new X86IMUL(instr));
                    break;

                case "div":
                    Instructions.Add(new X86DIV(instr));
                    break;

                case "neg":
                    Instructions.Add(new X86NEG(instr));
                    break;

                case "not":
                    Instructions.Add(new X86NOT(instr));
                    break;

                case "xor":
                    Instructions.Add(new X86XOR(instr));
                    break;

                case "pop":
                    Instructions.Add(new X86POP(instr));
                    break;
                }
            }
        }
Exemplo n.º 13
0
        private bool ExecuteJump(string disasmStr, Disasm disasm, string mnemonic)
        {
            bool shouldJump = false;

            if (mnemonic == "jmp")
            {
                shouldJump = true;
            }
            else if (mnemonic == "je" || mnemonic == "jz") // Jump short if equal (ZF=1).
            {
                shouldJump = EFlags.HasFlag(EFlags.ZeroFlag);
            }
            else if (mnemonic == "jne" || mnemonic == "jnz") // Jump short if not equal (ZF=0).
            {
                shouldJump = !EFlags.HasFlag(EFlags.ZeroFlag);
            }
            else if (mnemonic == "ja" || mnemonic == "jnbe") // Jump short if not below or equal (CF=0 and ZF=0).
            {
                shouldJump = !EFlags.HasFlag(EFlags.CarryFlag) && !EFlags.HasFlag(EFlags.ZeroFlag);
            }
            else if (mnemonic == "jb" || mnemonic == "jc" || mnemonic == "jnae")  // Jump short if not above or equal (CF=1).
            {
                shouldJump = EFlags.HasFlag(EFlags.CarryFlag);
            }
            else if (mnemonic == "jng" || mnemonic == "jle") // Jump short if not greater (ZF=1 or SF != OF).
            {
                shouldJump = EFlags.HasFlag(EFlags.ZeroFlag) || (EFlags.HasFlag(EFlags.SignFlag) != EFlags.HasFlag(EFlags.OverflowFlag));
            }
            else if (mnemonic == "jnc" || mnemonic == "jnb" || mnemonic == "jae") // Jump short if not carry (CF=0).
            {
                shouldJump = !EFlags.HasFlag(EFlags.CarryFlag);
            }
            else if (mnemonic == "jna" || mnemonic == "jbe") // Jump short if not above (CF=1 or ZF=1).
            {
                shouldJump = EFlags.HasFlag(EFlags.CarryFlag) || EFlags.HasFlag(EFlags.ZeroFlag);
            }
            else if (mnemonic == "jge" || mnemonic == "jnl") // Jump short if greater or equal (SF=OF).
            {
                shouldJump = EFlags.HasFlag(EFlags.SignFlag) == EFlags.HasFlag(EFlags.OverflowFlag);
            }
            else if (mnemonic == "jg" || mnemonic == "jnle") // Jump short if greater (ZF=0 and SF=OF).
            {
                shouldJump = !EFlags.HasFlag(EFlags.ZeroFlag) && (EFlags.HasFlag(EFlags.SignFlag) == EFlags.HasFlag(EFlags.OverflowFlag));
            }
            else if (mnemonic == "jl" || mnemonic == "jnge") // Jump short if less (SF != OF).
            {
                shouldJump = EFlags.HasFlag(EFlags.SignFlag) != EFlags.HasFlag(EFlags.OverflowFlag);
            }
            else if (mnemonic == "jecxz") // Jump short if ECX register is 0.
            {
                shouldJump = Ecx.Value == 0;
            }
            else if (mnemonic == "jcxz") // Jump short if CX register is 0.
            {
                shouldJump = Ecx.Cx == 0;
            }
            else if (mnemonic == "jno") // Jump short if not overflow (OF=0)
            {
                shouldJump = !EFlags.HasFlag(EFlags.OverflowFlag);
            }
            else if (mnemonic == "jnp" || mnemonic == "jpo") // Jump short if not parity (PF=0)
            {
                shouldJump = !EFlags.HasFlag(EFlags.ParityFlag);
            }
            else if (mnemonic == "jns") // Jump short if not sign (SF=0)
            {
                shouldJump = !EFlags.HasFlag(EFlags.SignFlag);
            }
            else if (mnemonic == "jo") // Jump short if overflow (OF=1)
            {
                shouldJump = !EFlags.HasFlag(EFlags.OverflowFlag);
            }
            else if (mnemonic == "jp" || mnemonic == "jpe") // Jump short if parity (PF=1)
            {
                shouldJump = !EFlags.HasFlag(EFlags.ParityFlag);
            }
            else if (mnemonic == "js") // Jump short if sign (SF=1)
            {
                shouldJump = !EFlags.HasFlag(EFlags.SignFlag);
            }
            else
            {
                throw new Exception("Invalid jump type detected.");
            }

            if (!shouldJump)
            {
                return(false);
            }

            // We should jump.
            return(true);
        }
Exemplo n.º 14
0
        private bool ExecuteASM(Disasm disasm, UnmanagedBuffer buffer, bool followCalls)
        {
            if (Interrupted)
            {
                return(false);
            }

            var entryPoint        = buffer.Ptr.ToInt32();
            var disassemblyString = disasm.CompleteInstr;

            // Sanitize the instruction.
            if (disassemblyString.IndexOf(";") != -1)
            {
                disassemblyString = disassemblyString.Remove(disassemblyString.IndexOf(";"));
            }

            disassemblyString = Regex.Replace(disassemblyString, @"\s+", " ", RegexOptions.IgnoreCase).Trim();

            if (Regex.IsMatch(disassemblyString, @"[!@#$%^&()={}\\|/?<>.~`""'_]"))
            {
                return(false);
            }

            if (disassemblyString.Length == 0 || disassemblyString.EndsWith(":"))
            {
                return(false);
            }

            var tokens   = disassemblyString.Split(' ');
            var mnemonic = tokens[0];

            //Console.WriteLine("0x{0:X8} {1}", disasm.EIP.ToInt64(), disasm.CompleteInstr);

            if (disassemblyString.Contains("call far") || disassemblyString.Contains("xmm"))
            {
                return(false);
            }

            List <InstructionArgument> arguments = new List <InstructionArgument>();
            // TODO Support for floating point opcodes

            var parametersList = disassemblyString.Replace(mnemonic, String.Empty).Trim().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var parameter in parametersList)
            {
                arguments.Add(new InstructionArgument(this, parameter.Trim()));
            }
            if (mnemonic[0] == 'j')
            {
                if (ExecuteJump(disassemblyString, disasm, mnemonic))
                {
                    var jumpOffset = arguments[0].GetValue();
                    if (arguments[0].Type == ArgumentType.Memory)
                    {
                        jumpOffset += (uint)entryPoint - 0x400C00;
                    }
                    disasm.EIP = new IntPtr(jumpOffset);
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                InstructionArgument src   = null;
                InstructionArgument dst   = null;
                InstructionArgument extra = null;

                if (parametersList.Length == 1)
                {
                    dst = src = arguments[0];
                }
                else if (parametersList.Length == 2)
                {
                    dst = arguments[0];
                    src = arguments[1];
                }
                else if (parametersList.Length == 3)
                {
                    extra = arguments[2];
                }

                switch (mnemonic)
                {
                case "ret":
                case "retn":
                    // Actually use the stack here.
                    if (JumpBacks.Count > 0)
                    {
                        Pop(4);
                        disasm.EIP = new IntPtr(JumpBacks[0]);
                        JumpBacks.RemoveAt(0);
                        return(true);
                    }
                    return(false);

                case "leave":
                    break;

                case "nop": break;

                    #region Data transfer
                case "mov":
                    if (parametersList.Length != 2 || dst.Type == ArgumentType.Immediate)
                    {
                        break;
                    }
                    if (src.Type == ArgumentType.Immediate && src.Size > dst.Size)
                    {
                        break;
                    }
                    if (src.Type != ArgumentType.Immediate && src.Size != dst.Size)
                    {
                        break;
                    }
                    dst.SetValue(src.GetValue());
                    break;

                case "movzx":
                {
                    if (parametersList.Length != 2 || dst.Type != ArgumentType.Register ||
                        src.Type == ArgumentType.Immediate || src.Size >= dst.Size)
                    {
                        break;
                    }
                    //! TODO Unhack this - Handles indirect jumptables
                    //! TODO: Really need to fix memory - this superbly fails now
                    //if (dst.Register == null)
                    //{

                    /*if (src.Size == 4)
                     *  addr = buffer.ReadDword(src.Address - 0x400C00);
                     * else if (src.Size == 2)
                     *  addr = (uint)buffer.ReadWord(src.Address - 0x400C00);
                     * else if (src.Size == 1)
                     *  addr = (uint)buffer.ReadByte(src.Address - 0x400C00);*/
                    //}
                    dst.SetValue(src.GetValue());
                    break;
                }

                case "movsb":
                    WriteByteToMemory(Edi.Value, ReadByteFromMemory(Esi.Value));
                    Ecx.Value--;
                    if (EFlags.HasFlag(EFlags.DirectionFlag))
                    {
                        Edi.Value--;
                        Esi.Value--;
                    }
                    else
                    {
                        Edi.Value++;
                        Esi.Value++;
                    }
                    break;

                case "movsw":
                    WriteWordToMemory(Edi.Value, ReadWordFromMemory(Esi.Value));
                    Ecx.Value--;
                    if (EFlags.HasFlag(EFlags.DirectionFlag))
                    {
                        Edi.Value -= 2;
                        Esi.Value -= 2;
                    }
                    else
                    {
                        Edi.Value += 2;
                        Esi.Value += 2;
                    }
                    break;

                case "movsd":
                    WriteDwordToMemory(Edi.Value, ReadDwordFromMemory(Esi.Value));
                    Ecx.Value--;
                    if (EFlags.HasFlag(EFlags.DirectionFlag))
                    {
                        Edi.Value -= 4;
                        Esi.Value -= 4;
                    }
                    else
                    {
                        Edi.Value += 4;
                        Esi.Value += 4;
                    }
                    break;

                case "stosb":
                    WriteByteToMemory(Edi.Value, Eax.Al);
                    Ecx.Value--;
                    if (EFlags.HasFlag(EFlags.DirectionFlag))
                    {
                        Edi.Value--;
                        Esi.Value--;
                    }
                    else
                    {
                        Edi.Value++;
                        Esi.Value++;
                    }
                    break;

                case "stosw":
                    WriteWordToMemory(Edi.Value, Eax.Ax);
                    Ecx.Value--;
                    if (EFlags.HasFlag(EFlags.DirectionFlag))
                    {
                        Edi.Value -= 2;
                        Esi.Value -= 2;
                    }
                    else
                    {
                        Edi.Value += 2;
                        Esi.Value += 2;
                    }
                    break;

                case "stosd":
                    WriteDwordToMemory(Edi.Value, Eax.Value);
                    Ecx.Value--;
                    if (EFlags.HasFlag(EFlags.DirectionFlag))
                    {
                        Edi.Value -= 4;
                        Esi.Value -= 4;
                    }
                    else
                    {
                        Edi.Value += 4;
                        Esi.Value += 4;
                    }
                    break;

                case "xchg":
                    if (parametersList.Length != 2 || dst.Type != ArgumentType.Register ||
                        src.Type == ArgumentType.Immediate || src.Size != dst.Size)
                    {
                        break;
                    }

                    uint tmp = src.GetValue();
                    src.SetValue(dst.GetValue());
                    dst.SetValue(tmp);
                    break;

                case "lea":
                    if (parametersList.Length == 2 && dst.Type == ArgumentType.Register && src.Type == ArgumentType.Memory && src.Size > 1)
                    {
                        dst.SetValue(src.Address);
                    }
                    break;

                    #endregion
                    #region Basic maths
                case "inc":
                    if (parametersList.Length == 1 && dst.Type != ArgumentType.Immediate)
                    {
                        ulong val = (ulong)dst.GetValue() + 1;
                        UpdateFlags(val, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.AdjustFlag | EFlags.ParityFlag);
                        dst.SetValue((uint)val);
                    }
                    break;

                case "dec":
                    if (parametersList.Length == 1 && dst.Type != ArgumentType.Immediate)
                    {
                        ulong val = (ulong)dst.GetValue() - 1;
                        UpdateFlags(val, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.AdjustFlag | EFlags.ParityFlag);
                        dst.SetValue((uint)val);
                    }
                    break;

                case "not":
                    if (parametersList.Length == 1 && dst.Type != ArgumentType.Immediate)
                    {
                        dst.SetValue(~dst.GetValue());
                    }
                    break;

                case "neg":
                    if (parametersList.Length == 1 && dst.Type != ArgumentType.Immediate)
                    {
                        ulong val = (ulong)(-(long)dst.GetValue());
                        UpdateFlags(val, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.AdjustFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                        dst.SetValue((uint)val);
                    }
                    break;

                case "bswap":
                    if (parametersList.Length != 1 || dst.Type != ArgumentType.Register || dst.Size != 4)
                    {
                        break;
                    }
                    uint dval = dst.GetValue();
                    dst.SetValue((uint)((dval << 24) | ((dval & 0xFF00) << 8) | ((dval & 0xFF0000) >> 8) | (dval >> 24)));
                    break;

                case "add":
                    if (parametersList.Length == 2)
                    {
                        ulong val = (ulong)dst.GetValue() + src.GetValue();
                        UpdateFlags(val, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.AdjustFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                        dst.SetValue((uint)val);
                    }
                    break;

                case "sub":
                    if (parametersList.Length == 2)
                    {
                        ulong val = (ulong)dst.GetValue() - (ulong)src.GetValue();
                        UpdateFlags(val, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.AdjustFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                        dst.SetValue((uint)val);
                    }
                    break;

                case "mul":     // unsigned multiply
                    // The OF and CF flags are set to 0 if the upper half of the result is 0, otherwise they are set to 1
                    if (parametersList.Length != 1 || src.Type == ArgumentType.Immediate)
                    {
                        break;
                    }
                    switch (src.Size)
                    {
                    case 1:
                        ushort r16 = (ushort)(Eax.Al * src.GetValue());
                        Eax.Ax = r16;
                        ToggleFlagIf(EFlags.OverflowFlag | EFlags.CarryFlag, (r16 >> 8) == 0);
                        break;

                    case 2:
                        uint r32 = Eax.Ax * src.GetValue();
                        Edx.Dx = (ushort)(r32 >> 16);            // high order
                        Eax.Ax = (ushort)(r32 & 0xFFFF);         // low order
                        ToggleFlagIf(EFlags.OverflowFlag | EFlags.CarryFlag, Edx.Dx == 0);
                        break;

                    case 4:
                        ulong r64 = Eax.Ax * src.GetValue();
                        Edx.Value = (uint)(r64 >> 32);            // high order
                        Eax.Value = (uint)(r64 & 0xFFFFFFFF);     // low order
                        ToggleFlagIf(EFlags.OverflowFlag | EFlags.CarryFlag, Edx.Value == 0);
                        break;
                    }
                    break;

                case "div":
                    if (src.Type == ArgumentType.Immediate)
                    {
                        break;
                    }
                    ulong dividend, quotient;
                    uint  divisor = src.GetValue();
                    if (divisor == 0)
                    {
                        break;
                    }

                    if (src.Size == 1)
                    {
                        dividend = Eax.Ax;
                        quotient = dividend / divisor;
                        if (quotient > 0xFF)
                        {
                            break;
                        }
                        Eax.Al = (byte)quotient;
                        Eax.Ah = (byte)(dividend % divisor);
                    }
                    else if (src.Size == 2)
                    {
                        dividend = ((uint)Edx.Dx << 16) & Eax.Ax;
                        quotient = dividend / divisor;
                        if (quotient > 0xFFFF)
                        {
                            break;
                        }
                        Eax.Ax = (ushort)quotient;
                        Edx.Dx = (ushort)(dividend % divisor);
                    }
                    else if (src.Size == 4)
                    {
                        dividend = ((ulong)Edx.Value << 32) & Eax.Value;
                        quotient = dividend / divisor;
                        if (quotient > 0xFFFFFFFF)
                        {
                            break;
                        }
                        Eax.Value = (uint)quotient;
                        Edx.Value = (uint)(dividend % divisor);
                    }
                    break;

                case "imul":   // Signed multiply
                case "idiv":   // Signed division
                    break;     // NYI

                    #endregion
                    #region Bitwise operators
                case "and":
                    if (parametersList.Length == 2)
                    {
                        uint result = dst.GetValue() & src.GetValue();
                        dst.SetValue(result);
                        ClearFlags(EFlags.OverflowFlag | EFlags.CarryFlag);
                        UpdateFlags(result, dst.Size, EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag);
                    }
                    break;

                case "or":
                    if (parametersList.Length == 2)
                    {
                        uint result = dst.GetValue() | src.GetValue();
                        dst.SetValue(result);
                        ClearFlags(EFlags.OverflowFlag | EFlags.CarryFlag);
                        UpdateFlags(result, dst.Size, EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag);
                    }
                    else
                    {
                        throw new ArgumentException();
                    }

                    break;

                case "xor":
                    if (parametersList.Length == 2)
                    {
                        uint result = dst.GetValue() ^ src.GetValue();
                        dst.SetValue(result);
                        ClearFlags(EFlags.OverflowFlag | EFlags.CarryFlag);
                        UpdateFlags(result, dst.Size, EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag);
                    }
                    break;

                case "stc":     // set carry flag
                    SetFlags(EFlags.CarryFlag);
                    break;

                case "std":     // set direction flag
                    SetFlags(EFlags.DirectionFlag);
                    break;

                case "clc":     // clear carry flag
                    ClearFlags(EFlags.CarryFlag);
                    break;

                case "cld":     // clear direction flag
                    ClearFlags(EFlags.DirectionFlag);
                    break;

                case "shr":     // shift right
                {
                    if (parametersList.Length != 2 || dst.Type == ArgumentType.Immediate ||
                        src.Type == ArgumentType.Memory || (src.Type == ArgumentType.Register && src.RegisterName != "cl"))
                    {
                        break;
                    }
                    uint result = dst.GetValue() >> (byte)src.GetValue();
                    dst.SetValue(result);

                    if (src.Type == ArgumentType.Immediate && src.GetValue() == 1)
                    {
                        UpdateFlags(result, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                    }
                    else
                    {
                        UpdateFlags(result, dst.Size, EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                    }
                    break;
                }

                case "shl":     // shift left
                case "sal":     // shift arithmetic left (signed)
                {
                    if (parametersList.Length != 2 || dst.Type == ArgumentType.Immediate || src.Type == ArgumentType.Memory || (src.Type == ArgumentType.Register && src.RegisterName != "cl"))
                    {
                        break;
                    }

                    ulong result = (ulong)dst.GetValue() << (byte)src.GetValue();
                    dst.SetValue((uint)result);

                    if (src.Type == ArgumentType.Immediate && src.GetValue() == 1)
                    {
                        UpdateFlags(result, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                    }
                    else
                    {
                        UpdateFlags(result, dst.Size, EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                    }
                    break;
                }

                case "sar":     // shift arithmetic right (signed)
                {
                    if (parametersList.Length != 2 || dst.Type == ArgumentType.Immediate || src.Type == ArgumentType.Memory || (src.Type == ArgumentType.Register && src.RegisterName != "cl"))
                    {
                        break;
                    }
                    uint result = (uint)((int)dst.GetValue() >> (byte)src.GetValue());
                    dst.SetValue(result);

                    if (src.Type == ArgumentType.Immediate && src.GetValue() == 1)
                    {
                        UpdateFlags(result, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                    }
                    else
                    {
                        UpdateFlags(result, dst.Size, EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                    }
                    break;
                }

                case "ror":     // rotate right
                {
                    // bits >> n | (bits << (32 - n));
                    uint data        = dst.GetValue();
                    uint bitsToShift = src.GetValue();
                    data = data >> (int)bitsToShift | (data << (32 - (int)bitsToShift));
                    dst.SetValue(data);

                    if (src.Type == ArgumentType.Immediate && src.GetValue() == 1)
                    {
                        UpdateFlags(data, dst.Size, EFlags.OverflowFlag | EFlags.CarryFlag);
                    }
                    else
                    {
                        UpdateFlags(data, dst.Size, EFlags.CarryFlag);
                    }
                    break;
                }

                case "rol":     // rotate left
                {
                    // bits << n | (bits >> (32 - n));
                    uint data2        = dst.GetValue();
                    uint bitsToShift2 = src.GetValue();
                    uint data         = data2 << (int)bitsToShift2 | (data2 >> (32 - (int)bitsToShift2));
                    dst.SetValue(data);

                    if (src.Type == ArgumentType.Immediate && src.GetValue() == 1)
                    {
                        UpdateFlags(data, dst.Size, EFlags.OverflowFlag | EFlags.CarryFlag);
                    }
                    else
                    {
                        UpdateFlags(data, dst.Size, EFlags.CarryFlag);
                    }
                    break;
                }

                    #endregion
                case "call":
                    // TODO Use the stack to keep s and r (saved registers (0) and jumpback offset (+4))
                    // TODO Half done. (see below)
                    var offset = (int)disasm.Instruction.AddrValue - buffer.Ptr.ToInt32();
                    CallOffsets.Add((uint)offset);
                    if (followCalls)
                    {
                        Push(offset + 5);   // Push the return address on the stack
                        JumpBacks.Add((uint)(disasm.EIP.ToInt32() + 5));
                        disasm.EIP = new IntPtr((int)disasm.Instruction.AddrValue);
                        return(true);
                    }
                    return(false);

                case "cmp":
                    UpdateFlags((ulong)dst.GetValue() - (ulong)src.GetValue(), dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.AdjustFlag | EFlags.ParityFlag | EFlags.CarryFlag);
                    break;

                case "test":
                    ClearFlags(EFlags.OverflowFlag | EFlags.CarryFlag);
                    UpdateFlags(dst.GetValue() & src.GetValue(), dst.Size, EFlags.SignFlag | EFlags.ZeroFlag | EFlags.ParityFlag);
                    break;

                case "sbb":
                    if (parametersList.Length != 2)
                    {
                        break;
                    }
                    ulong newValue = (ulong)dst.GetValue() - (ulong)src.GetValue();
                    if (EFlags.HasFlag(EFlags.CarryFlag))
                    {
                        newValue -= 1;
                    }
                    dst.SetValue((uint)newValue);
                    UpdateFlags(newValue, dst.Size, EFlags.OverflowFlag | EFlags.SignFlag | EFlags.ZeroFlag | EFlags.AdjustFlag | EFlags.CarryFlag);
                    break;

                    #region Stack operations
                case "push":
                    // todo: check for stack overflow (stack pointer < base address)
                    if (parametersList.Length == 1)
                    {
                        uint s = dst.Size;
                        if (s == 2 || s == 4)
                        {
                            WriteMemory(Esp - s, dst.GetValue());
                            Esp.Value -= s;
                        }
                    }
                    break;

                case "pop":
                    // todo: check for stack overflow (stack pointer > base address + memory size)
                    if (parametersList.Length == 1 && dst.Type != ArgumentType.Immediate)
                    {
                        uint s = dst.Size;
                        if (s == 2 || s == 4)
                        {
                            dst.SetValue(ReadMemory(Esp, s));
                            Esp.Value += s;
                        }
                    }
                    break;

                case "pusha":
                    if (parametersList.Length == 0)
                    {
                        WriteMemory(Esp - 2, Eax.Ax);
                        WriteMemory(Esp - 4, Ecx.Cx);
                        WriteMemory(Esp - 6, Edx.Dx);
                        WriteMemory(Esp - 8, Ebx.Bx);
                        WriteMemory(Esp - 10, Esp.Sp);
                        WriteMemory(Esp - 12, Ebp.Bp);
                        WriteMemory(Esp - 14, Esi.Si);
                        WriteMemory(Esp - 16, Edi.Di);
                        Esp.Value -= 16;
                    }
                    break;

                case "pushad":
                    if (parametersList.Length == 0)
                    {
                        WriteMemory(Esp - 4, Eax.Value);
                        WriteMemory(Esp - 8, Ecx.Value);
                        WriteMemory(Esp - 12, Edx.Value);
                        WriteMemory(Esp - 16, Ebx.Value);
                        WriteMemory(Esp - 20, Esp.Value);
                        WriteMemory(Esp - 24, Ebp.Value);
                        WriteMemory(Esp - 28, Esi.Value);
                        WriteMemory(Esp - 32, Edi.Value);
                        Esp.Value -= 32;
                    }
                    break;

                case "popa":
                    if (parametersList.Length == 0)
                    {
                        Edi.Di = ReadWordFromMemory(Esp);
                        Esi.Si = ReadWordFromMemory(Esp + 2);
                        Ebp.Bp = ReadWordFromMemory(Esp + 4);
                        //Esp.Sp = ReadWord(Esp + 6);    // ignored
                        Ebx.Bx     = ReadWordFromMemory(Esp + 8);
                        Edx.Dx     = ReadWordFromMemory(Esp + 10);
                        Ecx.Cx     = ReadWordFromMemory(Esp + 12);
                        Eax.Ax     = ReadWordFromMemory(Esp + 14);
                        Esp.Value += 16;
                    }
                    else
                    {
                        throw new ArgumentException();
                    }
                    break;

                case "popad":
                    if (parametersList.Length == 0)
                    {
                        Edi.Value = ReadDwordFromMemory(Esp);
                        Esi.Value = ReadDwordFromMemory(Esp + 4);
                        Ebp.Value = ReadDwordFromMemory(Esp + 8);
                        //Esp.Value = ReadDoubleword(Esp + 12);    // ignored
                        Ebx.Value  = ReadDwordFromMemory(Esp + 16);
                        Edx.Value  = ReadDwordFromMemory(Esp + 20);
                        Ecx.Value  = ReadDwordFromMemory(Esp + 24);
                        Eax.Value  = ReadDwordFromMemory(Esp + 28);
                        Esp.Value += 32;
                    }
                    break;
                    // todo: pushf and popf, and effects on eflags
                    #endregion
                }
            }
            return(false);
        }
Exemplo n.º 15
0
 public X86PUSH(Disasm rawInstruction) : base()
 {
     Operands    = new IX86Operand[1];
     Operands[0] = GetOperand(rawInstruction.Argument1);
 }
Exemplo n.º 16
0
        /// <summary>
        ///     Initializes a new instance of the OnyxDetour class.
        /// </summary>
        public OnyxDetour(IntPtr _targetAddress, Delegate _detour, string _detourName = null)
        {
            if (_detourName != null)
            {
                m_name = _detourName;
            }
            if (_targetAddress == IntPtr.Zero)
            {
                throw new ArgumentNullException("_targetAddress");
            }
            if (_detour == null)
            {
                throw new ArgumentNullException("_detour");
            }

            m_detour        = _detour;
            m_targetAddress = _targetAddress;
            IntPtr detourAddress = Marshal.GetFunctionPointerForDelegate(_detour);

            m_checkThread = CheckThread;
            var pCheckThread = Marshal.GetFunctionPointerForDelegate(m_checkThread);
            var fasm         = new RemoteFasm();

            fasm.Clear();
            fasm.AddLine("@checkthread:");
            fasm.AddLine("call $+5");
            fasm.AddLine("add dword [esp], {0}", 5 + 4 + 1);
            fasm.AddLine("push 0{0:X}h", pCheckThread.ToInt64());
            fasm.AddLine("retn");
            fasm.AddLine("@checkthread_TestResults:");
            fasm.AddLine("test eax,eax");
            fasm.AddLine("jz @functionretn");
            fasm.AddLine("@userfunction:");
            fasm.AddLine("push 0{0:X}h", detourAddress.ToInt64());
            fasm.AddLine("retn");
            fasm.AddLine("@functionretn:");
            var jumperBytes = fasm.Assemble();

            pJumperCodeCave = Onyx.Instance.Memory.AllocateMemory(256);
            Onyx.Instance.Memory.WriteBytes(pJumperCodeCave, jumperBytes);

            fasm.Clear();
            fasm.AddLine("push 0{0:X}h", pJumperCodeCave.ToInt64());
            fasm.AddLine("retn");
            m_detourBytes = fasm.Assemble();

            disasm = new Disasm();
            var realEip           = m_targetAddress;
            var bytesDisassembled = 0;

            while (bytesDisassembled < m_detourBytes.Length)
            {
                var managedInstructionBuffer = Onyx.Instance.Memory.ReadBytes(realEip, 15);
                var instructionBuffer        = new UnmanagedBuffer(managedInstructionBuffer);
                disasm.EIP = instructionBuffer.Ptr;
                var length = BeaEngine32.Disasm(disasm);
                if ((length != (int)BeaConstants.SpecialInfo.OUT_OF_BLOCK) && (length != (int)BeaConstants.SpecialInfo.UNKNOWN_OPCODE))
                {
                    bytesDisassembled += length;
                    if ((disasm.Instruction.BranchType == (int)BeaConstants.BranchType.JmpType) && (disasm.Instruction.AddrValue != 0))
                    {
                        // jmp = modify EIP
                        //disasm.EIP = (IntPtr)disasm.Instruction.AddrValue;
                    }
                    realEip = (IntPtr)((ulong)realEip + (ulong)length);
                }
                else
                {
                    throw new Exception(String.Format("Disassembly error occured, exception code = {0}", length));
                }
            }

            //Store the orginal bytes of decoded instructions in memory after jumper code
            m_originalBytes = Onyx.Instance.Memory.ReadBytes(m_targetAddress, bytesDisassembled);
            var pOriginalFunction = pJumperCodeCave.Add((UInt32)jumperBytes.Length);

            Onyx.Instance.Memory.WriteBytes(pOriginalFunction, m_originalBytes);
            m_originalFunction = Marshal.GetDelegateForFunctionPointer(pOriginalFunction, _detour.GetType());

            var pReturnerCodeCave = pJumperCodeCave.Add((UInt32)jumperBytes.Length + (UInt32)bytesDisassembled);

            fasm.Clear();
            fasm.AddLine("push 0{0:X}h", m_targetAddress.Add((UInt32)bytesDisassembled).ToInt64());
            fasm.AddLine("retn");
            var returnerBytes = fasm.Assemble();

            Onyx.Instance.Memory.WriteBytes(pReturnerCodeCave, returnerBytes);

            // adding calling thread to exclusions
            Onyx.Instance.Detours.GlobalExcludedThreadId.Add(OnyxNative.GetCurrentThreadId());
        }
Exemplo n.º 17
0
 public DisassemblyInstruction(Disasm disasm, int length, byte[] instructionData)
 {
     Length = length;
     InstructionData = instructionData;
     CompleteInstruction = disasm.CompleteInstr;
     Architecture = disasm.Archi;
     Options = disasm.Options;
     Instruction = disasm.Instruction;
     Argument1 = disasm.Argument1;
     Argument2 = disasm.Argument2;
     Argument3 = disasm.Argument3;
     Prefix = disasm.Prefix;
 }
        /// <summary>
        /// Disassemble a given piece of shellcode.
        /// </summary>
        /// <param name="disasmBytes">The byte array to disassemble</param>
        /// <param name="architecture">The architecture to target. Either 32 or 64 bit Windows</param>
        /// <param name="disasmBox">The listbox to place the disassembly</param>
        /// <param name="showOffsets">Boolean to determine whether or not to display address offsets in the disassembly listing.</param>
        public void disassembleSC(byte[] disasmBytes, uint architecture, System.Windows.Forms.RichTextBox disasmBox, bool showOffsets)
        {
            var disasm = new Disasm();

            disasm.Options = 0x200;//display in NASM syntax

            if (architecture == 32)
            {
                disasm.Archi = 32;
            }
            else if (architecture == 64)
            {
                disasm.Archi = 64;
            }

            int    size             = disasmBytes.Length;
            IntPtr executionPointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(size);

            System.Runtime.InteropServices.Marshal.Copy(disasmBytes, 0, executionPointer, size);
            disasm.EIP = new IntPtr(executionPointer.ToInt64());

            int result;
            var disasmPtr = Marshal.AllocHGlobal(Marshal.SizeOf(disasm));

            disasmBox.AppendText("Disassembled shellcode with " + architecture + "bit\n");
            var EIPrange = (executionPointer.ToInt64() + size / 2);

            try
            {
                while (disasm.EIP.ToInt64() < EIPrange)
                {
                    System.Runtime.InteropServices.Marshal.StructureToPtr(disasm, disasmPtr, false);
                    result = BeaEngine.Disasm(disasmPtr);
                    Marshal.PtrToStructure(disasmPtr, disasm);
                    if (result == (int)BeaConstants.SpecialInfo.UNKNOWN_OPCODE)
                    {
                        disasmBox.AppendText("Unknown opcode error @ " + disasm.EIP.ToString("X") + "\n");
                        break;
                    }

                    if (showOffsets)
                    {
                        disasmBox.AppendText(disasm.EIP.ToString("X") + "h : " + disasm.CompleteInstr.ToString() + "\n");
                    }
                    else
                    {
                        disasmBox.AppendText(disasm.CompleteInstr.ToString() + "\n");
                    }

                    if (disasm.Instruction.Opcode.ToString("X") == "C3")
                    {
                        break;
                    }
                    disasm.EIP = new IntPtr(disasm.EIP.ToInt64() + result);
                }
            }
            catch
            {
                disasmBox.AppendText("Something went wrong with disassembly\n");
            }
        }
Exemplo n.º 19
0
        public static Instruction[] PeToInstructions(string FilePath)
        {
            UnmanagedBuffer    buffer    = new UnmanagedBuffer(File.ReadAllBytes(FilePath));
            List <Instruction> instructs = new List <Instruction>();
            Disasm             disasm    = new Disasm();

            disasm.EIP = new IntPtr(buffer.Ptr.ToInt64() + 0x400);

            List <int> Addresses = new List <int>();

            while (true)
            {
                int result = Asm.Net.src.BeaEngine.BeaEngine.Disasm(disasm);
                Addresses.Add(disasm.EIP.ToInt32());

                if (result == (int)BeaConstants.SpecialInfo.UNKNOWN_OPCODE)
                {
                    break;
                }

                //Console.WriteLine("0x" + disasm.EIP.ToString("X") + " " + disasm.CompleteInstr);

                //convert the data to instructions so we are able to execute it in Asm.Net
                //We also need to change the pointers for push, call, inc, dec etc... so Asm.Net is able to understand it

                switch (disasm.Instruction.Opcode)
                {
                case (int)OpcodeList.CALL:
                {
                    string tmp      = disasm.Argument1.ArgMnemonic.Substring(0, disasm.Argument1.ArgMnemonic.Length - 1).Replace("FFFFFFFF", "");
                    int    Jmpvalue = Convert.ToInt32(tmp, 16);

                    CALL call = new CALL(Jmpvalue);
                    call.NativeVirtualAddress.Address = disasm.EIP.ToInt32();
                    instructs.Add(call);
                    break;
                }

                case (int)OpcodeList.INC_EAX:
                {
                    INC_EAX IncEax = new INC_EAX();
                    IncEax.NativeVirtualAddress.Address = disasm.EIP.ToInt32();
                    instructs.Add(IncEax);
                    break;
                }

                case (int)OpcodeList.INC_EDX:
                {
                    break;
                }

                case (int)OpcodeList.JE:
                {
                    break;
                }

                case (int)OpcodeList.JMP:
                {
                    string tmp      = disasm.Argument1.ArgMnemonic.Substring(0, disasm.Argument1.ArgMnemonic.Length - 1);
                    int    Jmpvalue = Convert.ToInt32(tmp.Replace("FFFFFFFF", ""), 16);

                    JMP jmp = new JMP(Jmpvalue);
                    jmp.NativeVirtualAddress.Address = disasm.EIP.ToInt32();
                    //instructs.Add(jmp);
                    break;
                }

                case (int)OpcodeList.JNZ:
                {
                    string tmp      = disasm.Argument1.ArgMnemonic.Substring(0, disasm.Argument1.ArgMnemonic.Length - 1);
                    int    Jmpvalue = Convert.ToInt32(tmp.Replace("FFFFFFFF", ""), 16);

                    JNZ jnz = new JNZ(Jmpvalue);
                    jnz.NativeVirtualAddress.Address = disasm.EIP.ToInt32();
                    //instructs.Add(jnz);
                    break;
                }

                case (int)OpcodeList.MOV_EAX:
                {
                    string  tmp      = disasm.Argument2.ArgMnemonic.Substring(0, disasm.Argument2.ArgMnemonic.Length - 1);
                    int     MovValue = Convert.ToInt32(tmp, 16);
                    MOV_EAX MovEAX   = new MOV_EAX(new VirtualAddress(0, MovValue));
                    MovEAX.NativeVirtualAddress.Address = disasm.EIP.ToInt32();
                    instructs.Add(MovEAX);
                    break;
                }

                case (int)OpcodeList.NOP:
                {
                    NOP nop = new NOP();
                    nop.NativeVirtualAddress.Address = disasm.EIP.ToInt32();
                    instructs.Add(nop);
                    break;
                }

                case (int)OpcodeList.PUSH_EAX:
                {
                    break;
                }

                case (int)OpcodeList.RET:
                {
                    RET ret = new RET();
                    ret.NativeVirtualAddress.Address = disasm.EIP.ToInt32();
                    instructs.Add(ret);
                    break;
                }

                case (int)OpcodeList.ADD:
                {
                    //need to reverse check the opcodes...
                    Instruction ADD = null;
                    switch (disasm.Argument1.ArgMnemonic)
                    {
                    case "eax":
                    {
                        switch (disasm.Argument2.ArgMnemonic)
                        {
                        case "al":
                        {
                            ADD = new ADD_BYTE_PTR_EAX_AL();
                            break;
                        }
                        }
                        break;
                    }
                    }

                    if (ADD != null)
                    {
                        ADD.NativeVirtualAddress.Address = disasm.EIP.ToInt32();
                        instructs.Add(ADD);
                    }
                    break;
                }

                case (int)OpcodeList.XOR_REGISTER:
                {
                    Instruction xor = null;
                    switch (disasm.Argument1.ArgMnemonic)
                    {
                    case "eax":
                    {
                        switch (disasm.Argument2.ArgMnemonic)
                        {
                        case "eax": { xor = new XOR_EAX_EAX(); break; }

                        case "ecx": { xor = new XOR_EAX_ECX(); break; }

                        case "edx": { xor = new XOR_EAX_EDX(); break; }

                        case "ebx": { xor = new XOR_EAX_EBX(); break; }

                        case "esp": { xor = new XOR_EAX_ESP(); break; }

                        case "ebp": { xor = new XOR_EAX_EBP(); break; }

                        case "esi": { xor = new XOR_EAX_ESI(); break; }

                        case "edi": { xor = new XOR_EAX_EDI(); break; }
                        }
                        break;
                    }

                    case "ecx":
                    {
                        switch (disasm.Argument2.ArgMnemonic)
                        {
                        case "eax": { xor = new XOR_ECX_EAX(); break; }

                        case "ecx": { xor = new XOR_ECX_ECX(); break; }

                        case "edx": { xor = new XOR_ECX_EDX(); break; }

                        case "ebx": { xor = new XOR_ECX_EBX(); break; }

                        case "esp": { xor = new XOR_ECX_ESP(); break; }

                        case "ebp": { xor = new XOR_ECX_EBP(); break; }

                        case "esi": { xor = new XOR_ECX_ESI(); break; }

                        case "edi": { xor = new XOR_ECX_EDI(); break; }
                        }
                        break;
                    }

                    case "edx":
                    {
                        switch (disasm.Argument2.ArgMnemonic)
                        {
                        case "eax": { xor = new XOR_EDX_EAX(); break; }

                        case "ecx": { xor = new XOR_EDX_ECX(); break; }

                        case "edx": { xor = new XOR_EDX_EDX(); break; }

                        case "ebx": { xor = new XOR_EDX_EBX(); break; }

                        case "esp": { xor = new XOR_EDX_ESP(); break; }

                        case "ebp": { xor = new XOR_EDX_EBP(); break; }

                        case "esi": { xor = new XOR_EDX_ESI(); break; }

                        case "edi": { xor = new XOR_EDX_EDI(); break; }
                        }
                        break;
                    }

                    case "ebx":
                    {
                        switch (disasm.Argument2.ArgMnemonic)
                        {
                        case "eax": { xor = new XOR_EBX_EAX(); break; }

                        case "ecx": { xor = new XOR_EBX_ECX(); break; }

                        case "edx": { xor = new XOR_EBX_EDX(); break; }

                        case "ebx": { xor = new XOR_EBX_EBX(); break; }

                        case "esp": { xor = new XOR_EBX_ESP(); break; }

                        case "ebp": { xor = new XOR_EBX_EBP(); break; }

                        case "esi": { xor = new XOR_EBX_ESI(); break; }

                        case "edi": { xor = new XOR_EBX_EDI(); break; }
                        }
                        break;
                    }

                    case "esp":
                    {
                        switch (disasm.Argument2.ArgMnemonic)
                        {
                        case "eax": { xor = new XOR_ESP_EAX(); break; }

                        case "ecx": { xor = new XOR_ESP_ECX(); break; }

                        case "edx": { xor = new XOR_ESP_EDX(); break; }

                        case "ebx": { xor = new XOR_ESP_EBX(); break; }

                        case "esp": { xor = new XOR_ESP_ESP(); break; }

                        case "ebp": { xor = new XOR_ESP_EBP(); break; }

                        case "esi": { xor = new XOR_ESP_ESI(); break; }

                        case "edi": { xor = new XOR_ESP_EDI(); break; }
                        }
                        break;
                    }

                    case "ebp":
                    {
                        switch (disasm.Argument2.ArgMnemonic)
                        {
                        case "eax": { xor = new XOR_EBP_EAX(); break; }

                        case "ecx": { xor = new XOR_EBP_ECX(); break; }

                        case "edx": { xor = new XOR_EBP_EDX(); break; }

                        case "ebx": { xor = new XOR_EBP_EBX(); break; }

                        case "esp": { xor = new XOR_EBP_ESP(); break; }

                        case "ebp": { xor = new XOR_EBP_EBP(); break; }

                        case "esi": { xor = new XOR_EBP_ESI(); break; }

                        case "edi": { xor = new XOR_EBP_EDI(); break; }
                        }
                        break;
                    }

                    case "esi":
                    {
                        switch (disasm.Argument2.ArgMnemonic)
                        {
                        case "eax": { xor = new XOR_ESI_EAX(); break; }

                        case "ecx": { xor = new XOR_ESI_ECX(); break; }

                        case "edx": { xor = new XOR_ESI_EDX(); break; }

                        case "ebx": { xor = new XOR_ESI_EBX(); break; }

                        case "esp": { xor = new XOR_ESI_ESP(); break; }

                        case "ebp": { xor = new XOR_ESI_EBP(); break; }

                        case "esi": { xor = new XOR_ESI_ESI(); break; }

                        case "edi": { xor = new XOR_ESI_EDI(); break; }
                        }
                        break;
                    }

                    case "edi":
                    {
                        switch (disasm.Argument2.ArgMnemonic)
                        {
                        case "eax": { xor = new XOR_EDI_EAX(); break; }

                        case "ecx": { xor = new XOR_EDI_ECX(); break; }

                        case "edx": { xor = new XOR_EDI_EDX(); break; }

                        case "ebx": { xor = new XOR_EDI_EBX(); break; }

                        case "esp": { xor = new XOR_EDI_ESP(); break; }

                        case "ebp": { xor = new XOR_EDI_EBP(); break; }

                        case "esi": { xor = new XOR_EDI_ESI(); break; }

                        case "edi": { xor = new XOR_EDI_EDI(); break; }
                        }
                        break;
                    }
                    }

                    if (xor != null)     //this check is just for temp, not all the XOR instructions are added
                    {
                        xor.NativeVirtualAddress.Address = disasm.EIP.ToInt32();
                        instructs.Add(xor);
                    }
                    break;
                }
                }

                disasm.EIP = new IntPtr(disasm.EIP.ToInt64() + result);
            }

            //set all the pointers correct
            int offset = Options.MemoryBaseAddress;

            foreach (Instruction instruction in instructs)
            {
                switch (instruction.ToByteArray()[0])
                {
                case (int)OpcodeList.CALL:
                {
                    break;
                }

                case (int)OpcodeList.INC_EAX:
                {
                    break;
                }

                case (int)OpcodeList.INC_EDX:
                {
                    break;
                }

                case (int)OpcodeList.JE:
                {
                    break;
                }

                case (int)OpcodeList.JMP:
                {
                    //lets set our new jmp pointer, We also should load the modules which are required to run this program
                    //We need to load the Import Table and get all the .dll's from it and getting all the instructions from it
                    bool NewSet = false;
                    foreach (Instruction instruct in instructs)
                    {
                        if (Addresses.Contains(((IJump)instruction).JumpAddress))
                        {
                            //Set the ASM.net pointer
                            int index = Addresses.IndexOf(((IJump)instruction).JumpAddress) - 1;
                        }

                        //if (((IJump)instruction).JumpAddress == instruct.NativeVirtualAddress.Address)
                        //{
                        //}
                    }

                    //if (!NewSet)
                    //    throw new Exception("Unable to find the JMP Pointer, Invalid memory address ?");
                    break;
                }

                case (int)OpcodeList.MOV_EAX:
                {
                    break;
                }

                case (int)OpcodeList.NOP:
                {
                    break;
                }

                case (int)OpcodeList.PUSH_EAX:
                {
                    break;
                }

                case (int)OpcodeList.RET:
                {
                    break;
                }
                }

                instruction.VirtualAddress.Address = offset;
                offset += instruction.VirtualAddress.Size;
            }

            return(instructs.ToArray());
        }