Skip to content
Merged
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
107 changes: 91 additions & 16 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ on:
branches: [ "master" ]
workflow_dispatch:

env:
DOTNET_RUNTIME: net8.0
SETUP_DOTNET_VERSION: 8.0.x

BEAENGINE_TAG: v5.3.0

jobs:
build-windows:
name: Build Windows artifacts
Expand All @@ -27,20 +33,70 @@ jobs:
if ($LASTEXITCODE) { exit $LASTEXITCODE }
Remove-Item Release\net48\*.pdb, Release\net48\*.xml, Release\net48\Test.Rename.*

dotnet publish -c Release -f net8.0 -o publish-net8.0 de4dot
Remove-Item publish-net8.0\*.pdb, publish-net8.0\*.xml
dotnet publish -c Release -f $env:DOTNET_RUNTIME -o publish-$env:DOTNET_RUNTIME de4dot
Remove-Item publish-$env:DOTNET_RUNTIME\*.pdb, publish-$env:DOTNET_RUNTIME\*.xml

- name: Build BeaEngine
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'

git clone --depth 1 --branch $env:BEAENGINE_TAG https://github.com/BeaEngine/beaengine.git beaengine

# Remove cmake malpractice
(Get-Content beaengine/CMakeLists.txt) |
Where-Object { $_ -notmatch '\s*list\s*\(APPEND\s+BEA_FLAGS\s+/M' } |
Set-Content beaengine/CMakeLists.txt

# Win32 for .NET 4.8
cmake -S beaengine -B build-beaengine-32 `
-A Win32 `
-DoptBUILD_DLL=ON `
-DoptHAS_OPTIMIZED=ON `
-DoptHAS_SYMBOLS=OFF `
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded

cmake --build build-beaengine-32 --config Release

$dll32 = Get-ChildItem -Recurse build-beaengine-32 -Filter BeaEngine*.dll | Select-Object -First 1

if (-not $dll32) {
throw "32-bit BeaEngine.dll not found"
}

Copy-Item $dll32.FullName Release/net48/BeaEngine.dll
Copy-Item beaengine/src/COPYING.txt Release/net48/LICENSES/LICENSE.BeaEngine.GPL.txt
Copy-Item beaengine/src/COPYING.LESSER.txt Release/net48/LICENSES/LICENSE.BeaEngine.LGPL.txt

# Win64 for .NET 8+
cmake -S beaengine -B build-beaengine-64 `
-A x64 `
-DoptBUILD_DLL=ON `
-DoptHAS_OPTIMIZED=ON `
-DoptHAS_SYMBOLS=OFF `
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded

cmake --build build-beaengine-64 --config Release

$dll64 = Get-ChildItem -Recurse build-beaengine-64 -Filter BeaEngine*.dll | Select-Object -First 1

if (-not $dll64) {
throw "64-bit BeaEngine.dll not found"
}

Copy-Item $dll64.FullName publish-$env:DOTNET_RUNTIME/BeaEngine.dll
Copy-Item beaengine/src/COPYING.txt publish-$env:DOTNET_RUNTIME/LICENSES/LICENSE.BeaEngine.GPL.txt
Copy-Item beaengine/src/COPYING.LESSER.txt publish-$env:DOTNET_RUNTIME/LICENSES/LICENSE.BeaEngine.LGPL.txt

- uses: actions/upload-artifact@v4
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')
with:
name: de4dotEx-net48
path: Release/net48

- uses: actions/upload-artifact@v4
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')
with:
name: de4dotEx-net8.0-win-x64
path: publish-net8.0
name: de4dotEx-${{ env.DOTNET_RUNTIME }}-win-x64
path: publish-${{ env.DOTNET_RUNTIME }}

build-linux:
name: Build Linux artifacts & package .deb
Expand All @@ -52,19 +108,38 @@ jobs:
- name: Set up .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
dotnet-version: ${{ env.SETUP_DOTNET_VERSION }}

- name: Publish ${{ env.DOTNET_RUNTIME }}
run: |
dotnet publish -c Release -f "${DOTNET_RUNTIME}" -o publish-${DOTNET_RUNTIME} de4dot
rm -rf publish-${DOTNET_RUNTIME}/*.pdb publish-${DOTNET_RUNTIME}/*.xml

- name: Publish net8.0
- name: Build BeaEngine
run: |
dotnet publish -c Release -f net8.0 -o publish-net8.0 de4dot
rm -rf publish-net8.0/*.pdb publish-net8.0/*.xml
set -euo pipefail

git clone --depth 1 --branch "$BEAENGINE_TAG" https://github.com/BeaEngine/beaengine.git

cmake -S beaengine -B build64 \
-DoptBUILD_DLL=ON \
-DoptHAS_OPTIMIZED=ON \
-DoptHAS_SYMBOLS=OFF

cmake --build build64

so64=$(find build64 -name "libBeaEngine*.so" | head -n 1)
[[ -n "$so64" ]] || { echo "libBeaEngine not found"; exit 1; }

cp "$so64" publish-${DOTNET_RUNTIME}/libBeaEngine.so
cp beaengine/src/COPYING.txt publish-${DOTNET_RUNTIME}/LICENSES/LICENSE.BeaEngine.GPL.txt
cp beaengine/src/COPYING.LESSER.txt publish-${DOTNET_RUNTIME}/LICENSES/LICENSE.BeaEngine.LGPL.txt

- name: Upload publish folder
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')
uses: actions/upload-artifact@v4
with:
name: de4dotEx-net8.0-linux-x64
path: publish-net8.0
name: de4dotEx-${{ env.DOTNET_RUNTIME }}-linux-x64
path: publish-${{ env.DOTNET_RUNTIME }}

- name: Extract version from Git tag
if: startsWith(github.ref, 'refs/tags/')
Expand All @@ -77,7 +152,7 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
run: |
mkdir -p deb-root/opt/de4dotEx
cp -r publish-net8.0/* deb-root/opt/de4dotEx/
cp -r "publish-$DOTNET_RUNTIME/*" deb-root/opt/de4dotEx/

mkdir -p deb-root/usr/local/bin
ln -s /opt/de4dotEx/de4dot deb-root/usr/local/bin/de4dot
Expand All @@ -90,7 +165,7 @@ jobs:
Priority: optional
Architecture: amd64
Maintainer: G DATA Advanced Analytics GmbH <mwa@gdata-adan.de>
Depends: libicu77 | libicu76 | libicu74 | libicu72 | libicu70 | libicu67 | libicu66
Depends: libicu78 | libicu77 | libicu76 | libicu74 | libicu72 | libicu70 | libicu67 | libicu66
Description: .NET deobfuscator and unpacker
de4dot is a .NET deobfuscator and unpacker. It will try its best to
restore a packed and obfuscated assembly to almost the original
Expand All @@ -106,5 +181,5 @@ jobs:
- uses: actions/upload-artifact@v4
if: startsWith(github.ref, 'refs/tags/')
with:
name: de4dotEx-${{ steps.get_version.outputs.VERSION }}-net8.0-x64-deb
name: de4dotEx-${{ steps.get_version.outputs.VERSION }}-${{ env.DOTNET_RUNTIME }}-x64-deb
path: de4dotEx-${{ steps.get_version.outputs.VERSION }}.deb
26 changes: 12 additions & 14 deletions de4dot.code/deobfuscators/ConfuserEx/ProxyCallFixer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,30 +139,28 @@ protected override void GetCallInfo(object context, FieldDef field, out IMethod
}

result *= GetMagicNumber(field.CustomAttributes[0]);
calledMethod = module.ResolveMemberRef(new MDToken(result).Rid);
calledMethod = module.ResolveToken(result) as IMethod;

if (calledMethod == null)
throw new Exception();
throw new Exception($"Resolved token is wrong: {result:X8}");

var charNum = GetCharNum(instructions, parameters.Last());
callOpcode = GetCallOpCode(calledMethod, charNum, ctx.ByteNum);

ctx.CreateMethod.Body = originalMethod.Body; // restore
}

private OpCode GetCallOpCode(IMethod calledMethod, int charNum, int byteNum)
{
if (calledMethod.ResolveMethodDef().IsStatic) return OpCodes.Call;
private OpCode GetCallOpCode(IMethod calledMethod, int charNum, int byteNum) {
if (calledMethod is not MemberRef && calledMethod.ResolveMethodDef().IsStatic) return OpCodes.Call;

var charOpCode = (byte) (charNum ^ byteNum);

if (charOpCode == 0x28)
return OpCodes.Call;
if (charOpCode == 0x6F)
return OpCodes.Callvirt;
if (charOpCode == 0x73)
return OpCodes.Newobj;
throw new Exception();
return charOpCode switch {
0x28 => OpCodes.Call,
0x6F => OpCodes.Callvirt,
0x73 => OpCodes.Newobj,
_ => throw new Exception($"Invalid charOpCode {charOpCode:X2}")
};
}

private int EmulateNativeMethod(MethodDef externalMethod, int parameter)
Expand Down Expand Up @@ -256,7 +254,7 @@ private int GetCharNum(IList<Instruction> instructions, Parameter byteParam)
if ((Parameter) instrs[0].Operand != byteParam)
continue;

return (int) instructions[i - 5].Operand;
return (int) instructions[i - 5].Operand; // ldc.i4 placed by ReplaceFieldNameChar()
}
throw new Exception();
}
Expand Down Expand Up @@ -413,4 +411,4 @@ private void ReplaceMetadataToken(ref IList<Instruction> instructions, int metad
}
}
}
}
}
2 changes: 1 addition & 1 deletion de4dot.code/deobfuscators/ConfuserEx/x86/Bea/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace de4dot.Bea
{
public static class BeaConstants
{
public static int INSTRUCT_LENGTH = 80;
public const int INSTRUCT_LENGTH = 80;

public enum SegmentRegister : byte
{
Expand Down
66 changes: 21 additions & 45 deletions de4dot.code/deobfuscators/ConfuserEx/x86/Bea/Engine.cs
Original file line number Diff line number Diff line change
@@ -1,45 +1,21 @@
using System.IO;
using System.Runtime.InteropServices;

namespace de4dot.Bea
{
public static class BeaEngine
{
// 'de4dot\bin\de4dot.blocks.dll' -> 'de4dot\bin\'
private static string _executingPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

static BeaEngine()
{
//TODO: Better handle native DLL discovery
SetDllDirectory(_executingPath);
}

[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool SetDllDirectory(string lpPathName);

[DllImport("BeaEngine")]
public static extern int Disasm([In, Out, MarshalAs(UnmanagedType.LPStruct)] Disasm disasm);

[DllImport("BeaEngine")]
private static extern string BeaEngineVersion();

[DllImport("BeaEngine")]
private static extern string BeaEngineRevision();

public static string Version
{
get
{
return BeaEngineVersion();
}
}

public static string Revision
{
get
{
return BeaEngineRevision();
}
}
}
}
using System;
using System.Runtime.InteropServices;

namespace de4dot.Bea
{
public static class BeaEngine
{
[DllImport("BeaEngine")]
public static extern int Disasm([In, Out, MarshalAs(UnmanagedType.LPStruct)] Disasm disasm);

[DllImport("BeaEngine")]
private static extern IntPtr BeaEngineVersion(); // returning string would call free() on a const char*

[DllImport("BeaEngine")]
private static extern IntPtr BeaEngineRevision();

public static string Version => Marshal.PtrToStringAnsi(BeaEngineVersion());

public static string Revision => Marshal.PtrToStringAnsi(BeaEngineRevision());
}
}
22 changes: 11 additions & 11 deletions de4dot.code/deobfuscators/ConfuserEx/x86/Bea/Structs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class REX_Struct
public byte state;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public class PrefixInfo
{
public int Number;
Expand All @@ -32,7 +32,7 @@ public class PrefixInfo
public byte BranchTaken;
public byte BranchNotTaken;
public REX_Struct REX;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
public string alignment;
}

Expand All @@ -53,7 +53,7 @@ public class EFLStruct
public byte alignment;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public class RegisterType
{
public Int64 type;
Expand All @@ -74,16 +74,16 @@ public class RegisterType
}


[StructLayout(LayoutKind.Sequential, Pack = 1)]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public class MemoryType
{
public Int32 BaseRegister;
public Int32 IndexRegister;
public Int64 BaseRegister;
public Int64 IndexRegister;
public Int32 Scale;
public Int64 Displacement;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public class InstructionType
{
public Int32 Category;
Expand All @@ -98,12 +98,12 @@ public class InstructionType
public RegisterType ImplicitUsedRegs;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public class ArgumentType
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string OpMnemonic;
public Int32 OpType;
public Int64 OpType;
public Int32 OpSize;
public Int32 OpPosition;
public UInt32 AccessMode;
Expand All @@ -112,13 +112,13 @@ public class ArgumentType
public UInt32 SegmentReg;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public class Disasm
{
public IntPtr EIP;
public UInt64 VirtualAddr;
public UInt32 SecurityBlock;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = BeaConstants.INSTRUCT_LENGTH)]
public string CompleteInstr;
public UInt32 Archi;
public UInt64 Options;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
using System.Collections.Generic;
using de4dot.Bea;
using de4dot.code.deobfuscators.ConfuserEx.x86;

namespace ConfuserDeobfuscator.Engine.Routines.Ex.x86.Instructions
namespace de4dot.code.deobfuscators.ConfuserEx.x86.Instructions
{
class X86ADD : X86Instruction
{
public X86ADD(Disasm rawInstruction) : base()
public X86ADD(Disasm rawInstruction)
{
Operands = new IX86Operand[2];
Operands[0] = GetOperand(rawInstruction.Operand1);
Operands[1] = GetOperand(rawInstruction.Operand2);
Operands[1] = GetOperand(rawInstruction.Operand2);
}

public override X86OpCode OpCode { get { return X86OpCode.ADD; } }
Expand Down
Loading
Loading