Work around a bug in EF
This commit is contained in:
parent
d6958fac23
commit
dcbcaa098e
|
@ -17,8 +17,10 @@
|
||||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
|
using dot10.DotNet.Emit;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
using de4dot.code.renamer;
|
using de4dot.code.renamer;
|
||||||
|
|
||||||
|
@ -163,9 +165,54 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
addResourceToBeRemoved(resourceMethodsRestorer.Resource, "GetManifestResourceStream type resource");
|
addResourceToBeRemoved(resourceMethodsRestorer.Resource, "GetManifestResourceStream type resource");
|
||||||
|
|
||||||
fixInterfaces();
|
fixInterfaces();
|
||||||
|
stringDecrypterBugWorkaround();
|
||||||
base.deobfuscateEnd();
|
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() {
|
public override IEnumerable<int> getStringDecrypterMethods() {
|
||||||
var list = new List<int>();
|
var list = new List<int>();
|
||||||
if (stringDecrypter.Method != null)
|
if (stringDecrypter.Method != null)
|
||||||
|
|
|
@ -45,6 +45,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
StreamHelperType streamHelperType;
|
StreamHelperType streamHelperType;
|
||||||
EfConstantsReader stringMethodConsts;
|
EfConstantsReader stringMethodConsts;
|
||||||
bool isV32OrLater;
|
bool isV32OrLater;
|
||||||
|
int? validStringDecrypterValue;
|
||||||
|
|
||||||
class StreamHelperType {
|
class StreamHelperType {
|
||||||
public TypeDef type;
|
public TypeDef type;
|
||||||
|
@ -76,6 +77,10 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int? ValidStringDecrypterValue {
|
||||||
|
get { return validStringDecrypterValue;}
|
||||||
|
}
|
||||||
|
|
||||||
public TypeDef Type {
|
public TypeDef Type {
|
||||||
get { return stringType; }
|
get { return stringType; }
|
||||||
}
|
}
|
||||||
|
@ -391,6 +396,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
}
|
}
|
||||||
|
|
||||||
public string decrypt(int val) {
|
public string decrypt(int val) {
|
||||||
|
validStringDecrypterValue = val;
|
||||||
while (true) {
|
while (true) {
|
||||||
int offset = magic1 ^ i3 ^ val ^ i6;
|
int offset = magic1 ^ i3 ^ val ^ i6;
|
||||||
reader.BaseStream.Position = offset;
|
reader.BaseStream.Position = offset;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user