• Stars
    star
    290
  • Rank 142,981 (Top 3 %)
  • Language
    C#
  • License
    MIT License
  • Created about 8 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

.NET Patcher library using dnlib

dnpatch

[WIP] .NET Patcher library using dnlib.

If you have questions feel free to ask me via Gitter! I'm glad to help you out! Taking feature requests!

Build status Github All Releases Join the chat at https://gitter.im/dnpatch/Lobby

IMPORTANT

The master branch provides you the current stable build of dnpatch. However, I will most likely not provide support for it anymore since version 1.0 is on it's way in the v1 branch.

What is dnpatch?

dnpatch is the ultimate library for all your .NET patching needs. It offers automated assembly patching, signature scanning and last but but not least bypassing of obfuscators by its ability to find methods in renamed/obfuscated types. Since the stars on GitHub exploded in a few days, dnpatch has been extended by a couple of projects. The most important one is dnpatch.deobfuscation which integrates de4dot directly into dnpatch. Also there is dnpatch.script, which gives you the ability to write patchers with pure JSON! The library itself uses dnlib (see next part).

Notes

Since dnpatch uses dnlib, it is highly recommended to use dnSpy to analyze your assemblies first, to ensure that you use the correct names, offsets, etc, because it uses dnlib aswell.

Recommendations

It is highly recommended that you calculate the instruction's index instead of defining it, to improve the likelihood of compatibility with future updates.

Patching

The constructor takes the filename of the assembly.

Patcher patcher = new Patcher("Test.exe");

If you want to keep the old maxstack (for example for obfuscated assemblies) use the overload:

Patcher patcher = new Patcher("Test.exe", true);

Targeting Methods

All methods take an object called Target as an argument. The object is defined as follows:

public string Namespace { get; set; } // needed
public string Class { get; set; } // needed
public string Method { get; set; } // needed

/* If you want to patch multiple indexes in the method */
public int[] Indexes { get; set; }
public Instruction[] Instructions { get; set; }

/* If you want to patch 1 index in the method */
public int Index { get; set; } = -1;
public Instruction Instruction { get; set; }

/* If the path to the method has more than 1 nested class use this */
public string[] NestedClasses { get; set; }

/* If the path to the method has 1 nested class use this */
public string NestedClass { get; set; }

/* If you want to set the parameters for the method (if it's overloaded) use this */
public string[] Parameters { get; set; }

/* If you want to set the return type for the method use this */
public string ReturnType { get; set; }

/* If you want to rewrite the getters or setters of a property use this */
public string Property { get; set; } // The name
public PropertyMethod PropertyMethod { get; set; } // See below, determines patch target

ReturnType and Parameters are case sensitive! Example:

  • String[]
  • Int32
  • etc

PropertyMethod is defined as this:

public enum PropertyMethod
{
	Get,
	Set
}

Please make sure that you don't assign inconsistent values, e.g.

var target = new Target
{
    Instructions = ...
    Instruction = ...
}

If you want to patch multiple methods create a Target[] and pass it to the functions, it is accepted by the most of them.

Creating Instructions

Reference dnlib and create an Instruction[] or Instruction with your Instruction(s), then assign assign indexes where the Instructions are.You can find them by reverse engineering your assembly via dnSpy or any other decompiler.

Small Example:

Instruction[] opCodes = {
    Instruction.Create(OpCodes.Ldstr, "Hello Sir 1"),
    Instruction.Create(OpCodes.Ldstr, "Hello Sir 2")
};
int[] indexes = {
    0, // index of Instruction
    2
};
Target target = new Target()
{
    Namespace = "Test",
    Class = "Program",
    Method = "Print",
    Instructions = opCodes,
    Indexes = indexes
};

Patch the whole methodbody

To clear the whole methodbody and write your instructions, make sure that you don't assign the Indexes or Index property.

Here is an example:

Instruction[] opCodes = {
    Instruction.Create(OpCodes.Ldstr, "Hello Sir"),
    Instruction.Create(OpCodes.Call, p.BuildCall(typeof(Console), "WriteLine", typeof(void), new[] { typeof(string) })),
    Instruction.Create(OpCodes.Ret)
};
Target target = new Target()
{
    Namespace = "Test",
    Class = "Program",
    Method = "Print",
    Instructions = opCodes
};

Apply the patch

To apply your modified instructions you can call the method 'Patch':

patcher.Patch(Target);

or

patcher.Patch(Target[]);

Finding an instruction

In some cases, it might be useful to find an instruction within a method, for example if the method was updated.

Instruction opCode = Instruction.Create(OpCodes.Ldstr, "TheTrain");
Instruction toFind = Instruction.Create(OpCodes.Ldstr, "TheWord");
Target target = new Target()
{
    Namespace = "Test",
    Class = "Program",
    Method = "FindMe",
    Instruction = opCode // you can also set it later
};
target.Index = p.FindInstruction(target, toFind);
// now you have the full Target object

Let's say there are multiple identical instructions. What now, baoss? Well, it's simple. There's an overload that takes an int which is the occurence of the instruction which you'd like to find.

Instruction opCode = Instruction.Create(OpCodes.Ldstr, "TheTrain");
Instruction toFind = Instruction.Create(OpCodes.Ldstr, "TheWord");
Target target = new Target()
{
    Namespace = "Test",
    Class = "Program",
    Method = "FindMe",
    Instruction = opCode // you can also set it later
};
target.Index = p.FindInstruction(target, toFind, 2); // Sir, find the second occurence!

Finding methods by OpCode signature

You can find methods (Target[]) by scanning their body for an OpCode signature

OpCode[] codes = new OpCode[] {
	OpCodes.Ldstr,
	OpCodes.Call
};
var result = p.FindMethodsByOpCodeSignature(codes); // holds Target[]

Replacing instructions

In some cases it might be easier to just replace an instruction. At this point of development, it doesn't make much sense, but the features will come soon.

Instruction opCode = Instruction.Create(OpCodes.Ldstr, "I love kittens");
Target target = new Target()
{
    Namespace = "Test",
    Class = "Program",
    Method = "ReplaceMe",
    Instruction = opCode,
    Index = 0
};
p.ReplaceInstruction(target);

Removing instructions

Let's say you want to remove instructions... Well it's simple as this:

Target target = new Target()
{
    Namespace = "Test",
    Class = "Program",
    Method = "RemoveMe",
    Indexes = new[]{0,1} // the indexes, you can also just use 'Index'
};
p.RemoveInstruction(target);

Patching operands

Hmmm.... What if you find the console output offending? You can modify the Ldstr without even creating an instruction :)

Target target = new Target()
{
    Namespace = "Test",
    Class = "Program",
    Method = "PrintAlot",
    Index = 0
};
p.PatchOperand(target, "PatchedOperand"); // pass the Target and a string to replace

or incase you need to modify an int:

p.PatchOperand(target, 1337);

It is also able to patch multiple operands in the same method by using int[] or string[].

Returning true/false

If you want to overwrite the methodbody with a return true/false statement you can do this:

target = new Target()
{
    Namespace = "Test",
    Class = "Program",
    Method = "VerifyMe"
};
p.WriteReturnBody(target, bool); // bool represents the return value

Clearing methodbodies

If you just want to empty a methodbody, use this amigo:

target = new Target()
{
    Namespace = "Test",
    Class = "Program",
    Method = "WriteLog"
};
p.WriteEmptyBody(target);

Getting instructions from target

Simply do this if you want to get instructions of the Target object:

target = new Target()
{
    Namespace = "Test",
    Class = "Program",
    Method = "WriteLog"
};
Instruction[] instructions = p.GetInstructions(target);

Writing return bodies

If you want to overwrite the body with a return true/false do this:

target = new Target()
{
    Namespace = "Test",
    Class = "Program",
    Method = "WriteLog"
};
p.WriteReturnBody(target, bool);
// bool is the return value, e.g. true will return true ;)

If you want to remove the body simply call this:

target = new Target()
{
    Namespace = "Test",
    Class = "Program",
    Method = "WriteLog"
};
p.WriteEmptyBody(target);

Find methods

If you want to find a method, you can simply scan the whole file by 2 ways:

p.FindInstructionsByOperand(string[]);
// or p.FindInstructionsByOperand(int[]);
// string[] with all operands in the method, if there are multiple identical operands, make sure to have the same amount as in the method.

// or do this via opcodes:
p.FindInstructionsByOpcode(OpCode[]);

Both ways return an Target[] which contains all targets pointing to the findings.

Find instructions in methods or classes

If you want to find the instructions and you know the class (and optionally the method), you can let this method return a Target[] with the pathes and indexes.

p.FindInstructionsByOperand(Target,int[],bool);
// int[]: the operands
// bool: if true it will search for the operands once, it will delete the index if the index was found

// for opcodes:
p.FindInstructionsByOpcode(Target,int[],bool);

Patch properties

Now you can rewrite a property's getter and setter like this:

target = new Target()
{
	Namespace = "Test",
	Class = "Program",
	Property = "IsPremium", // Property name
	PropertyMethod = PropertyMethod.Get, // Getter or Setter
	Instructions = new []
	{
		Instruction.Create(OpCodes.Ldc_I4_1),
		Instruction.Create(OpCodes.Ret)  
	} // the new instructions
};
p.RewriteProperty(target); // Will overwrite it with return true in getter

The property called 'Property' holds the name of the target property.
PropertyMethod can be 'PropertyMethod.Get' or 'PropertyMethod.Set'.
Instructions are the new Instructions for the getter or setter.

Building calls

To build calls like "Console.WriteLine(string)" you can use this method:

p.BuildCall(typeof(Console), "WriteLine", typeof(void), new[] { typeof(string) })
/* 
 * Type -> type, a Type instance
 * string -> method, the name of the method
 * Type -> returnType, a Type instance of the return value
 * Type[] -> parameters, an array with the parameter's Types
 */

Here is an IL example for Console.WriteLine:

Patcher p = new Patcher("Test.exe");
Instruction[] opcodesConsoleWriteLine = {
    Instruction.Create(OpCodes.Ldstr, "Hello Sir"), // String to print
    Instruction.Create(OpCodes.Call, p.BuildCall(typeof(Console), "WriteLine", typeof(void), new[] { typeof(string) })), // Console.WriteLine call
    Instruction.Create(OpCodes.Ret) // Always return smth
};
Target target = new Target()
{
    Namespace = "Test",
    Class = "Program",
    Method = "Print",
    Instructions = opcodesConsoleWriteLine
};
p.Patch(target);
p.Save("Test1.exe");

Injecting methods (Untested)

If you want to inject methods into classes, call InjectMethod. Make sure to set MethodDef and Instructions. Optionally set Locals, ParameterDefs.

Target target = new Target();
MethodImplAttributes methImplFlags = MethodImplAttributes.IL | MethodImplAttributes.Managed;
MethodAttributes methFlags = MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot;
MethodDef meth1 = new MethodDefUser("MyMethod",
            MethodSig.CreateStatic(mod.CorLibTypes.Int32, mod.CorLibTypes.Int32, mod.CorLibTypes.Int32),
            methImplFlags, methFlags);
target.ParameterDefs = new[] { new ParamDefUser("a", 1) };
target.Locals = new[] { new Local(mod.CorLibTypes.Int32) };
target.MethodDef = meth1;
target.Class = "";
// ... target as always...
patcher.InjectMethod(target);

For now refer to this page: https://github.com/0xd4d/dnlib/blob/master/Examples/Example2.cs

Saving the patched assembly

If you want to save the assembly under a different name use this:

patcher.Save(String); // filename here

Or if you want to replace the original file:

patcher.Save(bool); // if true it will create a backup first (filename.bak)

Deobfuscation [BETA]

Baoss, what can I do if it's heavily obfuscated?! Well, listen careful to your grandpa Joe. Use 'dnpatch.deobfuscation'! It has magic powers! Nah, Joe is just kiddin', it uses the de4dot libraries. Reference the library dnpatch.deobfuscation and make sure that you also copy all others from the zip! Then do this:

Deobfuscation d = new Deobfuscation(string, string);
// string 1 -> file to deobfuscate
// string 2 -> new filename for the deobfuscated file
d.Deobfuscate(); // Deobfuscates the file and writes it to the disk

Scripting

With dnpatch.script you're now able to script patchers with JSON! Example JSON:

{
    "target":"Test.exe",
    "targets":[{
        "ns":"Test",
        "cl":"Program",
        "me":"ReplaceMe",
        "ac":"replace",
        "index":0,
        "instructions":[{
            "opcode":"ldstr",
            "operand":"script working"
        }]
    },{
        "ns":"Test",
        "cl":"Program",
        "me":"RemoveMe",
        "ac":"empty"
    }]
}

Name this file script.json and place it into TestScript build folder and use it with Test.exe. For more info please refer to the standalone repo.

Credits

I'd like to thank these people:

  • 0xd4d for creating dnlib
  • 0xd4d for creating de4dot
  • Rottweiler for the PRs and help!
  • 0megaD for the fixes which my eyes missed and for using dnpatch in his projects!
  • DivideREiS for fixing my typos and getting my lazy ass back to work on the BuildMemberRef/BuildCall method!

More Repositories

1

idacode

An integration for IDA and VS Code which connects both to easily execute and debug IDAPython scripts.
Python
602
star
2

CVE-2020-16938

Bypassing NTFS permissions to read any files as unprivileged user.
C++
183
star
3

ceload

Loading dbk64.sys and grabbing a handle to it
C++
127
star
4

long_night

A collection of themes based on pastel colors, created for reverse engineers
CSS
115
star
5

vacation3-emu

VAC3 module emulator
C
87
star
6

llvm8

Statically recompiling CHIP8 to Windows and macOS using LLVM
C++
85
star
7

BlueGate

PoC for the Remote Desktop Gateway vulnerability - CVE-2020-0609 & CVE-2020-0610
Python
76
star
8

awesome-ui

A curated list of awesome UI libraries, frameworks & guidelines
65
star
9

SMBGhost

Scanner for CVE-2020-0796 - A SMBv3.1.1 + SMB compression RCE
Python
57
star
10

beeless

BeeByte Deobfuscator. Used it to deobfuscate an Unity3D Game. Alternatively, de4dot works aswell.
C#
44
star
11

kdbg-driver-vagrant

Batchfile
42
star
12

JodelAPI

API-Wrapper for the Jodel app in .NET
C#
36
star
13

dbgmon

Allows you to parse all messages sent to DbgPrint without any process interaction.
C++
29
star
14

pooldump

C++
28
star
15

dlsym_hook

Instrumenting a binary without source code to bypass anti-debug checks
C++
27
star
16

Curveball

PoC for CVE-2020-0601 - CryptoAPI exploit
C
21
star
17

RACEAC

Bypassing EAC integrity checks by abusing a TOCTOU in Dead by Daylight.
C++
21
star
18

dnpatch.script

dnpatch script engine stand alone
C#
16
star
19

kdbg-driver-workstation

Batchfile
14
star
20

rapid-kdbg-hyperv

13
star
21

master-duel

Python
13
star
22

SteamManifestFixer

Patches Steam to download depot files without manifest data.
C++
13
star
23

FallGuys

FallGuys cheat that used internal functions present in one of the first published releases of the game. Includes speed hacks and no-stun.
C++
12
star
24

DeadByDaylight

Dead by Daylight utilities created while researching
C++
11
star
25

excusemewtf

Our team's CTF writeups
Jupyter Notebook
11
star
26

rw

allowing um r/w through km from um ioctl β„’
C++
11
star
27

dnSpy.dnpatch

dnpatch plugin for dnSpy!
C#
8
star
28

GitSpector

Desktop application to monitor Git repos and their build statuses, built with the power of Electron.
JavaScript
8
star
29

MaterialMessageBox

Custom QMessageBox/MessageDialog in QML for Qt Quick Controls 2.0
QML
7
star
30

hidenseek

Playing hide and seek in kernel mode.
C
7
star
31

Maze

C++
6
star
32

Wingman

The pluginbased Postman in C#
C#
5
star
33

NeptuneCI

Fast Continuous Integration Solution for GitHub
JavaScript
5
star
34

Switcheroo

Steam account switcher
C++
5
star
35

windows-driver-boilerplate-rs

pasted driver boilerplate
Rust
5
star
36

cve-info

Fetches information given a CVE
TypeScript
5
star
37

NETCompile

A library with functions to easily compile .NET apps/libs!
C#
5
star
38

snesutilities

SNES Rom extraction utilites.
Rust
5
star
39

kernel

Header-only library that assists you with exploiting the Windows kernel
C++
4
star
40

machina

Manage and execute assembly at runtime.
Rust
4
star
41

sam-rs

rust compiler plugin for compile time instruction assembling
Rust
4
star
42

llvm_test

Simple Hello World with LLVM
CMake
4
star
43

mmap-kernel-exploit

Gaining root by exploiting the mmap handler of a kernel module.
C
3
star
44

ll

some c++ stuff
C++
3
star
45

is-vm

Detecting VMs using the CPUID instruction
Assembly
3
star
46

Medusa

Medusa - .NET Multi-Scanner [BETA]
C#
3
star
47

ionScript

My own scriptlanguage using .NET as interpreter.
C#
3
star
48

sam

Compile time instruction assembler for Rust.
Rust
3
star
49

bn_memcpy

C++
3
star
50

docker-compiler-explorer

Dockerfile
2
star
51

dnSpyUpdater

Updater for dnSpy.
C#
2
star
52

sbb

Rust
2
star
53

pub.ioncodes.com

The index page of my public projects website
HTML
2
star
54

uwu

I should have never named this uwu...
C++
2
star
55

aseprite-ci

Build configurations to compile Aseprite via a GitLab CI Runner on Windows.
Batchfile
2
star
56

urldecode

Decodes a URL encoded String.
Rust
2
star
57

otf2ttf

Shell script for converting *.otf font files to *.ttf (Just want to get the SF font from my 🍎 on my Windows machine πŸ˜›)
Shell
2
star
58

ida_scripts

Python
2
star
59

cpp-makefile-template

Makefile
1
star
60

JodelWindows

Windows version of the Jodel app using my own API (JodelAPI on GitHub).
C#
1
star
61

iRecover

Password Recovery utility and library writtin in .NET
C#
1
star
62

RoguueLiike

Rogue-like game in MonoGame C#
C#
1
star
63

brainfuck_recompiler

Brainfuck recompiler to x64 asm
Rust
1
star
64

Axon

Objective-C header file parser
Swift
1
star
65

sam-web

Online assembler
JavaScript
1
star
66

ioncodes

1
star
67

eta-wen

HTML
1
star
68

Xiu

gameboy emulator in Rust
Rust
1
star
69

ionTheme

C# and VB.NET Theme as replacement for the odd windows style
C#
1
star
70

ctf

Docker image for CTFs
Dockerfile
1
star
71

Quickie

Find icons from different icon sets.
JavaScript
1
star
72

Korpus

Has nothing to do with IKEA, it's a remote tool
JavaScript
1
star
73

iRC

Simple commandline irc client
C#
1
star
74

Korpus.Server

Still has nothing to do with IKEA, it's the server for Korpus
JavaScript
1
star
75

efi-boilerplate

C++
1
star
76

exploit-templates

Templates for binary exploits
Python
1
star
77

CFade

Console Fader Animator class in C++
C++
1
star
78

ProxyDB

Database that manages all your proxies.
C#
1
star
79

wrapper

WinAPI C++ wrapper
C++
1
star
80

bs

IDPA
JavaScript
1
star
81

winconfig

My configs I use on Windows
Shell
1
star
82

nesextract

Tool to extract sprites from NES roms.
Rust
1
star
83

disrupt

Fast commandline disassembler
JavaScript
1
star
84

BeautySharpVS

Visual Studio Extension working with a PHP API for fast code publishing.
C#
1
star
85

snek

Snek forwards your iOS notifcations to Snek Server, Slack or Discord. Built for iOS 11.
Logos
1
star
86

yolo

yolo like a hipster does demos in 2k17
C++
1
star
87

yolo-rs

yolor - demotool
Rust
1
star
88

dnconventions

Convert the naming conventions of a .NET application
C#
1
star