Support Confuser 1.7 r74788 constants encrypter
This commit is contained in:
parent
6baa3f0e2f
commit
64b48ec315
|
@ -115,13 +115,18 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
return decrypted;
|
||||
}
|
||||
|
||||
static readonly byte[] defaultDecryptKey = new byte[8];
|
||||
public static byte[] decrypt(uint seed, byte[] encrypted) {
|
||||
return decrypt(seed, encrypted, defaultDecryptKey);
|
||||
}
|
||||
|
||||
public static byte[] decrypt(uint seed, byte[] encrypted, byte[] key) {
|
||||
var decrypted = new byte[encrypted.Length];
|
||||
ushort _m = (ushort)(seed >> 16);
|
||||
ushort _c = (ushort)seed;
|
||||
ushort m = _c; ushort c = _m;
|
||||
for (int i = 0; i < decrypted.Length; i++) {
|
||||
decrypted[i] = (byte)(encrypted[i] ^ (seed * m + c));
|
||||
decrypted[i] = (byte)(encrypted[i] ^ (seed * m + c) ^ key[i & 7]);
|
||||
m = (ushort)(seed * m + _m);
|
||||
c = (ushort)(seed * c + _c);
|
||||
}
|
||||
|
|
|
@ -350,6 +350,41 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int getDynamicEndIndex_v17_r74788(MethodDefinition method, VariableDefinition local) {
|
||||
var instrs = method.Body.Instructions;
|
||||
for (int i = 0; i < instrs.Count - 11; i++) {
|
||||
var stloc = instrs[i];
|
||||
if (!DotNetUtils.isStloc(stloc) || DotNetUtils.getLocalVar(method.Body.Variables, stloc) != local)
|
||||
continue;
|
||||
if (!DotNetUtils.isLdloc(instrs[i + 1]))
|
||||
continue;
|
||||
if (!DotNetUtils.isLdloc(instrs[i + 2]))
|
||||
continue;
|
||||
if (!DotNetUtils.isLdloc(instrs[i + 3]))
|
||||
continue;
|
||||
if (!DotNetUtils.isLdloc(instrs[i + 4]))
|
||||
continue;
|
||||
if (!DotNetUtils.isLdloc(instrs[i + 5]))
|
||||
continue;
|
||||
var ldci4 = instrs[i + 6];
|
||||
if (!DotNetUtils.isLdcI4(ldci4) || DotNetUtils.getLdcI4Value(ldci4) != 8)
|
||||
continue;
|
||||
if (instrs[i + 7].OpCode.Code != Code.Rem)
|
||||
continue;
|
||||
if (instrs[i + 8].OpCode.Code != Code.Ldelem_U1)
|
||||
continue;
|
||||
if (instrs[i + 9].OpCode.Code != Code.Xor)
|
||||
continue;
|
||||
if (instrs[i + 10].OpCode.Code != Code.Conv_U1)
|
||||
continue;
|
||||
if (instrs[i + 11].OpCode.Code != Code.Stelem_I1)
|
||||
continue;
|
||||
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int getDynamicStartIndex_v17_r73740(MethodDefinition method, int endIndex) {
|
||||
if (endIndex < 0)
|
||||
return -1;
|
||||
|
@ -365,37 +400,48 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static readonly byte[] defaultDecryptKey_v17 = new byte[8];
|
||||
protected byte[] decryptConstant_v17_r73740_dynamic(DecrypterInfo info, byte[] encrypted, uint offs, uint key) {
|
||||
return decryptConstant_v17_r73740_dynamic(info, encrypted, offs, key, defaultDecryptKey_v17);
|
||||
}
|
||||
|
||||
protected byte[] decryptConstant_v17_r73740_dynamic(DecrypterInfo info, byte[] encrypted, uint offs, uint key1, byte[] key2) {
|
||||
var local = getDynamicLocal_v17_r73740(info.decryptMethod);
|
||||
if (local == null)
|
||||
throw new ApplicationException("Could not find local");
|
||||
|
||||
int endIndex = getDynamicEndIndex_v17_r73740(info.decryptMethod, local);
|
||||
if (endIndex < 0)
|
||||
endIndex = getDynamicEndIndex_v17_r74788(info.decryptMethod, local);
|
||||
int startIndex = getDynamicStartIndex_v17_r73740(info.decryptMethod, endIndex);
|
||||
if (startIndex < 0)
|
||||
throw new ApplicationException("Could not find start/end index");
|
||||
|
||||
var constReader = new ConstantsReader(info.decryptMethod);
|
||||
return decrypt(encrypted, key, magic => {
|
||||
return decrypt(encrypted, key1, (magic, i) => {
|
||||
constReader.setConstantInt32(local, magic);
|
||||
int index = startIndex, result;
|
||||
if (!constReader.getNextInt32(ref index, out result) || index != endIndex)
|
||||
throw new ApplicationException("Could not decrypt integer");
|
||||
return (byte)result;
|
||||
return (byte)(result ^ key2[i & 7]);
|
||||
});
|
||||
}
|
||||
|
||||
protected byte[] decryptConstant_v17_r73764_native(DecrypterInfo info, byte[] encrypted, uint offs, uint key) {
|
||||
var x86Emu = new x86Emulator(new PeImage(fileData));
|
||||
return decrypt(encrypted, key, magic => (byte)x86Emu.emulate((uint)nativeMethod.RVA, magic));
|
||||
return decryptConstant_v17_r73764_native(info, encrypted, offs, key, defaultDecryptKey_v17);
|
||||
}
|
||||
|
||||
static byte[] decrypt(byte[] encrypted, uint key, Func<uint, byte> decryptFunc) {
|
||||
protected byte[] decryptConstant_v17_r73764_native(DecrypterInfo info, byte[] encrypted, uint offs, uint key1, byte[] key2) {
|
||||
var x86Emu = new x86Emulator(new PeImage(fileData));
|
||||
return decrypt(encrypted, key1, (magic, i) => (byte)(x86Emu.emulate((uint)nativeMethod.RVA, magic) ^ key2[i & 7]));
|
||||
}
|
||||
|
||||
static byte[] decrypt(byte[] encrypted, uint key, Func<uint, int, byte> decryptFunc) {
|
||||
var reader = new BinaryReader(new MemoryStream(encrypted));
|
||||
var decrypted = new byte[reader.ReadInt32() ^ key];
|
||||
for (int i = 0; i < decrypted.Length; i++) {
|
||||
uint magic = Utils.readEncodedUInt32(reader);
|
||||
decrypted[i] = decryptFunc(magic);
|
||||
decrypted[i] = decryptFunc(magic, i);
|
||||
}
|
||||
|
||||
return decrypted;
|
||||
|
|
|
@ -34,11 +34,14 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
v17_r74708_normal,
|
||||
v17_r74708_dynamic,
|
||||
v17_r74708_native,
|
||||
v17_r74788_normal,
|
||||
v17_r74788_dynamic,
|
||||
v17_r74788_native,
|
||||
}
|
||||
|
||||
class DecrypterInfoV17 : DecrypterInfo {
|
||||
public readonly ConfuserVersion version = ConfuserVersion.Unknown;
|
||||
public uint key4;
|
||||
public uint key4, key5;
|
||||
|
||||
public DecrypterInfoV17(ConfuserVersion version, MethodDefinition decryptMethod) {
|
||||
this.version = version;
|
||||
|
@ -54,6 +57,8 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
return false;
|
||||
if (!findKey4(decryptMethod, out key4))
|
||||
return false;
|
||||
if (!findKey5(decryptMethod, out key5))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -86,9 +91,14 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
|
||||
bool findKey4(MethodDefinition method, out uint key) {
|
||||
switch (version) {
|
||||
case ConfuserVersion.v17_r74708_normal: return findKey4_normal(method, out key);
|
||||
case ConfuserVersion.v17_r74708_dynamic: return findKey4_other(method, out key);
|
||||
case ConfuserVersion.v17_r74708_native: return findKey4_other(method, out key);
|
||||
case ConfuserVersion.v17_r74708_normal:
|
||||
case ConfuserVersion.v17_r74788_normal:
|
||||
return findKey4_normal(method, out key);
|
||||
case ConfuserVersion.v17_r74708_dynamic:
|
||||
case ConfuserVersion.v17_r74708_native:
|
||||
case ConfuserVersion.v17_r74788_dynamic:
|
||||
case ConfuserVersion.v17_r74788_native:
|
||||
return findKey4_other(method, out key);
|
||||
default:
|
||||
throw new ApplicationException("Invalid version");
|
||||
}
|
||||
|
@ -136,6 +146,37 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
key = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool findKey5(MethodDefinition method, out uint key) {
|
||||
switch (version) {
|
||||
case ConfuserVersion.v17_r74788_normal:
|
||||
case ConfuserVersion.v17_r74788_dynamic:
|
||||
case ConfuserVersion.v17_r74788_native:
|
||||
return findKey5_v17_r74788(method, out key);
|
||||
default:
|
||||
key = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool findKey5_v17_r74788(MethodDefinition method, out uint key) {
|
||||
var instrs = method.Body.Instructions;
|
||||
for (int i = 0; i < instrs.Count; i++) {
|
||||
i = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Reflection.Module System.Reflection.Assembly::GetModule(System.String)");
|
||||
if (i < 0)
|
||||
break;
|
||||
if (i + 1 >= instrs.Count)
|
||||
break;
|
||||
var ldci4 = instrs[i + 1];
|
||||
if (!DotNetUtils.isLdcI4(ldci4))
|
||||
continue;
|
||||
|
||||
key = (uint)DotNetUtils.getLdcI4Value(ldci4);
|
||||
return true;
|
||||
}
|
||||
key = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Detected {
|
||||
|
@ -168,16 +209,23 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
var method = getDecryptMethod();
|
||||
if (method == null)
|
||||
return;
|
||||
if (DotNetUtils.callsMethod(method, "System.Reflection.Module System.Reflection.Assembly::GetModule(System.String)"))
|
||||
initVersion(method, ConfuserVersion.v17_r74788_normal, ConfuserVersion.v17_r74788_dynamic, ConfuserVersion.v17_r74788_native);
|
||||
else
|
||||
initVersion(method, ConfuserVersion.v17_r74708_normal, ConfuserVersion.v17_r74708_dynamic, ConfuserVersion.v17_r74708_native);
|
||||
|
||||
initMethod = cctor;
|
||||
}
|
||||
|
||||
void initVersion(MethodDefinition method, ConfuserVersion normal, ConfuserVersion dynamic, ConfuserVersion native) {
|
||||
if (DeobUtils.hasInteger(method, 0x100) &&
|
||||
DeobUtils.hasInteger(method, 0x10000) &&
|
||||
DeobUtils.hasInteger(method, 0xFFFF))
|
||||
version = ConfuserVersion.v17_r74708_normal;
|
||||
version = normal;
|
||||
else if ((nativeMethod = findNativeMethod(method)) == null)
|
||||
version = ConfuserVersion.v17_r74708_dynamic;
|
||||
version = dynamic;
|
||||
else
|
||||
version = ConfuserVersion.v17_r74708_native;
|
||||
|
||||
initMethod = cctor;
|
||||
version = native;
|
||||
}
|
||||
|
||||
MethodDefinition getDecryptMethod() {
|
||||
|
@ -215,6 +263,9 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
case ConfuserVersion.v17_r74708_normal: return decryptConstant_v17_r74708_normal(info, encrypted, offs, typeCode);
|
||||
case ConfuserVersion.v17_r74708_dynamic: return decryptConstant_v17_r74708_dynamic(info, encrypted, offs, typeCode);
|
||||
case ConfuserVersion.v17_r74708_native: return decryptConstant_v17_r74708_native(info, encrypted, offs, typeCode);
|
||||
case ConfuserVersion.v17_r74788_normal: return decryptConstant_v17_r74788_normal(info, encrypted, offs, typeCode);
|
||||
case ConfuserVersion.v17_r74788_dynamic: return decryptConstant_v17_r74788_dynamic(info, encrypted, offs, typeCode);
|
||||
case ConfuserVersion.v17_r74788_native: return decryptConstant_v17_r74788_native(info, encrypted, offs, typeCode);
|
||||
default:
|
||||
throw new ApplicationException("Invalid version");
|
||||
}
|
||||
|
@ -232,6 +283,22 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
return decryptConstant_v17_r73764_native(info, encrypted, offs, info.key4);
|
||||
}
|
||||
|
||||
byte[] decryptConstant_v17_r74788_normal(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) {
|
||||
return ConfuserUtils.decrypt(info.key4 * (offs + typeCode), encrypted, getKey_v17_r74788(info));
|
||||
}
|
||||
|
||||
byte[] decryptConstant_v17_r74788_dynamic(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) {
|
||||
return decryptConstant_v17_r73740_dynamic(info, encrypted, offs, info.key4, getKey_v17_r74788(info));
|
||||
}
|
||||
|
||||
byte[] decryptConstant_v17_r74788_native(DecrypterInfoV17 info, byte[] encrypted, uint offs, byte typeCode) {
|
||||
return decryptConstant_v17_r73764_native(info, encrypted, offs, info.key4, getKey_v17_r74788(info));
|
||||
}
|
||||
|
||||
byte[] getKey_v17_r74788(DecrypterInfoV17 info) {
|
||||
return module.GetSignatureBlob(info.decryptMethod.MetadataToken.ToUInt32() ^ info.key5);
|
||||
}
|
||||
|
||||
public override void initialize() {
|
||||
if ((resource = findResource(initMethod)) == null)
|
||||
throw new ApplicationException("Could not find encrypted consts resource");
|
||||
|
|
Loading…
Reference in New Issue
Block a user