From e0b61d54d1e117d7c1fbbc18a1aec2ddd66d1bd2 Mon Sep 17 00:00:00 2001 From: Melissa Eckardt Date: Wed, 15 Jul 2026 15:47:02 +0200 Subject: [PATCH] DeepSea: Fix junk block removal for newer versions --- .../DeepSea/ArrayBlockDeobfuscator.cs | 50 ++++++++++++++++--- .../deobfuscators/DeepSea/ArrayBlockState.cs | 36 ++++++++----- .../DeepSea/DsMethodCallInliner.cs | 2 + 3 files changed, 69 insertions(+), 19 deletions(-) diff --git a/de4dot.code/deobfuscators/DeepSea/ArrayBlockDeobfuscator.cs b/de4dot.code/deobfuscators/DeepSea/ArrayBlockDeobfuscator.cs index 02f97b0e8..23e0789e4 100644 --- a/de4dot.code/deobfuscators/DeepSea/ArrayBlockDeobfuscator.cs +++ b/de4dot.code/deobfuscators/DeepSea/ArrayBlockDeobfuscator.cs @@ -67,20 +67,22 @@ protected override bool Deobfuscate(Block block) { constantsReader = null; var instrs = block.Instructions; for (int i = 0; i < instrs.Count; i++) { - bool ch = Deobfuscate1(block, i); - if (ch) { + if (Deobfuscate1(block, i)) { modified = true; continue; } - ch = Deobfuscate2(block, i); - if (ch) { + if (Deobfuscate2(block, i)) { modified = true; continue; } - ch = Deobfuscate3(block, i); - if (ch) { + if (Deobfuscate3(block, i)) { + modified = true; + continue; + } + + if (Deobfuscate4(block, i)) { modified = true; continue; } @@ -214,6 +216,42 @@ bool Deobfuscate3(Block block, int i) { return true; } + bool Deobfuscate4(Block block, int i) { + var instrs = block.Instructions; + if (i + 1 >= instrs.Count) + return false; + + int start = i; + var ldsfld = instrs[i]; + if (ldsfld.OpCode.Code != Code.Ldsfld) + return false; + var info = arrayBlockState.GetFieldInfo(ldsfld.Operand as IField); + if (info == null) + return false; + + if (!instrs[i + 1].IsLdcI4()) + return false; + + for (; i < instrs.Count; i++) { + if (instrs[i].OpCode.FlowControl != FlowControl.Next) + return false; + if (instrs[i].OpCode.Code == Code.Ldsfld + && arrayBlockState.GetFieldInfo(instrs[i].Operand as IField) == null) + return false; + if (instrs[i].OpCode.Code is Code.Stelem_I1 or Code.Stelem_I2 or Code.Stelem_I4) + break; + } + + if (i >= instrs.Count) + return false; + var stelem = instrs[i]; + if (!IsStelem(info, stelem.OpCode.Code)) + return false; + + block.Remove(start, i - start + 1); + return true; + } + DsConstantsReader GetConstantsReader(Block block) { if (constantsReader != null) return constantsReader; diff --git a/de4dot.code/deobfuscators/DeepSea/ArrayBlockState.cs b/de4dot.code/deobfuscators/DeepSea/ArrayBlockState.cs index a30accc0b..0c78b3b40 100644 --- a/de4dot.code/deobfuscators/DeepSea/ArrayBlockState.cs +++ b/de4dot.code/deobfuscators/DeepSea/ArrayBlockState.cs @@ -110,19 +110,27 @@ bool InitializeArrays2(ISimpleDeobfuscator simpleDeobfuscator, MethodDef method) if (!ldci4.IsLdcI4()) continue; i++; + bool hasCall = true; var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Newarr, OpCodes.Dup, OpCodes.Ldtoken, OpCodes.Call, OpCodes.Stsfld); - if (instrs == null) - continue; + if (instrs == null) { + instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Newarr, OpCodes.Dup, OpCodes.Ldtoken, OpCodes.Stsfld); + if (instrs == null) + continue; + hasCall = false; + } var arrayInitField = instrs[2].Operand as FieldDef; if (arrayInitField == null || arrayInitField.InitialValue == null || arrayInitField.InitialValue.Length == 0) continue; - var calledMethod = instrs[3].Operand as IMethod; - if (calledMethod == null || calledMethod.FullName != "System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)") - continue; + if (hasCall) { + var calledMethod = instrs[3].Operand as IMethod; + if (calledMethod == null || calledMethod.FullName != + "System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)") + continue; + } - var targetField = instrs[4].Operand as FieldDef; + var targetField = instrs[hasCall ? 4 : 3].Operand as FieldDef; if (targetField == null || targetField.FieldType.GetElementType() != ElementType.SZArray) continue; var etype = ((SZArraySig)targetField.FieldType).Next.GetElementType(); @@ -186,17 +194,19 @@ bool RemoveInitCode(Blocks blocks, FieldInfo info) { if (ldtoken.Operand != info.arrayInitField) continue; var call = instrs[i + 4]; - if (call.OpCode.Code != Code.Call) - continue; - var calledMethod = call.Operand as IMethod; - if (calledMethod == null || calledMethod.FullName != "System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)") - continue; - var stsfld = instrs[i + 5]; + bool hasCall = call.OpCode.Code == Code.Call; + if (hasCall) { + var calledMethod = call.Operand as IMethod; + if (calledMethod == null || calledMethod.FullName != + "System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)") + continue; + } + var stsfld = instrs[i + (hasCall ? 5 : 4)]; if (stsfld.OpCode.Code != Code.Stsfld) continue; if (stsfld.Operand != info.field) continue; - block.Remove(i, 6); + block.Remove(i, hasCall ? 6 : 5); i--; removedSomething = true; } diff --git a/de4dot.code/deobfuscators/DeepSea/DsMethodCallInliner.cs b/de4dot.code/deobfuscators/DeepSea/DsMethodCallInliner.cs index b39a6553b..2f3fe7d6d 100644 --- a/de4dot.code/deobfuscators/DeepSea/DsMethodCallInliner.cs +++ b/de4dot.code/deobfuscators/DeepSea/DsMethodCallInliner.cs @@ -53,6 +53,8 @@ bool InlineMethod(Instruction callInstr, int instrIndex) { if (method == null) { if (callInstr.Operand is MethodSpec ms) method = ms.Method as MethodDef; + if (callInstr.Operand is MemberRef mref) + method = mref.ResolveMethod(); if (method == null) return false; }