/// <summary> /// Get an Instruction's Details. /// </summary> /// <param name="hInstruction"> /// An instruction handle. /// </param> /// <returns> /// The instruction's details. A null reference indicates the instruction was disassembled without /// details. /// </returns> internal static NativeInstructionDetail?GetInstructionDetail(NativeInstructionHandle hInstruction) { var pInstruction = hInstruction.DangerousAddRefAndGetHandle(); try { // ... // // First, we calculate the memory address of the <c>NativeInstruction.Details</c> field, which is // always relative to the memory address of its defining <c>NativeInstruction</c> structure. This is // NOT the actual memory address of the instruction's details. var instructionDetailOffset = Marshal.OffsetOf(typeof(NativeInstruction), nameof(NativeInstruction.Details)); var pInstructionDetail = (IntPtr)((long)pInstruction + (long)instructionDetailOffset); // ... // // Second, we read the value of the <c>NativeInstruction.Details</c> field, which IS the actual memory // address of the instruction's details. If the value is not equal to <c>IntPtr.Zero</c>, that indicates // the instruction was disassembled with details. var ppInstructionDetail = Marshal.ReadIntPtr(pInstructionDetail); NativeInstructionDetail?instructionDetail = null; if (ppInstructionDetail != IntPtr.Zero) { instructionDetail = MarshalExtension.PtrToStructure <NativeInstructionDetail>(ppInstructionDetail); } return(instructionDetail); } finally { hInstruction.DangerousRelease(); } }
/// <summary> /// Get Next Instruction. /// </summary> /// <returns> /// A boolean true if an instruction is returned. A boolean false otherwise. /// </returns> /// <exception cref="System.ObjectDisposedException"> /// Thrown if the enumerator is disposed. /// </exception> public bool MoveNext() { this.CheckDisposed(); var pCode = this._pinnedCode.AddrOfPinnedObject() + this._currentOffset; var pCount = (UIntPtr)1; var pInstructions = IntPtr.Zero; var pSize = (UIntPtr)this._codeSize - this._currentOffset; // Disassemble Binary Code. // // ... var pResultCode = CapstoneImport.Disassemble((UIntPtr)(ulong)(long)_disassembler.Handle.DangerousGetHandle(), pCode, pSize, this._currentAddress, pCount, ref pInstructions); var iResultCode = (int)pResultCode; var nativeInstructions = MarshalExtension.PtrToStructure <NativeInstruction>(pInstructions, iResultCode); if (nativeInstructions == null || nativeInstructions.Length == 0) { return(false); } var instruction = nativeInstructions[0]; this._currentInstruction = this._disassembler.CreateInstruction(instruction); this._currentAddress += (ulong)this._currentInstruction.Bytes.Length; this._currentOffset += this._currentInstruction.Bytes.Length; return(true); }
/// <summary> /// Get an Instruction's Architecture Specific Details. /// </summary> /// <typeparam name="TInstructionDetails"> /// The type of the instruction's architecture specific details. /// </typeparam> /// <param name="instruction"> /// An instruction. /// </param> /// <returns> /// The instruction's architecture specific details. A null reference indicates the instruction was /// disassembled without its details. /// </returns> internal static TInstructionDetails?GetInstructionDetail <TInstructionDetails>(ref NativeInstruction instruction) where TInstructionDetails : struct { TInstructionDetails?instructionDetails = null; if (instruction.Details != IntPtr.Zero) { // ... // // Throws an exception if the operation fails. var pInstructionDetails = instruction.Details + NativeCapstone.MagicInstructionArchitectureDetailsFieldOffset; instructionDetails = MarshalExtension.PtrToStructure <TInstructionDetails>(pInstructionDetails); } return(instructionDetails); }
/// <summary> /// Get an Instruction's Details. /// </summary> /// <param name="instruction"> /// An instruction. /// </param> /// <returns> /// The instruction's details. A null reference indicates the instruction was disassembled without /// details. /// </returns> internal static NativeInstructionDetail?GetInstructionDetail(ref NativeInstruction instruction) { NativeInstructionDetail?instructionDetails = null; if (instruction.Details != IntPtr.Zero) { // ... // // Throws an exception if the operation fails. var pInstructionDetails = instruction.Details; instructionDetails = MarshalExtension.PtrToStructure <NativeInstructionDetail>(pInstructionDetails); } return(instructionDetails); }
/// <summary> /// Get an Instruction. /// </summary> /// <param name="hInstruction"> /// An instruction handle. /// </param> /// <returns> /// An instruction. /// </returns> internal static NativeInstruction GetInstruction(NativeInstructionHandle hInstruction) { var pInstruction = hInstruction.DangerousAddRefAndGetHandle(); try { // ... // // Throws an exception if the operation fails. var instruction = MarshalExtension.PtrToStructure <NativeInstruction>(pInstruction); return(instruction); } finally { hInstruction.DangerousRelease(); } }
/// <summary> /// Marshal a Pointer to a Collection of Structures. /// </summary> /// <typeparam name="T"> /// The collection's type. /// </typeparam> /// <param name="p"> /// A pointer to a collection. The pointer should be initialized to the collection's starting address. /// </param> /// <param name="size"> /// The collection's size. /// </param> /// <returns> /// The destination collection. /// </returns> internal static T[] PtrToStructure <T>(IntPtr p, int size) { var array = new T[size]; var index = p; for (var i = 0; i < size; i++) { var element = MarshalExtension.PtrToStructure <T>(index); array[i] = element; index += Marshal.SizeOf(typeof(T)); } return(array); }
/// <summary> /// Disassemble Binary Code. /// </summary> /// <param name="handle"> /// A Capstone handle. Should not be a null reference. /// </param> /// <param name="code"> /// A collection of bytes representing the binary code to disassemble. Should not be a null reference. /// </param> /// <param name="count"> /// The number of instructions to disassemble. A 0 indicates all instructions should be disassembled. /// </param> /// <param name="startingAddress"> /// The address of the first instruction in the collection of bytes to disassemble. /// </param> /// <returns> /// A native instruction handle. /// </returns> /// <exception cref="System.InvalidOperationException"> /// Thrown if the binary code could not be disassembled. /// </exception> public static SafeNativeInstructionHandle Disassemble(SafeCapstoneHandle handle, byte[] code, int count, ulong startingAddress) { // Copy Code to Unmanaged Memory. // // ... var pCode = MarshalExtension.AllocHGlobal <byte>(code.Length); Marshal.Copy(code, 0, pCode, code.Length); var pCount = (UIntPtr)count; var pHandle = handle.DangerousGetHandle(); var pInstructions = IntPtr.Zero; var pSize = (UIntPtr)code.Length; // var uStartingAddress = (ulong) startingAddress; // Disassemble Binary Code. // // ... var pResultCode = CapstoneImport.Disassemble(unchecked ((UIntPtr)(ulong)(ulong)handle.DangerousGetHandle()), pCode, pSize, startingAddress, pCount, ref pInstructions); if (pResultCode == UIntPtr.Zero) { throw new InvalidOperationException("Unable to disassemble binary code."); } var iResultCode = (int)pResultCode; var instructions = MarshalExtension.PtrToStructure <NativeInstruction>(pInstructions, iResultCode); // Free Unmanaged Memory. // // Avoid a memory leak. Marshal.FreeHGlobal(pCode); var instructionHandle = new SafeNativeInstructionHandle(instructions, pInstructions, pResultCode); return(instructionHandle); }