示例#1
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);
                }
            }
        }
示例#2
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);
             }
        }