Support methods proxy in Confuser 1.0 r48717
This commit is contained in:
parent
4a6713b728
commit
e657db9c8c
|
@ -30,6 +30,13 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
MethodDefinitionAndDeclaringTypeDict<ProxyCreatorInfo> methodToInfo = new MethodDefinitionAndDeclaringTypeDict<ProxyCreatorInfo>();
|
||||
FieldDefinitionAndDeclaringTypeDict<MethodDefinition> fieldToMethod = new FieldDefinitionAndDeclaringTypeDict<MethodDefinition>();
|
||||
string ourAsm;
|
||||
ConfuserVersion version = ConfuserVersion.Unknown;
|
||||
|
||||
enum ConfuserVersion {
|
||||
Unknown,
|
||||
v10_r42915,
|
||||
v10_r48717,
|
||||
}
|
||||
|
||||
enum ProxyCreatorType {
|
||||
None,
|
||||
|
@ -40,10 +47,12 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
class ProxyCreatorInfo {
|
||||
public readonly MethodDefinition creatorMethod;
|
||||
public readonly ProxyCreatorType proxyCreatorType;
|
||||
public readonly ConfuserVersion version;
|
||||
|
||||
public ProxyCreatorInfo(MethodDefinition creatorMethod, ProxyCreatorType proxyCreatorType) {
|
||||
public ProxyCreatorInfo(MethodDefinition creatorMethod, ProxyCreatorType proxyCreatorType, ConfuserVersion version) {
|
||||
this.creatorMethod = creatorMethod;
|
||||
this.proxyCreatorType = proxyCreatorType;
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,6 +61,11 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
public readonly FieldDefinition field;
|
||||
public readonly MethodDefinition creatorMethod;
|
||||
|
||||
public DelegateInitInfo(FieldDefinition field, MethodDefinition creatorMethod) {
|
||||
this.field = field;
|
||||
this.creatorMethod = creatorMethod;
|
||||
}
|
||||
|
||||
public DelegateInitInfo(string data, FieldDefinition field, MethodDefinition creatorMethod) {
|
||||
this.data = Convert.FromBase64String(data);
|
||||
this.field = field;
|
||||
|
@ -99,6 +113,21 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
var info = (DelegateInitInfo)context;
|
||||
var creatorInfo = methodToInfo.find(info.creatorMethod);
|
||||
|
||||
switch (creatorInfo.version) {
|
||||
case ConfuserVersion.v10_r42915:
|
||||
getCallInfo_v10_r42915(info, creatorInfo, out calledMethod, out callOpcode);
|
||||
break;
|
||||
|
||||
case ConfuserVersion.v10_r48717:
|
||||
getCallInfo_v10_r48717(info, creatorInfo, out calledMethod, out callOpcode);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ApplicationException("Unknown version");
|
||||
}
|
||||
}
|
||||
|
||||
void getCallInfo_v10_r42915(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out MethodReference calledMethod, out OpCode callOpcode) {
|
||||
var reader = new BinaryReader(new MemoryStream(info.data));
|
||||
|
||||
bool isCallvirt = false;
|
||||
|
@ -106,7 +135,8 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
isCallvirt = reader.ReadBoolean();
|
||||
|
||||
var asmRef = readAssemblyNameReference(reader);
|
||||
uint token = reader.ReadUInt32();
|
||||
// If < 1.0 r42919, then high byte is 06, else it's cleared.
|
||||
uint token = (reader.ReadUInt32() & 0x00FFFFFF) | 0x06000000;
|
||||
if (reader.BaseStream.Position != reader.BaseStream.Length)
|
||||
throw new ApplicationException("Extra data");
|
||||
|
||||
|
@ -118,6 +148,22 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
callOpcode = getCallOpCode(creatorInfo, isCallvirt);
|
||||
}
|
||||
|
||||
void getCallInfo_v10_r48717(DelegateInitInfo info, ProxyCreatorInfo creatorInfo, out MethodReference calledMethod, out OpCode callOpcode) {
|
||||
int offs = creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt ? 2 : 1;
|
||||
uint token = BitConverter.ToUInt32(Encoding.Unicode.GetBytes(info.field.Name.ToCharArray(), offs, 2), 0);
|
||||
if (info.field.Name[0] == (char)1)
|
||||
calledMethod = (MethodReference)module.LookupToken((int)token);
|
||||
else {
|
||||
var asmRef = module.AssemblyReferences[info.field.Name[0] - 2];
|
||||
calledMethod = createMethodReference(asmRef, token);
|
||||
}
|
||||
|
||||
bool isCallvirt = false;
|
||||
if (creatorInfo.proxyCreatorType == ProxyCreatorType.CallOrCallvirt && info.field.Name[1] == '\r')
|
||||
isCallvirt = true;
|
||||
callOpcode = getCallOpCode(creatorInfo, isCallvirt);
|
||||
}
|
||||
|
||||
// A method token is not a stable value so this method can fail to return the correct method!
|
||||
// There's nothing I can do about that. It's an obfuscator bug.
|
||||
MethodReference createMethodReference(AssemblyNameReference asmRef, uint methodToken) {
|
||||
|
@ -168,13 +214,22 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
foreach (var method in type.Methods) {
|
||||
if (method.Body == null || !method.IsStatic || !method.IsAssembly)
|
||||
continue;
|
||||
if (!DotNetUtils.isMethod(method, "System.Void", "(System.String,System.RuntimeFieldHandle)"))
|
||||
ConfuserVersion theVersion = ConfuserVersion.Unknown;
|
||||
|
||||
if (DotNetUtils.isMethod(method, "System.Void", "(System.String,System.RuntimeFieldHandle)"))
|
||||
theVersion = ConfuserVersion.v10_r42915;
|
||||
else if (DotNetUtils.isMethod(method, "System.Void", "(System.RuntimeFieldHandle)"))
|
||||
theVersion = ConfuserVersion.v10_r48717;
|
||||
else
|
||||
continue;
|
||||
|
||||
var proxyType = getProxyCreatorType(method);
|
||||
if (proxyType == ProxyCreatorType.None)
|
||||
continue;
|
||||
|
||||
setDelegateCreatorMethod(method);
|
||||
methodToInfo.add(method, new ProxyCreatorInfo(method, proxyType));
|
||||
methodToInfo.add(method, new ProxyCreatorInfo(method, proxyType, theVersion));
|
||||
version = theVersion;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,6 +306,14 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
}
|
||||
|
||||
FieldDefinitionAndDeclaringTypeDict<DelegateInitInfo> createDelegateInitInfos(MethodDefinition method) {
|
||||
switch (version) {
|
||||
case ConfuserVersion.v10_r42915: return createDelegateInitInfos_v10_r42915(method);
|
||||
case ConfuserVersion.v10_r48717: return createDelegateInitInfos_v10_r48717(method);
|
||||
default: throw new ApplicationException("Invalid version");
|
||||
}
|
||||
}
|
||||
|
||||
FieldDefinitionAndDeclaringTypeDict<DelegateInitInfo> createDelegateInitInfos_v10_r42915(MethodDefinition method) {
|
||||
var infos = new FieldDefinitionAndDeclaringTypeDict<DelegateInitInfo>();
|
||||
var instrs = method.Body.Instructions;
|
||||
for (int i = 0; i < instrs.Count - 2; i++) {
|
||||
|
@ -284,6 +347,33 @@ namespace de4dot.code.deobfuscators.Confuser {
|
|||
return infos;
|
||||
}
|
||||
|
||||
FieldDefinitionAndDeclaringTypeDict<DelegateInitInfo> createDelegateInitInfos_v10_r48717(MethodDefinition method) {
|
||||
var infos = new FieldDefinitionAndDeclaringTypeDict<DelegateInitInfo>();
|
||||
var instrs = method.Body.Instructions;
|
||||
for (int i = 0; i < instrs.Count - 1; i++) {
|
||||
var ldtoken = instrs[i];
|
||||
if (ldtoken.OpCode.Code != Code.Ldtoken)
|
||||
continue;
|
||||
var delegateField = ldtoken.Operand as FieldDefinition;
|
||||
if (delegateField == null)
|
||||
continue;
|
||||
var delegateType = delegateField.FieldType as TypeDefinition;
|
||||
if (!DotNetUtils.derivesFromDelegate(delegateType))
|
||||
continue;
|
||||
|
||||
var call = instrs[i + 1];
|
||||
if (call.OpCode.Code != Code.Call)
|
||||
continue;
|
||||
var delegateCreatorMethod = call.Operand as MethodDefinition;
|
||||
if (delegateCreatorMethod == null || !isDelegateCreatorMethod(delegateCreatorMethod))
|
||||
continue;
|
||||
|
||||
infos.add(delegateField, new DelegateInitInfo(delegateField, delegateCreatorMethod));
|
||||
i += 1;
|
||||
}
|
||||
return infos;
|
||||
}
|
||||
|
||||
static FieldDefinitionAndDeclaringTypeDict<MethodDefinition> createFieldToMethodDictionary(TypeDefinition type) {
|
||||
var dict = new FieldDefinitionAndDeclaringTypeDict<MethodDefinition>();
|
||||
foreach (var method in type.Methods) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user