Skip to content

Commit 264157f

Browse files
committed
Refactored Disassembler.
1 parent 5a6ca41 commit 264157f

File tree

6 files changed

+99
-56
lines changed

6 files changed

+99
-56
lines changed

Memory/Disassembler.cs

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Diagnostics.Contracts;
4+
using System.Linq;
45
using System.Runtime.InteropServices;
56
using ReClassNET.Native;
67
using ReClassNET.Util;
@@ -9,43 +10,73 @@ namespace ReClassNET.Memory
910
{
1011
public class Disassembler
1112
{
12-
public List<DisassembledInstruction> DisassembleRemoteCode(RemoteProcess process, IntPtr address, int length)
13+
private readonly NativeHelper nativeHelper;
14+
15+
public Disassembler(NativeHelper nativeHelper)
1316
{
14-
Contract.Requires(process != null);
17+
Contract.Requires(nativeHelper != null);
1518

16-
var instructions = new List<DisassembledInstruction>();
19+
this.nativeHelper = nativeHelper;
20+
}
21+
22+
public List<DisassembledInstruction> RemoteDisassembleCode(RemoteProcess process, IntPtr address, int length)
23+
{
24+
Contract.Requires(process != null);
1725

1826
var buffer = process.ReadRemoteMemory(address, length);
1927

2028
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
2129
try
2230
{
23-
var eip = handle.AddrOfPinnedObject();
24-
var end = eip + length;
25-
var virtualAddress = address;
26-
27-
var instruction = new InstructionData();
28-
while (true)
31+
return DisassembleCode(handle.AddrOfPinnedObject(), length, address).ToList();
32+
}
33+
finally
34+
{
35+
if (handle.IsAllocated)
2936
{
30-
if (!process.NativeHelper.DisassembleCode(eip, end.Sub(eip).ToInt32(), virtualAddress, out instruction))
31-
{
32-
break;
33-
}
37+
handle.Free();
38+
}
39+
}
40+
}
3441

35-
instructions.Add(new DisassembledInstruction
36-
{
37-
Address = virtualAddress,
38-
Length = instruction.Length,
39-
Instruction = instruction.Instruction
40-
});
42+
public IEnumerable<DisassembledInstruction> DisassembleCode(IntPtr address, int length, IntPtr virtualAddress)
43+
{
44+
var instructions = new List<DisassembledInstruction>();
4145

42-
eip = eip + instruction.Length;
43-
if (eip.CompareTo(end) >= 0 || buffer[eip.Sub(handle.AddrOfPinnedObject()).ToInt32()] == 0xCC)
44-
{
45-
break;
46-
}
47-
virtualAddress = virtualAddress + instruction.Length;
46+
var eip = address;
47+
var end = address + length;
48+
49+
var instruction = new InstructionData();
50+
while (eip.CompareTo(end) == -1)
51+
{
52+
if (!nativeHelper.DisassembleCode(eip, end.Sub(eip).ToInt32(), virtualAddress, out instruction))
53+
{
54+
break;
4855
}
56+
57+
yield return new DisassembledInstruction
58+
{
59+
Address = virtualAddress,
60+
Length = instruction.Length,
61+
Data = instruction.Data,
62+
Instruction = instruction.Instruction
63+
};
64+
65+
eip = eip + instruction.Length;
66+
virtualAddress = virtualAddress + instruction.Length;
67+
}
68+
}
69+
70+
public List<DisassembledInstruction> RemoteDisassembleFunction(RemoteProcess process, IntPtr address, int length)
71+
{
72+
Contract.Requires(process != null);
73+
74+
var buffer = process.ReadRemoteMemory(address, length);
75+
76+
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
77+
try
78+
{
79+
return DisassembleFunction(handle.AddrOfPinnedObject(), length, address).ToList();
4980
}
5081
finally
5182
{
@@ -54,8 +85,13 @@ public List<DisassembledInstruction> DisassembleRemoteCode(RemoteProcess process
5485
handle.Free();
5586
}
5687
}
88+
}
5789

58-
return instructions;
90+
public IEnumerable<DisassembledInstruction> DisassembleFunction(IntPtr address, int length, IntPtr virtualAddress)
91+
{
92+
// Read until first CC.
93+
return DisassembleCode(address, length, virtualAddress)
94+
.TakeUntil(i => i.Length == 1 && i.Data[0] == 0xCC);
5995
}
6096

6197
public DisassembledInstruction GetPreviousInstruction(RemoteProcess process, IntPtr address)
@@ -134,6 +170,9 @@ public class DisassembledInstruction
134170
{
135171
public IntPtr Address;
136172
public int Length;
173+
public byte[] Data;
137174
public string Instruction;
175+
176+
public override string ToString() => $"{Address.ToString(Constants.StringHexFormat)} - {Instruction}";
138177
}
139178
}

Native/NativeDataExchange.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ public struct InstructionData
105105
{
106106
public int Length;
107107

108+
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)]
109+
public byte[] Data;
110+
108111
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
109112
public string Instruction;
110113
};
@@ -196,10 +199,16 @@ public struct RegisterInfo
196199
public RegisterInfo Registers;
197200
}
198201

202+
public enum DebugContinueStatus
203+
{
204+
Handled,
205+
NotHandled
206+
}
207+
199208
[StructLayout(LayoutKind.Sequential)]
200209
public struct DebugEventHeader
201210
{
202-
public int ContinueStatus;
211+
public DebugContinueStatus ContinueStatus;
203212

204213
public IntPtr ProcessId;
205214
public IntPtr ThreadId;

NativeHelper/DisassembleCode.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ bool __stdcall DisassembleCode(RC_Pointer address, RC_Size length, RC_Pointer vi
2323
}
2424

2525
instruction->Length = disamLength;
26+
std::memcpy(instruction->Data, address, disamLength);
2627
MultiByteToWideChar(0, 0, disasm.CompleteInstr, -1, instruction->Instruction, 64);
2728

2829
return true;

NativeHelper/ReClassNET_Plugin.hpp

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <type_traits>
4+
#include <cstdint>
45

56
// Types
67

@@ -82,6 +83,12 @@ enum class ControlRemoteProcessAction
8283
Terminate
8384
};
8485

86+
enum DebugContinueStatus
87+
{
88+
Handled,
89+
NotHandled
90+
};
91+
8592
enum class HardwareBreakpointRegister
8693
{
8794
InvalidRegister,
@@ -92,19 +99,19 @@ enum class HardwareBreakpointRegister
9299
Dr3
93100
};
94101

95-
enum class HardwareBreakpointType
102+
enum class HardwareBreakpointTrigger
96103
{
104+
Execute,
97105
Access,
98-
ReadWrite,
99106
Write,
100107
};
101108

102109
enum class HardwareBreakpointSize
103110
{
104-
Size1,
105-
Size2,
106-
Size4,
107-
Size8
111+
Size1 = 1,
112+
Size2 = 2,
113+
Size4 = 4,
114+
Size8 = 8
108115
};
109116

110117
enum class DebugEventType
@@ -118,12 +125,6 @@ enum class DebugEventType
118125
Exception
119126
};
120127

121-
enum class ContinueStatus
122-
{
123-
Continue,
124-
125-
};
126-
127128
// Structures
128129

129130
struct EnumerateProcessData
@@ -135,6 +136,7 @@ struct EnumerateProcessData
135136
struct InstructionData
136137
{
137138
int Length;
139+
uint8_t Data[15];
138140
RC_UnicodeChar Instruction[64];
139141
};
140142

@@ -235,7 +237,7 @@ struct ExceptionDebugInfo
235237

236238
struct DebugEvent
237239
{
238-
ContinueStatus ContinueStatus;
240+
DebugContinueStatus ContinueStatus;
239241

240242
RC_Pointer ProcessId;
241243
RC_Pointer ThreadId;
@@ -287,8 +289,8 @@ typedef bool(__stdcall *DebuggerAttachToProcess_Delegate)(RC_Pointer id);
287289

288290
typedef void(__stdcall *DebuggerDetachFromProcess_Delegate)(RC_Pointer id);
289291

290-
typedef bool(__stdcall *DebuggerWaitForDebugEvent_Delegate)(DebugEvent* info);
292+
typedef bool(__stdcall *DebuggerWaitForDebugEvent_Delegate)(DebugEvent* evt, int timeoutInMilliseconds);
291293

292294
typedef void(__stdcall *DebuggerContinueEvent_Delegate)(DebugEvent* evt);
293295

294-
typedef bool(__stdcall *DebuggerSetHardwareBreakpoint_Delegate)(RC_Pointer processId, RC_Pointer address, HardwareBreakpointRegister reg, HardwareBreakpointType type, HardwareBreakpointSize size, bool set);
296+
typedef bool(__stdcall *DebuggerSetHardwareBreakpoint_Delegate)(RC_Pointer processId, RC_Pointer address, HardwareBreakpointRegister reg, HardwareBreakpointTrigger type, HardwareBreakpointSize size, bool set);

Nodes/BaseFunctionPtrNode.cs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,10 @@ private void DisassembleRemoteCode(MemoryBuffer memory, IntPtr address)
118118

119119
if (!address.IsNull() && memory.Process.IsValid)
120120
{
121-
var disassembler = new Disassembler();
121+
var disassembler = new Disassembler(memory.Process.NativeHelper);
122122
instructions.AddRange(
123-
disassembler.DisassembleRemoteCode(memory.Process, address, 200)
124-
#if WIN64
125-
.Select(i => $"{i.Address.ToString("X08")} {i.Instruction}")
126-
#else
127-
.Select(i => $"{i.Address.ToString("X04")} {i.Instruction}")
128-
#endif
123+
disassembler.RemoteDisassembleFunction(memory.Process, address, 200)
124+
.Select(i => $"{i.Address.ToString(Constants.StringHexFormat)} {i.Instruction}")
129125
);
130126
}
131127
}

Nodes/FunctionNode.cs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,16 +122,12 @@ private void DisassembleRemoteCode(MemoryBuffer memory, IntPtr address)
122122
{
123123
memorySize = 0;
124124

125-
var disassembler = new Disassembler();
126-
foreach (var instruction in disassembler.DisassembleRemoteCode(memory.Process, address, 4096))
125+
var disassembler = new Disassembler(memory.Process.NativeHelper);
126+
foreach (var instruction in disassembler.RemoteDisassembleFunction(memory.Process, address, 4096))
127127
{
128128
memorySize += instruction.Length;
129129

130-
#if WIN64
131-
instructions.Add($"{instruction.Address.ToString("X08")} {instruction.Instruction}");
132-
#else
133-
instructions.Add($"{instruction.Address.ToString("X04")} {instruction.Instruction}");
134-
#endif
130+
instructions.Add($"{instruction.Address.ToString(Constants.StringHexFormat)} {instruction.Instruction}");
135131
}
136132

137133
ParentNode?.ChildHasChanged(this);

0 commit comments

Comments
 (0)