/de4dot.code/deobfuscators/CodeFort/Deobfuscator.cs

https://github.com/brianhama/de4dot · C# · 157 lines · 113 code · 26 blank · 18 comment · 10 complexity · 461e6f2e73c93629f5ad6bb13f4493e0 MD5 · raw file

  1. /*
  2. Copyright (C) 2011-2015 de4dot@gmail.com
  3. This file is part of de4dot.
  4. de4dot is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. de4dot is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with de4dot. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. using System.Collections.Generic;
  16. using dnlib.DotNet;
  17. using de4dot.blocks;
  18. namespace de4dot.code.deobfuscators.CodeFort {
  19. public class DeobfuscatorInfo : DeobfuscatorInfoBase {
  20. public const string THE_NAME = "CodeFort";
  21. public const string THE_TYPE = "cf";
  22. const string DEFAULT_REGEX = @"!^[a-zA-Z]{1,3}$&!^[_<>{}$.`-]$&" + DeobfuscatorBase.DEFAULT_ASIAN_VALID_NAME_REGEX;
  23. BoolOption dumpEmbeddedAssemblies;
  24. public DeobfuscatorInfo() : base(DEFAULT_REGEX) =>
  25. dumpEmbeddedAssemblies = new BoolOption(null, MakeArgName("embedded"), "Dump embedded assemblies", true);
  26. public override string Name => THE_NAME;
  27. public override string Type => THE_TYPE;
  28. public override IDeobfuscator CreateDeobfuscator() =>
  29. new Deobfuscator(new Deobfuscator.Options {
  30. ValidNameRegex = validNameRegex.Get(),
  31. DumpEmbeddedAssemblies = dumpEmbeddedAssemblies.Get(),
  32. });
  33. protected override IEnumerable<Option> GetOptionsInternal() =>
  34. new List<Option>() {
  35. dumpEmbeddedAssemblies,
  36. };
  37. }
  38. class Deobfuscator : DeobfuscatorBase {
  39. Options options;
  40. ProxyCallFixer proxyCallFixer;
  41. StringDecrypter stringDecrypter;
  42. AssemblyDecrypter assemblyDecrypter;
  43. CfMethodCallInliner cfMethodCallInliner;
  44. internal class Options : OptionsBase {
  45. public bool DumpEmbeddedAssemblies { get; set; }
  46. }
  47. public override string Type => DeobfuscatorInfo.THE_TYPE;
  48. public override string TypeLong => DeobfuscatorInfo.THE_NAME;
  49. public override string Name => DeobfuscatorInfo.THE_NAME;
  50. public Deobfuscator(Options options) : base(options) => this.options = options;
  51. protected override int DetectInternal() {
  52. int val = 0;
  53. int sum = ToInt32(proxyCallFixer.Detected) +
  54. ToInt32(stringDecrypter.Detected) +
  55. ToInt32(assemblyDecrypter.Detected);
  56. if (sum > 0)
  57. val += 100 + 10 * (sum - 1);
  58. return val;
  59. }
  60. protected override void ScanForObfuscator() {
  61. proxyCallFixer = new ProxyCallFixer(module);
  62. proxyCallFixer.FindDelegateCreator();
  63. stringDecrypter = new StringDecrypter(module);
  64. stringDecrypter.Find();
  65. assemblyDecrypter = new AssemblyDecrypter(module);
  66. assemblyDecrypter.Find();
  67. }
  68. public override bool GetDecryptedModule(int count, ref byte[] newFileData, ref DumpedMethods dumpedMethods) {
  69. if (count != 0 || !assemblyDecrypter.EncryptedDetected)
  70. return false;
  71. newFileData = assemblyDecrypter.Decrypt();
  72. return newFileData != null;
  73. }
  74. public override IDeobfuscator ModuleReloaded(ModuleDefMD module) {
  75. var newOne = new Deobfuscator(options);
  76. newOne.SetModule(module);
  77. newOne.proxyCallFixer = new ProxyCallFixer(module);
  78. newOne.proxyCallFixer.FindDelegateCreator();
  79. newOne.stringDecrypter = new StringDecrypter(module);
  80. newOne.stringDecrypter.Find();
  81. newOne.assemblyDecrypter = new AssemblyDecrypter(module, assemblyDecrypter);
  82. newOne.assemblyDecrypter.Find();
  83. return newOne;
  84. }
  85. public override void DeobfuscateBegin() {
  86. base.DeobfuscateBegin();
  87. staticStringInliner.Add(stringDecrypter.Method, (method, gim, args) => stringDecrypter.Decrypt((string)args[0]));
  88. DeobfuscatedFile.StringDecryptersAdded();
  89. proxyCallFixer.Find();
  90. cfMethodCallInliner = new CfMethodCallInliner(proxyCallFixer);
  91. DumpEmbeddedAssemblies();
  92. }
  93. void DumpEmbeddedAssemblies() {
  94. if (assemblyDecrypter.MainAssemblyHasAssemblyResolver && !options.DumpEmbeddedAssemblies)
  95. return;
  96. foreach (var info in assemblyDecrypter.GetAssemblyInfos(DeobfuscatedFile, this)) {
  97. DeobfuscatedFile.CreateAssemblyFile(info.data, info.asmSimpleName, info.extension);
  98. AddResourceToBeRemoved(info.resource, $"Embedded assembly: {info.asmFullName}");
  99. }
  100. AddCctorInitCallToBeRemoved(assemblyDecrypter.InitMethod);
  101. AddCallToBeRemoved(module.EntryPoint, assemblyDecrypter.InitMethod);
  102. AddTypeToBeRemoved(assemblyDecrypter.Type, "Assembly resolver type");
  103. }
  104. public override void DeobfuscateMethodEnd(Blocks blocks) {
  105. proxyCallFixer.Deobfuscate(blocks);
  106. InlineMethods(blocks);
  107. base.DeobfuscateMethodEnd(blocks);
  108. }
  109. void InlineMethods(Blocks blocks) {
  110. cfMethodCallInliner.DeobfuscateBegin(blocks);
  111. cfMethodCallInliner.Deobfuscate(blocks.MethodBlocks.GetAllBlocks());
  112. }
  113. public override void DeobfuscateEnd() {
  114. RemoveProxyDelegates(proxyCallFixer);
  115. AddTypeToBeRemoved(proxyCallFixer.ProxyMethodsType, "Type with proxy methods");
  116. if (CanRemoveStringDecrypterType)
  117. AddTypeToBeRemoved(stringDecrypter.Type, "String decrypter type");
  118. base.DeobfuscateEnd();
  119. }
  120. public override IEnumerable<int> GetStringDecrypterMethods() {
  121. var list = new List<int>();
  122. if (stringDecrypter.Method != null)
  123. list.Add(stringDecrypter.Method.MDToken.ToInt32());
  124. return list;
  125. }
  126. }
  127. }