Detect Confuser 1.4 r58802 proxy methods creator
This commit is contained in:
parent
e3e051b876
commit
9cf4887061
|
@ -46,6 +46,7 @@ namespace de4dot.code.deobfuscators.Confuser {
|
||||||
v13_r55346,
|
v13_r55346,
|
||||||
v13_r55604,
|
v13_r55604,
|
||||||
v14_r58564,
|
v14_r58564,
|
||||||
|
v14_r58802,
|
||||||
v14_r58857,
|
v14_r58857,
|
||||||
v17_r73740_normal,
|
v17_r73740_normal,
|
||||||
v17_r73740_native,
|
v17_r73740_native,
|
||||||
|
@ -206,6 +207,7 @@ namespace de4dot.code.deobfuscators.Confuser {
|
||||||
case ConfuserVersion.v13_r55346:
|
case ConfuserVersion.v13_r55346:
|
||||||
case ConfuserVersion.v13_r55604:
|
case ConfuserVersion.v13_r55604:
|
||||||
case ConfuserVersion.v14_r58564:
|
case ConfuserVersion.v14_r58564:
|
||||||
|
case ConfuserVersion.v14_r58802:
|
||||||
getCallInfo_v10_r48717(info, creatorInfo, out calledMethod, out callOpcode);
|
getCallInfo_v10_r48717(info, creatorInfo, out calledMethod, out callOpcode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -265,18 +267,22 @@ namespace de4dot.code.deobfuscators.Confuser {
|
||||||
}
|
}
|
||||||
|
|
||||||
void getCallInfo_v10_r48717(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out MethodReference calledMethod, out OpCode callOpcode) {
|
void getCallInfo_v10_r48717(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out MethodReference calledMethod, out OpCode callOpcode) {
|
||||||
bool? isNew = isNewFieldNameEncoding(info);
|
bool isNew = creatorInfo.version == ConfuserVersion.v14_r58802;
|
||||||
if (isNew == null) {
|
|
||||||
|
int offs = creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt ? 2 : 1;
|
||||||
|
if (isNew)
|
||||||
|
offs--;
|
||||||
|
int callvirtOffs = isNew ? 0 : 1;
|
||||||
|
|
||||||
|
// This is an obfuscator bug. Field names are stored in the #Strings heap,
|
||||||
|
// and strings in that heap are UTF8 zero terminated strings, but Confuser
|
||||||
|
// can generate names with zeros in them. This was fixed in 1.4 58857.
|
||||||
|
if (offs + 2 > info.field.Name.Length) {
|
||||||
calledMethod = null;
|
calledMethod = null;
|
||||||
callOpcode = OpCodes.Call;
|
callOpcode = OpCodes.Call;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int offs = creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt ? 2 : 1;
|
|
||||||
if (isNew.Value)
|
|
||||||
offs--;
|
|
||||||
int callvirtOffs = isNew.Value ? 0 : 1;
|
|
||||||
|
|
||||||
uint token = BitConverter.ToUInt32(Encoding.Unicode.GetBytes(info.field.Name.ToCharArray(), offs, 2), 0) ^ creatorInfo.magic;
|
uint token = BitConverter.ToUInt32(Encoding.Unicode.GetBytes(info.field.Name.ToCharArray(), offs, 2), 0) ^ creatorInfo.magic;
|
||||||
uint table = token >> 24;
|
uint table = token >> 24;
|
||||||
if (table != 0 && table != 6 && table != 0x0A && table != 0x2B)
|
if (table != 0 && table != 6 && table != 0x0A && table != 0x2B)
|
||||||
|
@ -284,7 +290,7 @@ namespace de4dot.code.deobfuscators.Confuser {
|
||||||
|
|
||||||
// 1.3 r55346 now correctly uses method reference tokens and finally fixed the old
|
// 1.3 r55346 now correctly uses method reference tokens and finally fixed the old
|
||||||
// bug of using methoddef tokens to reference external methods.
|
// bug of using methoddef tokens to reference external methods.
|
||||||
if (isNew.Value || info.field.Name[0] == (char)1 || table != 0x06)
|
if (isNew || info.field.Name[0] == (char)1 || table != 0x06)
|
||||||
calledMethod = (MethodReference)module.LookupToken((int)token);
|
calledMethod = (MethodReference)module.LookupToken((int)token);
|
||||||
else {
|
else {
|
||||||
var asmRef = module.AssemblyReferences[info.field.Name[0] - 2];
|
var asmRef = module.AssemblyReferences[info.field.Name[0] - 2];
|
||||||
|
@ -297,35 +303,6 @@ namespace de4dot.code.deobfuscators.Confuser {
|
||||||
callOpcode = getCallOpCode(creatorInfo, isCallvirt);
|
callOpcode = getCallOpCode(creatorInfo, isCallvirt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if Confuser 1.4 r58802 or later
|
|
||||||
bool? isNewFieldNameEncoding(DelegateInitInfo info) {
|
|
||||||
var creatorInfo = methodToInfo.find(info.creatorMethod);
|
|
||||||
int oldLen, newLen;
|
|
||||||
switch (creatorInfo.proxyCreatorType) {
|
|
||||||
case ProxyCreatorType.Newobj:
|
|
||||||
oldLen = 3;
|
|
||||||
newLen = 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ProxyCreatorType.CallOrCallvirt:
|
|
||||||
oldLen = 4;
|
|
||||||
newLen = 3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: throw new ApplicationException("Invalid proxy creator type");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.field.Name.Length == oldLen)
|
|
||||||
return false;
|
|
||||||
if (info.field.Name.Length != newLen) {
|
|
||||||
// This is an obfuscator bug. Field names are stored in the #Strings heap,
|
|
||||||
// and strings in that heap are UTF8 zero terminated strings, but Confuser
|
|
||||||
// can generate names with zeros in them. This was fixed in 1.4 58857.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void getCallInfo_v14_r58857(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out MethodReference calledMethod, out OpCode callOpcode) {
|
void getCallInfo_v14_r58857(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out MethodReference calledMethod, out OpCode callOpcode) {
|
||||||
int offs = creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt ? 1 : 0;
|
int offs = creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt ? 1 : 0;
|
||||||
var nameInfo = decryptFieldName(info.field.Name);
|
var nameInfo = decryptFieldName(info.field.Name);
|
||||||
|
@ -501,8 +478,12 @@ namespace de4dot.code.deobfuscators.Confuser {
|
||||||
MethodDefinition nativeMethod = null;
|
MethodDefinition nativeMethod = null;
|
||||||
uint magic;
|
uint magic;
|
||||||
if (findMagic_v14_r58564(method, out magic)) {
|
if (findMagic_v14_r58564(method, out magic)) {
|
||||||
if (!DotNetUtils.callsMethod(method, "System.Byte[] System.Convert::FromBase64String(System.String)"))
|
if (!DotNetUtils.callsMethod(method, "System.Byte[] System.Convert::FromBase64String(System.String)")) {
|
||||||
|
if (!isMethodCreator_v14_r58802(method, proxyType))
|
||||||
theVersion = ConfuserVersion.v14_r58564;
|
theVersion = ConfuserVersion.v14_r58564;
|
||||||
|
else
|
||||||
|
theVersion = ConfuserVersion.v14_r58802;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
theVersion = ConfuserVersion.v14_r58857;
|
theVersion = ConfuserVersion.v14_r58857;
|
||||||
}
|
}
|
||||||
|
@ -559,6 +540,48 @@ namespace de4dot.code.deobfuscators.Confuser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isMethodCreator_v14_r58802(MethodDefinition method, ProxyCreatorType proxyType) {
|
||||||
|
int index = getFieldNameIndex(method);
|
||||||
|
if (index < 0)
|
||||||
|
throw new ApplicationException("Could not find field name index");
|
||||||
|
switch (proxyType) {
|
||||||
|
case ProxyCreatorType.Newobj:
|
||||||
|
if (index == 1)
|
||||||
|
return false;
|
||||||
|
if (index == 0)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ProxyCreatorType.CallOrCallvirt:
|
||||||
|
if (index == 2)
|
||||||
|
return false;
|
||||||
|
if (index == 1)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: throw new ApplicationException("Invalid proxy creator type");
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ApplicationException("Could not find field name index");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getFieldNameIndex(MethodDefinition method) {
|
||||||
|
var instrs = method.Body.Instructions;
|
||||||
|
for (int i = 0; i < instrs.Count; i++) {
|
||||||
|
i = ConfuserUtils.findCallMethod(instrs, i, Code.Callvirt, "System.Byte[] System.Text.Encoding::GetBytes(System.Char[],System.Int32,System.Int32)");
|
||||||
|
if (i < 0)
|
||||||
|
break;
|
||||||
|
if (i < 2)
|
||||||
|
continue;
|
||||||
|
var ldci4 = instrs[i - 2];
|
||||||
|
if (!DotNetUtils.isLdcI4(ldci4))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return DotNetUtils.getLdcI4Value(ldci4);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int countCalls(MethodDefinition method, string methodFullName) {
|
static int countCalls(MethodDefinition method, string methodFullName) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
foreach (var instr in method.Body.Instructions) {
|
foreach (var instr in method.Body.Instructions) {
|
||||||
|
@ -1031,6 +1054,11 @@ namespace de4dot.code.deobfuscators.Confuser {
|
||||||
|
|
||||||
case ConfuserVersion.v14_r58564:
|
case ConfuserVersion.v14_r58564:
|
||||||
minRev = 58564;
|
minRev = 58564;
|
||||||
|
maxRev = 58741;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ConfuserVersion.v14_r58802:
|
||||||
|
minRev = 58802;
|
||||||
maxRev = 58852;
|
maxRev = 58852;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user