Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions README-CEx.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
## de4dot CEx
A de4dot fork with full support for vanilla ConfuserEx

## Features
* Supports x86 (native) mode
* Supports normal mode
* Decrypts and inlines constants
* Decrypts resources
* Fixes control flow
* Fixes proxy calls
* Deobfuscated assemblies are runnable

## Notes
* You have to unpack the obfuscated assembly **before** running this deobfuscator. The easiest way is to dump the module/s just after the methods have been decrypted.
* This deobfuscator uses method invocation for constant decryption, therefore you always **risk** running malware if it's present in the obfuscated assembly. Be cautious and use a VM/Sandboxie!

### [Original README](./README.md)
---

## Samples

### Before (obfuscated symbols shortened):
```csharp
ublic byte[] ShiftAddress(uint address)
{
byte[] array = new byte[4];
for (;;)
{
IL_07:
int num = -2174478396;
for (;;)
{
uint num2;
switch ((num2 = (uint)<Module>.a(num)) % 7u)
{
case 0u:
goto IL_07;
case 1u:
{
int num3 = 0;
num = (int)(num2 * 81144519u ^ 2359132411u);
continue;
}
case 2u:
num = (int)(num2 * 2975731004u ^ 34171348176);
continue;
case 3u:
{
int num3;
num3++;
num = (int)(num2 * 2174567110u ^ 244457623u);
continue;
}
case 5u:
{
int num3;
num = ((num3 >= 4) ? 631278122 : 1299552879);
continue;
}
case 6u:
{
int num3;
array[num3] = (byte)(address >> num3 * 8 & 255u);
num = 556578930;
continue;
}
}
return array;
}
}
return array;
}
```

### After:
```csharp
public byte[] ShiftAddress(uint address)
{
byte[] array = new byte[4];
for (int i = 0; i < 4; i++)
{
array[i] = (byte)(address >> i * 8 & 255u);
}
return array;
}
```

### Before (obfuscated symbols shortened):
```csharp
public bool WriteBytes(uint address, List<byte> buffer)
{
byte[] array = buffer.ToArray();
IntPtr intPtr;
uint num = Memory.a(this.Handle, b((long)((ulong)address)), array, (uint)array.Length, out intPtr);
for (;;)
{
IL_25:
int num2 = 482469350;
for (;;)
{
uint num3;
switch ((num3 = (uint)<Module>.c(num2)) % 5u)
{
case 0u:
this.d.Account.Log.WriteLine(<Module>.e<string>(3167610260u));
num2 = (int)(num3 * 3588940066u ^ 1074051690u);
continue;
case 2u:
return false;
case 3u:
goto IL_25;
case 4u:
num2 = (int)(((num != 0u) ? 4496537787u : 434512514u) ^ num3 * 589449693u);
continue;
}
goto Block_1;
}
}
Block_1:
return true;
}
```

### After:
```csharp
public bool WriteBytes(uint address, List<byte> buffer)
{
byte[] array = buffer.ToArray();
IntPtr intPtr;
if (Memory.WriteProcessMemory(this.Handle, (IntPtr)((long)((ulong)address)), array, (uint)array.Length, out intPtr) == 0u)
{
this.Owner.Console.Log.WriteLine("WriteBytes failed: WriteProcessMemory failed");
return false;
}
return true;
}
```
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ Supported obfuscators/packers
* Spices.Net
* Xenocode

There are some other obfuscators/packers that are not in supported list explicitly, so their status is unclear:

* Confuser
* ConfuserEx - Merged from https://github.com/ViRb3/de4dot-cex , [read the full ReadMe by @ViRb3](README-CEx.md) for more info. You may need a native library for [BeaEngine](https://github.com/BeaEngine/beaengine) (version `5.3.0`) for your platform to use the corresponding functionality! If you use another version you may need to recompile with the updated [C# bindings](https://github.com/BeaEngine/beaengine/tree/master/headers/C%23%20headers).
* Osu
* PCL

Some of the above obfuscators are rarely used (eg. Goliath.NET), so they have had much less testing. Help me out by reporting bugs or problems you find.

Warning
Expand Down
21 changes: 19 additions & 2 deletions de4dot.blocks/Block.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,25 @@ You should have received a copy of the GNU General Public License
using dnlib.DotNet.Emit;

namespace de4dot.blocks {
public class Block : BaseBlock {
List<Instr> instructions = new List<Instr>();
public enum BlockType
{
Normal,
Switch,
SwitchCase
}

public class Block : BaseBlock
{
public Block()
{
SwitchData = new SwitchData(this);
}

public BlockType BlockType = BlockType.Normal;
public SwitchData SwitchData;
public bool Processed = false;

List<Instr> instructions = new List<Instr>();

// List of all explicit (non-fall-through) targets. It's just one if it's a normal
// branch, but if it's a switch, it could be many targets.
Expand Down
20 changes: 20 additions & 0 deletions de4dot.blocks/SwitchData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace de4dot.blocks
{
public class SwitchData
{
protected readonly Block _block;

public int? Key;
public bool IsKeyHardCoded;

public SwitchData(Block block)
{
_block = block;
}

public virtual bool Initialize()
{
return false;
}
}
}
12 changes: 6 additions & 6 deletions de4dot.blocks/cflow/Int32Value.cs
Original file line number Diff line number Diff line change
Expand Up @@ -450,8 +450,8 @@ public static Int32Value Shl(Int32Value a, Int32Value b) {
return CreateUnknown();
if (b.Value == 0)
return a;
if (b.Value < 0 || b.Value >= sizeof(int) * 8)
return CreateUnknown();
//if (b.Value < 0 || b.Value >= sizeof(int) * 8)
// return CreateUnknown();
int shift = b.Value;
uint validMask = (a.ValidMask << shift) | (uint.MaxValue >> (sizeof(int) * 8 - shift));
return new Int32Value(a.Value << shift, validMask);
Expand All @@ -462,8 +462,8 @@ public static Int32Value Shr(Int32Value a, Int32Value b) {
return CreateUnknown();
if (b.Value == 0)
return a;
if (b.Value < 0 || b.Value >= sizeof(int) * 8)
return CreateUnknown();
//if (b.Value < 0 || b.Value >= sizeof(int) * 8)
// return CreateUnknown();
int shift = b.Value;
uint validMask = a.ValidMask >> shift;
if (a.IsBitValid(sizeof(int) * 8 - 1))
Expand All @@ -476,8 +476,8 @@ public static Int32Value Shr_Un(Int32Value a, Int32Value b) {
return CreateUnknown();
if (b.Value == 0)
return a;
if (b.Value < 0 || b.Value >= sizeof(int) * 8)
return CreateUnknown();
//if (b.Value < 0 || b.Value >= sizeof(int) * 8)
// return CreateUnknown();
int shift = b.Value;
uint validMask = (a.ValidMask >> shift) | (uint.MaxValue << (sizeof(int) * 8 - shift));
return new Int32Value((int)((uint)a.Value >> shift), validMask);
Expand Down
19 changes: 11 additions & 8 deletions de4dot.code/ObfuscatedFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -264,12 +264,13 @@ IDeobfuscator DetectObfuscator2(IEnumerable<IDeobfuscator> deobfuscators) {
foreach (var deob in deobfuscators) {
this.deob = deob; // So we can call deob.CanInlineMethods in deobfuscate()
int val;
try {
val = deob.Detect();
}
//TODO: Re-enable exception handler
//try {
val = deob.Detect();
/*}
catch {
val = deob.Type == "un" ? 1 : 0;
}
}*/
Logger.v("{0,3}: {1}", val, deob.TypeLong);
if (val > 0 && deob.Type != "un")
allDetected.Add(deob);
Expand Down Expand Up @@ -552,9 +553,10 @@ void DeobfuscateMethods() {
}

int oldIndentLevel = Logger.Instance.IndentLevel;
try {
//TODO: Re-enable exception handler
//try {
Deobfuscate(method, cflowDeobfuscator, methodPrinter, isVerbose, isVV);
}
/*}
catch (Exception ex) {
if (!CanLoadMethodBody(method)) {
if (isVerbose)
Expand All @@ -569,8 +571,9 @@ void DeobfuscateMethods() {
}
finally {
Logger.Instance.IndentLevel = oldIndentLevel;
}
RemoveNoInliningAttribute(method);
}*/

RemoveNoInliningAttribute(method);

if (isVerbose)
Logger.Instance.DeIndent();
Expand Down
Loading