public static unsafe DecomposedResult Decompose(CodeInfo nci, int maxInstructions) { CodeInfoStruct *ci = null; DecomposedInstructionStruct *insts = null; var gch = new GCHandle(); var usedInstructionsCount = 0; try { if ((ci = AcquireCodeInfoStruct(nci, out gch)) == null) { throw new OutOfMemoryException(); } var dr = new DecomposedResult(maxInstructions); distorm_decompose64(ci, dr.InstructionsPointer, maxInstructions, &usedInstructionsCount); dr.UsedInstructions = usedInstructionsCount; return(dr); } finally { if (gch.IsAllocated) { gch.Free(); } if (ci != null) { Free(ci); } } }
public unsafe DecomposedResult(int maxInstructions) { MaxInstructions = maxInstructions; _instMem = new byte[maxInstructions * sizeof(DecomposedInstructionStruct)]; _gch = GCHandle.Alloc(_instMem, GCHandleType.Pinned); _instructionsPointer = (DecomposedInstructionStruct *)_gch.AddrOfPinnedObject(); }
private static unsafe void TestInstructionsUnmanaged(DecomposedInstructionStruct *insts) { Assert.That(insts[0].Address.ToInt32(), Is.EqualTo(0x1000)); Assert.That(insts[0].Opcode, Is.EqualTo(Opcode.RET)); Assert.That(insts[0].Size, Is.EqualTo(1)); Assert.That(insts[1].Address.ToInt32(), Is.EqualTo(0x1001)); Assert.That(insts[1].Opcode, Is.EqualTo(Opcode.XOR)); Assert.That(insts[1].Operands[0].Type, Is.EqualTo(OperandType.Register)); Assert.That(insts[1].Operands[0].Register, Is.EqualTo(Register.R_EAX)); Assert.That(insts[1].Operands[0].Size, Is.EqualTo(32)); Assert.That(insts[1].Operands[1].Type, Is.EqualTo(OperandType.Register)); Assert.That(insts[1].Operands[1].Register, Is.EqualTo(Register.R_EAX)); Assert.That(insts[1].Operands[1].Size, Is.EqualTo(32)); Assert.That(insts[1].Size, Is.EqualTo(2)); Assert.That(insts[2].Address.ToInt32(), Is.EqualTo(0x1003)); Assert.That(insts[2].Opcode, Is.EqualTo(Opcode.RET)); Assert.That(insts[2].Size, Is.EqualTo(1)); }
public static unsafe DecomposedInstruction FromUnsafe(DecomposedInstructionStruct *srcInst) { var di = new DecomposedInstruction { Address = srcInst->Address, Flags = srcInst->Flags, Size = srcInst->Size, _segment = srcInst->segment, Base = srcInst->ibase, Scale = srcInst->scale, Opcode = srcInst->Opcode, UnusedPrefixesMask = srcInst->UnusedPrefixesMask, Meta = srcInst->meta, RegistersMask = srcInst->UsedRegistersMask, ModifiedFlagsMask = srcInst->modifiedFlagsMask, TestedFlagsMask = srcInst->testedFlagsMask, UndefinedFlagsMask = srcInst->undefinedFlagsMask }; /* Simple fields: */ /* Immediate variant. */ var immVariant = new ImmVariant { ImmediateValue = srcInst->ImmediateValue, Size = 0 }; /* The size of the immediate is in one of the operands, if at all. Look for it below. Zero by default. */ /* Count operands. */ var operandsNo = 0; for (operandsNo = 0; operandsNo < DecomposedInstructionStruct.OPERANDS_NO; operandsNo++) { if (srcInst->Operands[operandsNo].Type == OperandType.None) { break; } } var ops = new Operand[operandsNo]; for (var j = 0; j < operandsNo; j++) { var srcOp = srcInst->Operands[j]; if (srcOp.Type == OperandType.Immediate) { /* Set the size of the immediate operand. */ immVariant.Size = srcInst->Operands[j].Size; } var op = new Operand { Type = srcOp.Type, Index = srcOp.index, Size = srcOp.Size }; ops[j] = op; } di.Operands = ops; /* Attach the immediate variant. */ di.ImmediateValue = immVariant; /* Displacement variant. */ var disp = new DispVariant { Displacement = srcInst->Displacement, Size = srcInst->dispSize }; di.Displacement = disp; return(di); }