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
3 changes: 1 addition & 2 deletions de4dot.blocks/cflow/InstructionEmulator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -532,9 +532,8 @@ void Emulate_Sizeof(Instruction instr){
void Emulate_Newarr(Instruction instr)
{
var val = valueStack.Pop();
if (val.IsInt32())
if (val.IsInt32() && val is Int32Value { Value: < 500000 } arrSize)
{
Int32Value arrSize = (Int32Value)val;
List<Value> arr = new List<Value>(arrSize.Value);
for (int i = 0; i < arrSize.Value; i++) {
arr.Add(new UnknownValue());
Expand Down
7 changes: 4 additions & 3 deletions de4dot.code/deobfuscators/dotNET_Reactor/v4/Deobfuscator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,8 @@ public override IDeobfuscator ModuleReloaded(ModuleDefMD module) {
newOne.peImage = new MyPEImage(fileData);
newOne.methodsDecrypter = new MethodsDecrypter(module, methodsDecrypter);
newOne.proxyCallFixer = new ProxyCallFixer(module, proxyCallFixer);
newOne.devirtualizer = new Devirtualizer(module, devirtualizer);
newOne.devirtualizer = new Devirtualizer(DeobfuscatedFile, module);
newOne.devirtualizer.Find();
newOne.stringDecrypter = new StringDecrypter(module, stringDecrypter);
newOne.booleanDecrypter = new BooleanDecrypter(module, booleanDecrypter);
newOne.assemblyResolver = new AssemblyResolver(module, assemblyResolver);
Expand All @@ -462,7 +463,7 @@ void FreePEImage() {
}

void RemoveMethods() {
if (methodsDecrypter.Method != null) {
if (methodsDecrypter.Method != null && options.DecryptMethods) {
AddEntryPointCallToBeRemoved(methodsDecrypter.Method);
}

Expand Down Expand Up @@ -501,7 +502,7 @@ void RemoveMethods() {
if (antiDebug != null)
AddCallToBeRemoved(method, antiDebug);

if (methodsDecrypter.Method != null)
if (methodsDecrypter.Method != null && options.DecryptMethods)
AddCallToBeRemoved(method, methodsDecrypter.Method);

// AntiILDASM
Expand Down
234 changes: 64 additions & 170 deletions de4dot.code/deobfuscators/dotNET_Reactor/v4/EncryptedResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,13 +237,69 @@ public byte[] Encrypt(byte[] data) {
}
}

class DecrypterV2 : IDecrypter {
private abstract class EmulatingDecrypterBase
{
protected MethodDef method;
protected List<Instruction> instructions;
protected List<Local> locals;
protected readonly InstructionEmulator instrEmulator = new();
protected Local emuLocal;

/**
* Locates the instructions that are responsible for producing the key stream for decrypting the resource.
*/
protected bool FindStartEnd(IList<Instruction> instrs, out int startIndex, out int endIndex, out Local tmpLocal) {
for (int i = 0; i + 8 < instrs.Count; i++) {
if (instrs[i].OpCode.Code != Code.Conv_R_Un)
continue;
if (instrs[i + 1].OpCode.Code != Code.Conv_R8)
continue;
if (instrs[i + 2].OpCode.Code != Code.Conv_U4)
continue;
if (instrs[i + 3].OpCode.Code != Code.Add)
continue;
int newEndIndex = i + 3;
int newStartIndex = -1;
for (int j = newEndIndex; j >= 0; j--) {
// Search upwards for array access or br.
if (instrs[j].OpCode.Code != Code.Ldelem_U1 && (!instrs[j].IsBr() || instrs[j - 1].OpCode.Code == Code.Bne_Un_S))
continue;

// Go down to next local load, where the actual decryption should begin.
for (int k = j + 1; k < newEndIndex; k++) {
if (instrs[k].IsLdloc()) {
newStartIndex = k;
break;
}
}
break;
}
endIndex = newEndIndex;
startIndex = newStartIndex;
tmpLocal = CheckLocal(instrs[startIndex], true);
return true;
}
endIndex = 0;
startIndex = 0;
tmpLocal = null;
return false;
}

/**
* Gets the Local referenced by the instruction if it's either ldloc or stloc (determined by isLdloc).
*/
protected Local CheckLocal(Instruction instr, bool isLdloc) {
if (isLdloc && !instr.IsLdloc())
return null;
if (!isLdloc && !instr.IsStloc())
return null;

return instr.GetLocal(locals);
}
}

class DecrypterV2 : EmulatingDecrypterBase, IDecrypter {
readonly byte[] key, iv;
MethodDef method;
List<Instruction> instructions;
List<Local> locals;
readonly InstructionEmulator instrEmulator = new InstructionEmulator();
Local emuLocal;
Parameter emuArg;
MethodDef emuMethod;
bool isNewDecrypter;
Expand Down Expand Up @@ -310,49 +366,6 @@ bool Find(IList<Instruction> instrs, out int startIndex, out int endIndex, out L
return true;
}

bool FindStartEnd(IList<Instruction> instrs, out int startIndex, out int endIndex, out Local tmpLocal) {
for (int i = 0; i + 8 < instrs.Count; i++) {
if (instrs[i].OpCode.Code != Code.Conv_R_Un)
continue;
if (instrs[i + 1].OpCode.Code != Code.Conv_R8)
continue;
if (instrs[i + 2].OpCode.Code != Code.Conv_U4)
continue;
if (instrs[i + 3].OpCode.Code != Code.Add)
continue;
int newEndIndex = i + 3;
int newStartIndex = -1;
for (int x = newEndIndex; x > 0; x--)
if (instrs[x].OpCode.FlowControl != FlowControl.Next) {
newStartIndex = x + 1;
break;
}
if (newStartIndex < 0)
continue;

var checkLocs = new List<Local>();
int ckStartIndex = -1;
for (int y = newEndIndex; y >= newStartIndex; y--) {
var loc = CheckLocal(instrs[y], true);
if (loc == null)
continue;
if (!checkLocs.Contains(loc))
checkLocs.Add(loc);
if (checkLocs.Count == 3)
break;
ckStartIndex = y;
}
endIndex = newEndIndex;
startIndex = Math.Max(ckStartIndex, newStartIndex);
tmpLocal = CheckLocal(instrs[startIndex], true);
return true;
}
endIndex = 0;
startIndex = 0;
tmpLocal = null;
return false;
}

bool FindStartEnd2(ref IList<Instruction> instrs, out int startIndex, out int endIndex, out Local tmpLocal, out Parameter tmpArg, ref MethodDef methodDef, ref List<Local> locals) {
foreach (var instr in instrs) {
if (instr.OpCode == OpCodes.Call) {
Expand Down Expand Up @@ -436,15 +449,6 @@ bool FindEnd(IList<Instruction> instrs, int startIndex, out int endIndex) {
return false;
}

Local CheckLocal(Instruction instr, bool isLdloc) {
if (isLdloc && !instr.IsLdloc())
return null;
else if (!isLdloc && !instr.IsStloc())
return null;

return instr.GetLocal(locals);
}

public byte[] Decrypt(EmbeddedResource resource) {
var encrypted = resource.CreateReader().ToArray();
var decrypted = new byte[encrypted.Length];
Expand Down Expand Up @@ -517,13 +521,7 @@ public byte[] Encrypt(byte[] data) {
}
}

class DecrypterV3 : IDecrypter {
readonly MethodDef method;
List<Instruction> instructions;
readonly List<Local> locals;
readonly InstructionEmulator instrEmulator = new InstructionEmulator();
Local emuLocal;

class DecrypterV3 : EmulatingDecrypterBase, IDecrypter {
public DnrDecrypterType DecrypterType => DnrDecrypterType.V3;

public DecrypterV3(MethodDef method) {
Expand Down Expand Up @@ -578,48 +576,6 @@ bool Find(IList<Instruction> instrs, out int startIndex, out int endIndex, out L
return true;
}

/**
* Locates the instructions that are responsible for producing the key stream for decrypting the resource.
*/
bool FindStartEnd(IList<Instruction> instrs, out int startIndex, out int endIndex, out Local tmpLocal) {
for (int i = 0; i + 8 < instrs.Count; i++) {
if (instrs[i].OpCode.Code != Code.Conv_R_Un)
continue;
if (instrs[i + 1].OpCode.Code != Code.Conv_R8)
continue;
if (instrs[i + 2].OpCode.Code != Code.Conv_U4)
continue;
if (instrs[i + 3].OpCode.Code != Code.Add)
continue;
int newEndIndex = i + 3;

int newStartIndex = -1;
for (int j = newEndIndex; j >= 0; j--) {
// Search upwards for array access.
if (instrs[j].OpCode.Code != Code.Ldelem_U1)
continue;

// Go down to next local load, where actual decryption should begin.
for (int k = j + 1; k < newEndIndex; k++) {
if (instrs[k].IsLdloc()) {
newStartIndex = k;
break;
}
}
break;
}

endIndex = newEndIndex;
startIndex = newStartIndex;
tmpLocal = CheckLocal(instrs[startIndex], true);
return true;
}
endIndex = 0;
startIndex = 0;
tmpLocal = null;
return false;
}

bool FindStart(IList<Instruction> instrs, out int startIndex, out Local tmpLocal) {
for (int i = 0; i + 8 < instrs.Count; i++) {
if (instrs[i].OpCode.Code != Code.Conv_U)
Expand Down Expand Up @@ -675,18 +631,6 @@ bool FindEnd(IList<Instruction> instrs, int startIndex, out int endIndex) {
return false;
}

/**
* Gets the Local referenced by the instruction if it's either ldloc or stloc (determined by isLdloc).
*/
Local CheckLocal(Instruction instr, bool isLdloc) {
if (isLdloc && !instr.IsLdloc())
return null;
if (!isLdloc && !instr.IsStloc())
return null;

return instr.GetLocal(locals);
}

public byte[] Decrypt(EmbeddedResource resource) {
var encrypted = resource.CreateReader().ToArray();
var decrypted = new byte[encrypted.Length];
Expand Down Expand Up @@ -766,14 +710,10 @@ public byte[] Encrypt(byte[] data) {
}
}

class DecrypterV4 : IDecrypter {
class DecrypterV4 : EmulatingDecrypterBase, IDecrypter {
readonly byte[] key, iv;
MethodDef decryptMethod;
MethodDef emuMethod;
List<Instruction> instructions;
List<Local> locals;
readonly InstructionEmulator instrEmulator = new InstructionEmulator();
Local emuLocal;

public DnrDecrypterType DecrypterType => DnrDecrypterType.V4;

Expand Down Expand Up @@ -908,43 +848,6 @@ bool Find(IList<Instruction> instrs, out int startIndex, out int endIndex, out L
return true;
}

bool FindStartEnd(IList<Instruction> instrs, out int startIndex, out int endIndex, out Local tmpLocal) {
for (int i = 0; i + 8 < instrs.Count; i++) {
if (instrs[i].OpCode.Code != Code.Conv_R_Un)
continue;
if (instrs[i + 1].OpCode.Code != Code.Conv_R8)
continue;
if (instrs[i + 2].OpCode.Code != Code.Conv_U4)
continue;
if (instrs[i + 3].OpCode.Code != Code.Add)
continue;
int newEndIndex = i + 3;
int newStartIndex = -1;
for (int j = newEndIndex; j >= 0; j--) {
// Search upwards for array access.
if (instrs[j].OpCode.Code != Code.Ldelem_U1)
continue;

// Go down to next local load, where actual decryption should begin.
for (int k = j + 1; k < newEndIndex; k++) {
if (instrs[k].IsLdloc()) {
newStartIndex = k;
break;
}
}
break;
}
endIndex = newEndIndex;
startIndex = newStartIndex;
tmpLocal = CheckLocal(instrs[startIndex], true);
return true;
}
endIndex = 0;
startIndex = 0;
tmpLocal = null;
return false;
}

bool FindStart(IList<Instruction> instrs, out int startIndex, out Local tmpLocal) {
for (int i = 0; i + 8 < instrs.Count; i++) {
if (instrs[i].OpCode.Code != Code.Conv_U)
Expand Down Expand Up @@ -1000,15 +903,6 @@ bool FindEnd(IList<Instruction> instrs, int startIndex, out int endIndex) {
return false;
}

Local CheckLocal(Instruction instr, bool isLdloc) {
if (isLdloc && !instr.IsLdloc())
return null;
else if (!isLdloc && !instr.IsStloc())
return null;

return instr.GetLocal(locals);
}

public byte[] Decrypt(EmbeddedResource resource) {
var encrypted = resource.CreateReader().ToArray();
var decrypted = new byte[encrypted.Length];
Expand Down
Loading
Loading