mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-26 07:29:00 -07:00
70 lines
5.0 KiB
C#
70 lines
5.0 KiB
C#
using System.Reflection;
|
|
using System.Collections;
|
|
using System.Reflection.PortableExecutable;
|
|
using Iced.Intel;
|
|
|
|
internal static class NativeInspect
|
|
{
|
|
static object Prop(object o, string n) => o.GetType().GetProperty(n)!.GetValue(o)!;
|
|
static string Label(object m) => m == null ? "<native>" : Prop(Prop(m,"DeclaringType"),"Name") + "::" + Prop(m,"Name");
|
|
public static void Run(Type main, object metadata, string binary, string typeName, string methodName)
|
|
{
|
|
var methods = ((IEnumerable)metadata.GetType().GetField("methodDefs")!.GetValue(metadata)!).Cast<object>()
|
|
.Select(m => (Method:m, Address:(ulong)Prop(m,"MethodPointer"))).Where(m=>m.Address!=0).OrderBy(m=>m.Address).ToArray();
|
|
// An address target (decimal or 0x hex) disassembles that instruction window directly.
|
|
var raw = typeName.Replace("0x", "").Trim();
|
|
if (raw.Length > 4 &&
|
|
(ulong.TryParse(raw, out var fixedAddress) ||
|
|
ulong.TryParse(raw, System.Globalization.NumberStyles.HexNumber, null, out fixedAddress)))
|
|
{
|
|
DisassembleOne(main, metadata, binary, fixedAddress, methods);
|
|
return;
|
|
}
|
|
var bytes=File.ReadAllBytes(binary);
|
|
using var pe=new PEReader(new MemoryStream(bytes));
|
|
ulong imageBase=pe.PEHeaders.PEHeader!.ImageBase;
|
|
int Raw(ulong address) { var rva=address-imageBase; var s=pe.PEHeaders.SectionHeaders.First(s=>rva>=(ulong)s.VirtualAddress && rva<(ulong)(s.VirtualAddress+s.SizeOfRawData)); return (int)(rva-(ulong)s.VirtualAddress)+s.PointerToRawData; }
|
|
object Nearest(ulong address) => methods.LastOrDefault(m=>m.Address<=address).Method;
|
|
foreach(var item in methods.Where(m=>Prop(Prop(m.Method,"DeclaringType"),"Name").ToString()==typeName && (methodName=="" || Prop(m.Method,"Name").ToString()==methodName)))
|
|
{
|
|
Console.WriteLine($"\nMETHOD {Label(item.Method)} 0x{item.Address:X}");
|
|
Emit(main, pe, imageBase, bytes, Raw, Nearest, methods, item.Address);
|
|
}
|
|
}
|
|
|
|
static void DisassembleOne(Type main, object metadata, string binary, ulong address, (object Method, ulong Address)[] methods)
|
|
{
|
|
var bytes=File.ReadAllBytes(binary);
|
|
using var pe=new PEReader(new MemoryStream(bytes));
|
|
ulong imageBase=pe.PEHeaders.PEHeader!.ImageBase;
|
|
int Raw(ulong address) { var rva=address-imageBase; var s=pe.PEHeaders.SectionHeaders.First(s=>rva>=(ulong)s.VirtualAddress && rva<(ulong)(s.VirtualAddress+s.SizeOfRawData)); return (int)(rva-(ulong)s.VirtualAddress)+s.PointerToRawData; }
|
|
object Nearest(ulong address) => methods.LastOrDefault(m=>m.Address<=address).Method;
|
|
Console.WriteLine($"\nMETHOD {Label(Nearest(address))}+0x{address - (Nearest(address)!=null ? (ulong)Prop(Nearest(address),"MethodPointer") : 0):X} 0x{address:X}");
|
|
Emit(main, pe, imageBase, bytes, Raw, Nearest, methods, address);
|
|
}
|
|
|
|
static void Emit(Type main, PEReader pe, ulong imageBase, byte[] bytes, Func<ulong,int> Raw, Func<ulong,object> Nearest,
|
|
(object Method, ulong Address)[] methods, ulong start)
|
|
{
|
|
var item = (Method: Nearest(start), Address: start);
|
|
foreach(var section in pe.PEHeaders.SectionHeaders.Where(s=>(s.SectionCharacteristics & SectionCharacteristics.MemExecute)!=0))
|
|
for(int i=section.PointerToRawData;i<section.PointerToRawData+section.SizeOfRawData-5;i++)
|
|
if(bytes[i]==0xE8 && (ulong)((long)imageBase+section.VirtualAddress+i-section.PointerToRawData+5+BitConverter.ToInt32(bytes,i+1))==item.Address)
|
|
{ ulong addr=imageBase+(ulong)(section.VirtualAddress+i-section.PointerToRawData); Console.WriteLine($"CALLER 0x{addr:X} {Label(Nearest(addr))}"); }
|
|
var decoder=Decoder.Create(64,new ByteArrayCodeReader(bytes,Raw(item.Address),Math.Min(10000,bytes.Length-Raw(item.Address)))); decoder.IP=item.Address;
|
|
var formatter=new IntelFormatter(); var output=new LineOutput();
|
|
var next = methods.FirstOrDefault(m => m.Address > item.Address).Address;
|
|
for(int i=0;i<1500 && (next == 0 || decoder.IP < next);i++)
|
|
{
|
|
decoder.Decode(out var instruction); output.Value=""; formatter.Format(instruction,output);
|
|
string note="";
|
|
if(instruction.FlowControl==FlowControl.Call && instruction.Op0Kind==OpKind.NearBranch64)
|
|
{ var called=Nearest(instruction.NearBranchTarget); if(called!=null && (ulong)Prop(called,"MethodPointer")==instruction.NearBranchTarget) note=" ; "+Label(called); }
|
|
if(instruction.IsIPRelativeMemoryOperand)
|
|
{ try { var literal=main.GetMethod("GetLiteralByAddress")!.Invoke(null,new object[]{instruction.IPRelativeMemoryAddress}); if(literal!=null) note+=" ; literal: "+literal; } catch {} }
|
|
Console.WriteLine($"{instruction.IP:X}: {output.Value}{note}");
|
|
}
|
|
}
|
|
sealed class LineOutput:FormatterOutput { public string Value=""; public override void Write(string text,FormatterTextKind kind)=>Value+=text; }
|
|
}
|