Skip to content

Commit 828e590

Browse files
committed
VmProtectDumperUnsafeInvoke Update
Added VmProtectDumperUnsafeInvoke method, prepare for future updates. Thanks, https://github.com/Washi1337
1 parent 277c620 commit 828e590

20 files changed

+336
-100
lines changed
File renamed without changes.

Images/showcase.gif

1.39 MB
Loading
File renamed without changes.

README.md

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<p align="center">
2-
<img width="256" heigth="256" src="VMUP/media/vmup.png">
2+
<img width="256" heigth="256" src="Images/vmup.png">
33
<h1 align="center">VMUnprotect.NET</h1>
44
<p align="center">
55
<strong>VMUnprotect</strong> is a project engaged in hunting virtualized <a href="https://vmpsoft.com">VMProtect</a> methods. It makes use of <a href="https://github.com/pardeike/Harmony">Harmony</a> to dynamically read <strong>VMP</strong> behavior. Currently only supports method administration. Works on <a href="https://vmpsoft.com/20210919/vmprotect-3-5-1/">VMProtect 3.5.1</a> (Latest) and few versions back.
@@ -12,11 +12,15 @@
1212
</p>
1313

1414
## Showcase
15-
<img src="VMUP/media/gif.gif">
15+
<img src="Images/showcase.gif">
1616

1717
# Usage
1818
```sh
19-
VMUnprotect.exe <path to assembly> [args to assembly]
19+
VMUnprotect.exe
20+
-f, --file Required. Path to file.
21+
--usetranspiler (Default: false) Use an older method that makes use of Transpiler (not recommended).
22+
--help Display this help screen.
23+
--version Display version information.
2024
```
2125

2226
# Supported Protections
@@ -32,61 +36,51 @@ Virtualization Tools | Yes
3236
Strip Debug Information | Yes
3337
Pack the Output File | No
3438

35-
# Usage can be found in ```MiddleMan.cs```
39+
# Usage can be found in ```Methods\MiddleMan.cs```
3640
```csharp
37-
namespace VMUnprotect
38-
{
39-
/// <summary>
40-
/// Works as Middle Man to make life easier
41-
/// </summary>
42-
internal static class MiddleMan
41+
internal static class MiddleMan
4342
{
44-
/// <summary>
45-
/// This function manipulate can manipulate, log actual invokes from virtualized VMP functions.
46-
/// </summary>
47-
public static object VmpMethodLogger(object obj, BindingFlags? bindingFlags, Binder binder, ref object[] parameters, CultureInfo culture, MethodBase methodBase)
43+
public static void Prefix(ref object __instance, ref object obj, ref object[] parameters, ref object[] arguments)
4844
{
49-
// Invoke the method and get return value.
50-
var returnValue = methodBase.Invoke(obj, parameters);
45+
var virtualizedMethodName = new StackTrace().GetFrame(7).GetMethod();
46+
var method = (MethodBase) __instance;
5147

52-
// TODO: Add option to disable this because can cause bugs and can be broken easily
53-
var trace = new StackTrace();
54-
var frame = trace.GetFrame(5); // <--
55-
var method = frame.GetMethod();
56-
57-
if (method.IsConstructor)
58-
ConsoleLogger.Warn($"VMP Method (Constructor) {method.FullDescription()}");
59-
60-
ConsoleLogger.Warn($"VMP Method: {method.FullDescription()}");
61-
62-
ConsoleLogger.Warn("MethodName: {0}", methodBase.Name);
63-
ConsoleLogger.Warn("FullDescription: {0}", methodBase.FullDescription());
64-
ConsoleLogger.Warn("MethodType: {0}", methodBase.GetType());
65-
if (obj != null) ConsoleLogger.Warn("obj: {0}", obj.GetType());
48+
ConsoleLogger.Warn("\tVMP MethodName: {0} (MDToken {1:X4})", virtualizedMethodName.FullDescription(), virtualizedMethodName.MetadataToken.ToString());
49+
ConsoleLogger.Warn("\tMethodName: {0}", method.Name);
50+
ConsoleLogger.Warn("\tFullDescription: {0}", method.FullDescription());
51+
ConsoleLogger.Warn("\tMethodType: {0}", method.GetType());
52+
if (obj != null) ConsoleLogger.Warn("\nObj: {0}", obj.GetType());
6653

6754
// Loop through parameters and log them
6855
for (var i = 0; i < parameters.Length; i++)
6956
{
70-
var parameter = parameters[i];
71-
ConsoleLogger.Warn("Parameter ({1}) [{0}]: ({2})", i, parameter.GetType(), parameter);
57+
var parameter = parameters[i] ?? "null";
58+
ConsoleLogger.Warn("\tParameter ({1}) [{0}]: ({2})", i, parameter.GetType(), parameter);
7259
}
7360

74-
ConsoleLogger.Warn("MDToken: {0}", methodBase.MetadataToken);
75-
ConsoleLogger.Warn("Returns: {0}", returnValue);
76-
77-
if (returnValue != null)
78-
ConsoleLogger.Warn("Return type: {0}\n", returnValue.GetType());
61+
var returnType = method is MethodInfo info ? info.ReturnType.FullName : "System.Object";
62+
ConsoleLogger.Warn("\tMDToken: 0x{0:X4}", method.MetadataToken);
63+
ConsoleLogger.Warn("\tReturn Type: {0}", returnType);
64+
}
7965

80-
return returnValue;
66+
public static void Postfix(ref object __instance, ref object __result, ref object obj, ref object[] parameters, ref object[] arguments)
67+
{
68+
ConsoleLogger.Warn("\tReturns: {0}", __result);
8169
}
8270
}
83-
}
8471
```
8572

8673
## Current Features
8774
- Tracing invokes in virtualized methods.
8875
- Manipulating parameters and return values.
8976

77+
## Todo
78+
- Change this to support more VM's
79+
- VMP Stack tracing
80+
- Bypass VMP Debugger Detection
81+
- Bypass VMP CRC Check
82+
- Nice WPF GUI
83+
9084
# FAQ
9185
### What is code virtualization?
9286
As VMProtect describes it on their's website. Code virtualization is the next step in software protection. Most protection systems encrypt the code and then decrypt it at the application’s startup. VMProtect doesn’t decrypt the code at all! Instead, the encrypted code runs on a virtual CPU that is markedly different from generic x86 and x64 CPUs as the command set is different for each protected file.
@@ -95,7 +89,13 @@ As VMProtect describes it on their's website. Code virtualization is the next st
9589
No, isn't even meant for devirtualization.
9690

9791
# Credits
92+
* [Washi](https://github.com/Washi1337) Overall credits for the project and inspiration with UnsafeInvokeInternal, thanks <3
93+
9894
This tool uses the following (open source) software:
9995
* [dnlib](https://github.com/0xd4d/dnlib) by [0xd4d](https://github.com/0xd4d), licensed under the MIT license, for reading/writing assemblies.
100-
* [Harmony](https://github.com/pardeike/Harmony) by [Andreas Pardeike](https://github.com/pardeike), licensed under the MIT license, for patching the stacktrace which allows for reflection invocation to be used.
96+
* [Harmony](https://github.com/pardeike/Harmony) by [Andreas Pardeike](https://github.com/pardeike), licensed under the MIT license
10197
* [Serilog](https://github.com/serilog/serilog) provides diagnostic logging to files, the console, and elsewhere. It is easy to set up, has a clean API.
98+
99+
100+
## Want to support this project?
101+
BTC: bc1q048wrqztka5x2syt9mtj68uuf73vqry60s38vf
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using CommandLine;
2+
3+
namespace VMUnprotect
4+
{
5+
public class CommandLineOptions
6+
{
7+
[Option('f', "file", HelpText = "Path to file.", Required = true)]
8+
public string FilePath { get; set; }
9+
10+
[Option(Default = false, HelpText = "Use an older method that makes use of Transpiler (not recommended).", Required = false)]
11+
public bool UseTranspiler { get; set; }
12+
}
13+
}
Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
using HarmonyLib;
1+
using dnlib.DotNet;
2+
using HarmonyLib;
23
using System;
34
using System.Reflection;
45
using VMUnprotect.Hooks.Methods;
6+
using VMUnprotect.Init;
57
using VMUnprotect.Utils;
68

79
namespace VMUnprotect.Hooks
@@ -14,31 +16,61 @@ public static class HooksManager
1416
// Harmony instance
1517
private static Harmony Harmony { get; set; }
1618

19+
public static MDToken FunctionHandlerToken
20+
{
21+
get;
22+
private set;
23+
}
24+
1725
/// <summary>
1826
/// Applies Harmony patches to VMP functions.
1927
/// </summary>
2028
/// <param name="runtimeStructure">Structure of VMP Runtime</param>
21-
internal static void HooksApply(VmRuntimeStructure runtimeStructure)
29+
/// <param name="options">Options</param>
30+
internal static void HooksApply(VmRuntimeStructure runtimeStructure, CommandLineOptions options)
2231
{
2332
// Enable Harmony Debug file.
2433
Harmony.DEBUG = true;
2534

2635
Harmony = new Harmony("com.hussaryyn.vmup");
27-
Harmony.PatchAll(typeof(Loader).Assembly);
36+
Harmony.PatchAll();
2837

2938
// Check if functionHandler was found.
3039
if (runtimeStructure.FunctionHandler is null)
3140
throw new ArgumentException("Could not locate Function Handler.");
3241

42+
// Save VMP Function Handler MDToken for check
43+
FunctionHandlerToken = runtimeStructure.FunctionHandler.MDToken;
44+
3345
// resolve method.
34-
var mdToken = runtimeStructure.FunctionHandler.MDToken.ToInt32();
35-
var resolvedVmpHandler = Loader.VmpAssembly.ManifestModule.ResolveMethod(mdToken);
46+
ConsoleLogger.Debug("Found VMPFunctionHandler, MDToken 0x{0:X4}", FunctionHandlerToken.ToInt32());
47+
48+
if (options.UseTranspiler)
49+
{
50+
// Resolve VMP Method Handler
51+
var resolvedVmpHandler = Loader.VmpAssembly.ManifestModule.ResolveMethod(FunctionHandlerToken.ToInt32());
52+
53+
// Prepare Transpiler
54+
var transpiler = typeof(VmProtectDumperTranspiler).GetMethod(nameof(VmProtectDumperTranspiler.Transpiler));
55+
ConsoleLogger.Debug("Applying Transpiler and replacing Invokes.");
56+
57+
// Apply transpiler to the function handler (This is old method not recommended)
58+
Harmony.Patch(resolvedVmpHandler, transpiler: new HarmonyMethod(transpiler));
59+
}
60+
else
61+
{
62+
// Get method for patch
63+
var invokeMethod = typeof(object).Assembly.GetType("System.Reflection.RuntimeMethodInfo")
64+
.GetMethod("UnsafeInvokeInternal", BindingFlags.NonPublic | BindingFlags.Instance);
3665

37-
ConsoleLogger.Debug("Found VMPFunctionHandler, MDToken {0}", mdToken);
38-
ConsoleLogger.Debug("Applying Transpiler and replacing Invokes.");
66+
// Prepare prefix and postfix
67+
var prefix = typeof(VmProtectDumperUnsafeInvoke).GetMethod(nameof(VmProtectDumperUnsafeInvoke.InvokePrefix));
68+
var postfix = typeof(VmProtectDumperUnsafeInvoke).GetMethod(nameof(VmProtectDumperUnsafeInvoke.InvokePostfix));
3969

40-
// Apply transpiler to the function handler.
41-
Harmony.Patch(resolvedVmpHandler, transpiler: new HarmonyMethod(typeof(VmProtectDumper).GetMethod(nameof(VmProtectDumper.Transpiler), (BindingFlags) (-1))));
70+
// Patch
71+
Harmony.Patch(invokeMethod, new HarmonyMethod(prefix));
72+
Harmony.Patch(invokeMethod, postfix: new HarmonyMethod(postfix));
73+
}
4274
}
4375
}
4476
}

VMUP/VMUnprotect/Hooks/Methods/GetCallingAssemblyPatch.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using HarmonyLib;
22
using System.Reflection;
3+
using VMUnprotect.Init;
34
using VMUnprotect.Utils;
45

56
namespace VMUnprotect.Hooks.Methods
@@ -8,7 +9,7 @@ namespace VMUnprotect.Hooks.Methods
89
/// Harmony Patch for GetCallingAssembly
910
/// </summary>
1011
[HarmonyPatch(typeof(Assembly))]
11-
[HarmonyPatch("GetCallingAssembly")]
12+
[HarmonyPatch(nameof(Assembly.GetCallingAssembly))]
1213
public class GetCallingAssemblyPatch
1314
{
1415
public static void Postfix(ref Assembly __result)

VMUP/VMUnprotect/Hooks/Methods/GetEntryAssemblyPatch.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using HarmonyLib;
22
using System.Reflection;
3+
using VMUnprotect.Init;
34
using VMUnprotect.Utils;
45

56
namespace VMUnprotect.Hooks.Methods
@@ -8,7 +9,7 @@ namespace VMUnprotect.Hooks.Methods
89
/// Harmony Patch for GetEntryAssembly
910
/// </summary>
1011
[HarmonyPatch(typeof(Assembly))]
11-
[HarmonyPatch("GetEntryAssembly")]
12+
[HarmonyPatch(nameof(Assembly.GetEntryAssembly))]
1213
public class GetEntryAssemblyPatch
1314
{
1415
public static void Postfix(ref Assembly __result)

0 commit comments

Comments
 (0)