mirror of https://github.com/icedland/iced.git
Update README how-tos
This commit is contained in:
parent
65c3df1de1
commit
b23e9ddd37
235
README.md
235
README.md
|
@ -179,19 +179,21 @@ static class HowTo_Assemble {
|
||||||
1000000B = cmp dword ptr [rax+rcx*8+10h],0FFFFFFFFh
|
1000000B = cmp dword ptr [rax+rcx*8+10h],0FFFFFFFFh
|
||||||
10000010 = jne short 0000000010000031h
|
10000010 = jne short 0000000010000031h
|
||||||
10000012 = inc rax
|
10000012 = inc rax
|
||||||
10000015 = lea rcx,[10000031h]
|
10000015 = lea rcx,[10000034h]
|
||||||
1000001C = rep stosd
|
1000001C = rep stosd
|
||||||
1000001E = xacquire lock add qword ptr [rax+rcx],7Bh
|
1000001E = xacquire lock add qword ptr [rax+rcx],7Bh
|
||||||
10000025 = vaddpd zmm1{k3}{z},zmm2,zmm3 {rz-sae}
|
10000025 = vaddpd zmm1{k3}{z},zmm2,zmm3 {rz-sae}
|
||||||
1000002B = vunpcklps xmm2{k5}{z},xmm6,dword bcst [rax]
|
1000002B = vunpcklps xmm2{k5}{z},xmm6,dword bcst [rax]
|
||||||
10000031 = pop r15
|
10000031 = pop r15
|
||||||
10000033 = ret
|
10000033 = ret
|
||||||
|
10000034 = pause
|
||||||
*/
|
*/
|
||||||
public static MemoryStream Example() {
|
public static MemoryStream Example() {
|
||||||
// The assembler supports all modes: 16-bit, 32-bit and 64-bit.
|
// The assembler supports all modes: 16-bit, 32-bit and 64-bit.
|
||||||
var c = new Assembler(64);
|
var c = new Assembler(64);
|
||||||
|
|
||||||
var label1 = c.CreateLabel();
|
var label1 = c.CreateLabel();
|
||||||
|
var data1 = c.CreateLabel();
|
||||||
|
|
||||||
c.push(r15);
|
c.push(r15);
|
||||||
c.add(rax, r15);
|
c.add(rax, r15);
|
||||||
|
@ -208,7 +210,7 @@ static class HowTo_Assemble {
|
||||||
c.inc(rax);
|
c.inc(rax);
|
||||||
|
|
||||||
// Labels can be referenced by memory operands (64-bit only) and call/jmp/jcc/loopcc instructions
|
// Labels can be referenced by memory operands (64-bit only) and call/jmp/jcc/loopcc instructions
|
||||||
c.lea(rcx, __[label1]);
|
c.lea(rcx, __[data1]);
|
||||||
|
|
||||||
// The assembler has prefix properties that will be added to the following instruction
|
// The assembler has prefix properties that will be added to the following instruction
|
||||||
c.rep.stosd();
|
c.rep.stosd();
|
||||||
|
@ -225,6 +227,8 @@ static class HowTo_Assemble {
|
||||||
c.Label(ref label1);
|
c.Label(ref label1);
|
||||||
c.pop(r15);
|
c.pop(r15);
|
||||||
c.ret();
|
c.ret();
|
||||||
|
c.Label(ref data1);
|
||||||
|
c.db(0xF3, 0x90); // pause
|
||||||
|
|
||||||
const ulong RIP = 0x1000_0000;
|
const ulong RIP = 0x1000_0000;
|
||||||
var stream = new MemoryStream();
|
var stream = new MemoryStream();
|
||||||
|
@ -320,7 +324,7 @@ static class HowTo_ColorizedText {
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class FormatterOutputImpl : FormatterOutput {
|
sealed class FormatterOutputImpl : FormatterOutput {
|
||||||
public List<(string text, FormatterTextKind kind)> List =
|
public readonly List<(string text, FormatterTextKind kind)> List =
|
||||||
new List<(string text, FormatterTextKind kind)>();
|
new List<(string text, FormatterTextKind kind)>();
|
||||||
public override void Write(string text, FormatterTextKind kind) => List.Add((text, kind));
|
public override void Write(string text, FormatterTextKind kind) => List.Add((text, kind));
|
||||||
}
|
}
|
||||||
|
@ -362,6 +366,7 @@ static class HowTo_ColorizedText {
|
||||||
```C#
|
```C#
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using Iced.Intel;
|
using Iced.Intel;
|
||||||
|
|
||||||
static class HowTo_MoveCode {
|
static class HowTo_MoveCode {
|
||||||
|
@ -378,14 +383,101 @@ static class HowTo_MoveCode {
|
||||||
// relative addressing and it tries to access data too far away, the encoder will fail.
|
// relative addressing and it tries to access data too far away, the encoder will fail.
|
||||||
// The easiest solution is to use OS alloc functions that allocate memory close to the
|
// The easiest solution is to use OS alloc functions that allocate memory close to the
|
||||||
// original code (+/-2GB).
|
// original code (+/-2GB).
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method produces the following output:
|
||||||
|
Original code:
|
||||||
|
00007FFAC46ACDA4 mov [rsp+10h],rbx
|
||||||
|
00007FFAC46ACDA9 mov [rsp+18h],rsi
|
||||||
|
00007FFAC46ACDAE push rbp
|
||||||
|
00007FFAC46ACDAF push rdi
|
||||||
|
00007FFAC46ACDB0 push r14
|
||||||
|
00007FFAC46ACDB2 lea rbp,[rsp-100h]
|
||||||
|
00007FFAC46ACDBA sub rsp,200h
|
||||||
|
00007FFAC46ACDC1 mov rax,[rel 7FFAC47524E0h]
|
||||||
|
00007FFAC46ACDC8 xor rax,rsp
|
||||||
|
00007FFAC46ACDCB mov [rbp+0F0h],rax
|
||||||
|
00007FFAC46ACDD2 mov r8,[rel 7FFAC474F208h]
|
||||||
|
00007FFAC46ACDD9 lea rax,[rel 7FFAC46F4A58h]
|
||||||
|
00007FFAC46ACDE0 xor edi,edi
|
||||||
|
|
||||||
|
Original + patched code:
|
||||||
|
00007FFAC46ACDA4 mov rax,123456789ABCDEF0h
|
||||||
|
00007FFAC46ACDAE jmp rax
|
||||||
|
00007FFAC46ACDB0 push r14
|
||||||
|
00007FFAC46ACDB2 lea rbp,[rsp-100h]
|
||||||
|
00007FFAC46ACDBA sub rsp,200h
|
||||||
|
00007FFAC46ACDC1 mov rax,[rel 7FFAC47524E0h]
|
||||||
|
00007FFAC46ACDC8 xor rax,rsp
|
||||||
|
00007FFAC46ACDCB mov [rbp+0F0h],rax
|
||||||
|
00007FFAC46ACDD2 mov r8,[rel 7FFAC474F208h]
|
||||||
|
00007FFAC46ACDD9 lea rax,[rel 7FFAC46F4A58h]
|
||||||
|
00007FFAC46ACDE0 xor edi,edi
|
||||||
|
|
||||||
|
Moved code:
|
||||||
|
00007FFAC48ACDA4 mov [rsp+10h],rbx
|
||||||
|
00007FFAC48ACDA9 mov [rsp+18h],rsi
|
||||||
|
00007FFAC48ACDAE push rbp
|
||||||
|
00007FFAC48ACDAF push rdi
|
||||||
|
00007FFAC48ACDB0 jmp 00007FFAC46ACDB0h
|
||||||
|
*/
|
||||||
public static void Example() {
|
public static void Example() {
|
||||||
|
Console.WriteLine("Original code:");
|
||||||
|
Disassemble(exampleCode, exampleCodeRIP);
|
||||||
|
|
||||||
var codeReader = new ByteArrayCodeReader(exampleCode);
|
var codeReader = new ByteArrayCodeReader(exampleCode);
|
||||||
var decoder = Decoder.Create(exampleCodeBitness, codeReader);
|
var decoder = Decoder.Create(exampleCodeBitness, codeReader);
|
||||||
decoder.IP = exampleCodeRIP;
|
decoder.IP = exampleCodeRIP;
|
||||||
|
|
||||||
var instructions = new InstructionList();
|
// In 64-bit mode, we need 12 bytes to jump to any address:
|
||||||
while (codeReader.CanReadByte)
|
// mov rax,imm64 // 10
|
||||||
decoder.Decode(out instructions.AllocUninitializedElement());
|
// jmp rax // 2
|
||||||
|
// We overwrite rax because it's probably not used by the called function.
|
||||||
|
// In 32-bit mode, a normal JMP is just 5 bytes
|
||||||
|
const uint requiredBytes = 10 + 2;
|
||||||
|
uint totalBytes = 0;
|
||||||
|
var origInstructions = new InstructionList();
|
||||||
|
while (codeReader.CanReadByte) {
|
||||||
|
decoder.Decode(out var instr);
|
||||||
|
origInstructions.Add(instr);
|
||||||
|
totalBytes += (uint)instr.Length;
|
||||||
|
if (instr.Code == Code.INVALID)
|
||||||
|
throw new Exception("Found garbage");
|
||||||
|
if (totalBytes >= requiredBytes)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (instr.FlowControl) {
|
||||||
|
case FlowControl.Next:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FlowControl.UnconditionalBranch:
|
||||||
|
if (instr.Op0Kind == OpKind.NearBranch64) {
|
||||||
|
var target = instr.NearBranchTarget;
|
||||||
|
// You could check if it's just jumping forward a few bytes and follow it
|
||||||
|
// but this is a simple example so we'll fail.
|
||||||
|
}
|
||||||
|
goto default;
|
||||||
|
|
||||||
|
case FlowControl.IndirectBranch:// eg. jmp reg/mem
|
||||||
|
case FlowControl.ConditionalBranch:// eg. je, jno, etc
|
||||||
|
case FlowControl.Return:// eg. ret
|
||||||
|
case FlowControl.Call:// eg. call method
|
||||||
|
case FlowControl.IndirectCall:// eg. call reg/mem
|
||||||
|
case FlowControl.Interrupt:// eg. int n
|
||||||
|
case FlowControl.XbeginXabortXend:
|
||||||
|
case FlowControl.Exception:// eg. ud0
|
||||||
|
default:
|
||||||
|
throw new Exception("Not supported by this simple example");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (totalBytes < requiredBytes)
|
||||||
|
throw new Exception("Not enough bytes!");
|
||||||
|
Debug.Assert(origInstructions.Count > 0);
|
||||||
|
// Create a JMP instruction that branches to the original code, except those instructions
|
||||||
|
// that we we'll re-encode. We don't need to do it if it already ends in 'ret'
|
||||||
|
ref readonly var lastInstr = ref origInstructions[origInstructions.Count - 1];
|
||||||
|
if (lastInstr.FlowControl != FlowControl.Return)
|
||||||
|
origInstructions.Add(Instruction.CreateBranch(Code.Jmp_rel32_64, lastInstr.NextIP));
|
||||||
|
|
||||||
// Relocate the code to some new location. It can fix short/near branches and
|
// Relocate the code to some new location. It can fix short/near branches and
|
||||||
// convert them to short/near/long forms if needed. This also works even if it's a
|
// convert them to short/near/long forms if needed. This also works even if it's a
|
||||||
|
@ -399,7 +491,7 @@ static class HowTo_MoveCode {
|
||||||
// should be enough unless you must relocate different blocks to different locations.
|
// should be enough unless you must relocate different blocks to different locations.
|
||||||
var codeWriter = new CodeWriterImpl();
|
var codeWriter = new CodeWriterImpl();
|
||||||
ulong relocatedBaseAddress = exampleCodeRIP + 0x200000;
|
ulong relocatedBaseAddress = exampleCodeRIP + 0x200000;
|
||||||
var block = new InstructionBlock(codeWriter, instructions, relocatedBaseAddress);
|
var block = new InstructionBlock(codeWriter, origInstructions, relocatedBaseAddress);
|
||||||
// This method can also encode more than one block but that's rarely needed, see above comment.
|
// This method can also encode more than one block but that's rarely needed, see above comment.
|
||||||
bool success = BlockEncoder.TryEncode(decoder.Bitness, block, out var errorMessage, out _);
|
bool success = BlockEncoder.TryEncode(decoder.Bitness, block, out var errorMessage, out _);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
@ -407,30 +499,61 @@ static class HowTo_MoveCode {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var newCode = codeWriter.ToArray();
|
var newCode = codeWriter.ToArray();
|
||||||
Console.WriteLine("New code bytes:");
|
|
||||||
for (int i = 0; i < newCode.Length;) {
|
|
||||||
for (int j = 0; j < 16 && i < newCode.Length; i++, j++) {
|
|
||||||
if (j != 0)
|
|
||||||
Console.Write(", ");
|
|
||||||
Console.Write("0x");
|
|
||||||
Console.Write(newCode[i].ToString("X2"));
|
|
||||||
}
|
|
||||||
Console.WriteLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disassemble the new relocated code. It's identical to the original code except that
|
// Patch the original code. Pretend that we use some OS API to write to memory...
|
||||||
// the RIP relative instructions have been updated.
|
// We could use the BlockEncoder/Encoder for this but it's easy to do yourself too.
|
||||||
Console.WriteLine("Disassembled code:");
|
// This is 'mov rax,imm64; jmp rax'
|
||||||
|
const ulong YOUR_FUNC = 0x123456789ABCDEF0;// Address of your code
|
||||||
|
exampleCode[0] = 0x48;// \ 'MOV RAX,imm64'
|
||||||
|
exampleCode[1] = 0xB8;// /
|
||||||
|
ulong v = YOUR_FUNC;
|
||||||
|
for (int i = 0; i < 8; i++, v >>= 8)
|
||||||
|
exampleCode[2 + i] = (byte)v;
|
||||||
|
exampleCode[10] = 0xFF;// \ JMP RAX
|
||||||
|
exampleCode[11] = 0xE0;// /
|
||||||
|
|
||||||
|
// Disassemble it
|
||||||
|
Console.WriteLine("Original + patched code:");
|
||||||
var formatter = new NasmFormatter();
|
var formatter = new NasmFormatter();
|
||||||
var output = new StringOutput();
|
var output = new StringOutput();
|
||||||
var newReader = new ByteArrayCodeReader(newCode);
|
codeReader = new ByteArrayCodeReader(exampleCode);
|
||||||
var newDecoder = Decoder.Create(decoder.Bitness, newReader);
|
decoder = Decoder.Create(exampleCodeBitness, codeReader);
|
||||||
newDecoder.IP = block.RIP;
|
decoder.IP = exampleCodeRIP;
|
||||||
while (newReader.CanReadByte) {
|
while (codeReader.CanReadByte) {
|
||||||
newDecoder.Decode(out var instr);
|
Instruction instr;
|
||||||
|
if (decoder.IP == exampleCodeRIP + requiredBytes && lastInstr.NextIP - decoder.IP != 0) {
|
||||||
|
// The instruction was partially overwritten, so just show it as a 'db x,y,z' instead of garbage
|
||||||
|
var len = (int)(lastInstr.NextIP - decoder.IP);
|
||||||
|
var index = (int)(decoder.IP - exampleCodeRIP);
|
||||||
|
instr = Instruction.CreateDeclareByte(exampleCode, index, len);
|
||||||
|
instr.NextIP = decoder.IP;
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
codeReader.ReadByte();
|
||||||
|
decoder.IP += (ulong)len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
instr = decoder.Decode();
|
||||||
formatter.Format(instr, output);
|
formatter.Format(instr, output);
|
||||||
Console.WriteLine($"{instr.IP:X16} {output.ToStringAndReset()}");
|
Console.WriteLine($"{instr.IP:X16} {output.ToStringAndReset()}");
|
||||||
}
|
}
|
||||||
|
Console.WriteLine();
|
||||||
|
|
||||||
|
// Disassemble the moved code
|
||||||
|
Console.WriteLine("Moved code:");
|
||||||
|
Disassemble(newCode, relocatedBaseAddress);
|
||||||
|
}
|
||||||
|
static void Disassemble(byte[] data, ulong ip) {
|
||||||
|
var formatter = new NasmFormatter();
|
||||||
|
var output = new StringOutput();
|
||||||
|
var codeReader = new ByteArrayCodeReader(data);
|
||||||
|
var decoder = Decoder.Create(exampleCodeBitness, codeReader);
|
||||||
|
decoder.IP = ip;
|
||||||
|
while (codeReader.CanReadByte) {
|
||||||
|
decoder.Decode(out var instr);
|
||||||
|
formatter.Format(instr, output);
|
||||||
|
Console.WriteLine($"{instr.IP:X16} {output.ToStringAndReset()}");
|
||||||
|
}
|
||||||
|
Console.WriteLine();
|
||||||
}
|
}
|
||||||
sealed class CodeWriterImpl : CodeWriter {
|
sealed class CodeWriterImpl : CodeWriter {
|
||||||
readonly List<byte> allBytes = new List<byte>();
|
readonly List<byte> allBytes = new List<byte>();
|
||||||
|
@ -472,9 +595,9 @@ static class HowTo_InstructionInfo {
|
||||||
Op1Access: Read
|
Op1Access: Read
|
||||||
Op0: r64_or_mem
|
Op0: r64_or_mem
|
||||||
Op1: r64_reg
|
Op1: r64_reg
|
||||||
RSP:Read
|
Used reg: RSP:Read
|
||||||
RBX:Read
|
Used reg: RBX:Read
|
||||||
[SS:RSP+0x10;UInt64;Write]
|
Used mem: [SS:RSP+0x10;UInt64;Write]
|
||||||
00007FFAC46ACDA9 mov [rsp+18h],rsi
|
00007FFAC46ACDA9 mov [rsp+18h],rsi
|
||||||
OpCode: REX.W 89 /r
|
OpCode: REX.W 89 /r
|
||||||
Instruction: MOV r/m64, r64
|
Instruction: MOV r/m64, r64
|
||||||
|
@ -489,9 +612,9 @@ static class HowTo_InstructionInfo {
|
||||||
Op1Access: Read
|
Op1Access: Read
|
||||||
Op0: r64_or_mem
|
Op0: r64_or_mem
|
||||||
Op1: r64_reg
|
Op1: r64_reg
|
||||||
RSP:Read
|
Used reg: RSP:Read
|
||||||
RSI:Read
|
Used reg: RSI:Read
|
||||||
[SS:RSP+0x18;UInt64;Write]
|
Used mem: [SS:RSP+0x18;UInt64;Write]
|
||||||
00007FFAC46ACDAE push rbp
|
00007FFAC46ACDAE push rbp
|
||||||
OpCode: 50+ro
|
OpCode: 50+ro
|
||||||
Instruction: PUSH r64
|
Instruction: PUSH r64
|
||||||
|
@ -503,9 +626,9 @@ static class HowTo_InstructionInfo {
|
||||||
SP Increment: -8
|
SP Increment: -8
|
||||||
Op0Access: Read
|
Op0Access: Read
|
||||||
Op0: r64_opcode
|
Op0: r64_opcode
|
||||||
RBP:Read
|
Used reg: RBP:Read
|
||||||
RSP:ReadWrite
|
Used reg: RSP:ReadWrite
|
||||||
[SS:RSP+0xFFFFFFFFFFFFFFF8;UInt64;Write]
|
Used mem: [SS:RSP+0xFFFFFFFFFFFFFFF8;UInt64;Write]
|
||||||
00007FFAC46ACDAF push rdi
|
00007FFAC46ACDAF push rdi
|
||||||
OpCode: 50+ro
|
OpCode: 50+ro
|
||||||
Instruction: PUSH r64
|
Instruction: PUSH r64
|
||||||
|
@ -517,9 +640,9 @@ static class HowTo_InstructionInfo {
|
||||||
SP Increment: -8
|
SP Increment: -8
|
||||||
Op0Access: Read
|
Op0Access: Read
|
||||||
Op0: r64_opcode
|
Op0: r64_opcode
|
||||||
RDI:Read
|
Used reg: RDI:Read
|
||||||
RSP:ReadWrite
|
Used reg: RSP:ReadWrite
|
||||||
[SS:RSP+0xFFFFFFFFFFFFFFF8;UInt64;Write]
|
Used mem: [SS:RSP+0xFFFFFFFFFFFFFFF8;UInt64;Write]
|
||||||
00007FFAC46ACDB0 push r14
|
00007FFAC46ACDB0 push r14
|
||||||
OpCode: 50+ro
|
OpCode: 50+ro
|
||||||
Instruction: PUSH r64
|
Instruction: PUSH r64
|
||||||
|
@ -531,9 +654,9 @@ static class HowTo_InstructionInfo {
|
||||||
SP Increment: -8
|
SP Increment: -8
|
||||||
Op0Access: Read
|
Op0Access: Read
|
||||||
Op0: r64_opcode
|
Op0: r64_opcode
|
||||||
R14:Read
|
Used reg: R14:Read
|
||||||
RSP:ReadWrite
|
Used reg: RSP:ReadWrite
|
||||||
[SS:RSP+0xFFFFFFFFFFFFFFF8;UInt64;Write]
|
Used mem: [SS:RSP+0xFFFFFFFFFFFFFFF8;UInt64;Write]
|
||||||
00007FFAC46ACDB2 lea rbp,[rsp-100h]
|
00007FFAC46ACDB2 lea rbp,[rsp-100h]
|
||||||
OpCode: REX.W 8D /r
|
OpCode: REX.W 8D /r
|
||||||
Instruction: LEA r64, m
|
Instruction: LEA r64, m
|
||||||
|
@ -547,8 +670,8 @@ static class HowTo_InstructionInfo {
|
||||||
Op1Access: NoMemAccess
|
Op1Access: NoMemAccess
|
||||||
Op0: r64_reg
|
Op0: r64_reg
|
||||||
Op1: mem
|
Op1: mem
|
||||||
RBP:Write
|
Used reg: RBP:Write
|
||||||
RSP:Read
|
Used reg: RSP:Read
|
||||||
00007FFAC46ACDBA sub rsp,200h
|
00007FFAC46ACDBA sub rsp,200h
|
||||||
OpCode: REX.W 81 /5 id
|
OpCode: REX.W 81 /5 id
|
||||||
Instruction: SUB r/m64, imm32
|
Instruction: SUB r/m64, imm32
|
||||||
|
@ -564,7 +687,7 @@ static class HowTo_InstructionInfo {
|
||||||
Op1Access: Read
|
Op1Access: Read
|
||||||
Op0: r64_or_mem
|
Op0: r64_or_mem
|
||||||
Op1: imm32sex64
|
Op1: imm32sex64
|
||||||
RSP:ReadWrite
|
Used reg: RSP:ReadWrite
|
||||||
00007FFAC46ACDC1 mov rax,[7FFAC47524E0h]
|
00007FFAC46ACDC1 mov rax,[7FFAC47524E0h]
|
||||||
OpCode: REX.W 8B /r
|
OpCode: REX.W 8B /r
|
||||||
Instruction: MOV r64, r/m64
|
Instruction: MOV r64, r/m64
|
||||||
|
@ -579,8 +702,8 @@ static class HowTo_InstructionInfo {
|
||||||
Op1Access: Read
|
Op1Access: Read
|
||||||
Op0: r64_reg
|
Op0: r64_reg
|
||||||
Op1: r64_or_mem
|
Op1: r64_or_mem
|
||||||
RAX:Write
|
Used reg: RAX:Write
|
||||||
[DS:0x7FFAC47524E0;UInt64;Read]
|
Used mem: [DS:0x7FFAC47524E0;UInt64;Read]
|
||||||
00007FFAC46ACDC8 xor rax,rsp
|
00007FFAC46ACDC8 xor rax,rsp
|
||||||
OpCode: REX.W 33 /r
|
OpCode: REX.W 33 /r
|
||||||
Instruction: XOR r64, r/m64
|
Instruction: XOR r64, r/m64
|
||||||
|
@ -597,8 +720,8 @@ static class HowTo_InstructionInfo {
|
||||||
Op1Access: Read
|
Op1Access: Read
|
||||||
Op0: r64_reg
|
Op0: r64_reg
|
||||||
Op1: r64_or_mem
|
Op1: r64_or_mem
|
||||||
RAX:ReadWrite
|
Used reg: RAX:ReadWrite
|
||||||
RSP:Read
|
Used reg: RSP:Read
|
||||||
00007FFAC46ACDCB mov [rbp+0F0h],rax
|
00007FFAC46ACDCB mov [rbp+0F0h],rax
|
||||||
OpCode: REX.W 89 /r
|
OpCode: REX.W 89 /r
|
||||||
Instruction: MOV r/m64, r64
|
Instruction: MOV r/m64, r64
|
||||||
|
@ -613,9 +736,9 @@ static class HowTo_InstructionInfo {
|
||||||
Op1Access: Read
|
Op1Access: Read
|
||||||
Op0: r64_or_mem
|
Op0: r64_or_mem
|
||||||
Op1: r64_reg
|
Op1: r64_reg
|
||||||
RBP:Read
|
Used reg: RBP:Read
|
||||||
RAX:Read
|
Used reg: RAX:Read
|
||||||
[SS:RBP+0xF0;UInt64;Write]
|
Used mem: [SS:RBP+0xF0;UInt64;Write]
|
||||||
00007FFAC46ACDD2 mov r8,[7FFAC474F208h]
|
00007FFAC46ACDD2 mov r8,[7FFAC474F208h]
|
||||||
OpCode: REX.W 8B /r
|
OpCode: REX.W 8B /r
|
||||||
Instruction: MOV r64, r/m64
|
Instruction: MOV r64, r/m64
|
||||||
|
@ -630,8 +753,8 @@ static class HowTo_InstructionInfo {
|
||||||
Op1Access: Read
|
Op1Access: Read
|
||||||
Op0: r64_reg
|
Op0: r64_reg
|
||||||
Op1: r64_or_mem
|
Op1: r64_or_mem
|
||||||
R8:Write
|
Used reg: R8:Write
|
||||||
[DS:0x7FFAC474F208;UInt64;Read]
|
Used mem: [DS:0x7FFAC474F208;UInt64;Read]
|
||||||
00007FFAC46ACDD9 lea rax,[7FFAC46F4A58h]
|
00007FFAC46ACDD9 lea rax,[7FFAC46F4A58h]
|
||||||
OpCode: REX.W 8D /r
|
OpCode: REX.W 8D /r
|
||||||
Instruction: LEA r64, m
|
Instruction: LEA r64, m
|
||||||
|
@ -645,7 +768,7 @@ static class HowTo_InstructionInfo {
|
||||||
Op1Access: NoMemAccess
|
Op1Access: NoMemAccess
|
||||||
Op0: r64_reg
|
Op0: r64_reg
|
||||||
Op1: mem
|
Op1: mem
|
||||||
RAX:Write
|
Used reg: RAX:Write
|
||||||
00007FFAC46ACDE0 xor edi,edi
|
00007FFAC46ACDE0 xor edi,edi
|
||||||
OpCode: o32 33 /r
|
OpCode: o32 33 /r
|
||||||
Instruction: XOR r32, r/m32
|
Instruction: XOR r32, r/m32
|
||||||
|
@ -662,7 +785,7 @@ static class HowTo_InstructionInfo {
|
||||||
Op1Access: None
|
Op1Access: None
|
||||||
Op0: r32_reg
|
Op0: r32_reg
|
||||||
Op1: r32_or_mem
|
Op1: r32_or_mem
|
||||||
RDI:Write
|
Used reg: RDI:Write
|
||||||
*/
|
*/
|
||||||
public static void Example() {
|
public static void Example() {
|
||||||
var codeReader = new ByteArrayCodeReader(exampleCode);
|
var codeReader = new ByteArrayCodeReader(exampleCode);
|
||||||
|
@ -731,9 +854,9 @@ static class HowTo_InstructionInfo {
|
||||||
Console.WriteLine($"{tab}Op{i}: {opCode.GetOpKind(i)}");
|
Console.WriteLine($"{tab}Op{i}: {opCode.GetOpKind(i)}");
|
||||||
// The returned iterator is a struct, nothing is allocated unless you box it
|
// The returned iterator is a struct, nothing is allocated unless you box it
|
||||||
foreach (var regInfo in info.GetUsedRegisters())
|
foreach (var regInfo in info.GetUsedRegisters())
|
||||||
Console.WriteLine($"{tab}{regInfo.ToString()}");
|
Console.WriteLine($"{tab}Used reg: {regInfo.ToString()}");
|
||||||
foreach (var memInfo in info.GetUsedMemory())
|
foreach (var memInfo in info.GetUsedMemory())
|
||||||
Console.WriteLine($"{tab}{memInfo.ToString()}");
|
Console.WriteLine($"{tab}Used mem: {memInfo.ToString()}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue