Skip to content

Commit 802cbbb

Browse files
committed
AntiDebug Cleanup
1 parent 1e97b55 commit 802cbbb

12 files changed

+198
-114
lines changed

VMUP/VMUnprotect.Core/Engine.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ public Engine(Context context) {
1414
internal static Context Ctx { get; private set; } = null!;
1515
public static ILogger Logger { get; private set; } = new EmptyLogger();
1616

17+
18+
/// <summary>
19+
/// Prepare assembly to launch
20+
/// </summary>
1721
public void Start() {
1822
var fileEntryPoint = Ctx.VmpAssembly.EntryPoint;
1923
var moduleHandle = Ctx.VmpAssembly.ManifestModule.ModuleHandle;
@@ -34,15 +38,22 @@ public void Start() {
3438
Logger.Info("--- Invoking assembly.\n");
3539
fileEntryPoint.Invoke(null, parameters.Length == 0 ? null : new object[] {new[] {string.Empty}}); // parse arguments from commandlineoptions
3640
}
41+
42+
/// <summary>
43+
/// Apply Harmony Patches
44+
/// </summary>
3745
private static void ApplyHooks() {
3846
try {
3947
HooksManager.HooksApply(Ctx);
4048
}
4149
catch (Exception ex) {
42-
Logger.Error("Failed to apply Harmony patches: {0}", ex.StackTrace);
50+
Logger.Error("Failed to apply Harmony patches: {0}", ex);
4351
}
4452
}
4553

54+
/// <summary>
55+
/// Search for VMProtect Function Handler, etc...
56+
/// </summary>
4657
private void AnalyzeStructure() {
4758
try {
4859
VmAnalyzer.Run(Ctx);

VMUP/VMUnprotect.Core/Hooks/HooksManager.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using HarmonyLib;
22
using System;
3-
using System.Reflection;
43
using VMUnprotect.Core.Abstraction;
54
using VMUnprotect.Core.Hooks.Methods;
65

@@ -37,12 +36,18 @@ internal static void HooksApply(Context ctx) {
3736

3837
// Apply transpiler to the function handler (This is old method not recommended)
3938
ctx.Harmony.Patch(resolvedVmpHandler, transpiler: new HarmonyMethod(transpiler));
40-
}
41-
break;
39+
} break;
4240
case false: {
41+
var runtimeMethodInfoType = AccessTools.TypeByName("System.Reflection.RuntimeMethodInfo");
42+
43+
if (runtimeMethodInfoType is null)
44+
throw new Exception("Failed to find System.Reflection.RuntimeMethodInfo");
45+
4346
// Get method for patch
44-
var invokeMethod = typeof(object).Assembly.GetType("System.Reflection.RuntimeMethodInfo")
45-
.GetMethod("UnsafeInvokeInternal", BindingFlags.NonPublic | BindingFlags.Instance);
47+
var invokeMethod = AccessTools.DeclaredMethod(runtimeMethodInfoType, "UnsafeInvokeInternal");
48+
49+
if (invokeMethod is null)
50+
throw new Exception($"Failed to find {nameof(runtimeMethodInfoType)}.UnsafeInvokeInternal");
4651

4752
// Prepare prefix and postfix
4853
var prefix = typeof(VmProtectDumperUnsafeInvoke).GetMethod(nameof(VmProtectDumperUnsafeInvoke.InvokePrefix));
@@ -51,8 +56,7 @@ internal static void HooksApply(Context ctx) {
5156
// Patch
5257
ctx.Harmony.Patch(invokeMethod, new HarmonyMethod(prefix));
5358
ctx.Harmony.Patch(invokeMethod, postfix: new HarmonyMethod(postfix));
54-
}
55-
break;
59+
} break;
5660
}
5761
}
5862
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using HarmonyLib;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.Linq;
5+
using System.Reflection.Emit;
6+
using VMUnprotect.Core.Abstraction;
7+
8+
namespace VMUnprotect.Core.Hooks.Methods {
9+
[HarmonyPatch(typeof(Debugger), "get_IsAttached")]
10+
public class DebugIsAttachedPatch {
11+
private static ILogger CtxLogger => Engine.Ctx.Logger;
12+
13+
/// <summary>
14+
/// Transpiler overwrites body so we can't just return
15+
/// </summary>
16+
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) {
17+
var codes = new List<CodeInstruction>(instructions) {
18+
new(OpCodes.Ldc_I4_0),
19+
new(OpCodes.Ret)
20+
};
21+
22+
//MessageBox.Show("IsAttached returned false", "IsAttached");
23+
return codes.AsEnumerable();
24+
}
25+
}
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using HarmonyLib;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.Linq;
5+
using System.Reflection.Emit;
6+
using VMUnprotect.Core.Abstraction;
7+
8+
namespace VMUnprotect.Core.Hooks.Methods {
9+
[HarmonyPatch(typeof(Debugger), nameof(Debugger.IsLogging))]
10+
public class DebugIsLoggingPatch {
11+
private static ILogger CtxLogger => Engine.Ctx.Logger;
12+
13+
/// <summary>
14+
/// Transpiler overwrites body so we can't just return
15+
/// </summary>
16+
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) {
17+
var codes = new List<CodeInstruction>(instructions) {
18+
new(OpCodes.Ldc_I4_0),
19+
new(OpCodes.Ret)
20+
};
21+
22+
//MessageBox.Show("IsAttached returned false", "IsAttached");
23+
return codes.AsEnumerable();
24+
}
25+
}
26+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using HarmonyLib;
2+
using System.Reflection;
3+
using VMUnprotect.Core.Abstraction;
4+
5+
namespace VMUnprotect.Core.Hooks.Methods {
6+
/// <summary>
7+
/// Harmony Patch for GetCallingAssembly
8+
/// </summary>
9+
[HarmonyPatch(typeof(Assembly), nameof(Assembly.GetCallingAssembly))]
10+
public class GetCallingAssemblyPatch {
11+
private static ILogger CtxLogger => Engine.Ctx.Logger;
12+
public static void Postfix(ref Assembly __result) {
13+
if (__result != typeof(string).Assembly)
14+
return;
15+
16+
//MessageBox.Show($"Swapped {__result.FullName} | GetCallingAssembly", "GetCallingAssembly");
17+
__result = Engine.Ctx.VmpAssembly;
18+
}
19+
}
20+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using HarmonyLib;
2+
using System.Reflection;
3+
using VMUnprotect.Core.Abstraction;
4+
5+
namespace VMUnprotect.Core.Hooks.Methods {
6+
/// <summary>
7+
/// Harmony Patch for GetEntryAssembly
8+
/// </summary>
9+
[HarmonyPatch(typeof(Assembly), nameof(Assembly.GetEntryAssembly))]
10+
public class GetEntryAssemblyPatch {
11+
private static ILogger CtxLogger => Engine.Ctx.Logger;
12+
13+
public static void Postfix(ref Assembly __result) {
14+
if (__result != typeof(string).Assembly)
15+
return;
16+
17+
//MessageBox.Show($"Swapped {__result.FullName} | GetEntryAssembly", "GetEntryAssembly");
18+
__result = Engine.Ctx.VmpAssembly;
19+
}
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using HarmonyLib;
2+
using System.Reflection;
3+
using VMUnprotect.Core.Abstraction;
4+
5+
namespace VMUnprotect.Core.Hooks.Methods {
6+
/// <summary>
7+
/// Harmony Patch for GetExecutingAssembly
8+
/// </summary>
9+
[HarmonyPatch(typeof(Assembly), nameof(Assembly.GetExecutingAssembly))]
10+
public class GetExecutingAssemblyPatch {
11+
private static ILogger CtxLogger => Engine.Ctx.Logger;
12+
13+
public static void Postfix(ref Assembly __result) {
14+
if (__result != typeof(string).Assembly)
15+
return;
16+
17+
//MessageBox.Show($"Swapped {__result.FullName} | GetExecutingAssembly", "GetExecutingAssembly");
18+
__result = Engine.Ctx.VmpAssembly;
19+
}
20+
}
21+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using System.Linq;
3+
4+
namespace VMUnprotect.Core.Hooks.Methods {
5+
public static class NtQueryInformationProcessPatch {
6+
private static IntPtr _ntQueryInformationProcessPtr = new(0x0);
7+
private static Delegate? NtQueryInformationProcessDelegate { get; set; }
8+
9+
public static void OverwriteProcessInformation(object obj, ref object[] arguments) {
10+
if (!Engine.Ctx.Options.BypassAntiDebug)
11+
return;
12+
13+
/*__kernel_entry NTSTATUS NtQueryInformationProcess(
14+
[in] HANDLE ProcessHandle,
15+
[in] PROCESSINFOCLASS ProcessInformationClass,
16+
[out] PVOID ProcessInformation,
17+
[in] ULONG ProcessInformationLength,
18+
[out, optional] PULONG ReturnLength
19+
);*/
20+
21+
if (obj is not null && obj.Equals(NtQueryInformationProcessDelegate))
22+
arguments[2] = (IntPtr) 0x0; // [out] PVOID ProcessInformation = 0x0
23+
}
24+
25+
public static void GetDelegateForFunctionPointer(object __result, object[] parameters) {
26+
if (!Engine.Ctx.Options.BypassAntiDebug)
27+
return;
28+
29+
// Steal IntPtr
30+
if (parameters.Any(x => x.Equals("NtQueryInformationProcess")))
31+
_ntQueryInformationProcessPtr = (IntPtr) __result;
32+
33+
// Steal Delegate
34+
if (parameters.Any(x => x.Equals(_ntQueryInformationProcessPtr)))
35+
NtQueryInformationProcessDelegate = (Delegate) __result;
36+
}
37+
}
38+
}

VMUP/VMUnprotect.Core/Hooks/Methods/VmProtectBypassAntiDebug.cs

Lines changed: 0 additions & 79 deletions
This file was deleted.

VMUP/VMUnprotect.Core/Hooks/Methods/VmProtectDumperUnsafeInvoke.cs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Diagnostics;
2-
using System.Reflection;
32
using VMUnprotect.Core.Abstraction;
43
using VMUnprotect.Core.MiddleMan;
54

@@ -22,18 +21,14 @@ public static bool InvokePrefix(ref object __result, ref object __instance, ref
2221
if (!isVmpFunction)
2322
return true;
2423

25-
var methodInfo = (MethodInfo) __instance;
26-
27-
// Skip debugging functions
28-
if (!VmProtectBypassAntiDebug.Filter(out __result, obj, arguments, methodInfo))
29-
return false;
24+
// Bypass NtQueryInformationProcess Anti Debug Feature
25+
NtQueryInformationProcessPatch.OverwriteProcessInformation(obj, ref arguments);
3026

3127
CtxLogger.Info("VmProtectDumperUnsafeInvoke Prefix:");
3228
CtxLogger.Warn("{");
3329
return UnsafeInvokeMiddleMan.Prefix(ref __result, ref __instance, ref obj, ref parameters, ref arguments);
3430
}
3531

36-
3732
/// <summary>
3833
/// Postfix of UnsafeInvoke, this runs after.
3934
/// </summary>
@@ -45,8 +40,8 @@ public static void InvokePostfix(ref object __instance, ref object __result, ref
4540
if (!isVmpFunction)
4641
return;
4742

48-
// Find NtQueryInformationProcessDelegate
49-
VmProtectBypassAntiDebug.FindNtQueryInformationProcessDelegate(__result, parameters);
43+
// Steal delegate for NtQueryInformationProcess
44+
NtQueryInformationProcessPatch.GetDelegateForFunctionPointer(__result, parameters);
5045

5146
// Log it
5247
CtxLogger.Info("VmProtectDumperUnsafeInvoke Result:");

0 commit comments

Comments
 (0)