Skip to content

Commit 752a6f4

Browse files
committed
Change the way return values are obtained from the target process
1 parent e2d38e1 commit 752a6f4

File tree

4 files changed

+36
-16
lines changed

4 files changed

+36
-16
lines changed

src/SharpMonoInjector/Assembler.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ public void AddRsp(byte arg)
5454
_asm.Add(arg);
5555
}
5656

57+
public void MovRaxTo(IntPtr dest)
58+
{
59+
_asm.AddRange(new byte[] { 0x48, 0xA3 });
60+
_asm.AddRange(BitConverter.GetBytes((long)dest));
61+
}
62+
5763
public void Push(IntPtr arg)
5864
{
5965
_asm.Add((int)arg < 128 ? (byte)0x6A : (byte)0x68);
@@ -77,6 +83,12 @@ public void AddEsp(byte arg)
7783
_asm.Add(arg);
7884
}
7985

86+
public void MovEaxTo(IntPtr dest)
87+
{
88+
_asm.Add(0xA3);
89+
_asm.AddRange(BitConverter.GetBytes((int)dest));
90+
}
91+
8092
public void Return()
8193
{
8294
_asm.Add(0xC3);

src/SharpMonoInjector/Injector.cs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,11 @@ private void CloseAssembly(IntPtr assembly)
308308

309309
private IntPtr Execute(IntPtr address, params IntPtr[] args)
310310
{
311-
byte[] code = Assemble(address, args);
311+
IntPtr retValPtr = Is64Bit
312+
? _memory.AllocateAndWrite((long)0)
313+
: _memory.AllocateAndWrite(0);
314+
315+
byte[] code = Assemble(address, retValPtr, args);
312316
IntPtr alloc = _memory.AllocateAndWrite(code);
313317

314318
IntPtr thread = Native.CreateRemoteThread(
@@ -322,23 +326,24 @@ private IntPtr Execute(IntPtr address, params IntPtr[] args)
322326
if (result == WaitResult.WAIT_FAILED)
323327
throw new InjectorException("Failed to wait for a remote thread", new Win32Exception(Marshal.GetLastWin32Error()));
324328

325-
if (!Native.GetExitCodeThread(thread, out IntPtr exitCode))
326-
throw new InjectorException("Failed to get the exit code of a remote thread", new Win32Exception(Marshal.GetLastWin32Error()));
329+
IntPtr ret = Is64Bit
330+
? (IntPtr)_memory.ReadLong(retValPtr)
331+
: (IntPtr)_memory.ReadInt(retValPtr);
327332

328-
if ((long)exitCode == 0x00000000C0000005)
333+
if ((long)ret == 0x00000000C0000005)
329334
throw new InjectorException($"An access violation occurred while executing {Exports.First(e => e.Value == address).Key}()");
330335

331-
return exitCode;
336+
return ret;
332337
}
333338

334-
private byte[] Assemble(IntPtr address, IntPtr[] args)
339+
private byte[] Assemble(IntPtr functionPtr, IntPtr retValPtr, IntPtr[] args)
335340
{
336341
return Is64Bit
337-
? Assemble64(address, args)
338-
: Assemble86(address, args);
342+
? Assemble64(functionPtr, retValPtr, args)
343+
: Assemble86(functionPtr, retValPtr, args);
339344
}
340345

341-
private byte[] Assemble86(IntPtr address, IntPtr[] args)
346+
private byte[] Assemble86(IntPtr functionPtr, IntPtr retValPtr, IntPtr[] args)
342347
{
343348
Assembler asm = new Assembler();
344349

@@ -352,15 +357,16 @@ private byte[] Assemble86(IntPtr address, IntPtr[] args)
352357
for (int i = args.Length - 1; i >= 0; i--)
353358
asm.Push(args[i]);
354359

355-
asm.MovEax(address);
360+
asm.MovEax(functionPtr);
356361
asm.CallEax();
357362
asm.AddEsp((byte)(args.Length * 4));
363+
asm.MovEaxTo(retValPtr);
358364
asm.Return();
359365

360366
return asm.ToByteArray();
361367
}
362368

363-
private byte[] Assemble64(IntPtr address, IntPtr[] args)
369+
private byte[] Assemble64(IntPtr functionPtr, IntPtr retValPtr, IntPtr[] args)
364370
{
365371
Assembler asm = new Assembler();
366372

@@ -372,7 +378,7 @@ private byte[] Assemble64(IntPtr address, IntPtr[] args)
372378
asm.CallRax();
373379
}
374380

375-
asm.MovRax(address);
381+
asm.MovRax(functionPtr);
376382

377383
for (int i = 0; i < args.Length; i++) {
378384
switch (i) {
@@ -393,6 +399,7 @@ private byte[] Assemble64(IntPtr address, IntPtr[] args)
393399

394400
asm.CallRax();
395401
asm.AddRsp(40);
402+
asm.MovRaxTo(retValPtr);
396403
asm.Return();
397404

398405
return asm.ToByteArray();

src/SharpMonoInjector/Memory.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ public int ReadInt(IntPtr address)
4848
return BitConverter.ToInt32(ReadBytes(address, 4), 0);
4949
}
5050

51+
public long ReadLong(IntPtr address)
52+
{
53+
return BitConverter.ToInt64(ReadBytes(address, 8), 0);
54+
}
55+
5156
public byte[] ReadBytes(IntPtr address, int size)
5257
{
5358
byte[] bytes = new byte[size];

src/SharpMonoInjector/Native.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,5 @@ public static class Native
135135

136136
[DllImport("kernel32.dll", SetLastError = true)]
137137
public static extern WaitResult WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);
138-
139-
[DllImport("kernel32.dll", SetLastError = true)]
140-
[return: MarshalAs(UnmanagedType.Bool)]
141-
public static extern bool GetExitCodeThread(IntPtr hThread, out IntPtr lpExitCode);
142138
}
143139
}

0 commit comments

Comments
 (0)