Work around a bug in EF

This commit is contained in:
de4dot 2012-12-08 01:12:20 +01:00
parent d6958fac23
commit dcbcaa098e
2 changed files with 53 additions and 0 deletions

View File

@ -17,8 +17,10 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
using de4dot.code.renamer;
@ -163,9 +165,54 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
addResourceToBeRemoved(resourceMethodsRestorer.Resource, "GetManifestResourceStream type resource");
fixInterfaces();
stringDecrypterBugWorkaround();
base.deobfuscateEnd();
}
void stringDecrypterBugWorkaround() {
// There's a bug in Eazfuscator.NET when the VM and string encryption features are
// enabled. The string decrypter's initialization code checks to make sure it's not
// called by eg. a dynamic method. When it's called from the VM code, it is
// called by MethodBase.Invoke() and the string decrypter antis set in causing it
// to fail.
// One way to work around this is to make sure the string decrypter has been called
// once. That way, any VM code calling it won't trigger a failure.
// We can put this code in <Module>::.cctor() since it gets executed before any
// other code.
// Note that we can't call the string decrypter from <Module>::.cctor() since
// its DeclaringType property will return null (since it's the global type). We
// must call another created class which calls the string decrypter.
// You must use --dont-rename --keep-types --preserve-tokens and decrypt strings
if (!Operations.KeepObfuscatorTypes || Operations.DecryptStrings == OpDecryptString.None ||
(Operations.RenamerFlags & (RenamerFlags.RenameNamespaces | RenamerFlags.RenameTypes)) != 0)
return;
if (stringDecrypter.ValidStringDecrypterValue == null)
return;
var newType = module.UpdateRowId(new TypeDefUser(Guid.NewGuid().ToString("B"), module.CorLibTypes.Object.TypeDefOrRef));
module.Types.Add(newType);
var newMethod = module.UpdateRowId(new MethodDefUser("x", MethodSig.CreateStatic(module.CorLibTypes.Void), 0, MethodAttributes.Static | MethodAttributes.HideBySig));
newType.Methods.Add(newMethod);
newMethod.Body = new CilBody();
newMethod.Body.MaxStack = 1;
newMethod.Body.Instructions.Add(Instruction.CreateLdcI4(stringDecrypter.ValidStringDecrypterValue.Value));
newMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Call, stringDecrypter.Method));
newMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Pop));
newMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
var cctor = module.GlobalType.FindOrCreateStaticConstructor();
var blocks = new Blocks(cctor);
var block = blocks.MethodBlocks.getAllBlocks()[0];
block.insert(0, Instruction.Create(OpCodes.Call, newMethod));
IList<Instruction> allInstructions;
IList<ExceptionHandler> allExceptionHandlers;
blocks.getCode(out allInstructions, out allExceptionHandlers);
DotNetUtils.restoreBody(cctor, allInstructions, allExceptionHandlers);
}
public override IEnumerable<int> getStringDecrypterMethods() {
var list = new List<int>();
if (stringDecrypter.Method != null)

View File

@ -45,6 +45,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
StreamHelperType streamHelperType;
EfConstantsReader stringMethodConsts;
bool isV32OrLater;
int? validStringDecrypterValue;
class StreamHelperType {
public TypeDef type;
@ -76,6 +77,10 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
}
}
public int? ValidStringDecrypterValue {
get { return validStringDecrypterValue;}
}
public TypeDef Type {
get { return stringType; }
}
@ -391,6 +396,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
}
public string decrypt(int val) {
validStringDecrypterValue = val;
while (true) {
int offset = magic1 ^ i3 ^ val ^ i6;
reader.BaseStream.Position = offset;