Unpack compressed Confuser assemblies
This commit is contained in:
parent
7321e51a78
commit
2e99bac40c
|
@ -81,6 +81,7 @@
|
|||
<Compile Include="deobfuscators\Confuser\ProxyCallFixerV1.cs" />
|
||||
<Compile Include="deobfuscators\Confuser\ResourceDecrypter.cs" />
|
||||
<Compile Include="deobfuscators\Confuser\StringDecrypter.cs" />
|
||||
<Compile Include="deobfuscators\Confuser\Unpacker.cs" />
|
||||
<Compile Include="deobfuscators\Confuser\x86Emulator.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\v4\ProxyCallFixer.cs" />
|
||||
<Compile Include="deobfuscators\ILProtector\MethodReader.cs" />
|
||||
|
|
|
@ -79,6 +79,7 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
SingleValueInliner singleValueInliner;
|
||||
DoubleValueInliner doubleValueInliner;
|
||||
StringDecrypter stringDecrypter;
|
||||
Unpacker unpacker;
|
||||
|
||||
bool startedDeobfuscating = false;
|
||||
|
||||
|
@ -129,7 +130,8 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
toInt32(antiDumping != null ? antiDumping.Detected : false) +
|
||||
toInt32(resourceDecrypter != null ? resourceDecrypter.Detected : false) +
|
||||
toInt32(constantsDecrypter != null ? constantsDecrypter.Detected : false) +
|
||||
toInt32(stringDecrypter != null ? stringDecrypter.Detected : false);
|
||||
toInt32(stringDecrypter != null ? stringDecrypter.Detected : false) +
|
||||
toInt32(unpacker != null ? unpacker.Detected : false);
|
||||
if (sum > 0)
|
||||
val += 100 + 10 * (sum - 1);
|
||||
|
||||
|
@ -171,6 +173,9 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
antiDumping.find(DeobfuscatedFile);
|
||||
stringDecrypter = new StringDecrypter(module);
|
||||
stringDecrypter.find(DeobfuscatedFile);
|
||||
initializeStringDecrypter();
|
||||
unpacker = new Unpacker(module);
|
||||
unpacker.find(DeobfuscatedFile, this);
|
||||
}
|
||||
|
||||
byte[] getFileData() {
|
||||
|
@ -179,29 +184,48 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
return ModuleBytes = DeobUtils.readModule(module);
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum DecryptState {
|
||||
CanDecryptMethods = 1,
|
||||
CanUnpack = 2,
|
||||
}
|
||||
DecryptState decryptState = DecryptState.CanDecryptMethods | DecryptState.CanUnpack;
|
||||
public override bool getDecryptedModule(int count, ref byte[] newFileData, ref DumpedMethods dumpedMethods) {
|
||||
if (count != 0 || (!jitMethodsDecrypter.Detected && !memoryMethodsDecrypter.Detected))
|
||||
return false;
|
||||
|
||||
byte[] fileData = getFileData();
|
||||
var peImage = new PeImage(fileData);
|
||||
|
||||
if (jitMethodsDecrypter != null && jitMethodsDecrypter.Detected) {
|
||||
jitMethodsDecrypter.initialize();
|
||||
if (!jitMethodsDecrypter.decrypt(peImage, fileData, ref dumpedMethods))
|
||||
return false;
|
||||
if ((decryptState & DecryptState.CanDecryptMethods) != 0) {
|
||||
if (jitMethodsDecrypter != null && jitMethodsDecrypter.Detected) {
|
||||
jitMethodsDecrypter.initialize();
|
||||
if (!jitMethodsDecrypter.decrypt(peImage, fileData, ref dumpedMethods))
|
||||
return false;
|
||||
|
||||
newFileData = fileData;
|
||||
return true;
|
||||
decryptState &= ~DecryptState.CanDecryptMethods;
|
||||
newFileData = fileData;
|
||||
ModuleBytes = newFileData;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (memoryMethodsDecrypter != null && memoryMethodsDecrypter.Detected) {
|
||||
memoryMethodsDecrypter.initialize();
|
||||
if (!memoryMethodsDecrypter.decrypt(peImage, fileData, ref dumpedMethods))
|
||||
return false;
|
||||
|
||||
decryptState &= ~DecryptState.CanDecryptMethods;
|
||||
newFileData = fileData;
|
||||
ModuleBytes = newFileData;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (memoryMethodsDecrypter != null && memoryMethodsDecrypter.Detected) {
|
||||
memoryMethodsDecrypter.initialize();
|
||||
if (!memoryMethodsDecrypter.decrypt(peImage, fileData, ref dumpedMethods))
|
||||
return false;
|
||||
|
||||
newFileData = fileData;
|
||||
return true;
|
||||
if ((decryptState & DecryptState.CanUnpack) != 0) {
|
||||
if (unpacker != null && unpacker.Detected) {
|
||||
decryptState &= ~DecryptState.CanUnpack;
|
||||
decryptState |= DecryptState.CanDecryptMethods;
|
||||
newFileData = unpacker.unpack();
|
||||
ModuleBytes = newFileData;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -210,6 +234,7 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
public override IDeobfuscator moduleReloaded(ModuleDefinition module) {
|
||||
var newOne = new Deobfuscator(options);
|
||||
DeobfuscatedFile.setDeobfuscator(newOne);
|
||||
newOne.decryptState = decryptState;
|
||||
newOne.DeobfuscatedFile = DeobfuscatedFile;
|
||||
newOne.ModuleBytes = ModuleBytes;
|
||||
newOne.setModule(module);
|
||||
|
@ -224,6 +249,7 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
|
||||
removeObfuscatorAttribute();
|
||||
initializeConstantsDecrypter();
|
||||
initializeStringDecrypter();
|
||||
|
||||
if (jitMethodsDecrypter != null) {
|
||||
addModuleCctorInitCallToBeRemoved(jitMethodsDecrypter.InitMethod);
|
||||
|
@ -250,19 +276,26 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
if (proxyCallFixerV1 != null)
|
||||
proxyCallFixerV1.find();
|
||||
|
||||
startedDeobfuscating = true;
|
||||
}
|
||||
|
||||
bool hasInitializedStringDecrypter = false;
|
||||
void initializeStringDecrypter() {
|
||||
if (hasInitializedStringDecrypter)
|
||||
return;
|
||||
hasInitializedStringDecrypter = true;
|
||||
|
||||
if (stringDecrypter != null) {
|
||||
stringDecrypter.initialize();
|
||||
staticStringInliner.add(stringDecrypter.Method, (method, gim, args) => stringDecrypter.decrypt(staticStringInliner.Method, (int)args[0]));
|
||||
}
|
||||
|
||||
startedDeobfuscating = true;
|
||||
}
|
||||
|
||||
bool hasInitializeConstantsDecrypter = false;
|
||||
bool hasInitializedConstantsDecrypter = false;
|
||||
void initializeConstantsDecrypter() {
|
||||
if (hasInitializeConstantsDecrypter)
|
||||
if (hasInitializedConstantsDecrypter)
|
||||
return;
|
||||
hasInitializeConstantsDecrypter = true;
|
||||
hasInitializedConstantsDecrypter = true;
|
||||
|
||||
decryptResources();
|
||||
constantsDecrypter.initialize();
|
||||
|
|
104
de4dot.code/deobfuscators/Confuser/Unpacker.cs
Normal file
104
de4dot.code/deobfuscators/Confuser/Unpacker.cs
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
Copyright (C) 2011-2012 de4dot@gmail.com
|
||||
|
||||
This file is part of de4dot.
|
||||
|
||||
de4dot is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
de4dot is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Confuser {
|
||||
class Unpacker {
|
||||
ModuleDefinition module;
|
||||
EmbeddedResource resource;
|
||||
|
||||
public bool Detected {
|
||||
get { return resource != null; }
|
||||
}
|
||||
|
||||
public Unpacker(ModuleDefinition module) {
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
static string[] requiredFields = new string[] {
|
||||
"System.String",
|
||||
};
|
||||
static string[] requiredEntryPointLocals = new string[] {
|
||||
"System.Byte[]",
|
||||
"System.Diagnostics.Process",
|
||||
"System.Int32",
|
||||
"System.IO.BinaryReader",
|
||||
"System.IO.Stream",
|
||||
"System.String",
|
||||
"System.String[]",
|
||||
};
|
||||
public void find(ISimpleDeobfuscator simpleDeobfuscator, IDeobfuscator deob) {
|
||||
var entryPoint = module.EntryPoint;
|
||||
if (entryPoint == null)
|
||||
return;
|
||||
if (!new LocalTypes(entryPoint).all(requiredEntryPointLocals))
|
||||
return;
|
||||
var type = entryPoint.DeclaringType;
|
||||
if (!new FieldTypes(type).all(requiredFields))
|
||||
return;
|
||||
if (findDecryptMethod(type) == null)
|
||||
return;
|
||||
|
||||
var cctor = DotNetUtils.getMethod(type, ".cctor");
|
||||
if (cctor == null)
|
||||
return;
|
||||
|
||||
simpleDeobfuscator.deobfuscate(cctor);
|
||||
simpleDeobfuscator.decryptStrings(cctor, deob);
|
||||
|
||||
resource = findResource(cctor);
|
||||
}
|
||||
|
||||
EmbeddedResource findResource(MethodDefinition method) {
|
||||
return DotNetUtils.getResource(module, DotNetUtils.getCodeStrings(method)) as EmbeddedResource;
|
||||
}
|
||||
|
||||
static string[] requiredDecryptLocals = new string[] {
|
||||
"System.Byte[]",
|
||||
"System.IO.Compression.DeflateStream",
|
||||
"System.IO.MemoryStream",
|
||||
};
|
||||
static MethodDefinition findDecryptMethod(TypeDefinition type) {
|
||||
foreach (var method in type.Methods) {
|
||||
if (!method.IsStatic || method.Body == null)
|
||||
continue;
|
||||
if (!DotNetUtils.isMethod(method, "System.Byte[]", "(System.Byte[])"))
|
||||
continue;
|
||||
if (!new LocalTypes(method).all(requiredDecryptLocals))
|
||||
continue;
|
||||
|
||||
return method;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] unpack() {
|
||||
if (resource == null)
|
||||
return null;
|
||||
var data = resource.GetResourceData();
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
data[i] ^= (byte)i;
|
||||
data = DeobUtils.inflate(data, true);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user