Merge branch 'master' into confuser
This commit is contained in:
commit
a7d9b67b28
2
.gitmodules
vendored
2
.gitmodules
vendored
|
@ -1,3 +1,3 @@
|
||||||
[submodule "dnlib"]
|
[submodule "dnlib"]
|
||||||
path = dnlib
|
path = dnlib
|
||||||
url = git@bitbucket.org:0xd4d/dnlib.git
|
url = git@github.com:0xd4d/dnlib.git
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
|
|
|
@ -17,6 +17,6 @@
|
||||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
</LICENSE>
|
</LICENSE>
|
||||||
|
|
||||||
Official site: https://bitbucket.org/0xd4d/de4dot
|
Official site: https://github.com/0xd4d/de4dot
|
||||||
|
|
||||||
See the file COPYING for more details.
|
See the file COPYING for more details.
|
||||||
|
|
|
@ -21,4 +21,4 @@
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
</LICENSE>
|
</LICENSE>
|
||||||
|
|
||||||
Official site: https://bitbucket.org/0xd4d/dnlib
|
Official site: https://github.com/0xd4d/dnlib
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
|
|
|
@ -174,9 +174,9 @@ namespace de4dot.blocks {
|
||||||
public static bool IsPinvokeMethod(MethodDef method, string dll, string funcName) {
|
public static bool IsPinvokeMethod(MethodDef method, string dll, string funcName) {
|
||||||
if (method == null)
|
if (method == null)
|
||||||
return false;
|
return false;
|
||||||
if (method.ImplMap == null || method.ImplMap.Name.String != funcName)
|
if (method.ImplMap == null)
|
||||||
return false;
|
return false;
|
||||||
return GetDllName(dll).Equals(GetDllName(method.ImplMap.Module.Name.String), StringComparison.OrdinalIgnoreCase);
|
return method.ImplMap.IsPinvokeMethod(dll, funcName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MethodDef GetMethod(ModuleDefMD module, IMethod method) {
|
public static MethodDef GetMethod(ModuleDefMD module, IMethod method) {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
|
using dnlib.Threading;
|
||||||
|
|
||||||
namespace de4dot.blocks {
|
namespace de4dot.blocks {
|
||||||
public struct GenericArgsSubstitutor {
|
public struct GenericArgsSubstitutor {
|
||||||
|
@ -291,7 +292,7 @@ namespace de4dot.blocks {
|
||||||
newSig.Params.Add(Create2(sig.Params[i]));
|
newSig.Params.Add(Create2(sig.Params[i]));
|
||||||
newSig.GenParamCount = sig.GenParamCount;
|
newSig.GenParamCount = sig.GenParamCount;
|
||||||
if (sig.ParamsAfterSentinel != null) {
|
if (sig.ParamsAfterSentinel != null) {
|
||||||
newSig.ParamsAfterSentinel = new List<TypeSig>();
|
newSig.ParamsAfterSentinel = ThreadSafeListCreator.Create<TypeSig>();
|
||||||
for (int i = 0; i < sig.ParamsAfterSentinel.Count; i++)
|
for (int i = 0; i < sig.ParamsAfterSentinel.Count; i++)
|
||||||
newSig.ParamsAfterSentinel.Add(Create2(sig.ParamsAfterSentinel[i]));
|
newSig.ParamsAfterSentinel.Add(Create2(sig.ParamsAfterSentinel[i]));
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
|
|
|
@ -95,6 +95,8 @@ namespace de4dot.blocks.cflow {
|
||||||
return EmulateBranch(2, Int32Value.CompareEq((Int32Value)val1, (Int32Value)val2));
|
return EmulateBranch(2, Int32Value.CompareEq((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
return EmulateBranch(2, Int64Value.CompareEq((Int64Value)val1, (Int64Value)val2));
|
return EmulateBranch(2, Int64Value.CompareEq((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
return EmulateBranch(2, Real8Value.CompareEq((Real8Value)val1, (Real8Value)val2));
|
||||||
else if (val1.IsNull() && val2.IsNull())
|
else if (val1.IsNull() && val2.IsNull())
|
||||||
return EmulateBranch(2, true);
|
return EmulateBranch(2, true);
|
||||||
else
|
else
|
||||||
|
@ -109,6 +111,8 @@ namespace de4dot.blocks.cflow {
|
||||||
return EmulateBranch(2, Int32Value.CompareNeq((Int32Value)val1, (Int32Value)val2));
|
return EmulateBranch(2, Int32Value.CompareNeq((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
return EmulateBranch(2, Int64Value.CompareNeq((Int64Value)val1, (Int64Value)val2));
|
return EmulateBranch(2, Int64Value.CompareNeq((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
return EmulateBranch(2, Real8Value.CompareNeq((Real8Value)val1, (Real8Value)val2));
|
||||||
else if (val1.IsNull() && val2.IsNull())
|
else if (val1.IsNull() && val2.IsNull())
|
||||||
return EmulateBranch(2, false);
|
return EmulateBranch(2, false);
|
||||||
else
|
else
|
||||||
|
@ -123,6 +127,8 @@ namespace de4dot.blocks.cflow {
|
||||||
return EmulateBranch(2, Int32Value.CompareGe((Int32Value)val1, (Int32Value)val2));
|
return EmulateBranch(2, Int32Value.CompareGe((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
return EmulateBranch(2, Int64Value.CompareGe((Int64Value)val1, (Int64Value)val2));
|
return EmulateBranch(2, Int64Value.CompareGe((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
return EmulateBranch(2, Real8Value.CompareGe((Real8Value)val1, (Real8Value)val2));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -135,6 +141,8 @@ namespace de4dot.blocks.cflow {
|
||||||
return EmulateBranch(2, Int32Value.CompareGe_Un((Int32Value)val1, (Int32Value)val2));
|
return EmulateBranch(2, Int32Value.CompareGe_Un((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
return EmulateBranch(2, Int64Value.CompareGe_Un((Int64Value)val1, (Int64Value)val2));
|
return EmulateBranch(2, Int64Value.CompareGe_Un((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
return EmulateBranch(2, Real8Value.CompareGe_Un((Real8Value)val1, (Real8Value)val2));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -147,6 +155,8 @@ namespace de4dot.blocks.cflow {
|
||||||
return EmulateBranch(2, Int32Value.CompareGt((Int32Value)val1, (Int32Value)val2));
|
return EmulateBranch(2, Int32Value.CompareGt((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
return EmulateBranch(2, Int64Value.CompareGt((Int64Value)val1, (Int64Value)val2));
|
return EmulateBranch(2, Int64Value.CompareGt((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
return EmulateBranch(2, Real8Value.CompareGt((Real8Value)val1, (Real8Value)val2));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -159,6 +169,8 @@ namespace de4dot.blocks.cflow {
|
||||||
return EmulateBranch(2, Int32Value.CompareGt_Un((Int32Value)val1, (Int32Value)val2));
|
return EmulateBranch(2, Int32Value.CompareGt_Un((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
return EmulateBranch(2, Int64Value.CompareGt_Un((Int64Value)val1, (Int64Value)val2));
|
return EmulateBranch(2, Int64Value.CompareGt_Un((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
return EmulateBranch(2, Real8Value.CompareGt_Un((Real8Value)val1, (Real8Value)val2));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -171,6 +183,8 @@ namespace de4dot.blocks.cflow {
|
||||||
return EmulateBranch(2, Int32Value.CompareLe((Int32Value)val1, (Int32Value)val2));
|
return EmulateBranch(2, Int32Value.CompareLe((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
return EmulateBranch(2, Int64Value.CompareLe((Int64Value)val1, (Int64Value)val2));
|
return EmulateBranch(2, Int64Value.CompareLe((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
return EmulateBranch(2, Real8Value.CompareLe((Real8Value)val1, (Real8Value)val2));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -183,6 +197,8 @@ namespace de4dot.blocks.cflow {
|
||||||
return EmulateBranch(2, Int32Value.CompareLe_Un((Int32Value)val1, (Int32Value)val2));
|
return EmulateBranch(2, Int32Value.CompareLe_Un((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
return EmulateBranch(2, Int64Value.CompareLe_Un((Int64Value)val1, (Int64Value)val2));
|
return EmulateBranch(2, Int64Value.CompareLe_Un((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
return EmulateBranch(2, Real8Value.CompareLe_Un((Real8Value)val1, (Real8Value)val2));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -195,6 +211,8 @@ namespace de4dot.blocks.cflow {
|
||||||
return EmulateBranch(2, Int32Value.CompareLt((Int32Value)val1, (Int32Value)val2));
|
return EmulateBranch(2, Int32Value.CompareLt((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
return EmulateBranch(2, Int64Value.CompareLt((Int64Value)val1, (Int64Value)val2));
|
return EmulateBranch(2, Int64Value.CompareLt((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
return EmulateBranch(2, Real8Value.CompareLt((Real8Value)val1, (Real8Value)val2));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -207,6 +225,8 @@ namespace de4dot.blocks.cflow {
|
||||||
return EmulateBranch(2, Int32Value.CompareLt_Un((Int32Value)val1, (Int32Value)val2));
|
return EmulateBranch(2, Int32Value.CompareLt_Un((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
return EmulateBranch(2, Int64Value.CompareLt_Un((Int64Value)val1, (Int64Value)val2));
|
return EmulateBranch(2, Int64Value.CompareLt_Un((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
return EmulateBranch(2, Real8Value.CompareLt_Un((Real8Value)val1, (Real8Value)val2));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -218,6 +238,8 @@ namespace de4dot.blocks.cflow {
|
||||||
return EmulateBranch(1, Int32Value.CompareFalse((Int32Value)val1));
|
return EmulateBranch(1, Int32Value.CompareFalse((Int32Value)val1));
|
||||||
else if (val1.IsInt64())
|
else if (val1.IsInt64())
|
||||||
return EmulateBranch(1, Int64Value.CompareFalse((Int64Value)val1));
|
return EmulateBranch(1, Int64Value.CompareFalse((Int64Value)val1));
|
||||||
|
else if (val1.IsReal8())
|
||||||
|
return EmulateBranch(1, Real8Value.CompareFalse((Real8Value)val1));
|
||||||
else if (val1.IsNull())
|
else if (val1.IsNull())
|
||||||
return EmulateBranch(1, true);
|
return EmulateBranch(1, true);
|
||||||
else if (val1.IsObject() || val1.IsString())
|
else if (val1.IsObject() || val1.IsString())
|
||||||
|
@ -233,6 +255,8 @@ namespace de4dot.blocks.cflow {
|
||||||
return EmulateBranch(1, Int32Value.CompareTrue((Int32Value)val1));
|
return EmulateBranch(1, Int32Value.CompareTrue((Int32Value)val1));
|
||||||
else if (val1.IsInt64())
|
else if (val1.IsInt64())
|
||||||
return EmulateBranch(1, Int64Value.CompareTrue((Int64Value)val1));
|
return EmulateBranch(1, Int64Value.CompareTrue((Int64Value)val1));
|
||||||
|
else if (val1.IsReal8())
|
||||||
|
return EmulateBranch(1, Real8Value.CompareTrue((Real8Value)val1));
|
||||||
else if (val1.IsNull())
|
else if (val1.IsNull())
|
||||||
return EmulateBranch(1, false);
|
return EmulateBranch(1, false);
|
||||||
else if (val1.IsObject() || val1.IsString())
|
else if (val1.IsObject() || val1.IsString())
|
||||||
|
|
|
@ -70,6 +70,96 @@ namespace de4dot.blocks.cflow {
|
||||||
case Code.Ldloca_S:
|
case Code.Ldloca_S:
|
||||||
instructionEmulator.MakeLocalUnknown((Local)instr.Operand);
|
instructionEmulator.MakeLocalUnknown((Local)instr.Operand);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Code.Add:
|
||||||
|
case Code.Add_Ovf:
|
||||||
|
case Code.Add_Ovf_Un:
|
||||||
|
case Code.And:
|
||||||
|
case Code.Ceq:
|
||||||
|
case Code.Cgt:
|
||||||
|
case Code.Cgt_Un:
|
||||||
|
case Code.Clt:
|
||||||
|
case Code.Clt_Un:
|
||||||
|
case Code.Conv_I:
|
||||||
|
case Code.Conv_I1:
|
||||||
|
case Code.Conv_I2:
|
||||||
|
case Code.Conv_I4:
|
||||||
|
case Code.Conv_I8:
|
||||||
|
case Code.Conv_Ovf_I:
|
||||||
|
case Code.Conv_Ovf_I_Un:
|
||||||
|
case Code.Conv_Ovf_I1:
|
||||||
|
case Code.Conv_Ovf_I1_Un:
|
||||||
|
case Code.Conv_Ovf_I2:
|
||||||
|
case Code.Conv_Ovf_I2_Un:
|
||||||
|
case Code.Conv_Ovf_I4:
|
||||||
|
case Code.Conv_Ovf_I4_Un:
|
||||||
|
case Code.Conv_Ovf_I8:
|
||||||
|
case Code.Conv_Ovf_I8_Un:
|
||||||
|
case Code.Conv_Ovf_U:
|
||||||
|
case Code.Conv_Ovf_U_Un:
|
||||||
|
case Code.Conv_Ovf_U1:
|
||||||
|
case Code.Conv_Ovf_U1_Un:
|
||||||
|
case Code.Conv_Ovf_U2:
|
||||||
|
case Code.Conv_Ovf_U2_Un:
|
||||||
|
case Code.Conv_Ovf_U4:
|
||||||
|
case Code.Conv_Ovf_U4_Un:
|
||||||
|
case Code.Conv_Ovf_U8:
|
||||||
|
case Code.Conv_Ovf_U8_Un:
|
||||||
|
case Code.Conv_R_Un:
|
||||||
|
case Code.Conv_R4:
|
||||||
|
case Code.Conv_R8:
|
||||||
|
case Code.Conv_U:
|
||||||
|
case Code.Conv_U1:
|
||||||
|
case Code.Conv_U2:
|
||||||
|
case Code.Conv_U4:
|
||||||
|
case Code.Conv_U8:
|
||||||
|
case Code.Div:
|
||||||
|
case Code.Div_Un:
|
||||||
|
case Code.Dup:
|
||||||
|
case Code.Mul:
|
||||||
|
case Code.Mul_Ovf:
|
||||||
|
case Code.Mul_Ovf_Un:
|
||||||
|
case Code.Neg:
|
||||||
|
case Code.Not:
|
||||||
|
case Code.Or:
|
||||||
|
case Code.Rem:
|
||||||
|
case Code.Rem_Un:
|
||||||
|
case Code.Shl:
|
||||||
|
case Code.Shr:
|
||||||
|
case Code.Shr_Un:
|
||||||
|
case Code.Sub:
|
||||||
|
case Code.Sub_Ovf:
|
||||||
|
case Code.Sub_Ovf_Un:
|
||||||
|
case Code.Xor:
|
||||||
|
if (i + 1 < instrs.Count && instrs[i + 1].OpCode.Code == Code.Pop)
|
||||||
|
break;
|
||||||
|
if (!VerifyValidArgs(instr.Instruction))
|
||||||
|
break;
|
||||||
|
instructionEmulator.Emulate(instr.Instruction);
|
||||||
|
var tos = instructionEmulator.Peek();
|
||||||
|
Instruction newInstr = null;
|
||||||
|
if (tos.IsInt32()) {
|
||||||
|
var val = (Int32Value)tos;
|
||||||
|
if (val.AllBitsValid())
|
||||||
|
newInstr = Instruction.CreateLdcI4(val.Value);
|
||||||
|
}
|
||||||
|
else if (tos.IsInt64()) {
|
||||||
|
var val = (Int64Value)tos;
|
||||||
|
if (val.AllBitsValid())
|
||||||
|
newInstr = OpCodes.Ldc_I8.ToInstruction(val.Value);
|
||||||
|
}
|
||||||
|
else if (tos.IsReal8()) {
|
||||||
|
var val = (Real8Value)tos;
|
||||||
|
if (val.IsValid)
|
||||||
|
newInstr = GetLoadRealInstruction(val.Value);
|
||||||
|
}
|
||||||
|
if (newInstr != null) {
|
||||||
|
block.Insert(i + 1, Instruction.Create(OpCodes.Pop));
|
||||||
|
block.Insert(i + 2, newInstr);
|
||||||
|
i += 2;
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -84,6 +174,53 @@ namespace de4dot.blocks.cflow {
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VerifyValidArgs(Instruction instr) {
|
||||||
|
int pushes, pops;
|
||||||
|
instr.CalculateStackUsage(out pushes, out pops);
|
||||||
|
if (pops < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool retVal;
|
||||||
|
Value val2, val1;
|
||||||
|
switch (pops) {
|
||||||
|
case 0:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
val1 = instructionEmulator.Pop();
|
||||||
|
retVal = VerifyValidArg(val1);
|
||||||
|
instructionEmulator.Push(val1);
|
||||||
|
return retVal;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
val2 = instructionEmulator.Pop();
|
||||||
|
val1 = instructionEmulator.Pop();
|
||||||
|
retVal = VerifyValidArg(val2) && VerifyValidArg(val1);
|
||||||
|
instructionEmulator.Push(val1);
|
||||||
|
instructionEmulator.Push(val2);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool VerifyValidArg(Value value) {
|
||||||
|
if (value.IsInt32())
|
||||||
|
return ((Int32Value)value).AllBitsValid();
|
||||||
|
if (value.IsInt64())
|
||||||
|
return ((Int64Value)value).AllBitsValid();
|
||||||
|
if (value.IsReal8())
|
||||||
|
return ((Real8Value)value).IsValid;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Instruction GetLoadRealInstruction(double value) {
|
||||||
|
var floatVal = (float)value;
|
||||||
|
if (floatVal == value || double.IsNaN(value))
|
||||||
|
return OpCodes.Ldc_R4.ToInstruction(floatVal);
|
||||||
|
return OpCodes.Ldc_R8.ToInstruction(value);
|
||||||
|
}
|
||||||
|
|
||||||
bool FixLoadInstruction(Block block, int index, Value value) {
|
bool FixLoadInstruction(Block block, int index, Value value) {
|
||||||
if (value.IsInt32()) {
|
if (value.IsInt32()) {
|
||||||
var intValue = (Int32Value)value;
|
var intValue = (Int32Value)value;
|
||||||
|
|
|
@ -52,8 +52,12 @@ namespace de4dot.blocks.cflow {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(MethodDef method, bool emulateFromFirstInstruction) {
|
public void Initialize(MethodDef method, bool emulateFromFirstInstruction) {
|
||||||
this.parameterDefs = method.Parameters;
|
Initialize(method, method.Parameters, method.Body.Variables, method.Body.InitLocals, emulateFromFirstInstruction);
|
||||||
this.localDefs = method.Body.Variables;
|
}
|
||||||
|
|
||||||
|
public void Initialize(MethodDef method, IList<Parameter> methodParameters, IList<Local> methodLocals, bool initLocals, bool emulateFromFirstInstruction) {
|
||||||
|
this.parameterDefs = methodParameters;
|
||||||
|
this.localDefs = methodLocals;
|
||||||
valueStack.Initialize();
|
valueStack.Initialize();
|
||||||
protectedStackValues.Clear();
|
protectedStackValues.Clear();
|
||||||
|
|
||||||
|
@ -75,7 +79,7 @@ namespace de4dot.blocks.cflow {
|
||||||
args.Clear();
|
args.Clear();
|
||||||
args.AddRange(cached_args);
|
args.AddRange(cached_args);
|
||||||
locals.Clear();
|
locals.Clear();
|
||||||
locals.AddRange(method.Body.InitLocals && emulateFromFirstInstruction ? cached_zeroed_locals : cached_locals);
|
locals.AddRange(initLocals && emulateFromFirstInstruction ? cached_zeroed_locals : cached_locals);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetProtected(Value value) {
|
public void SetProtected(Value value) {
|
||||||
|
@ -429,9 +433,9 @@ namespace de4dot.blocks.cflow {
|
||||||
|
|
||||||
case Code.Unbox:
|
case Code.Unbox:
|
||||||
|
|
||||||
case Code.Conv_R_Un:
|
case Code.Conv_R_Un:Emulate_Conv_R_Un(instr); break;
|
||||||
case Code.Conv_R4:
|
case Code.Conv_R4: Emulate_Conv_R4(instr); break;
|
||||||
case Code.Conv_R8:
|
case Code.Conv_R8: Emulate_Conv_R8(instr); break;
|
||||||
|
|
||||||
case Code.Arglist:
|
case Code.Arglist:
|
||||||
case Code.Beq:
|
case Code.Beq:
|
||||||
|
@ -782,6 +786,36 @@ namespace de4dot.blocks.cflow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Emulate_Conv_R_Un(Instruction instr) {
|
||||||
|
var val1 = valueStack.Pop();
|
||||||
|
switch (val1.valueType) {
|
||||||
|
case ValueType.Int32: valueStack.Push(Int32Value.Conv_R_Un((Int32Value)val1)); break;
|
||||||
|
case ValueType.Int64: valueStack.Push(Int64Value.Conv_R_Un((Int64Value)val1)); break;
|
||||||
|
case ValueType.Real8: valueStack.Push(Real8Value.Conv_R_Un((Real8Value)val1)); break;
|
||||||
|
default: valueStack.Push(Real8Value.CreateUnknown()); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Emulate_Conv_R4(Instruction instr) {
|
||||||
|
var val1 = valueStack.Pop();
|
||||||
|
switch (val1.valueType) {
|
||||||
|
case ValueType.Int32: valueStack.Push(Int32Value.Conv_R4((Int32Value)val1)); break;
|
||||||
|
case ValueType.Int64: valueStack.Push(Int64Value.Conv_R4((Int64Value)val1)); break;
|
||||||
|
case ValueType.Real8: valueStack.Push(Real8Value.Conv_R4((Real8Value)val1)); break;
|
||||||
|
default: valueStack.Push(Real8Value.CreateUnknown()); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Emulate_Conv_R8(Instruction instr) {
|
||||||
|
var val1 = valueStack.Pop();
|
||||||
|
switch (val1.valueType) {
|
||||||
|
case ValueType.Int32: valueStack.Push(Int32Value.Conv_R8((Int32Value)val1)); break;
|
||||||
|
case ValueType.Int64: valueStack.Push(Int64Value.Conv_R8((Int64Value)val1)); break;
|
||||||
|
case ValueType.Real8: valueStack.Push(Real8Value.Conv_R8((Real8Value)val1)); break;
|
||||||
|
default: valueStack.Push(Real8Value.CreateUnknown()); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Emulate_Add(Instruction instr) {
|
void Emulate_Add(Instruction instr) {
|
||||||
var val2 = valueStack.Pop();
|
var val2 = valueStack.Pop();
|
||||||
var val1 = valueStack.Pop();
|
var val1 = valueStack.Pop();
|
||||||
|
@ -1064,6 +1098,8 @@ namespace de4dot.blocks.cflow {
|
||||||
valueStack.Push(Int32Value.Ceq((Int32Value)val1, (Int32Value)val2));
|
valueStack.Push(Int32Value.Ceq((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
valueStack.Push(Int64Value.Ceq((Int64Value)val1, (Int64Value)val2));
|
valueStack.Push(Int64Value.Ceq((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
valueStack.Push(Real8Value.Ceq((Real8Value)val1, (Real8Value)val2));
|
||||||
else if (val1.IsNull() && val2.IsNull())
|
else if (val1.IsNull() && val2.IsNull())
|
||||||
valueStack.Push(Int32Value.One);
|
valueStack.Push(Int32Value.One);
|
||||||
else
|
else
|
||||||
|
@ -1078,6 +1114,8 @@ namespace de4dot.blocks.cflow {
|
||||||
valueStack.Push(Int32Value.Cgt((Int32Value)val1, (Int32Value)val2));
|
valueStack.Push(Int32Value.Cgt((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
valueStack.Push(Int64Value.Cgt((Int64Value)val1, (Int64Value)val2));
|
valueStack.Push(Int64Value.Cgt((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
valueStack.Push(Real8Value.Cgt((Real8Value)val1, (Real8Value)val2));
|
||||||
else
|
else
|
||||||
valueStack.Push(Int32Value.CreateUnknownBool());
|
valueStack.Push(Int32Value.CreateUnknownBool());
|
||||||
}
|
}
|
||||||
|
@ -1090,6 +1128,8 @@ namespace de4dot.blocks.cflow {
|
||||||
valueStack.Push(Int32Value.Cgt_Un((Int32Value)val1, (Int32Value)val2));
|
valueStack.Push(Int32Value.Cgt_Un((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
valueStack.Push(Int64Value.Cgt_Un((Int64Value)val1, (Int64Value)val2));
|
valueStack.Push(Int64Value.Cgt_Un((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
valueStack.Push(Real8Value.Cgt_Un((Real8Value)val1, (Real8Value)val2));
|
||||||
else
|
else
|
||||||
valueStack.Push(Int32Value.CreateUnknownBool());
|
valueStack.Push(Int32Value.CreateUnknownBool());
|
||||||
}
|
}
|
||||||
|
@ -1102,6 +1142,8 @@ namespace de4dot.blocks.cflow {
|
||||||
valueStack.Push(Int32Value.Clt((Int32Value)val1, (Int32Value)val2));
|
valueStack.Push(Int32Value.Clt((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
valueStack.Push(Int64Value.Clt((Int64Value)val1, (Int64Value)val2));
|
valueStack.Push(Int64Value.Clt((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
valueStack.Push(Real8Value.Clt((Real8Value)val1, (Real8Value)val2));
|
||||||
else
|
else
|
||||||
valueStack.Push(Int32Value.CreateUnknownBool());
|
valueStack.Push(Int32Value.CreateUnknownBool());
|
||||||
}
|
}
|
||||||
|
@ -1114,6 +1156,8 @@ namespace de4dot.blocks.cflow {
|
||||||
valueStack.Push(Int32Value.Clt_Un((Int32Value)val1, (Int32Value)val2));
|
valueStack.Push(Int32Value.Clt_Un((Int32Value)val1, (Int32Value)val2));
|
||||||
else if (val1.IsInt64() && val2.IsInt64())
|
else if (val1.IsInt64() && val2.IsInt64())
|
||||||
valueStack.Push(Int64Value.Clt_Un((Int64Value)val1, (Int64Value)val2));
|
valueStack.Push(Int64Value.Clt_Un((Int64Value)val1, (Int64Value)val2));
|
||||||
|
else if (val1.IsReal8() && val2.IsReal8())
|
||||||
|
valueStack.Push(Real8Value.Clt_Un((Real8Value)val1, (Real8Value)val2));
|
||||||
else
|
else
|
||||||
valueStack.Push(Int32Value.CreateUnknownBool());
|
valueStack.Push(Int32Value.CreateUnknownBool());
|
||||||
}
|
}
|
||||||
|
|
|
@ -331,6 +331,24 @@ namespace de4dot.blocks.cflow {
|
||||||
return new Int64Value((long)(uint)a.Value, a.ValidMask | (Int64Value.NO_UNKNOWN_BITS << 32));
|
return new Int64Value((long)(uint)a.Value, a.ValidMask | (Int64Value.NO_UNKNOWN_BITS << 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Real8Value Conv_R_Un(Int32Value a) {
|
||||||
|
if (a.AllBitsValid())
|
||||||
|
return new Real8Value((float)(uint)a.Value);
|
||||||
|
return Real8Value.CreateUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Real8Value Conv_R4(Int32Value a) {
|
||||||
|
if (a.AllBitsValid())
|
||||||
|
return new Real8Value((float)(int)a.Value);
|
||||||
|
return Real8Value.CreateUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Real8Value Conv_R8(Int32Value a) {
|
||||||
|
if (a.AllBitsValid())
|
||||||
|
return new Real8Value((double)(int)a.Value);
|
||||||
|
return Real8Value.CreateUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
public static Int32Value Add(Int32Value a, Int32Value b) {
|
public static Int32Value Add(Int32Value a, Int32Value b) {
|
||||||
if (a.AllBitsValid() && b.AllBitsValid())
|
if (a.AllBitsValid() && b.AllBitsValid())
|
||||||
return new Int32Value(a.Value + b.Value);
|
return new Int32Value(a.Value + b.Value);
|
||||||
|
@ -556,7 +574,7 @@ namespace de4dot.blocks.cflow {
|
||||||
return new Int32Value((int)((uint)a.Value >> shift), validMask);
|
return new Int32Value((int)((uint)a.Value >> shift), validMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Int32Value Create(Bool3 b) {
|
public static Int32Value Create(Bool3 b) {
|
||||||
switch (b) {
|
switch (b) {
|
||||||
case Bool3.False: return Zero;
|
case Bool3.False: return Zero;
|
||||||
case Bool3.True: return One;
|
case Bool3.True: return One;
|
||||||
|
|
|
@ -224,6 +224,24 @@ namespace de4dot.blocks.cflow {
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Real8Value Conv_R_Un(Int64Value a) {
|
||||||
|
if (a.AllBitsValid())
|
||||||
|
return new Real8Value((float)(ulong)a.Value);
|
||||||
|
return Real8Value.CreateUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Real8Value Conv_R4(Int64Value a) {
|
||||||
|
if (a.AllBitsValid())
|
||||||
|
return new Real8Value((float)(long)a.Value);
|
||||||
|
return Real8Value.CreateUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Real8Value Conv_R8(Int64Value a) {
|
||||||
|
if (a.AllBitsValid())
|
||||||
|
return new Real8Value((double)(long)a.Value);
|
||||||
|
return Real8Value.CreateUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
public static Int64Value Add(Int64Value a, Int64Value b) {
|
public static Int64Value Add(Int64Value a, Int64Value b) {
|
||||||
if (a.AllBitsValid() && b.AllBitsValid())
|
if (a.AllBitsValid() && b.AllBitsValid())
|
||||||
return new Int64Value(a.Value + b.Value);
|
return new Int64Value(a.Value + b.Value);
|
||||||
|
@ -449,32 +467,24 @@ namespace de4dot.blocks.cflow {
|
||||||
return new Int64Value((long)((ulong)a.Value >> shift), validMask);
|
return new Int64Value((long)((ulong)a.Value >> shift), validMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Int32Value Create(Bool3 b) {
|
|
||||||
switch (b) {
|
|
||||||
case Bool3.False: return Int32Value.Zero;
|
|
||||||
case Bool3.True: return Int32Value.One;
|
|
||||||
default: return Int32Value.CreateUnknownBool();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Int32Value Ceq(Int64Value a, Int64Value b) {
|
public static Int32Value Ceq(Int64Value a, Int64Value b) {
|
||||||
return Create(CompareEq(a, b));
|
return Int32Value.Create(CompareEq(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Int32Value Cgt(Int64Value a, Int64Value b) {
|
public static Int32Value Cgt(Int64Value a, Int64Value b) {
|
||||||
return Create(CompareGt(a, b));
|
return Int32Value.Create(CompareGt(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Int32Value Cgt_Un(Int64Value a, Int64Value b) {
|
public static Int32Value Cgt_Un(Int64Value a, Int64Value b) {
|
||||||
return Create(CompareGt_Un(a, b));
|
return Int32Value.Create(CompareGt_Un(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Int32Value Clt(Int64Value a, Int64Value b) {
|
public static Int32Value Clt(Int64Value a, Int64Value b) {
|
||||||
return Create(CompareLt(a, b));
|
return Int32Value.Create(CompareLt(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Int32Value Clt_Un(Int64Value a, Int64Value b) {
|
public static Int32Value Clt_Un(Int64Value a, Int64Value b) {
|
||||||
return Create(CompareLt_Un(a, b));
|
return Int32Value.Create(CompareLt_Un(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Bool3 CompareEq(Int64Value a, Int64Value b) {
|
public static Bool3 CompareEq(Int64Value a, Int64Value b) {
|
||||||
|
|
|
@ -168,6 +168,100 @@ namespace de4dot.blocks.cflow {
|
||||||
return Int64Value.CreateUnknown();
|
return Int64Value.CreateUnknown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Real8Value Conv_R_Un(Real8Value a) {
|
||||||
|
return CreateUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Real8Value Conv_R4(Real8Value a) {
|
||||||
|
if (a.IsValid)
|
||||||
|
return new Real8Value((float)a.Value);
|
||||||
|
return CreateUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Real8Value Conv_R8(Real8Value a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Ceq(Real8Value a, Real8Value b) {
|
||||||
|
return Int32Value.Create(CompareEq(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Cgt(Real8Value a, Real8Value b) {
|
||||||
|
return Int32Value.Create(CompareGt(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Cgt_Un(Real8Value a, Real8Value b) {
|
||||||
|
return Int32Value.Create(CompareGt_Un(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Clt(Real8Value a, Real8Value b) {
|
||||||
|
return Int32Value.Create(CompareLt(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Clt_Un(Real8Value a, Real8Value b) {
|
||||||
|
return Int32Value.Create(CompareLt_Un(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 CompareEq(Real8Value a, Real8Value b) {
|
||||||
|
if (a.IsValid && b.IsValid)
|
||||||
|
return a.Value == b.Value ? Bool3.True : Bool3.False;
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 CompareNeq(Real8Value a, Real8Value b) {
|
||||||
|
if (a.IsValid && b.IsValid)
|
||||||
|
return a.Value != b.Value ? Bool3.True : Bool3.False;
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 CompareGt(Real8Value a, Real8Value b) {
|
||||||
|
if (a.IsValid && b.IsValid)
|
||||||
|
return a.Value > b.Value ? Bool3.True : Bool3.False;
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 CompareGt_Un(Real8Value a, Real8Value b) {
|
||||||
|
return Bool3.Unknown; //TODO:
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 CompareGe(Real8Value a, Real8Value b) {
|
||||||
|
if (a.IsValid && b.IsValid)
|
||||||
|
return a.Value >= b.Value ? Bool3.True : Bool3.False;
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 CompareGe_Un(Real8Value a, Real8Value b) {
|
||||||
|
return Bool3.Unknown; //TODO:
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 CompareLe(Real8Value a, Real8Value b) {
|
||||||
|
if (a.IsValid && b.IsValid)
|
||||||
|
return a.Value <= b.Value ? Bool3.True : Bool3.False;
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 CompareLe_Un(Real8Value a, Real8Value b) {
|
||||||
|
return Bool3.Unknown; //TODO:
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 CompareLt(Real8Value a, Real8Value b) {
|
||||||
|
if (a.IsValid && b.IsValid)
|
||||||
|
return a.Value < b.Value ? Bool3.True : Bool3.False;
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 CompareLt_Un(Real8Value a, Real8Value b) {
|
||||||
|
return Bool3.Unknown; //TODO:
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 CompareTrue(Real8Value a) {
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 CompareFalse(Real8Value a) {
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
if (!IsValid)
|
if (!IsValid)
|
||||||
return "<INVALID_REAL8>";
|
return "<INVALID_REAL8>";
|
||||||
|
|
|
@ -61,15 +61,14 @@ namespace de4dot.code {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasMethodBody(uint rid) {
|
public bool GetMethodBody(uint rid, RVA rva, IList<Parameter> parameters, GenericParamContext gpContext, out MethodBody methodBody) {
|
||||||
return GetDumpedMethod(rid) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MethodBody GetMethodBody(uint rid, RVA rva, IList<Parameter> parameters) {
|
|
||||||
var dm = GetDumpedMethod(rid);
|
var dm = GetDumpedMethod(rid);
|
||||||
if (dm == null)
|
if (dm == null) {
|
||||||
return null;
|
methodBody = null;
|
||||||
return MethodBodyReader.CreateCilBody(module, dm.code, dm.extraSections, parameters, dm.mhFlags, dm.mhMaxStack, dm.mhCodeSize, dm.mhLocalVarSigTok);
|
return false;
|
||||||
|
}
|
||||||
|
methodBody = MethodBodyReader.CreateCilBody(module, dm.code, dm.extraSections, parameters, dm.mhFlags, dm.mhMaxStack, dm.mhCodeSize, dm.mhLocalVarSigTok, gpContext);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
|
|
|
@ -73,6 +73,7 @@
|
||||||
<Compile Include="deobfuscators\Agile_NET\ResourceDecrypter.cs" />
|
<Compile Include="deobfuscators\Agile_NET\ResourceDecrypter.cs" />
|
||||||
<Compile Include="deobfuscators\Agile_NET\StackFrameHelper.cs" />
|
<Compile Include="deobfuscators\Agile_NET\StackFrameHelper.cs" />
|
||||||
<Compile Include="deobfuscators\Agile_NET\StringDecrypter.cs" />
|
<Compile Include="deobfuscators\Agile_NET\StringDecrypter.cs" />
|
||||||
|
<Compile Include="deobfuscators\Agile_NET\StringDecrypterInfo.cs" />
|
||||||
<Compile Include="deobfuscators\Agile_NET\vm\CilOperandInstructionRestorer.cs" />
|
<Compile Include="deobfuscators\Agile_NET\vm\CilOperandInstructionRestorer.cs" />
|
||||||
<Compile Include="deobfuscators\Agile_NET\vm\CsvmDataReader.cs" />
|
<Compile Include="deobfuscators\Agile_NET\vm\CsvmDataReader.cs" />
|
||||||
<Compile Include="deobfuscators\Agile_NET\vm\CsvmMethodData.cs" />
|
<Compile Include="deobfuscators\Agile_NET\vm\CsvmMethodData.cs" />
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
TypeDef cliSecureRtType;
|
TypeDef cliSecureRtType;
|
||||||
MethodDef postInitializeMethod;
|
MethodDef postInitializeMethod;
|
||||||
MethodDef initializeMethod;
|
MethodDef initializeMethod;
|
||||||
MethodDef stringDecrypterMethod;
|
Dictionary<StringDecrypterInfo, bool> stringDecrypterInfos = new Dictionary<StringDecrypterInfo, bool>();
|
||||||
MethodDef loadMethod;
|
MethodDef loadMethod;
|
||||||
bool foundSig;
|
bool foundSig;
|
||||||
|
|
||||||
|
@ -41,8 +41,8 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
get { return cliSecureRtType; }
|
get { return cliSecureRtType; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodDef StringDecrypterMethod {
|
public IEnumerable<StringDecrypterInfo> StringDecrypterInfos {
|
||||||
get { return stringDecrypterMethod; }
|
get { return stringDecrypterInfos.Keys; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodDef PostInitializeMethod {
|
public MethodDef PostInitializeMethod {
|
||||||
|
@ -66,7 +66,11 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
cliSecureRtType = Lookup(oldOne.cliSecureRtType, "Could not find CliSecureRt type");
|
cliSecureRtType = Lookup(oldOne.cliSecureRtType, "Could not find CliSecureRt type");
|
||||||
postInitializeMethod = Lookup(oldOne.postInitializeMethod, "Could not find postInitializeMethod method");
|
postInitializeMethod = Lookup(oldOne.postInitializeMethod, "Could not find postInitializeMethod method");
|
||||||
initializeMethod = Lookup(oldOne.initializeMethod, "Could not find initializeMethod method");
|
initializeMethod = Lookup(oldOne.initializeMethod, "Could not find initializeMethod method");
|
||||||
stringDecrypterMethod = Lookup(oldOne.stringDecrypterMethod, "Could not find stringDecrypterMethod method");
|
foreach (var info in oldOne.stringDecrypterInfos.Keys) {
|
||||||
|
var m = Lookup(info.Method, "Could not find string decrypter method");
|
||||||
|
var f = Lookup(info.Field, "Could not find string decrypter field");
|
||||||
|
stringDecrypterInfos[new StringDecrypterInfo(m, f)] = true;
|
||||||
|
}
|
||||||
loadMethod = Lookup(oldOne.loadMethod, "Could not find loadMethod method");
|
loadMethod = Lookup(oldOne.loadMethod, "Could not find loadMethod method");
|
||||||
foundSig = oldOne.foundSig;
|
foundSig = oldOne.foundSig;
|
||||||
}
|
}
|
||||||
|
@ -100,11 +104,11 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
if (!HasInitializeMethod(type, "_Initialize") && !HasInitializeMethod(type, "_Initialize64"))
|
if (!HasInitializeMethod(type, "_Initialize") && !HasInitializeMethod(type, "_Initialize64"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
stringDecrypterMethod = FindStringDecrypterMethod(type);
|
|
||||||
initializeMethod = calledMethod;
|
initializeMethod = calledMethod;
|
||||||
postInitializeMethod = FindMethod(type, "System.Void", "PostInitialize", "()");
|
postInitializeMethod = FindMethod(type, "System.Void", "PostInitialize", "()");
|
||||||
loadMethod = FindMethod(type, "System.IntPtr", "Load", "()");
|
loadMethod = FindMethod(type, "System.IntPtr", "Load", "()");
|
||||||
cliSecureRtType = type;
|
cliSecureRtType = type;
|
||||||
|
FindStringDecrypters();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,6 +116,15 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FindStringDecrypters() {
|
||||||
|
AddStringDecrypterMethod(FindStringDecrypterMethod(cliSecureRtType));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddStringDecrypterMethod(MethodDef method) {
|
||||||
|
if (method != null)
|
||||||
|
stringDecrypterInfos[new StringDecrypterInfo(method)] = true;
|
||||||
|
}
|
||||||
|
|
||||||
static string[] requiredFields6 = new string[] {
|
static string[] requiredFields6 = new string[] {
|
||||||
"System.Byte[]",
|
"System.Byte[]",
|
||||||
};
|
};
|
||||||
|
@ -134,7 +147,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
if (cs == null)
|
if (cs == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
stringDecrypterMethod = cs;
|
AddStringDecrypterMethod(cs);
|
||||||
cliSecureRtType = type;
|
cliSecureRtType = type;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -208,7 +221,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cliSecureRtType = type;
|
cliSecureRtType = type;
|
||||||
stringDecrypterMethod = cs;
|
AddStringDecrypterMethod(cs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,7 +180,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
FindCliSecureAttribute();
|
FindCliSecureAttribute();
|
||||||
cliSecureRtType = new CliSecureRtType(module);
|
cliSecureRtType = new CliSecureRtType(module);
|
||||||
cliSecureRtType.Find(ModuleBytes);
|
cliSecureRtType.Find(ModuleBytes);
|
||||||
stringDecrypter = new StringDecrypter(module, cliSecureRtType.StringDecrypterMethod);
|
stringDecrypter = new StringDecrypter(module, cliSecureRtType.StringDecrypterInfos);
|
||||||
stringDecrypter.Find();
|
stringDecrypter.Find();
|
||||||
resourceDecrypter = new ResourceDecrypter(module);
|
resourceDecrypter = new ResourceDecrypter(module);
|
||||||
resourceDecrypter.Find();
|
resourceDecrypter.Find();
|
||||||
|
@ -246,7 +246,8 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
base.DeobfuscateBegin();
|
base.DeobfuscateBegin();
|
||||||
|
|
||||||
cliSecureRtType.FindStringDecrypterMethod();
|
cliSecureRtType.FindStringDecrypterMethod();
|
||||||
stringDecrypter.Method = cliSecureRtType.StringDecrypterMethod;
|
stringDecrypter.AddDecrypterInfos(cliSecureRtType.StringDecrypterInfos);
|
||||||
|
stringDecrypter.Initialize();
|
||||||
|
|
||||||
AddAttributesToBeRemoved(cliSecureAttributes, "Obfuscator attribute");
|
AddAttributesToBeRemoved(cliSecureAttributes, "Obfuscator attribute");
|
||||||
|
|
||||||
|
@ -265,7 +266,8 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
|
|
||||||
proxyCallFixer.Find();
|
proxyCallFixer.Find();
|
||||||
|
|
||||||
staticStringInliner.Add(stringDecrypter.Method, (method, gim, args) => stringDecrypter.Decrypt((string)args[0]));
|
foreach (var info in stringDecrypter.StringDecrypterInfos)
|
||||||
|
staticStringInliner.Add(info.Method, (method, gim, args) => stringDecrypter.Decrypt((string)args[0]));
|
||||||
DeobfuscatedFile.StringDecryptersAdded();
|
DeobfuscatedFile.StringDecryptersAdded();
|
||||||
|
|
||||||
if (options.DecryptMethods) {
|
if (options.DecryptMethods) {
|
||||||
|
@ -295,6 +297,8 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DeobfuscateMethodEnd(Blocks blocks) {
|
public override void DeobfuscateMethodEnd(Blocks blocks) {
|
||||||
|
if (Operations.DecryptStrings != OpDecryptString.None)
|
||||||
|
stringDecrypter.Deobfuscate(blocks);
|
||||||
proxyCallFixer.Deobfuscate(blocks);
|
proxyCallFixer.Deobfuscate(blocks);
|
||||||
RemoveStackFrameHelperCode(blocks);
|
RemoveStackFrameHelperCode(blocks);
|
||||||
base.DeobfuscateMethodEnd(blocks);
|
base.DeobfuscateMethodEnd(blocks);
|
||||||
|
@ -310,8 +314,14 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
}
|
}
|
||||||
if (CanRemoveStringDecrypterType) {
|
if (CanRemoveStringDecrypterType) {
|
||||||
AddTypeToBeRemoved(stringDecrypter.Type, "String decrypter type");
|
AddTypeToBeRemoved(stringDecrypter.Type, "String decrypter type");
|
||||||
|
foreach (var info in stringDecrypter.StringDecrypterInfos) {
|
||||||
|
if (info.Method.DeclaringType != cliSecureRtType.Type)
|
||||||
|
AddMethodToBeRemoved(info.Method, "String decrypter method");
|
||||||
|
if (info.Field != null && info.Field.DeclaringType != stringDecrypter.Type)
|
||||||
|
AddFieldToBeRemoved(info.Field, "String decrypter field");
|
||||||
|
}
|
||||||
if (options.DecryptMethods)
|
if (options.DecryptMethods)
|
||||||
AddTypeToBeRemoved(cliSecureRtType.Type, "Obfuscator type");
|
AddTypeToBeRemoved(cliSecureRtType.Type ?? stringDecrypter.KeyArrayFieldType, "Obfuscator type");
|
||||||
}
|
}
|
||||||
if (options.DecryptMethods) {
|
if (options.DecryptMethods) {
|
||||||
AddResources("Obfuscator protection files");
|
AddResources("Obfuscator protection files");
|
||||||
|
@ -327,8 +337,8 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
|
|
||||||
public override IEnumerable<int> GetStringDecrypterMethods() {
|
public override IEnumerable<int> GetStringDecrypterMethods() {
|
||||||
var list = new List<int>();
|
var list = new List<int>();
|
||||||
if (stringDecrypter.Method != null)
|
foreach (var info in stringDecrypter.StringDecrypterInfos)
|
||||||
list.Add(stringDecrypter.Method.MDToken.ToInt32());
|
list.Add(info.Method.MDToken.ToInt32());
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,10 +62,15 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
FindResourceType();
|
FindResourceType();
|
||||||
}
|
}
|
||||||
|
|
||||||
static readonly string[] requiredFields = new string[] {
|
static readonly string[] requiredFields1 = new string[] {
|
||||||
"System.Reflection.Assembly",
|
"System.Reflection.Assembly",
|
||||||
"System.String[]",
|
"System.String[]",
|
||||||
};
|
};
|
||||||
|
static readonly string[] requiredFields2 = new string[] {
|
||||||
|
"System.Reflection.Assembly",
|
||||||
|
"System.String[]",
|
||||||
|
"System.Collections.Hashtable",
|
||||||
|
};
|
||||||
void FindResourceType() {
|
void FindResourceType() {
|
||||||
var cctor = DotNetUtils.GetModuleTypeCctor(module);
|
var cctor = DotNetUtils.GetModuleTypeCctor(module);
|
||||||
if (cctor == null)
|
if (cctor == null)
|
||||||
|
@ -77,7 +82,9 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
if (!DotNetUtils.IsMethod(calledMethod, "System.Void", "()"))
|
if (!DotNetUtils.IsMethod(calledMethod, "System.Void", "()"))
|
||||||
continue;
|
continue;
|
||||||
var type = calledMethod.DeclaringType;
|
var type = calledMethod.DeclaringType;
|
||||||
if (!new FieldTypes(type).Exactly(requiredFields))
|
var fieldTypes = new FieldTypes(type);
|
||||||
|
if (!fieldTypes.Exactly(requiredFields1) &&
|
||||||
|
!fieldTypes.Exactly(requiredFields2))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var resolveHandler = DotNetUtils.GetMethod(type, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)");
|
var resolveHandler = DotNetUtils.GetMethod(type, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)");
|
||||||
|
|
|
@ -18,38 +18,53 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
|
using dnlib.DotNet.Emit;
|
||||||
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
class StringDecrypter {
|
class StringDecrypter {
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
TypeDef stringDecrypterType;
|
TypeDef stringDecrypterType;
|
||||||
MethodDef stringDecrypterMethod;
|
FieldDef keyInitField;
|
||||||
|
FieldDef keyArrayField;
|
||||||
|
Dictionary<StringDecrypterInfo, bool> stringDecrypterInfos = new Dictionary<StringDecrypterInfo, bool>();
|
||||||
byte[] stringDecrypterKey;
|
byte[] stringDecrypterKey;
|
||||||
|
|
||||||
public bool Detected {
|
public bool Detected {
|
||||||
get { return stringDecrypterMethod != null; }
|
get { return stringDecrypterInfos.Count != 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeDef Type {
|
public TypeDef Type {
|
||||||
get { return stringDecrypterType; }
|
get { return stringDecrypterType; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodDef Method {
|
public TypeDef KeyArrayFieldType {
|
||||||
get { return stringDecrypterMethod; }
|
get { return keyArrayField == null ? null : keyArrayField.DeclaringType; }
|
||||||
set { stringDecrypterMethod = value; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringDecrypter(ModuleDefMD module, MethodDef stringDecrypterMethod) {
|
public IEnumerable<StringDecrypterInfo> StringDecrypterInfos {
|
||||||
|
get { return stringDecrypterInfos.Keys; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringDecrypter(ModuleDefMD module, IEnumerable<StringDecrypterInfo> stringDecrypterMethods) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.stringDecrypterMethod = stringDecrypterMethod;
|
foreach (var sdm in stringDecrypterMethods)
|
||||||
|
this.stringDecrypterInfos[sdm] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringDecrypter(ModuleDefMD module, StringDecrypter oldOne) {
|
public StringDecrypter(ModuleDefMD module, StringDecrypter oldOne) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
stringDecrypterType = Lookup(oldOne.stringDecrypterType, "Could not find stringDecrypterType");
|
stringDecrypterType = Lookup(oldOne.stringDecrypterType, "Could not find stringDecrypterType");
|
||||||
stringDecrypterMethod = Lookup(oldOne.stringDecrypterMethod, "Could not find stringDecrypterMethod");
|
keyInitField = Lookup(oldOne.keyInitField, "Could not find key init field");
|
||||||
|
keyArrayField = Lookup(oldOne.keyArrayField, "Could not find key array field");
|
||||||
|
foreach (var info in oldOne.stringDecrypterInfos.Keys) {
|
||||||
|
var m = Lookup(info.Method, "Could not find string decrypter method");
|
||||||
|
var f = Lookup(info.Field, "Could not find string decrypter field");
|
||||||
|
stringDecrypterInfos[new StringDecrypterInfo(m, f)] = true;
|
||||||
|
}
|
||||||
stringDecrypterKey = oldOne.stringDecrypterKey;
|
stringDecrypterKey = oldOne.stringDecrypterKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +72,11 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
return DeobUtils.Lookup(module, def, errorMessage);
|
return DeobUtils.Lookup(module, def, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddDecrypterInfos(IEnumerable<StringDecrypterInfo> infos) {
|
||||||
|
foreach (var info in infos)
|
||||||
|
stringDecrypterInfos[info] = true;
|
||||||
|
}
|
||||||
|
|
||||||
public void Find() {
|
public void Find() {
|
||||||
stringDecrypterKey = new byte[1] { 0xFF };
|
stringDecrypterKey = new byte[1] { 0xFF };
|
||||||
foreach (var type in module.Types) {
|
foreach (var type in module.Types) {
|
||||||
|
@ -64,6 +84,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
stringDecrypterType = type;
|
stringDecrypterType = type;
|
||||||
foreach (var field in type.Fields) {
|
foreach (var field in type.Fields) {
|
||||||
if (field.FullName == "<D234> <D234>::345" || field.FullName == "<ClassD234>/D234 <ClassD234>::345") {
|
if (field.FullName == "<D234> <D234>::345" || field.FullName == "<ClassD234>/D234 <ClassD234>::345") {
|
||||||
|
keyInitField = field;
|
||||||
stringDecrypterKey = field.InitialValue;
|
stringDecrypterKey = field.InitialValue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -73,6 +94,121 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Initialize() {
|
||||||
|
if (keyInitField == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var type in module.Types) {
|
||||||
|
var cctor = type.FindStaticConstructor();
|
||||||
|
if (cctor == null)
|
||||||
|
continue;
|
||||||
|
keyArrayField = GetKeyArrayField(cctor, keyInitField);
|
||||||
|
if (keyArrayField != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (keyArrayField == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var type in module.GetTypes()) {
|
||||||
|
FieldDef field;
|
||||||
|
var method = FindStringDecrypters(type, keyArrayField, out field);
|
||||||
|
if (method == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
stringDecrypterInfos[new StringDecrypterInfo(method, field)] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static FieldDef GetKeyArrayField(MethodDef method, FieldDef keyInitField) {
|
||||||
|
if (method == null || method.Body == null)
|
||||||
|
return null;
|
||||||
|
var instrs = method.Body.Instructions;
|
||||||
|
for (int i = 0; i < instrs.Count; i++) {
|
||||||
|
if (instrs[i].OpCode.Code != Code.Ldtoken)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
for (; i < instrs.Count; i++) {
|
||||||
|
var instr = instrs[i];
|
||||||
|
if (instr.OpCode.Code != Code.Stsfld)
|
||||||
|
continue;
|
||||||
|
var field = instr.Operand as FieldDef;
|
||||||
|
if (field == null || !field.IsStatic || field.DeclaringType != method.DeclaringType)
|
||||||
|
continue;
|
||||||
|
if (field.FieldSig.GetFieldType().GetFullName() != "System.Byte[]")
|
||||||
|
continue;
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MethodDef FindStringDecrypters(TypeDef type, FieldDef keyArrayField, out FieldDef field) {
|
||||||
|
FieldDef foundField = null;
|
||||||
|
foreach (var method in type.Methods) {
|
||||||
|
if (!method.IsAssembly || !method.IsStatic)
|
||||||
|
continue;
|
||||||
|
if (!DotNetUtils.IsMethod(method, "System.String", "(System.String)"))
|
||||||
|
continue;
|
||||||
|
if (!method.HasBody)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool accessedArrayField = false;
|
||||||
|
foreach (var instr in method.Body.Instructions) {
|
||||||
|
var f = instr.Operand as FieldDef;
|
||||||
|
accessedArrayField |= f == keyArrayField;
|
||||||
|
if (f == null || f == keyArrayField || f == foundField)
|
||||||
|
continue;
|
||||||
|
if (DotNetUtils.DerivesFromDelegate(f.DeclaringType))
|
||||||
|
continue;
|
||||||
|
if (f.FieldSig.GetFieldType().GetFullName() != "System.Collections.Hashtable" ||
|
||||||
|
foundField != null)
|
||||||
|
goto exit;
|
||||||
|
foundField = f;
|
||||||
|
}
|
||||||
|
if (!accessedArrayField)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
field = foundField;
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit: ;
|
||||||
|
field = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Deobfuscate(Blocks blocks) {
|
||||||
|
if (!blocks.Method.IsStaticConstructor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var decrypterFields = new Dictionary<FieldDef, bool>(stringDecrypterInfos.Count);
|
||||||
|
foreach (var info in stringDecrypterInfos.Keys) {
|
||||||
|
if (info.Field != null)
|
||||||
|
decrypterFields[info.Field] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var block in blocks.MethodBlocks.GetAllBlocks()) {
|
||||||
|
var instrs = block.Instructions;
|
||||||
|
for (int i = instrs.Count - 2; i >= 0; i--) {
|
||||||
|
var newobj = instrs[i];
|
||||||
|
if (newobj.OpCode.Code != Code.Newobj)
|
||||||
|
continue;
|
||||||
|
var ctor = newobj.Operand as IMethod;
|
||||||
|
if (ctor == null || ctor.FullName != "System.Void System.Collections.Hashtable::.ctor()")
|
||||||
|
continue;
|
||||||
|
var stsfld = instrs[i + 1];
|
||||||
|
if (stsfld.OpCode.Code != Code.Stsfld)
|
||||||
|
continue;
|
||||||
|
var field = stsfld.Operand as FieldDef;
|
||||||
|
if (field == null || !decrypterFields.ContainsKey(field))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
block.Remove(i, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string Decrypt(string es) {
|
public string Decrypt(string es) {
|
||||||
if (stringDecrypterKey == null)
|
if (stringDecrypterKey == null)
|
||||||
throw new ApplicationException("Trying to decrypt strings when stringDecrypterKey is null (could not find it!)");
|
throw new ApplicationException("Trying to decrypt strings when stringDecrypterKey is null (could not find it!)");
|
||||||
|
|
52
de4dot.code/deobfuscators/Agile_NET/StringDecrypterInfo.cs
Normal file
52
de4dot.code/deobfuscators/Agile_NET/StringDecrypterInfo.cs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2011-2014 de4dot@gmail.com
|
||||||
|
|
||||||
|
This file is part of de4dot.
|
||||||
|
|
||||||
|
de4dot is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
de4dot is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using dnlib.DotNet;
|
||||||
|
|
||||||
|
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
|
class StringDecrypterInfo {
|
||||||
|
public readonly MethodDef Method;
|
||||||
|
public readonly FieldDef Field;
|
||||||
|
|
||||||
|
public StringDecrypterInfo(MethodDef method)
|
||||||
|
: this(method, null) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringDecrypterInfo(MethodDef method, FieldDef field) {
|
||||||
|
this.Method = method;
|
||||||
|
this.Field = field;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
int hash = 0;
|
||||||
|
if (Method != null)
|
||||||
|
hash ^= Method.GetHashCode();
|
||||||
|
if (Field != null)
|
||||||
|
hash ^= Field.GetHashCode();
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj) {
|
||||||
|
var other = obj as StringDecrypterInfo;
|
||||||
|
return other != null &&
|
||||||
|
Method == other.Method &&
|
||||||
|
Field == other.Field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -232,13 +232,14 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
if (numLocals < 0)
|
if (numLocals < 0)
|
||||||
throw new ApplicationException("Invalid number of locals");
|
throw new ApplicationException("Invalid number of locals");
|
||||||
|
|
||||||
|
var gpContext = GenericParamContext.Create(cilMethod);
|
||||||
for (int i = 0; i < numLocals; i++)
|
for (int i = 0; i < numLocals; i++)
|
||||||
locals.Add(new Local(ReadTypeRef(reader)));
|
locals.Add(new Local(ReadTypeRef(reader, gpContext)));
|
||||||
|
|
||||||
return locals;
|
return locals;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeSig ReadTypeRef(BinaryReader reader) {
|
TypeSig ReadTypeRef(BinaryReader reader, GenericParamContext gpContext) {
|
||||||
var etype = (ElementType)reader.ReadInt32();
|
var etype = (ElementType)reader.ReadInt32();
|
||||||
switch (etype) {
|
switch (etype) {
|
||||||
case ElementType.Void: return module.CorLibTypes.Void;
|
case ElementType.Void: return module.CorLibTypes.Void;
|
||||||
|
@ -263,12 +264,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
case ElementType.ValueType:
|
case ElementType.ValueType:
|
||||||
case ElementType.Var:
|
case ElementType.Var:
|
||||||
case ElementType.MVar:
|
case ElementType.MVar:
|
||||||
return (module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef).ToTypeSig();
|
return (module.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef).ToTypeSig();
|
||||||
|
|
||||||
case ElementType.GenericInst:
|
case ElementType.GenericInst:
|
||||||
etype = (ElementType)reader.ReadInt32();
|
etype = (ElementType)reader.ReadInt32();
|
||||||
if (etype == ElementType.ValueType)
|
if (etype == ElementType.ValueType)
|
||||||
return (module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef).ToTypeSig();
|
return (module.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef).ToTypeSig();
|
||||||
// ElementType.Class
|
// ElementType.Class
|
||||||
return module.CorLibTypes.Object;
|
return module.CorLibTypes.Object;
|
||||||
|
|
||||||
|
@ -299,6 +300,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
if (numExceptions < 0)
|
if (numExceptions < 0)
|
||||||
throw new ApplicationException("Invalid number of exception handlers");
|
throw new ApplicationException("Invalid number of exception handlers");
|
||||||
|
|
||||||
|
var gpContext = GenericParamContext.Create(cilMethod);
|
||||||
for (int i = 0; i < numExceptions; i++) {
|
for (int i = 0; i < numExceptions; i++) {
|
||||||
var eh = new ExceptionHandler((ExceptionHandlerType)reader.ReadInt32());
|
var eh = new ExceptionHandler((ExceptionHandlerType)reader.ReadInt32());
|
||||||
eh.TryStart = GetInstruction(reader.ReadInt32());
|
eh.TryStart = GetInstruction(reader.ReadInt32());
|
||||||
|
@ -306,7 +308,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
eh.HandlerStart = GetInstruction(reader.ReadInt32());
|
eh.HandlerStart = GetInstruction(reader.ReadInt32());
|
||||||
eh.HandlerEnd = GetInstructionEnd(reader.ReadInt32());
|
eh.HandlerEnd = GetInstructionEnd(reader.ReadInt32());
|
||||||
if (eh.HandlerType == ExceptionHandlerType.Catch)
|
if (eh.HandlerType == ExceptionHandlerType.Catch)
|
||||||
eh.CatchType = module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef;
|
eh.CatchType = module.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef;
|
||||||
else if (eh.HandlerType == ExceptionHandlerType.Filter)
|
else if (eh.HandlerType == ExceptionHandlerType.Filter)
|
||||||
eh.FilterStart = GetInstruction(reader.ReadInt32());
|
eh.FilterStart = GetInstruction(reader.ReadInt32());
|
||||||
|
|
||||||
|
|
|
@ -34,12 +34,13 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override List<Instruction> ReadInstructions(MethodDef cilMethod, CsvmMethodData csvmMethod) {
|
protected override List<Instruction> ReadInstructions(MethodDef cilMethod, CsvmMethodData csvmMethod) {
|
||||||
|
var gpContext = GenericParamContext.Create(cilMethod);
|
||||||
var reader = new BinaryReader(new MemoryStream(csvmMethod.Instructions));
|
var reader = new BinaryReader(new MemoryStream(csvmMethod.Instructions));
|
||||||
var instrs = new List<Instruction>();
|
var instrs = new List<Instruction>();
|
||||||
uint offset = 0;
|
uint offset = 0;
|
||||||
while (reader.BaseStream.Position < reader.BaseStream.Length) {
|
while (reader.BaseStream.Position < reader.BaseStream.Length) {
|
||||||
int vmOpCode = reader.ReadUInt16();
|
int vmOpCode = reader.ReadUInt16();
|
||||||
var instr = opCodeDetector.Handlers[vmOpCode].Read(reader, module);
|
var instr = opCodeDetector.Handlers[vmOpCode].Read(reader, module, gpContext);
|
||||||
instr.Offset = offset;
|
instr.Offset = offset;
|
||||||
offset += (uint)GetInstructionSize(instr);
|
offset += (uint)GetInstructionSize(instr);
|
||||||
SetCilToVmIndex(instr, instrs.Count);
|
SetCilToVmIndex(instr, instrs.Count);
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public OpCodeHandlerSigInfo OpCodeHandlerSigInfo { get; set; }
|
public OpCodeHandlerSigInfo OpCodeHandlerSigInfo { get; set; }
|
||||||
public Predicate<UnknownHandlerInfo> Check { get; set; }
|
public Predicate<UnknownHandlerInfo> Check { get; set; }
|
||||||
public Func<BinaryReader, IInstructionOperandResolver, Instruction> Read { get; set; }
|
public Func<BinaryReader, IInstructionOperandResolver, GenericParamContext, Instruction> Read { get; set; }
|
||||||
|
|
||||||
public bool Detect(UnknownHandlerInfo info) {
|
public bool Detect(UnknownHandlerInfo info) {
|
||||||
var sigInfo = OpCodeHandlerSigInfo;
|
var sigInfo = OpCodeHandlerSigInfo;
|
||||||
|
@ -68,7 +68,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
static partial class OpCodeHandlers {
|
static partial class OpCodeHandlers {
|
||||||
static Instruction arithmetic_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction arithmetic_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
switch (reader.ReadByte()) {
|
switch (reader.ReadByte()) {
|
||||||
case 0: return OpCodes.Add.ToInstruction();
|
case 0: return OpCodes.Add.ToInstruction();
|
||||||
case 1: return OpCodes.Add_Ovf.ToInstruction();
|
case 1: return OpCodes.Add_Ovf.ToInstruction();
|
||||||
|
@ -91,22 +91,22 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Type System.Reflection.Module::ResolveType(System.Int32)");
|
return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Type System.Reflection.Module::ResolveType(System.Int32)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction newarr_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction newarr_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
return new Instruction(OpCodes.Newarr, resolver.ResolveToken(reader.ReadUInt32()));
|
return new Instruction(OpCodes.Newarr, resolver.ResolveToken(reader.ReadUInt32(), gpContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction box_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction box_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
var instr = new Instruction();
|
var instr = new Instruction();
|
||||||
switch (reader.ReadByte()) {
|
switch (reader.ReadByte()) {
|
||||||
case 0: instr.OpCode = OpCodes.Box; break;
|
case 0: instr.OpCode = OpCodes.Box; break;
|
||||||
case 1: instr.OpCode = OpCodes.Unbox_Any; break;
|
case 1: instr.OpCode = OpCodes.Unbox_Any; break;
|
||||||
default: throw new ApplicationException("Invalid opcode");
|
default: throw new ApplicationException("Invalid opcode");
|
||||||
}
|
}
|
||||||
instr.Operand = resolver.ResolveToken(reader.ReadUInt32());
|
instr.Operand = resolver.ResolveToken(reader.ReadUInt32(), gpContext);
|
||||||
return instr;
|
return instr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction call_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction call_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
var instr = new Instruction();
|
var instr = new Instruction();
|
||||||
switch (reader.ReadByte()) {
|
switch (reader.ReadByte()) {
|
||||||
case 0: instr.OpCode = OpCodes.Newobj; break;
|
case 0: instr.OpCode = OpCodes.Newobj; break;
|
||||||
|
@ -114,22 +114,22 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
case 2: instr.OpCode = OpCodes.Callvirt; break;
|
case 2: instr.OpCode = OpCodes.Callvirt; break;
|
||||||
default: throw new ApplicationException("Invalid opcode");
|
default: throw new ApplicationException("Invalid opcode");
|
||||||
}
|
}
|
||||||
instr.Operand = resolver.ResolveToken(reader.ReadUInt32());
|
instr.Operand = resolver.ResolveToken(reader.ReadUInt32(), gpContext);
|
||||||
return instr;
|
return instr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction cast_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction cast_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
var instr = new Instruction();
|
var instr = new Instruction();
|
||||||
switch (reader.ReadByte()) {
|
switch (reader.ReadByte()) {
|
||||||
case 0: instr.OpCode = OpCodes.Castclass; break;
|
case 0: instr.OpCode = OpCodes.Castclass; break;
|
||||||
case 1: instr.OpCode = OpCodes.Isinst; break;
|
case 1: instr.OpCode = OpCodes.Isinst; break;
|
||||||
default: throw new ApplicationException("Invalid opcode");
|
default: throw new ApplicationException("Invalid opcode");
|
||||||
}
|
}
|
||||||
instr.Operand = resolver.ResolveToken(reader.ReadUInt32());
|
instr.Operand = resolver.ResolveToken(reader.ReadUInt32(), gpContext);
|
||||||
return instr;
|
return instr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction compare_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction compare_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
int type = reader.ReadByte();
|
int type = reader.ReadByte();
|
||||||
Instruction instr = new Instruction();
|
Instruction instr = new Instruction();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -202,7 +202,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
new InstructionInfo1 { Type = 11, Second = true, Third = true, OpCode = OpCodes.Conv_Ovf_U_Un },
|
new InstructionInfo1 { Type = 11, Second = true, Third = true, OpCode = OpCodes.Conv_Ovf_U_Un },
|
||||||
new InstructionInfo1 { Type = 12, Second = true, Third = true, OpCode = OpCodes.Conv_R_Un },
|
new InstructionInfo1 { Type = 12, Second = true, Third = true, OpCode = OpCodes.Conv_R_Un },
|
||||||
};
|
};
|
||||||
static Instruction convert_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction convert_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
byte type = reader.ReadByte();
|
byte type = reader.ReadByte();
|
||||||
bool second = reader.ReadBoolean();
|
bool second = reader.ReadBoolean();
|
||||||
bool third = reader.ReadBoolean();
|
bool third = reader.ReadBoolean();
|
||||||
|
@ -221,7 +221,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
return instr;
|
return instr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction dup_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction dup_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
switch (reader.ReadByte()) {
|
switch (reader.ReadByte()) {
|
||||||
case 0: return OpCodes.Dup.ToInstruction();
|
case 0: return OpCodes.Dup.ToInstruction();
|
||||||
case 1: return OpCodes.Pop.ToInstruction();
|
case 1: return OpCodes.Pop.ToInstruction();
|
||||||
|
@ -259,7 +259,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
new InstructionInfo2 { First = true, Second = true, Value = 28, OpCode = OpCodes.Ldelem_Ref },
|
new InstructionInfo2 { First = true, Second = true, Value = 28, OpCode = OpCodes.Ldelem_Ref },
|
||||||
new InstructionInfo2 { First = true, Second = false, Value = 0, OpCode = OpCodes.Ldelem },
|
new InstructionInfo2 { First = true, Second = false, Value = 0, OpCode = OpCodes.Ldelem },
|
||||||
};
|
};
|
||||||
static Instruction ldelem_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction ldelem_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
Instruction instr = null;
|
Instruction instr = null;
|
||||||
bool first = reader.ReadBoolean();
|
bool first = reader.ReadBoolean();
|
||||||
bool second = reader.ReadBoolean();
|
bool second = reader.ReadBoolean();
|
||||||
|
@ -273,7 +273,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
if (second)
|
if (second)
|
||||||
instr = new Instruction(info.OpCode);
|
instr = new Instruction(info.OpCode);
|
||||||
else
|
else
|
||||||
instr = new Instruction(info.OpCode, resolver.ResolveToken((uint)value));
|
instr = new Instruction(info.OpCode, resolver.ResolveToken((uint)value, gpContext));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (instr == null)
|
if (instr == null)
|
||||||
|
@ -286,13 +286,13 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MethodInfo System.Type::GetMethod(System.String,System.Reflection.BindingFlags)");
|
return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MethodInfo System.Type::GetMethod(System.String,System.Reflection.BindingFlags)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction endfinally_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction endfinally_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
return OpCodes.Endfinally.ToInstruction();
|
return OpCodes.Endfinally.ToInstruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction ldfld_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction ldfld_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
byte b = reader.ReadByte();
|
byte b = reader.ReadByte();
|
||||||
var field = resolver.ResolveToken(reader.ReadUInt32()) as IField;
|
var field = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IField;
|
||||||
switch (b) {
|
switch (b) {
|
||||||
case 0: return new Instruction(null, new FieldInstructionOperand(OpCodes.Ldsfld, OpCodes.Ldfld, field));
|
case 0: return new Instruction(null, new FieldInstructionOperand(OpCodes.Ldsfld, OpCodes.Ldfld, field));
|
||||||
case 1: return new Instruction(null, new FieldInstructionOperand(OpCodes.Ldsflda, OpCodes.Ldflda, field));
|
case 1: return new Instruction(null, new FieldInstructionOperand(OpCodes.Ldsflda, OpCodes.Ldflda, field));
|
||||||
|
@ -301,11 +301,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction initobj_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction initobj_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
return new Instruction(OpCodes.Initobj, resolver.ResolveToken(reader.ReadUInt32()));
|
return new Instruction(OpCodes.Initobj, resolver.ResolveToken(reader.ReadUInt32(), gpContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction ldloc_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction ldloc_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
bool isLdarg = reader.ReadBoolean();
|
bool isLdarg = reader.ReadBoolean();
|
||||||
ushort index = reader.ReadUInt16();
|
ushort index = reader.ReadUInt16();
|
||||||
|
|
||||||
|
@ -322,7 +322,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
return instr;
|
return instr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction ldloca_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction ldloca_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
Instruction instr = new Instruction();
|
Instruction instr = new Instruction();
|
||||||
if (reader.ReadBoolean()) {
|
if (reader.ReadBoolean()) {
|
||||||
instr.OpCode = OpCodes.Ldarga;
|
instr.OpCode = OpCodes.Ldarga;
|
||||||
|
@ -336,19 +336,19 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
return instr;
|
return instr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction ldelema_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction ldelema_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
return new Instruction(OpCodes.Ldelema, null);
|
return new Instruction(OpCodes.Ldelema, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction ldlen_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction ldlen_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
return OpCodes.Ldlen.ToInstruction();
|
return OpCodes.Ldlen.ToInstruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction ldobj_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction ldobj_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
return new Instruction(OpCodes.Ldobj, null);
|
return new Instruction(OpCodes.Ldobj, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction ldstr_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction ldstr_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
return OpCodes.Ldstr.ToInstruction(reader.ReadString());
|
return OpCodes.Ldstr.ToInstruction(reader.ReadString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,8 +356,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MemberInfo System.Reflection.Module::ResolveMember(System.Int32)");
|
return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MemberInfo System.Reflection.Module::ResolveMember(System.Int32)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction ldtoken_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction ldtoken_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
return new Instruction(OpCodes.Ldtoken, resolver.ResolveToken(reader.ReadUInt32()));
|
return new Instruction(OpCodes.Ldtoken, resolver.ResolveToken(reader.ReadUInt32(), gpContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool leave_check(UnknownHandlerInfo info) {
|
static bool leave_check(UnknownHandlerInfo info) {
|
||||||
|
@ -366,12 +366,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
!DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MemberInfo System.Reflection.Module::ResolveMember(System.Int32)");
|
!DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MemberInfo System.Reflection.Module::ResolveMember(System.Int32)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction leave_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction leave_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
int displacement = reader.ReadInt32();
|
int displacement = reader.ReadInt32();
|
||||||
return new Instruction(OpCodes.Leave, new TargetDisplOperand(displacement));
|
return new Instruction(OpCodes.Leave, new TargetDisplOperand(displacement));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction ldc_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction ldc_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
switch ((ElementType)reader.ReadByte()) {
|
switch ((ElementType)reader.ReadByte()) {
|
||||||
case ElementType.I4: return Instruction.CreateLdcI4(reader.ReadInt32());
|
case ElementType.I4: return Instruction.CreateLdcI4(reader.ReadInt32());
|
||||||
case ElementType.I8: return OpCodes.Ldc_I8.ToInstruction(reader.ReadInt64());
|
case ElementType.I8: return OpCodes.Ldc_I8.ToInstruction(reader.ReadInt64());
|
||||||
|
@ -382,24 +382,24 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction ldftn_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction ldftn_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
byte code = reader.ReadByte();
|
byte code = reader.ReadByte();
|
||||||
uint token = reader.ReadUInt32();
|
uint token = reader.ReadUInt32();
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 0:
|
case 0:
|
||||||
return new Instruction(OpCodes.Ldftn, resolver.ResolveToken(token));
|
return new Instruction(OpCodes.Ldftn, resolver.ResolveToken(token, gpContext));
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
reader.ReadInt32(); // token of newobj .ctor
|
reader.ReadInt32(); // token of newobj .ctor
|
||||||
return new Instruction(OpCodes.Ldvirtftn, resolver.ResolveToken(token));
|
return new Instruction(OpCodes.Ldvirtftn, resolver.ResolveToken(token, gpContext));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new ApplicationException("Invalid opcode");
|
throw new ApplicationException("Invalid opcode");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction logical_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction logical_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
switch (reader.ReadByte()) {
|
switch (reader.ReadByte()) {
|
||||||
case 0: return OpCodes.And.ToInstruction();
|
case 0: return OpCodes.And.ToInstruction();
|
||||||
case 1: return OpCodes.Or.ToInstruction();
|
case 1: return OpCodes.Or.ToInstruction();
|
||||||
|
@ -425,7 +425,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction nop_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction nop_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
return OpCodes.Nop.ToInstruction();
|
return OpCodes.Nop.ToInstruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,7 +433,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MethodBase System.Reflection.Module::ResolveMethod(System.Int32)");
|
return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MethodBase System.Reflection.Module::ResolveMethod(System.Int32)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction ret_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction ret_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
reader.ReadInt32(); // token of current method
|
reader.ReadInt32(); // token of current method
|
||||||
return OpCodes.Ret.ToInstruction();
|
return OpCodes.Ret.ToInstruction();
|
||||||
}
|
}
|
||||||
|
@ -442,11 +442,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
return info.ExecuteMethod.Body.Variables.Count == 0;
|
return info.ExecuteMethod.Body.Variables.Count == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction rethrow_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction rethrow_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
return OpCodes.Rethrow.ToInstruction();
|
return OpCodes.Rethrow.ToInstruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction stloc_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction stloc_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
bool isStarg = reader.ReadBoolean();
|
bool isStarg = reader.ReadBoolean();
|
||||||
ushort index = reader.ReadUInt16();
|
ushort index = reader.ReadUInt16();
|
||||||
|
|
||||||
|
@ -464,11 +464,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
return instr;
|
return instr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction stobj_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction stobj_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
return new Instruction(OpCodes.Stobj, null);
|
return new Instruction(OpCodes.Stobj, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction switch_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction switch_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
int numTargets = reader.ReadInt32();
|
int numTargets = reader.ReadInt32();
|
||||||
int[] targetDispls = new int[numTargets];
|
int[] targetDispls = new int[numTargets];
|
||||||
for (int i = 0; i < targetDispls.Length; i++)
|
for (int i = 0; i < targetDispls.Length; i++)
|
||||||
|
@ -480,11 +480,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 {
|
||||||
return !DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MethodInfo System.Type::GetMethod(System.String,System.Reflection.BindingFlags)");
|
return !DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MethodInfo System.Type::GetMethod(System.String,System.Reflection.BindingFlags)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction throw_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction throw_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
return OpCodes.Throw.ToInstruction();
|
return OpCodes.Throw.ToInstruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction neg_read(BinaryReader reader, IInstructionOperandResolver resolver) {
|
static Instruction neg_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
switch (reader.ReadByte()) {
|
switch (reader.ReadByte()) {
|
||||||
case 0: return OpCodes.Neg.ToInstruction();
|
case 0: return OpCodes.Neg.ToInstruction();
|
||||||
case 1: return OpCodes.Not.ToInstruction();
|
case 1: return OpCodes.Not.ToInstruction();
|
||||||
|
|
BIN
de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM5.bin
Normal file
BIN
de4dot.code/deobfuscators/Agile_NET/vm/v2/CSVM5.bin
Normal file
Binary file not shown.
|
@ -53,10 +53,10 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
public readonly int BlockIndex;
|
public readonly int BlockIndex;
|
||||||
public int HashIndex;
|
public int HashIndex;
|
||||||
|
|
||||||
public HandlerState(List<BlockSigInfo> blockSigInfos, int blockIndex, int instructionIndex) {
|
public HandlerState(List<BlockSigInfo> blockSigInfos, int blockIndex, int hashIndex) {
|
||||||
this.BlockSigInfos = blockSigInfos;
|
this.BlockSigInfos = blockSigInfos;
|
||||||
this.BlockIndex = blockIndex;
|
this.BlockIndex = blockIndex;
|
||||||
this.HashIndex = instructionIndex;
|
this.HashIndex = hashIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HandlerState Clone() {
|
public HandlerState Clone() {
|
||||||
|
@ -164,6 +164,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nextState == null && findState.VisitedCompositeBlocks.Count != findState.CompositeState.BlockSigInfos.Count)
|
||||||
|
nextState = GetNextHandlerState(ref findState);
|
||||||
if (nextState == null) {
|
if (nextState == null) {
|
||||||
if (findState.VisitedCompositeBlocks.Count != findState.CompositeState.BlockSigInfos.Count)
|
if (findState.VisitedCompositeBlocks.Count != findState.CompositeState.BlockSigInfos.Count)
|
||||||
return false;
|
return false;
|
||||||
|
@ -181,6 +183,16 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HandlerState? GetNextHandlerState(ref FindHandlerState findState) {
|
||||||
|
for (int i = 0; i < findState.CompositeState.BlockSigInfos.Count; i++) {
|
||||||
|
if (findState.VisitedCompositeBlocks.ContainsKey(i))
|
||||||
|
continue;
|
||||||
|
return new HandlerState(findState.CompositeState.BlockSigInfos, i, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
static bool Compare(ref HandlerState handler, ref HandlerState composite) {
|
static bool Compare(ref HandlerState handler, ref HandlerState composite) {
|
||||||
var hhashes = handler.BlockSigInfos[handler.BlockIndex].Hashes;
|
var hhashes = handler.BlockSigInfos[handler.BlockIndex].Hashes;
|
||||||
int hi = handler.HashIndex;
|
int hi = handler.HashIndex;
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
foreach (var type in module.Types) {
|
foreach (var type in module.Types) {
|
||||||
if (!type.IsPublic || !type.IsAbstract)
|
if (!type.IsPublic || !type.IsAbstract)
|
||||||
continue;
|
continue;
|
||||||
if (type.HasFields || type.HasProperties || type.HasEvents)
|
if (type.HasProperties || type.HasEvents)
|
||||||
continue;
|
continue;
|
||||||
if (type.BaseType == null || type.BaseType.FullName != "System.Object")
|
if (type.BaseType == null || type.BaseType.FullName != "System.Object")
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.18052
|
// Runtime Version:4.0.30319.18444
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
|
@ -99,5 +99,15 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
return ((byte[])(obj));
|
return ((byte[])(obj));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized resource of type System.Byte[].
|
||||||
|
/// </summary>
|
||||||
|
internal static byte[] CSVM5 {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("CSVM5", resourceCulture);
|
||||||
|
return ((byte[])(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,4 +130,8 @@
|
||||||
<data name="CSVM4" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="CSVM4" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>CSVM4.bin;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>CSVM4.bin;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</data>
|
</data>
|
||||||
|
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||||
|
<data name="CSVM5" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>CSVM5.bin;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -35,7 +35,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
protected override List<Instruction> ReadInstructions(MethodDef cilMethod, CsvmMethodData csvmMethod) {
|
protected override List<Instruction> ReadInstructions(MethodDef cilMethod, CsvmMethodData csvmMethod) {
|
||||||
var reader = new BinaryReader(new MemoryStream(csvmMethod.Instructions));
|
var reader = new BinaryReader(new MemoryStream(csvmMethod.Instructions));
|
||||||
var instrs = new List<Instruction>();
|
var instrs = new List<Instruction>();
|
||||||
var handlerInfoReader = new OpCodeHandlerInfoReader(module);
|
var gpContext = GenericParamContext.Create(cilMethod);
|
||||||
|
var handlerInfoReader = new OpCodeHandlerInfoReader(module, gpContext);
|
||||||
|
|
||||||
int numVmInstrs = reader.ReadInt32();
|
int numVmInstrs = reader.ReadInt32();
|
||||||
var vmInstrs = new ushort[numVmInstrs];
|
var vmInstrs = new ushort[numVmInstrs];
|
||||||
|
|
|
@ -27,9 +27,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
class OpCodeHandlerInfoReader {
|
class OpCodeHandlerInfoReader {
|
||||||
IInstructionOperandResolver resolver;
|
IInstructionOperandResolver resolver;
|
||||||
Dictionary<HandlerTypeCode, Func<BinaryReader, Instruction>> readHandlers;
|
Dictionary<HandlerTypeCode, Func<BinaryReader, Instruction>> readHandlers;
|
||||||
|
readonly GenericParamContext gpContext;
|
||||||
|
|
||||||
public OpCodeHandlerInfoReader(IInstructionOperandResolver resolver) {
|
public OpCodeHandlerInfoReader(IInstructionOperandResolver resolver, GenericParamContext gpContext) {
|
||||||
this.resolver = resolver;
|
this.resolver = resolver;
|
||||||
|
this.gpContext = gpContext;
|
||||||
this.readHandlers = new Dictionary<HandlerTypeCode, Func<BinaryReader, Instruction>> {
|
this.readHandlers = new Dictionary<HandlerTypeCode, Func<BinaryReader, Instruction>> {
|
||||||
{ HandlerTypeCode.Add, Handler_Add },
|
{ HandlerTypeCode.Add, Handler_Add },
|
||||||
{ HandlerTypeCode.Add_Ovf, Handler_Add_Ovf },
|
{ HandlerTypeCode.Add_Ovf, Handler_Add_Ovf },
|
||||||
|
@ -176,7 +178,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Box(BinaryReader reader) {
|
Instruction Handler_Box(BinaryReader reader) {
|
||||||
var type = resolver.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef;
|
var type = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef;
|
||||||
return OpCodes.Box.ToInstruction(type);
|
return OpCodes.Box.ToInstruction(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,17 +195,17 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Call(BinaryReader reader) {
|
Instruction Handler_Call(BinaryReader reader) {
|
||||||
var method = resolver.ResolveToken(reader.ReadUInt32()) as IMethod;
|
var method = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod;
|
||||||
return OpCodes.Call.ToInstruction(method);
|
return OpCodes.Call.ToInstruction(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Callvirt(BinaryReader reader) {
|
Instruction Handler_Callvirt(BinaryReader reader) {
|
||||||
var method = resolver.ResolveToken(reader.ReadUInt32()) as IMethod;
|
var method = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod;
|
||||||
return OpCodes.Callvirt.ToInstruction(method);
|
return OpCodes.Callvirt.ToInstruction(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Castclass(BinaryReader reader) {
|
Instruction Handler_Castclass(BinaryReader reader) {
|
||||||
var type = resolver.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef;
|
var type = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef;
|
||||||
return OpCodes.Castclass.ToInstruction(type);
|
return OpCodes.Castclass.ToInstruction(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,12 +314,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Initobj(BinaryReader reader) {
|
Instruction Handler_Initobj(BinaryReader reader) {
|
||||||
var type = resolver.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef;
|
var type = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef;
|
||||||
return OpCodes.Initobj.ToInstruction(type);
|
return OpCodes.Initobj.ToInstruction(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Isinst(BinaryReader reader) {
|
Instruction Handler_Isinst(BinaryReader reader) {
|
||||||
var type = resolver.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef;
|
var type = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef;
|
||||||
return OpCodes.Isinst.ToInstruction(type);
|
return OpCodes.Isinst.ToInstruction(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,17 +351,17 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Ldfld_Ldsfld(BinaryReader reader) {
|
Instruction Handler_Ldfld_Ldsfld(BinaryReader reader) {
|
||||||
var field = resolver.ResolveToken(reader.ReadUInt32()) as IField;
|
var field = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IField;
|
||||||
return new Instruction(null, new FieldInstructionOperand(OpCodes.Ldsfld, OpCodes.Ldfld, field));
|
return new Instruction(null, new FieldInstructionOperand(OpCodes.Ldsfld, OpCodes.Ldfld, field));
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Ldflda_Ldsflda(BinaryReader reader) {
|
Instruction Handler_Ldflda_Ldsflda(BinaryReader reader) {
|
||||||
var field = resolver.ResolveToken(reader.ReadUInt32()) as IField;
|
var field = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IField;
|
||||||
return new Instruction(null, new FieldInstructionOperand(OpCodes.Ldsflda, OpCodes.Ldflda, field));
|
return new Instruction(null, new FieldInstructionOperand(OpCodes.Ldsflda, OpCodes.Ldflda, field));
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Ldftn(BinaryReader reader) {
|
Instruction Handler_Ldftn(BinaryReader reader) {
|
||||||
var method = resolver.ResolveToken(reader.ReadUInt32()) as IMethod;
|
var method = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod;
|
||||||
return OpCodes.Ldftn.ToInstruction(method);
|
return OpCodes.Ldftn.ToInstruction(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,12 +386,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Ldtoken(BinaryReader reader) {
|
Instruction Handler_Ldtoken(BinaryReader reader) {
|
||||||
var member = resolver.ResolveToken(reader.ReadUInt32()) as ITokenOperand;
|
var member = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITokenOperand;
|
||||||
return OpCodes.Ldtoken.ToInstruction(member);
|
return OpCodes.Ldtoken.ToInstruction(member);
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Ldvirtftn(BinaryReader reader) {
|
Instruction Handler_Ldvirtftn(BinaryReader reader) {
|
||||||
var method = resolver.ResolveToken(reader.ReadUInt32()) as IMethod;
|
var method = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod;
|
||||||
reader.ReadUInt32();
|
reader.ReadUInt32();
|
||||||
return OpCodes.Ldvirtftn.ToInstruction(method);
|
return OpCodes.Ldvirtftn.ToInstruction(method);
|
||||||
}
|
}
|
||||||
|
@ -415,12 +417,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Newarr(BinaryReader reader) {
|
Instruction Handler_Newarr(BinaryReader reader) {
|
||||||
var type = resolver.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef;
|
var type = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef;
|
||||||
return OpCodes.Newarr.ToInstruction(type);
|
return OpCodes.Newarr.ToInstruction(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Newobj(BinaryReader reader) {
|
Instruction Handler_Newobj(BinaryReader reader) {
|
||||||
var method = resolver.ResolveToken(reader.ReadUInt32()) as IMethod;
|
var method = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod;
|
||||||
return OpCodes.Newobj.ToInstruction(method);
|
return OpCodes.Newobj.ToInstruction(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,7 +451,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Ret(BinaryReader reader) {
|
Instruction Handler_Ret(BinaryReader reader) {
|
||||||
var method = resolver.ResolveToken(reader.ReadUInt32()) as IMethod;
|
var method = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod;
|
||||||
return OpCodes.Ret.ToInstruction();
|
return OpCodes.Ret.ToInstruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,7 +480,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Stfld_Stsfld(BinaryReader reader) {
|
Instruction Handler_Stfld_Stsfld(BinaryReader reader) {
|
||||||
var field = resolver.ResolveToken(reader.ReadUInt32()) as IField;
|
var field = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IField;
|
||||||
return new Instruction(null, new FieldInstructionOperand(OpCodes.Stsfld, OpCodes.Stfld, field));
|
return new Instruction(null, new FieldInstructionOperand(OpCodes.Stsfld, OpCodes.Stfld, field));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,7 +519,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction Handler_Unbox_Any(BinaryReader reader) {
|
Instruction Handler_Unbox_Any(BinaryReader reader) {
|
||||||
var type = resolver.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef;
|
var type = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef;
|
||||||
return OpCodes.Unbox_Any.ToInstruction(type);
|
return OpCodes.Unbox_Any.ToInstruction(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
ReadOpCodeHandlerInfos(CsvmResources.CSVM2),
|
ReadOpCodeHandlerInfos(CsvmResources.CSVM2),
|
||||||
ReadOpCodeHandlerInfos(CsvmResources.CSVM3),
|
ReadOpCodeHandlerInfos(CsvmResources.CSVM3),
|
||||||
ReadOpCodeHandlerInfos(CsvmResources.CSVM4),
|
ReadOpCodeHandlerInfos(CsvmResources.CSVM4),
|
||||||
|
ReadOpCodeHandlerInfos(CsvmResources.CSVM5),
|
||||||
};
|
};
|
||||||
|
|
||||||
static IList<MethodSigInfo> ReadOpCodeHandlerInfos(byte[] data) {
|
static IList<MethodSigInfo> ReadOpCodeHandlerInfos(byte[] data) {
|
||||||
|
|
|
@ -33,11 +33,13 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
public MyDeobfuscator(ModuleDefMD module) {
|
public MyDeobfuscator(ModuleDefMD module) {
|
||||||
cliSecureRtType = new CliSecureRtType(module);
|
cliSecureRtType = new CliSecureRtType(module);
|
||||||
cliSecureRtType.Find(null);
|
cliSecureRtType.Find(null);
|
||||||
stringDecrypter = new StringDecrypter(module, cliSecureRtType.StringDecrypterMethod);
|
stringDecrypter = new StringDecrypter(module, cliSecureRtType.StringDecrypterInfos);
|
||||||
stringDecrypter.Find();
|
stringDecrypter.Find();
|
||||||
cliSecureRtType.FindStringDecrypterMethod();
|
cliSecureRtType.FindStringDecrypterMethod();
|
||||||
stringDecrypter.Method = cliSecureRtType.StringDecrypterMethod;
|
stringDecrypter.AddDecrypterInfos(cliSecureRtType.StringDecrypterInfos);
|
||||||
staticStringInliner.Add(stringDecrypter.Method, (method, gim, args) => stringDecrypter.Decrypt((string)args[0]));
|
stringDecrypter.Initialize();
|
||||||
|
foreach (var info in stringDecrypter.StringDecrypterInfos)
|
||||||
|
staticStringInliner.Add(info.Method, (method, gim, args) => stringDecrypter.Decrypt((string)args[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestoreMethod(Blocks blocks) {
|
void RestoreMethod(Blocks blocks) {
|
||||||
|
@ -252,7 +254,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 {
|
||||||
if (cctor == null)
|
if (cctor == null)
|
||||||
continue;
|
continue;
|
||||||
requiredFields[0] = type.FullName;
|
requiredFields[0] = type.FullName;
|
||||||
if (!new FieldTypes(type).Exactly(requiredFields))
|
var fieldTypes = new FieldTypes(type);
|
||||||
|
if (!fieldTypes.All(requiredFields))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cflowDeobfuscator.Deobfuscate(cctor);
|
cflowDeobfuscator.Deobfuscate(cctor);
|
||||||
|
|
|
@ -70,7 +70,8 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
|
||||||
!ContainsString(method, "run under") &&
|
!ContainsString(method, "run under") &&
|
||||||
!ContainsString(method, "run with") &&
|
!ContainsString(method, "run with") &&
|
||||||
!ContainsString(method, "started under") &&
|
!ContainsString(method, "started under") &&
|
||||||
!ContainsString(method, "{0} detected"))
|
!ContainsString(method, "{0} detected") &&
|
||||||
|
!ContainsString(method, "{0} found"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
antiDebuggerType = type;
|
antiDebuggerType = type;
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
|
||||||
class MethodBodyReader : MethodBodyReaderBase {
|
class MethodBodyReader : MethodBodyReaderBase {
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
ushort maxStackSize;
|
ushort maxStackSize;
|
||||||
|
GenericParamContext gpContext;
|
||||||
|
|
||||||
public MethodBodyReader(ModuleDefMD module, IBinaryReader reader)
|
public MethodBodyReader(ModuleDefMD module, IBinaryReader reader)
|
||||||
: base(reader) {
|
: base(reader) {
|
||||||
|
@ -35,6 +36,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Read(MethodDef method) {
|
public void Read(MethodDef method) {
|
||||||
|
this.gpContext = GenericParamContext.Create(method);
|
||||||
this.parameters = method.Parameters;
|
this.parameters = method.Parameters;
|
||||||
SetLocals(GetLocals(method));
|
SetLocals(GetLocals(method));
|
||||||
|
|
||||||
|
@ -58,15 +60,15 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IField ReadInlineField(Instruction instr) {
|
protected override IField ReadInlineField(Instruction instr) {
|
||||||
return module.ResolveToken(reader.ReadUInt32()) as IField;
|
return module.ResolveToken(reader.ReadUInt32(), gpContext) as IField;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IMethod ReadInlineMethod(Instruction instr) {
|
protected override IMethod ReadInlineMethod(Instruction instr) {
|
||||||
return module.ResolveToken(reader.ReadUInt32()) as IMethod;
|
return module.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override MethodSig ReadInlineSig(Instruction instr) {
|
protected override MethodSig ReadInlineSig(Instruction instr) {
|
||||||
var sas = module.ResolveStandAloneSig(MDToken.ToRID(reader.ReadUInt32()));
|
var sas = module.ResolveStandAloneSig(MDToken.ToRID(reader.ReadUInt32()), gpContext);
|
||||||
return sas == null ? null : sas.MethodSig;
|
return sas == null ? null : sas.MethodSig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,11 +77,11 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override ITokenOperand ReadInlineTok(Instruction instr) {
|
protected override ITokenOperand ReadInlineTok(Instruction instr) {
|
||||||
return module.ResolveToken(reader.ReadUInt32()) as ITokenOperand;
|
return module.ResolveToken(reader.ReadUInt32(), gpContext) as ITokenOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override ITypeDefOrRef ReadInlineType(Instruction instr) {
|
protected override ITypeDefOrRef ReadInlineType(Instruction instr) {
|
||||||
return module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef;
|
return module.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadExceptionHandlers(int numExceptionHandlers) {
|
void ReadExceptionHandlers(int numExceptionHandlers) {
|
||||||
|
@ -101,7 +103,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
|
||||||
|
|
||||||
switch (eh.HandlerType) {
|
switch (eh.HandlerType) {
|
||||||
case ExceptionHandlerType.Catch:
|
case ExceptionHandlerType.Catch:
|
||||||
eh.CatchType = module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef;
|
eh.CatchType = module.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ExceptionHandlerType.Filter:
|
case ExceptionHandlerType.Filter:
|
||||||
|
|
|
@ -110,7 +110,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
|
||||||
MethodDef GetProxyCreateMethod(TypeDef type) {
|
MethodDef GetProxyCreateMethod(TypeDef type) {
|
||||||
if (DotNetUtils.FindFieldType(type, "System.ModuleHandle", true) == null)
|
if (DotNetUtils.FindFieldType(type, "System.ModuleHandle", true) == null)
|
||||||
return null;
|
return null;
|
||||||
if (type.Fields.Count < 1 || type.Fields.Count > 18)
|
if (type.Fields.Count < 1 || type.Fields.Count > 20)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
MethodDef createMethod = null;
|
MethodDef createMethod = null;
|
||||||
|
|
|
@ -157,7 +157,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
|
||||||
foreach (var method in GetDecrypterMethods(type)) {
|
foreach (var method in GetDecrypterMethods(type)) {
|
||||||
if (method == null)
|
if (method == null)
|
||||||
continue;
|
continue;
|
||||||
if (!new LocalTypes(method).Exactly(requiredLocals_sl))
|
if (!new LocalTypes(method).All(requiredLocals_sl))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
resourceDecrypterType = type;
|
resourceDecrypterType = type;
|
||||||
|
@ -180,6 +180,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CheckFlipBits(MethodDef method) {
|
static bool CheckFlipBits(MethodDef method) {
|
||||||
|
int nots = 0;
|
||||||
var instrs = method.Body.Instructions;
|
var instrs = method.Body.Instructions;
|
||||||
for (int i = 0; i < instrs.Count - 1; i++) {
|
for (int i = 0; i < instrs.Count - 1; i++) {
|
||||||
var ldloc = instrs[i];
|
var ldloc = instrs[i];
|
||||||
|
@ -189,14 +190,11 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
|
||||||
if (local == null || local.Type.GetElementType().GetPrimitiveSize() < 0)
|
if (local == null || local.Type.GetElementType().GetPrimitiveSize() < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var not = instrs[i + 1];
|
if (instrs[i + 1].OpCode.Code == Code.Not)
|
||||||
if (not.OpCode.Code != Code.Not)
|
nots++;
|
||||||
continue;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return (nots & 1) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UpdateFlags(MethodDef method, ISimpleDeobfuscator simpleDeobfuscator) {
|
bool UpdateFlags(MethodDef method, ISimpleDeobfuscator simpleDeobfuscator) {
|
||||||
|
|
|
@ -84,7 +84,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
|
||||||
|
|
||||||
if (!method.IsStatic || !DotNetUtils.IsMethod(method, "System.Void", "()"))
|
if (!method.IsStatic || !DotNetUtils.IsMethod(method, "System.Void", "()"))
|
||||||
return false;
|
return false;
|
||||||
if (type.Methods.Count < 3 || type.Methods.Count > 27)
|
if (type.Methods.Count < 3 || type.Methods.Count > 31)
|
||||||
return false;
|
return false;
|
||||||
if (DotNetUtils.GetPInvokeMethod(type, "mscoree", "StrongNameSignatureVerificationEx") != null) {
|
if (DotNetUtils.GetPInvokeMethod(type, "mscoree", "StrongNameSignatureVerificationEx") != null) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace de4dot.code.deobfuscators.Dotfuscator {
|
||||||
public class DeobfuscatorInfo : DeobfuscatorInfoBase {
|
public class DeobfuscatorInfo : DeobfuscatorInfoBase {
|
||||||
public const string THE_NAME = "Dotfuscator";
|
public const string THE_NAME = "Dotfuscator";
|
||||||
public const string THE_TYPE = "df";
|
public const string THE_TYPE = "df";
|
||||||
const string DEFAULT_REGEX = @"!^[a-z][a-z0-9]{0,2}$&!^A_[0-9]+$&" + DeobfuscatorBase.DEFAULT_ASIAN_VALID_NAME_REGEX;
|
const string DEFAULT_REGEX = @"!^(?:eval_)?[a-z][a-z0-9]{0,2}$&!^A_[0-9]+$&" + DeobfuscatorBase.DEFAULT_ASIAN_VALID_NAME_REGEX;
|
||||||
public DeobfuscatorInfo()
|
public DeobfuscatorInfo()
|
||||||
: base(DEFAULT_REGEX) {
|
: base(DEFAULT_REGEX) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,10 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
public const int MSG_CALL_MOVE_NEXT = 4;
|
public const int MSG_CALL_MOVE_NEXT = 4;
|
||||||
|
|
||||||
Module reflObfModule;
|
Module reflObfModule;
|
||||||
IEnumerable<int> ienumerable = null;
|
object ienumerable = null;
|
||||||
IEnumerator<int> ienumerator = null;
|
object ienumerator = null;
|
||||||
|
MethodInfo mi_get_Current;
|
||||||
|
MethodInfo mi_MoveNext;
|
||||||
|
|
||||||
[CreateUserGenericService]
|
[CreateUserGenericService]
|
||||||
public static IUserGenericService Create() {
|
public static IUserGenericService Create() {
|
||||||
|
@ -72,7 +74,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
var ctor = reflObfModule.ResolveMethod((int)ctorToken) as ConstructorInfo;
|
var ctor = reflObfModule.ResolveMethod((int)ctorToken) as ConstructorInfo;
|
||||||
if (ctor == null)
|
if (ctor == null)
|
||||||
throw new ApplicationException(string.Format("Invalid ctor with token: {0:X8}", ctorToken));
|
throw new ApplicationException(string.Format("Invalid ctor with token: {0:X8}", ctorToken));
|
||||||
ienumerable = (IEnumerable<int>)ctor.Invoke(args);
|
ienumerable = ctor.Invoke(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteEnumerableField(uint fieldToken, object value) {
|
void WriteEnumerableField(uint fieldToken, object value) {
|
||||||
|
@ -83,15 +85,74 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateEnumerator() {
|
void CreateEnumerator() {
|
||||||
ienumerator = ienumerable.GetEnumerator();
|
foreach (var method in ienumerable.GetType().GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) {
|
||||||
|
if (method.GetParameters().Length != 0)
|
||||||
|
continue;
|
||||||
|
var retType = method.ReturnType;
|
||||||
|
if (!retType.IsGenericType)
|
||||||
|
continue;
|
||||||
|
var genArgs = retType.GetGenericArguments();
|
||||||
|
if (genArgs.Length != 1)
|
||||||
|
continue;
|
||||||
|
if (genArgs[0] != typeof(int))
|
||||||
|
continue;
|
||||||
|
if (!FindEnumeratorMethods(retType))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ienumerator = method.Invoke(ienumerable, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ApplicationException("No GetEnumerator() method found");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindEnumeratorMethods(Type type) {
|
||||||
|
mi_get_Current = null;
|
||||||
|
mi_MoveNext = null;
|
||||||
|
|
||||||
|
foreach (var method in ienumerable.GetType().GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) {
|
||||||
|
if (Is_get_Current(method)) {
|
||||||
|
if (mi_get_Current != null)
|
||||||
|
return false;
|
||||||
|
mi_get_Current = method;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Is_MoveNext(method)) {
|
||||||
|
if (mi_MoveNext != null)
|
||||||
|
return false;
|
||||||
|
mi_MoveNext = method;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mi_get_Current != null && mi_MoveNext != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Is_get_Current(MethodInfo method) {
|
||||||
|
if (method.GetParameters().Length != 0)
|
||||||
|
return false;
|
||||||
|
if (method.ReturnType != typeof(int))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Is_MoveNext(MethodInfo method) {
|
||||||
|
if (method.GetParameters().Length != 0)
|
||||||
|
return false;
|
||||||
|
if (method.ReturnType != typeof(bool))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CallGetCurrent() {
|
int CallGetCurrent() {
|
||||||
return ienumerator.Current;
|
return (int)mi_get_Current.Invoke(ienumerator, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CallMoveNext() {
|
bool CallMoveNext() {
|
||||||
return ienumerator.MoveNext();
|
return (bool)mi_MoveNext.Invoke(ienumerator, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int? ValidStringDecrypterValue {
|
public int? ValidStringDecrypterValue {
|
||||||
get { return validStringDecrypterValue;}
|
get { return validStringDecrypterValue; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeDef Type {
|
public TypeDef Type {
|
||||||
|
@ -696,8 +696,8 @@ done: ;
|
||||||
if (initValue2 == null || !initValue2.AllBitsValid())
|
if (initValue2 == null || !initValue2.AllBitsValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int loopStart = GetIndexOfCall(instrs, index, leaveIndex, "System.Int32 System.Collections.Generic.IEnumerator`1<System.Int32>::get_Current()");
|
int loopStart = GetIndexOfCall(instrs, index, leaveIndex, "System.Int32", "()");
|
||||||
int loopEnd = GetIndexOfCall(instrs, loopStart, leaveIndex, "System.Boolean System.Collections.IEnumerator::MoveNext()");
|
int loopEnd = GetIndexOfCall(instrs, loopStart, leaveIndex, "System.Boolean", "()");
|
||||||
if (loopStart < 0 || loopEnd < 0)
|
if (loopStart < 0 || loopEnd < 0)
|
||||||
return false;
|
return false;
|
||||||
loopStart++;
|
loopStart++;
|
||||||
|
@ -720,7 +720,7 @@ done: ;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GetIndexOfCall(IList<Instruction> instrs, int startIndex, int endIndex, string fullMethodName) {
|
static int GetIndexOfCall(IList<Instruction> instrs, int startIndex, int endIndex, string returnType, string parameters) {
|
||||||
if (startIndex < 0 || endIndex < 0)
|
if (startIndex < 0 || endIndex < 0)
|
||||||
return -1;
|
return -1;
|
||||||
for (int i = startIndex; i < endIndex; i++) {
|
for (int i = startIndex; i < endIndex; i++) {
|
||||||
|
@ -728,7 +728,7 @@ done: ;
|
||||||
if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
|
if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
|
||||||
continue;
|
continue;
|
||||||
var method = instr.Operand as IMethod;
|
var method = instr.Operand as IMethod;
|
||||||
if (method == null || method.FullName != fullMethodName)
|
if (!DotNetUtils.IsMethod(method, returnType, parameters))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
|
|
|
@ -722,13 +722,85 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
decryptStringMethod.Body.ExceptionHandlers.Count >= 2 &&
|
decryptStringMethod.Body.ExceptionHandlers.Count >= 2 &&
|
||||||
new LocalTypes(decryptStringMethod).All(locals35) &&
|
new LocalTypes(decryptStringMethod).All(locals35) &&
|
||||||
CheckTypeFields2(fields35)) {
|
CheckTypeFields2(fields35)) {
|
||||||
return "3.5 - 4.1";
|
return "3.5 - 4.2";
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var fields43 = new string[] {
|
||||||
|
GetNestedTypeName(0),
|
||||||
|
GetNestedTypeName(1),
|
||||||
|
"System.Byte[]",
|
||||||
|
"System.Int16",
|
||||||
|
"System.Int32",
|
||||||
|
"System.Byte[]",
|
||||||
|
"System.Int32",
|
||||||
|
"System.Int32",
|
||||||
|
GetNestedTypeName(2),
|
||||||
|
};
|
||||||
|
var locals43 = CreateLocalsArray(
|
||||||
|
"System.Boolean",
|
||||||
|
"System.Byte",
|
||||||
|
"System.Byte[]",
|
||||||
|
"System.Char[]",
|
||||||
|
FindEnumeratorName(decryptStringMethod),
|
||||||
|
GetNestedTypeName(0),
|
||||||
|
"System.Diagnostics.StackFrame",
|
||||||
|
"System.Diagnostics.StackTrace",
|
||||||
|
"System.Int16",
|
||||||
|
"System.Int32",
|
||||||
|
"System.Int64",
|
||||||
|
"System.IO.Stream",
|
||||||
|
"System.Reflection.Assembly",
|
||||||
|
"System.Reflection.AssemblyName",
|
||||||
|
"System.Reflection.MethodBase",
|
||||||
|
"System.String",
|
||||||
|
"System.Text.StringBuilder",
|
||||||
|
"System.Type"
|
||||||
|
);
|
||||||
|
var olocals43 = CreateLocalsArray(
|
||||||
|
"System.Int32"
|
||||||
|
);
|
||||||
|
if (otherMethods.Count == 1 &&
|
||||||
|
decryptStringType.NestedTypes.Count == 3 &&
|
||||||
|
DotNetUtils.IsMethod(otherMethods[0], "System.Void", "(System.Byte[],System.Int32,System.Byte[])") &&
|
||||||
|
otherMethods[0].IsPrivate &&
|
||||||
|
otherMethods[0].IsStatic &&
|
||||||
|
new LocalTypes(otherMethods[0]).Exactly(olocals43) &&
|
||||||
|
decryptStringMethod.IsNoInlining &&
|
||||||
|
decryptStringMethod.IsAssembly &&
|
||||||
|
!decryptStringMethod.IsSynchronized &&
|
||||||
|
decryptStringMethod.Body.MaxStack >= 1 &&
|
||||||
|
decryptStringMethod.Body.MaxStack <= 8 &&
|
||||||
|
decryptStringMethod.Body.ExceptionHandlers.Count >= 2 &&
|
||||||
|
new LocalTypes(decryptStringMethod).All(locals43) &&
|
||||||
|
CheckTypeFields2(fields43)) {
|
||||||
|
return "4.3";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static string FindEnumeratorName(MethodDef method) {
|
||||||
|
foreach (var local in method.Body.Variables) {
|
||||||
|
var gis = local.Type as GenericInstSig;
|
||||||
|
if (gis == null)
|
||||||
|
continue;
|
||||||
|
if (gis.FullName == "System.Collections.Generic.IEnumerator`1<System.Int32>")
|
||||||
|
continue;
|
||||||
|
if (gis.GenericArguments.Count != 1)
|
||||||
|
continue;
|
||||||
|
if (gis.GenericArguments[0].GetFullName() != "System.Int32")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return gis.FullName;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
TypeDef GetNestedType(int n) {
|
TypeDef GetNestedType(int n) {
|
||||||
var type = stringDecrypter.Type;
|
var type = stringDecrypter.Type;
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeDef DelegateInitType {
|
public TypeDef DelegateInitType {
|
||||||
get { return delegateInitType ?? FindDelegateInitType();}
|
get { return delegateInitType ?? FindDelegateInitType(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeDef DelegateType {
|
public TypeDef DelegateType {
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
|
||||||
MethodDef strongNameCheckMethod;
|
MethodDef strongNameCheckMethod;
|
||||||
|
|
||||||
public bool Detected {
|
public bool Detected {
|
||||||
get { return strongNameType != null;}
|
get { return strongNameType != null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeDef Type {
|
public TypeDef Type {
|
||||||
|
|
|
@ -122,7 +122,6 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
bool emailMe = false;
|
bool emailMe = false;
|
||||||
foreach (var info in mainType.RuntimeFileInfos) {
|
foreach (var info in mainType.RuntimeFileInfos) {
|
||||||
var version = info.GetVersion();
|
var version = info.GetVersion();
|
||||||
emailMe |= version == null && System.IO.File.Exists(info.PathName);
|
|
||||||
emailMe |= version != null && version == new Version(1, 0, 7, 0);
|
emailMe |= version != null && version == new Version(1, 0, 7, 0);
|
||||||
Logger.v("Version: {0} ({1})", version == null ? "UNKNOWN" : version.ToString(), info.PathName);
|
Logger.v("Version: {0} ({1})", version == null ? "UNKNOWN" : version.ToString(), info.PathName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,50 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
IDecrypter decrypter;
|
IDecrypter decrypter;
|
||||||
bool methodReaderHasDelegateTypeFlag;
|
bool methodReaderHasDelegateTypeFlag;
|
||||||
|
|
||||||
|
static class CodeAllocator {
|
||||||
|
[DllImport("kernel32")]
|
||||||
|
static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, uint flAllocationType, uint flProtect);
|
||||||
|
|
||||||
|
const uint PAGE_EXECUTE_READWRITE = 0x40;
|
||||||
|
const uint MEM_COMMIT = 0x00001000;
|
||||||
|
const int ALIGNMENT = 0x10;
|
||||||
|
|
||||||
|
static IntPtr currentPage;
|
||||||
|
static int nextOffset;
|
||||||
|
static int pageSize;
|
||||||
|
|
||||||
|
public static IntPtr Allocate(byte[] code) {
|
||||||
|
if (code == null || code.Length == 0)
|
||||||
|
return IntPtr.Zero;
|
||||||
|
|
||||||
|
var addr = Allocate(code.Length);
|
||||||
|
Marshal.Copy(code, 0, addr, code.Length);
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntPtr Allocate(int size) {
|
||||||
|
if (size <= 0)
|
||||||
|
return IntPtr.Zero;
|
||||||
|
|
||||||
|
size = (size + ALIGNMENT - 1) & ~(ALIGNMENT - 1);
|
||||||
|
if (nextOffset + size > pageSize)
|
||||||
|
AllocNewPage(size);
|
||||||
|
|
||||||
|
var data = new IntPtr(currentPage.ToInt64() + nextOffset);
|
||||||
|
nextOffset += size;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AllocNewPage(int size) {
|
||||||
|
size = (size + 0xFFF) & ~0xFFF;
|
||||||
|
currentPage = VirtualAlloc(IntPtr.Zero, new UIntPtr((uint)size), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||||
|
if (currentPage == IntPtr.Zero)
|
||||||
|
throw new ApplicationException("VirtualAlloc() failed");
|
||||||
|
pageSize = size;
|
||||||
|
nextOffset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface IDecrypter {
|
interface IDecrypter {
|
||||||
byte[] Decrypt(int methodId, uint rid);
|
byte[] Decrypt(int methodId, uint rid);
|
||||||
}
|
}
|
||||||
|
@ -323,7 +367,7 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
pDecryptCallback = new IntPtr(p + IntPtr.Size * 40);
|
pDecryptCallback = new IntPtr(p + IntPtr.Size * 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
IntPtr GetStateAddr(object obj) {
|
public static IntPtr GetStateAddr(object obj) {
|
||||||
var flags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
var flags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||||
foreach (var fi in obj.GetType().GetFields(flags)) {
|
foreach (var fi in obj.GetType().GetFields(flags)) {
|
||||||
if (fi.FieldType == typeof(IntPtr))
|
if (fi.FieldType == typeof(IntPtr))
|
||||||
|
@ -335,7 +379,6 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
public byte[] Decrypt(int methodId, uint rid) {
|
public byte[] Decrypt(int methodId, uint rid) {
|
||||||
decryptedData = null;
|
decryptedData = null;
|
||||||
currentILBytes = dmd.reflectionModule.ResolveMethod(0x06000000 + (int)rid).GetMethodBody().GetILAsByteArray();
|
currentILBytes = dmd.reflectionModule.ResolveMethod(0x06000000 + (int)rid).GetMethodBody().GetILAsByteArray();
|
||||||
|
|
||||||
invoker.DynamicInvoke(new object[1] { methodId });
|
invoker.DynamicInvoke(new object[1] { methodId });
|
||||||
return decryptedData;
|
return decryptedData;
|
||||||
}
|
}
|
||||||
|
@ -358,7 +401,7 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
public unsafe DecrypterV2_0_12_0(DynamicMethodsDecrypter dmd)
|
public unsafe DecrypterV2_0_12_0(DynamicMethodsDecrypter dmd)
|
||||||
: base(dmd) {
|
: base(dmd) {
|
||||||
getCallerMethodAsILByteArrayDelegate = GetCallerMethodAsILByteArray;
|
getCallerMethodAsILByteArrayDelegate = GetCallerMethodAsILByteArray;
|
||||||
decryptCallbackDelegate = MyDecryptCallback;
|
decryptCallbackDelegate = DecryptCallback;
|
||||||
|
|
||||||
*(IntPtr*)pGetILBytes = Marshal.GetFunctionPointerForDelegate(getCallerMethodAsILByteArrayDelegate);
|
*(IntPtr*)pGetILBytes = Marshal.GetFunctionPointerForDelegate(getCallerMethodAsILByteArrayDelegate);
|
||||||
*(IntPtr*)pDecryptCallback = Marshal.GetFunctionPointerForDelegate(decryptCallbackDelegate);
|
*(IntPtr*)pDecryptCallback = Marshal.GetFunctionPointerForDelegate(decryptCallbackDelegate);
|
||||||
|
@ -368,7 +411,7 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
return currentILBytes;
|
return currentILBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe bool MyDecryptCallback(IntPtr a, byte* pMethodCode, int methodSize, int methodId) {
|
unsafe bool DecryptCallback(IntPtr a, byte* pMethodCode, int methodSize, int methodId) {
|
||||||
SaveDecryptedData(pMethodCode, methodSize);
|
SaveDecryptedData(pMethodCode, methodSize);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -386,7 +429,7 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
public unsafe DecrypterV2_0_12_3(DynamicMethodsDecrypter dmd)
|
public unsafe DecrypterV2_0_12_3(DynamicMethodsDecrypter dmd)
|
||||||
: base(dmd) {
|
: base(dmd) {
|
||||||
getCallerMethodAsILByteArrayDelegate = GetCallerMethodAsILByteArray;
|
getCallerMethodAsILByteArrayDelegate = GetCallerMethodAsILByteArray;
|
||||||
decryptCallbackDelegate = MyDecryptCallback;
|
decryptCallbackDelegate = DecryptCallback;
|
||||||
|
|
||||||
*(IntPtr*)pGetILBytes = Marshal.GetFunctionPointerForDelegate(getCallerMethodAsILByteArrayDelegate);
|
*(IntPtr*)pGetILBytes = Marshal.GetFunctionPointerForDelegate(getCallerMethodAsILByteArrayDelegate);
|
||||||
*(IntPtr*)pDecryptCallback = Marshal.GetFunctionPointerForDelegate(decryptCallbackDelegate);
|
*(IntPtr*)pDecryptCallback = Marshal.GetFunctionPointerForDelegate(decryptCallbackDelegate);
|
||||||
|
@ -396,12 +439,176 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
return currentILBytes;
|
return currentILBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe bool MyDecryptCallback(IntPtr a, byte* pMethodCode, int methodSize, int methodId, IntPtr e) {
|
unsafe bool DecryptCallback(IntPtr a, byte* pMethodCode, int methodSize, int methodId, IntPtr e) {
|
||||||
SaveDecryptedData(pMethodCode, methodSize);
|
SaveDecryptedData(pMethodCode, methodSize);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class DecrypterV2_0_13_0_Base : IDecrypter {
|
||||||
|
protected readonly DynamicMethodsDecrypter dmd;
|
||||||
|
protected byte[] currentILBytes;
|
||||||
|
byte[] decryptedData;
|
||||||
|
readonly Delegate invoker;
|
||||||
|
|
||||||
|
readonly GetCallerMethodAsILByteArrayDelegate getCallerMethodAsILByteArrayDelegate;
|
||||||
|
readonly DecryptCallbackDelegate decryptCallbackDelegate;
|
||||||
|
readonly IgnoreDelegate ignoreDelegate;
|
||||||
|
|
||||||
|
[DllImport("kernel32")]
|
||||||
|
static extern bool GetModuleHandleEx(uint dwFlags, IntPtr lpModuleName, out IntPtr phModule);
|
||||||
|
|
||||||
|
[return: MarshalAs(UnmanagedType.SafeArray)]
|
||||||
|
delegate byte[] GetCallerMethodAsILByteArrayDelegate(IntPtr a, int skipFrames, ref int flags, IntPtr d);
|
||||||
|
unsafe delegate bool DecryptCallbackDelegate(IntPtr a, byte* pMethodCode, int methodSize, int methodId, IntPtr e);
|
||||||
|
delegate IntPtr IgnoreDelegate(IntPtr a, IntPtr b);
|
||||||
|
|
||||||
|
public unsafe DecrypterV2_0_13_0_Base(DynamicMethodsDecrypter dmd) {
|
||||||
|
this.dmd = dmd;
|
||||||
|
this.invoker = (Delegate)dmd.invokerFieldInfo.GetValue(null);
|
||||||
|
|
||||||
|
byte* p = (byte*)DecrypterBaseV2_0_12_x.GetStateAddr(invoker.Target);
|
||||||
|
byte* pis = GetAddr(*(byte**)p);
|
||||||
|
p = *(byte**)pis;
|
||||||
|
byte* pam = *(byte**)(p + IntPtr.Size * 2);
|
||||||
|
p = *(byte**)(p + ((Environment.Version.Major - 2) / 2 * IntPtr.Size));
|
||||||
|
p += IntPtr.Size * 8 + 0x18;
|
||||||
|
p = LookUp(p, AppDomain.CurrentDomain.Id);
|
||||||
|
p = *(byte**)(p + IntPtr.Size * 16 + 0x18);
|
||||||
|
byte* pd = p + IntPtr.Size * 2;
|
||||||
|
p = *(byte**)(p + IntPtr.Size * 13);
|
||||||
|
|
||||||
|
getCallerMethodAsILByteArrayDelegate = GetCallerMethodAsILByteArray;
|
||||||
|
decryptCallbackDelegate = DecryptCallback;
|
||||||
|
ignoreDelegate = IgnoreMethod;
|
||||||
|
|
||||||
|
byte* pm = p + 0x28 * IntPtr.Size;
|
||||||
|
*(IntPtr*)(p + 0x29 * IntPtr.Size) = Marshal.GetFunctionPointerForDelegate(getCallerMethodAsILByteArrayDelegate);
|
||||||
|
*(IntPtr*)(p + 0x2A * IntPtr.Size) = Marshal.GetFunctionPointerForDelegate(decryptCallbackDelegate);
|
||||||
|
if (IntPtr.Size == 4)
|
||||||
|
*(IntPtr*)(p + 0x2B * IntPtr.Size) = Marshal.GetFunctionPointerForDelegate(ignoreDelegate);
|
||||||
|
InitCode(GetModuleHandle(pis), pam, pd, pm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsafe byte* GetModuleHandle(byte* addr) {
|
||||||
|
IntPtr hModule;
|
||||||
|
if (!GetModuleHandleEx(4, new IntPtr(addr), out hModule))
|
||||||
|
throw new ApplicationException("GetModuleHandleEx() failed");
|
||||||
|
return (byte*)hModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected unsafe abstract void InitCode(byte* ba, byte* pam, byte* pd, byte* pm);
|
||||||
|
|
||||||
|
static unsafe byte* GetAddr(byte* p) {
|
||||||
|
if (IntPtr.Size == 4) {
|
||||||
|
for (int i = 0; i < 20; i++, p++) {
|
||||||
|
if (*p == 0xA1)
|
||||||
|
return *(byte**)(p + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < 20; i++, p++)
|
||||||
|
if (*p == 0x4C && p[1] == 0x8B && p[2] == 0x15)
|
||||||
|
return p + 7 + *(int*)(p + 3);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsafe byte* LookUp(byte* p, int key) {
|
||||||
|
p = *(byte**)(p + IntPtr.Size);
|
||||||
|
p = *(byte**)(p + IntPtr.Size);
|
||||||
|
|
||||||
|
int f1 = 0;
|
||||||
|
int f2 = IntPtr.Size * 2;
|
||||||
|
int f3 = IntPtr.Size * 3;
|
||||||
|
int f4 = IntPtr.Size * 4;
|
||||||
|
int f5 = IntPtr.Size * 5 + 1;
|
||||||
|
|
||||||
|
byte* res = null;
|
||||||
|
while (true) {
|
||||||
|
if (*(p + f5) != 0)
|
||||||
|
break;
|
||||||
|
int k = *(int*)(p + f3);
|
||||||
|
if (k < key)
|
||||||
|
p = *(byte**)(p + f2);
|
||||||
|
else {
|
||||||
|
res = p;
|
||||||
|
p = *(byte**)(p + f1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *(byte**)(res + f4);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] aryDummy = new byte[7];
|
||||||
|
IntPtr dummy;
|
||||||
|
public unsafe byte[] Decrypt(int methodId, uint rid) {
|
||||||
|
fixed (byte* p = &aryDummy[0]) {
|
||||||
|
dummy = new IntPtr(p);
|
||||||
|
decryptedData = null;
|
||||||
|
currentILBytes = dmd.reflectionModule.ResolveMethod(0x06000000 + (int)rid).GetMethodBody().GetILAsByteArray();
|
||||||
|
invoker.DynamicInvoke(new object[1] { methodId });
|
||||||
|
}
|
||||||
|
dummy = IntPtr.Zero;
|
||||||
|
return decryptedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] GetCallerMethodAsILByteArray(IntPtr a, int skipFrames, ref int flags, IntPtr d) {
|
||||||
|
flags = 2;
|
||||||
|
return currentILBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe bool DecryptCallback(IntPtr a, byte* pMethodCode, int methodSize, int methodId, IntPtr e) {
|
||||||
|
decryptedData = new byte[methodSize];
|
||||||
|
Marshal.Copy(new IntPtr(pMethodCode), decryptedData, 0, decryptedData.Length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntPtr IgnoreMethod(IntPtr a, IntPtr b) {
|
||||||
|
return dummy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DecrypterV2_0_13_0 : DecrypterV2_0_13_0_Base {
|
||||||
|
public unsafe DecrypterV2_0_13_0(DynamicMethodsDecrypter dmd)
|
||||||
|
: base(dmd) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static readonly byte[] initCode_x86 = new byte[] {
|
||||||
|
0x8B, 0xCC, 0x8B, 0x41, 0x04, 0xFF, 0x71, 0x10,
|
||||||
|
0xFF, 0x71, 0x0C, 0xFF, 0x71, 0x08, 0xFF, 0x51,
|
||||||
|
0x14, 0xC2, 0x14, 0x00,
|
||||||
|
};
|
||||||
|
unsafe delegate void InitCode32Delegate(byte* pppam, byte* m, IntPtr s, byte* pd, byte* f);
|
||||||
|
unsafe delegate void InitCode64Delegate(byte* pppam, byte* m, IntPtr s, byte* pd);
|
||||||
|
protected unsafe override void InitCode(byte* ba, byte* pam, byte* pd, byte* pm) {
|
||||||
|
byte* ppam = (byte*)&pam;
|
||||||
|
byte* pppam = (byte*)&ppam;
|
||||||
|
if (IntPtr.Size == 4) {
|
||||||
|
var del = (InitCode32Delegate)Marshal.GetDelegateForFunctionPointer(CodeAllocator.Allocate(initCode_x86), typeof(InitCode32Delegate));
|
||||||
|
del(pppam, pm, new IntPtr(IntPtr.Size * 4), pd, ba + 0x00012500);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var del = (InitCode64Delegate)Marshal.GetDelegateForFunctionPointer(new IntPtr(ba + 0x00014CF0), typeof(InitCode64Delegate));
|
||||||
|
del(pppam, pm, new IntPtr(IntPtr.Size * 4), pd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DecrypterV2_0_13_1 : DecrypterV2_0_13_0_Base {
|
||||||
|
public unsafe DecrypterV2_0_13_1(DynamicMethodsDecrypter dmd)
|
||||||
|
: base(dmd) {
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe delegate void InitCodeDelegate(byte* pppam, byte* m, IntPtr s, byte* pd);
|
||||||
|
protected unsafe override void InitCode(byte* ba, byte* pam, byte* pd, byte* pm) {
|
||||||
|
int rva = IntPtr.Size == 4 ? 0x00013650 : 0x00016B50;
|
||||||
|
var del = (InitCodeDelegate)Marshal.GetDelegateForFunctionPointer(new IntPtr(ba + rva), typeof(InitCodeDelegate));
|
||||||
|
byte* ppam = (byte*)&pam;
|
||||||
|
byte* pppam = (byte*)&ppam;
|
||||||
|
del(pppam, pm, new IntPtr(IntPtr.Size * 4), pd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool MethodReaderHasDelegateTypeFlag {
|
public bool MethodReaderHasDelegateTypeFlag {
|
||||||
get { return methodReaderHasDelegateTypeFlag; }
|
get { return methodReaderHasDelegateTypeFlag; }
|
||||||
}
|
}
|
||||||
|
@ -456,9 +663,13 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
|
|
||||||
methodReaderHasDelegateTypeFlag = true;
|
methodReaderHasDelegateTypeFlag = true;
|
||||||
if (version < new Version(2, 0, 12, 3))
|
if (version < new Version(2, 0, 12, 3))
|
||||||
return CreateDecrypterV2_0_12_0();
|
return new DecrypterV2_0_12_0(this);
|
||||||
if (version < new Version(2, 0, 12, 4))
|
if (version == new Version(2, 0, 12, 3))
|
||||||
return CreateDecrypterV2_0_12_3();
|
return new DecrypterV2_0_12_3(this);
|
||||||
|
if (version == new Version(2, 0, 13, 0))
|
||||||
|
return new DecrypterV2_0_13_0(this);
|
||||||
|
if (version == new Version(2, 0, 13, 1))
|
||||||
|
return new DecrypterV2_0_13_1(this);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -503,14 +714,6 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
return new DecrypterV2_0_9_0(this, delegateField);
|
return new DecrypterV2_0_9_0(this, delegateField);
|
||||||
}
|
}
|
||||||
|
|
||||||
IDecrypter CreateDecrypterV2_0_12_0() {
|
|
||||||
return new DecrypterV2_0_12_0(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
IDecrypter CreateDecrypterV2_0_12_3() {
|
|
||||||
return new DecrypterV2_0_12_3(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
static readonly byte[] ilpPublicKeyToken = new byte[8] { 0x20, 0x12, 0xD3, 0xC0, 0x55, 0x1F, 0xE0, 0x3D };
|
static readonly byte[] ilpPublicKeyToken = new byte[8] { 0x20, 0x12, 0xD3, 0xC0, 0x55, 0x1F, 0xE0, 0x3D };
|
||||||
static Assembly GetProtectAssembly() {
|
static Assembly GetProtectAssembly() {
|
||||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) {
|
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) {
|
||||||
|
|
|
@ -32,6 +32,7 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
MethodFlags flags;
|
MethodFlags flags;
|
||||||
TypeDef delegateType;
|
TypeDef delegateType;
|
||||||
bool hasDelegateTypeFlag;
|
bool hasDelegateTypeFlag;
|
||||||
|
GenericParamContext gpContext;
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
enum MethodFlags {
|
enum MethodFlags {
|
||||||
|
@ -76,7 +77,8 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Read() {
|
public void Read(MethodDef method) {
|
||||||
|
gpContext = GenericParamContext.Create(method);
|
||||||
flags = (MethodFlags)reader.ReadByte();
|
flags = (MethodFlags)reader.ReadByte();
|
||||||
if (HasDelegateType) {
|
if (HasDelegateType) {
|
||||||
delegateType = Resolve<TypeDef>(ReadTypeToken());
|
delegateType = Resolve<TypeDef>(ReadTypeToken());
|
||||||
|
@ -108,7 +110,7 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
}
|
}
|
||||||
|
|
||||||
T Resolve<T>(int token) {
|
T Resolve<T>(int token) {
|
||||||
return (T)module.ResolveToken(token);
|
return (T)module.ResolveToken(token, gpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadTypeToken() {
|
int ReadTypeToken() {
|
||||||
|
@ -182,7 +184,7 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
var token = reader.ReadUInt32();
|
var token = reader.ReadUInt32();
|
||||||
if (MDToken.ToTable(token) != Table.StandAloneSig)
|
if (MDToken.ToTable(token) != Table.StandAloneSig)
|
||||||
return null;
|
return null;
|
||||||
var sas = module.ResolveStandAloneSig(MDToken.ToRID(token));
|
var sas = module.ResolveStandAloneSig(MDToken.ToRID(token), gpContext);
|
||||||
return sas == null ? null : sas.MethodSig;
|
return sas == null ? null : sas.MethodSig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
methodInfos.Remove(methodId.Value);
|
methodInfos.Remove(methodId.Value);
|
||||||
var methodReader = new MethodReader(module, methodInfo.data, parameters);
|
var methodReader = new MethodReader(module, methodInfo.data, parameters);
|
||||||
methodReader.HasDelegateTypeFlag = MethodReaderHasDelegateTypeFlag;
|
methodReader.HasDelegateTypeFlag = MethodReaderHasDelegateTypeFlag;
|
||||||
methodReader.Read();
|
methodReader.Read(method);
|
||||||
|
|
||||||
RestoreMethod(method, methodReader);
|
RestoreMethod(method, methodReader);
|
||||||
if (methodReader.DelegateType != null)
|
if (methodReader.DelegateType != null)
|
||||||
|
|
|
@ -64,6 +64,8 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
new VersionInfo(new Version(2, 0, 12, 0), new byte[] { 0x63, 0x8B, 0x5C, 0xE9, 0x89, 0x83, 0x57, 0x9D, 0xDC, 0xC3, 0xBD, 0xD9, 0xDB, 0x54, 0xBE, 0x66 }),
|
new VersionInfo(new Version(2, 0, 12, 0), new byte[] { 0x63, 0x8B, 0x5C, 0xE9, 0x89, 0x83, 0x57, 0x9D, 0xDC, 0xC3, 0xBD, 0xD9, 0xDB, 0x54, 0xBE, 0x66 }),
|
||||||
new VersionInfo(new Version(2, 0, 12, 2), new byte[] { 0xD5, 0x46, 0x38, 0xC7, 0x48, 0xF6, 0x3C, 0x1C, 0x1E, 0x7F, 0x3B, 0x7B, 0x5B, 0xE0, 0x49, 0x46 }),
|
new VersionInfo(new Version(2, 0, 12, 2), new byte[] { 0xD5, 0x46, 0x38, 0xC7, 0x48, 0xF6, 0x3C, 0x1C, 0x1E, 0x7F, 0x3B, 0x7B, 0x5B, 0xE0, 0x49, 0x46 }),
|
||||||
new VersionInfo(new Version(2, 0, 12, 3), new byte[] { 0x35, 0xA3, 0x53, 0xE9, 0x9E, 0x30, 0x6E, 0x9C, 0x0F, 0x46, 0x20, 0x9A, 0x91, 0xD2, 0x95, 0x18 }),
|
new VersionInfo(new Version(2, 0, 12, 3), new byte[] { 0x35, 0xA3, 0x53, 0xE9, 0x9E, 0x30, 0x6E, 0x9C, 0x0F, 0x46, 0x20, 0x9A, 0x91, 0xD2, 0x95, 0x18 }),
|
||||||
|
new VersionInfo(new Version(2, 0, 13, 0), new byte[] { 0x66, 0x21, 0xA1, 0x1F, 0x8F, 0x4A, 0xD2, 0xF8, 0x68, 0xEE, 0xD5, 0xD9, 0xC8, 0xB8, 0x17, 0xC7 }),
|
||||||
|
new VersionInfo(new Version(2, 0, 13, 1), new byte[] { 0xDF, 0x7A, 0xBF, 0x8B, 0xAD, 0x2B, 0x94, 0x6F, 0x37, 0xD9, 0x4B, 0xFC, 0x42, 0x7F, 0x0B, 0x37 }),
|
||||||
};
|
};
|
||||||
|
|
||||||
static readonly VersionInfo[] versionInfo64 = new VersionInfo[] {
|
static readonly VersionInfo[] versionInfo64 = new VersionInfo[] {
|
||||||
|
@ -89,6 +91,8 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
new VersionInfo(new Version(2, 0, 12, 0), new byte[] { 0x5F, 0x42, 0xA5, 0x6C, 0x19, 0xC6, 0x73, 0x9E, 0xE6, 0x74, 0x62, 0x3B, 0x8A, 0x51, 0xBB, 0x93 }),
|
new VersionInfo(new Version(2, 0, 12, 0), new byte[] { 0x5F, 0x42, 0xA5, 0x6C, 0x19, 0xC6, 0x73, 0x9E, 0xE6, 0x74, 0x62, 0x3B, 0x8A, 0x51, 0xBB, 0x93 }),
|
||||||
new VersionInfo(new Version(2, 0, 12, 2), new byte[] { 0x10, 0x91, 0xED, 0x05, 0x9C, 0x31, 0x0B, 0x63, 0x76, 0xD7, 0x4A, 0xEC, 0xDE, 0x99, 0x6D, 0xD0 }),
|
new VersionInfo(new Version(2, 0, 12, 2), new byte[] { 0x10, 0x91, 0xED, 0x05, 0x9C, 0x31, 0x0B, 0x63, 0x76, 0xD7, 0x4A, 0xEC, 0xDE, 0x99, 0x6D, 0xD0 }),
|
||||||
new VersionInfo(new Version(2, 0, 12, 3), new byte[] { 0x38, 0x86, 0xE0, 0xBF, 0xC6, 0x64, 0xB9, 0xA0, 0x07, 0xED, 0xDB, 0x02, 0x40, 0xD0, 0x57, 0xE8 }),
|
new VersionInfo(new Version(2, 0, 12, 3), new byte[] { 0x38, 0x86, 0xE0, 0xBF, 0xC6, 0x64, 0xB9, 0xA0, 0x07, 0xED, 0xDB, 0x02, 0x40, 0xD0, 0x57, 0xE8 }),
|
||||||
|
new VersionInfo(new Version(2, 0, 13, 0), new byte[] { 0xF0, 0x13, 0xC4, 0x6F, 0x31, 0x0F, 0x61, 0xEA, 0x89, 0x1E, 0x8A, 0x95, 0x8C, 0xBE, 0x2E, 0x44 }),
|
||||||
|
new VersionInfo(new Version(2, 0, 13, 1), new byte[] { 0xD4, 0x71, 0x75, 0xE2, 0xB1, 0xA5, 0xAE, 0xF5, 0x32, 0xD7, 0x72, 0xDE, 0x93, 0xDC, 0x0B, 0x68 }),
|
||||||
};
|
};
|
||||||
|
|
||||||
public RuntimeFileInfo(MethodDef protectMethod) {
|
public RuntimeFileInfo(MethodDef protectMethod) {
|
||||||
|
|
|
@ -112,6 +112,11 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
},
|
},
|
||||||
// 526BC020
|
// 526BC020
|
||||||
// 526BDD12
|
// 526BDD12
|
||||||
|
// 5296E242
|
||||||
|
// 52B2B2A3
|
||||||
|
// 52B3043C
|
||||||
|
// 53172907
|
||||||
|
// 531729C4
|
||||||
new EncryptionInfo {
|
new EncryptionInfo {
|
||||||
MagicLo = 0x9A683B87,
|
MagicLo = 0x9A683B87,
|
||||||
MagicHi = 0x928ECDA3,
|
MagicHi = 0x928ECDA3,
|
||||||
|
@ -177,6 +182,11 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
// 5166DB4F
|
// 5166DB4F
|
||||||
// 526BC020
|
// 526BC020
|
||||||
// 526BDD12
|
// 526BDD12
|
||||||
|
// 5296E242
|
||||||
|
// 52B2B2A3
|
||||||
|
// 52B3043C
|
||||||
|
// 53172907
|
||||||
|
// 531729C4
|
||||||
new EncryptionInfo {
|
new EncryptionInfo {
|
||||||
MagicLo = 0x1A731B13,
|
MagicLo = 0x1A731B13,
|
||||||
MagicHi = 0x1723891F,
|
MagicHi = 0x1723891F,
|
||||||
|
|
|
@ -194,6 +194,10 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt4_v5, Decrypt2_v2, Decrypt3_v6, Decrypt1_v9, Decrypt6, Decrypt8_v8, Decrypt9_v9, Decrypt7, Decrypt5 }, new uint[] { 0x513D4492, 0x5113E277 }));
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt4_v5, Decrypt2_v2, Decrypt3_v6, Decrypt1_v9, Decrypt6, Decrypt8_v8, Decrypt9_v9, Decrypt7, Decrypt5 }, new uint[] { 0x513D4492, 0x5113E277 }));
|
||||||
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt3_v6, Decrypt2_v2, Decrypt4_v8, Decrypt1_v10, Decrypt8_v9, Decrypt9_v10, Decrypt6, Decrypt7, Decrypt5 }, new uint[] { 0x526BDD12 }));
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt3_v6, Decrypt2_v2, Decrypt4_v8, Decrypt1_v10, Decrypt8_v9, Decrypt9_v10, Decrypt6, Decrypt7, Decrypt5 }, new uint[] { 0x526BDD12 }));
|
||||||
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt1_v10, Decrypt4_v8, Decrypt2_v2, Decrypt3_v6, Decrypt6, Decrypt8_v9, Decrypt9_v10, Decrypt7, Decrypt5 }, new uint[] { 0x526BC020 }));
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt1_v10, Decrypt4_v8, Decrypt2_v2, Decrypt3_v6, Decrypt6, Decrypt8_v9, Decrypt9_v10, Decrypt7, Decrypt5 }, new uint[] { 0x526BC020 }));
|
||||||
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt3_v7, Decrypt2_v6, Decrypt4_v9, Decrypt1_v11, Decrypt8_v10, Decrypt11_v1, Decrypt6, Decrypt7, Decrypt5 }, new uint[] { 0x5296E242, 0x52B3043C }));
|
||||||
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt4_v10, Decrypt1_v12, Decrypt3_v8, Decrypt2_v7, Decrypt6, Decrypt8_v11, Decrypt9_v11, Decrypt7, Decrypt5 }, new uint[] { 0x531729C4 }));
|
||||||
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt1_v13, Decrypt4_v11, Decrypt2_v8, Decrypt3_v9, Decrypt6, Decrypt8_v11, Decrypt9_v12, Decrypt7, Decrypt5 }, new uint[] { 0x52B2B2A3 }));
|
||||||
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt2_v9, Decrypt3_v10, Decrypt1_v10, Decrypt4_v12, Decrypt8_v12, Decrypt9_v13, Decrypt6, Decrypt7, Decrypt5 }, new uint[] { 0x53172907 }));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EncryptionVersion.Unknown:
|
case EncryptionVersion.Unknown:
|
||||||
|
@ -404,6 +408,18 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return Decrypt1(encrypted, 0x11, 0x11, 0x400);
|
return Decrypt1(encrypted, 0x11, 0x11, 0x400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt1_v11(byte[] encrypted) {
|
||||||
|
return Decrypt1(encrypted, 0x13, 0x13, 0x400);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt1_v12(byte[] encrypted) {
|
||||||
|
return Decrypt1(encrypted, 0x12, 0x12, 0x200);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt1_v13(byte[] encrypted) {
|
||||||
|
return Decrypt1(encrypted, 0x11, 0x11, 0x200);
|
||||||
|
}
|
||||||
|
|
||||||
byte[] Decrypt1(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
byte[] Decrypt1(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
||||||
var decrypted = new byte[encrypted.Length];
|
var decrypted = new byte[encrypted.Length];
|
||||||
for (int i = 0, ki = keyStart; i < decrypted.Length; i++) {
|
for (int i = 0, ki = keyStart; i < decrypted.Length; i++) {
|
||||||
|
@ -434,6 +450,22 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return Decrypt2(encrypted, 0x00FA + 0x63);
|
return Decrypt2(encrypted, 0x00FA + 0x63);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt2_v6(byte[] encrypted) {
|
||||||
|
return Decrypt2(encrypted, 0x00FA + 0x0B);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt2_v7(byte[] encrypted) {
|
||||||
|
return Decrypt2(encrypted, 0x00FA + 0x0E);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt2_v8(byte[] encrypted) {
|
||||||
|
return Decrypt2(encrypted, 0x00FA + 0x0D);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt2_v9(byte[] encrypted) {
|
||||||
|
return Decrypt2(encrypted, 0x00FA + 0x0C);
|
||||||
|
}
|
||||||
|
|
||||||
byte[] Decrypt2(byte[] encrypted, int offset) {
|
byte[] Decrypt2(byte[] encrypted, int offset) {
|
||||||
if ((encrypted.Length & 7) != 0)
|
if ((encrypted.Length & 7) != 0)
|
||||||
throw new ApplicationException("Invalid encryption #2 length");
|
throw new ApplicationException("Invalid encryption #2 length");
|
||||||
|
@ -481,6 +513,22 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return Decrypt3(encrypted, 0x015E + 0x7F);
|
return Decrypt3(encrypted, 0x015E + 0x7F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt3_v7(byte[] encrypted) {
|
||||||
|
return Decrypt3(encrypted, 0x015E + 0x0D);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt3_v8(byte[] encrypted) {
|
||||||
|
return Decrypt3(encrypted, 0x015E + 0x0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt3_v9(byte[] encrypted) {
|
||||||
|
return Decrypt3(encrypted, 0x015E + 0x12);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt3_v10(byte[] encrypted) {
|
||||||
|
return Decrypt3(encrypted, 0x015E + 0x0E);
|
||||||
|
}
|
||||||
|
|
||||||
static readonly byte[] decrypt3Shifts = new byte[16] { 5, 11, 14, 21, 6, 20, 17, 29, 4, 10, 3, 2, 7, 1, 26, 18 };
|
static readonly byte[] decrypt3Shifts = new byte[16] { 5, 11, 14, 21, 6, 20, 17, 29, 4, 10, 3, 2, 7, 1, 26, 18 };
|
||||||
byte[] Decrypt3(byte[] encrypted, int offset) {
|
byte[] Decrypt3(byte[] encrypted, int offset) {
|
||||||
if ((encrypted.Length & 7) != 0)
|
if ((encrypted.Length & 7) != 0)
|
||||||
|
@ -542,6 +590,22 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return Decrypt4(encrypted, 9, 9, 0x100);
|
return Decrypt4(encrypted, 9, 9, 0x100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt4_v9(byte[] encrypted) {
|
||||||
|
return Decrypt4(encrypted, 0x0B, 0x0B, 0x150);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt4_v10(byte[] encrypted) {
|
||||||
|
return Decrypt4(encrypted, 0x10, 0x10, 0x120);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt4_v11(byte[] encrypted) {
|
||||||
|
return Decrypt4(encrypted, 0x0F, 0x0E, 0x120);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt4_v12(byte[] encrypted) {
|
||||||
|
return Decrypt4(encrypted, 0x0C, 0x0C, 0x150);
|
||||||
|
}
|
||||||
|
|
||||||
byte[] Decrypt4(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
byte[] Decrypt4(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
||||||
var decrypted = new byte[encrypted.Length / 3 * 2 + 1];
|
var decrypted = new byte[encrypted.Length / 3 * 2 + 1];
|
||||||
|
|
||||||
|
@ -599,6 +663,18 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return Decrypt8(encrypted, 0xA, 0xA, 0x600);
|
return Decrypt8(encrypted, 0xA, 0xA, 0x600);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt8_v10(byte[] encrypted) {
|
||||||
|
return Decrypt8(encrypted, 0x14, 0x14, 0x600);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt8_v11(byte[] encrypted) {
|
||||||
|
return Decrypt8(encrypted, 0x19, 0x19, 0x500);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt8_v12(byte[] encrypted) {
|
||||||
|
return Decrypt8(encrypted, 0x14, 0x14, 0x600);
|
||||||
|
}
|
||||||
|
|
||||||
byte[] Decrypt8(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
byte[] Decrypt8(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
||||||
var decrypted = new byte[encrypted.Length];
|
var decrypted = new byte[encrypted.Length];
|
||||||
int ki = keyStart;
|
int ki = keyStart;
|
||||||
|
@ -636,6 +712,18 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return Decrypt9(encrypted, 5, 5, 0x510);
|
return Decrypt9(encrypted, 5, 5, 0x510);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt9_v11(byte[] encrypted) {
|
||||||
|
return Decrypt9(encrypted, 0x19, 0x19, 0x500);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt9_v12(byte[] encrypted) {
|
||||||
|
return Decrypt9(encrypted, 0x19, 0x19, 0x500);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt9_v13(byte[] encrypted) {
|
||||||
|
return Decrypt9(encrypted, 5, 5, 0x510);
|
||||||
|
}
|
||||||
|
|
||||||
byte[] Decrypt9(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
byte[] Decrypt9(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
||||||
var decrypted = new byte[encrypted.Length];
|
var decrypted = new byte[encrypted.Length];
|
||||||
int ki = keyStart;
|
int ki = keyStart;
|
||||||
|
@ -695,6 +783,38 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt11_v1(byte[] encrypted) {
|
||||||
|
return Decrypt11(encrypted, 5, 5, 0x510);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt11(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
||||||
|
byte[] dest = new byte[encrypted.Length];
|
||||||
|
|
||||||
|
for (int i = 0, ki = keyStart; i < encrypted.Length; i++, ki++) {
|
||||||
|
if (ki >= keyEnd)
|
||||||
|
ki = keyStart;
|
||||||
|
|
||||||
|
byte b;
|
||||||
|
switch (i % 3) {
|
||||||
|
case 0:
|
||||||
|
dest[i] = (byte)(encrypted[i] ^ mcKey.ReadByte(ki));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
b = (byte)(encrypted[i] ^ mcKey.ReadByte(ki));
|
||||||
|
dest[i] = (byte)((b << 4) | (b >> 4));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
b = encrypted[i];
|
||||||
|
dest[i] = (byte)((b << 4) | (b >> 4));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
byte[] blowfishKey;
|
byte[] blowfishKey;
|
||||||
byte[] GetBlowfishKey() {
|
byte[] GetBlowfishKey() {
|
||||||
if (blowfishKey != null)
|
if (blowfishKey != null)
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
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.Runtime.Remoting;
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
using AssemblyData;
|
using AssemblyData;
|
||||||
using de4dot.code.AssemblyClient;
|
using de4dot.code.AssemblyClient;
|
||||||
|
@ -30,6 +32,20 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DumpedMethods Decrypt(ServerClrVersion serverVersion, string filename, byte[] moduleCctorBytes) {
|
public static DumpedMethods Decrypt(ServerClrVersion serverVersion, string filename, byte[] moduleCctorBytes) {
|
||||||
|
Exception lastEx = null;
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
try {
|
||||||
|
return Decrypt2(serverVersion, filename, moduleCctorBytes);
|
||||||
|
}
|
||||||
|
catch (RemotingException ex) {
|
||||||
|
lastEx = ex;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw lastEx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DumpedMethods Decrypt2(ServerClrVersion serverVersion, string filename, byte[] moduleCctorBytes) {
|
||||||
using (var client = new NewProcessAssemblyClientFactory(serverVersion).Create(AssemblyServiceType.MethodDecrypter)) {
|
using (var client = new NewProcessAssemblyClientFactory(serverVersion).Create(AssemblyServiceType.MethodDecrypter)) {
|
||||||
client.Connect();
|
client.Connect();
|
||||||
client.WaitConnected();
|
client.WaitConnected();
|
||||||
|
|
|
@ -155,14 +155,15 @@ namespace de4dot.code.deobfuscators {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static bool FixProxyCalls(Dictionary<Block, List<RemoveInfo>> removeInfos) {
|
protected bool FixProxyCalls(MethodDef method, Dictionary<Block, List<RemoveInfo>> removeInfos) {
|
||||||
|
var gpContext = GenericParamContext.Create(method);
|
||||||
foreach (var block in removeInfos.Keys) {
|
foreach (var block in removeInfos.Keys) {
|
||||||
var list = removeInfos[block];
|
var list = removeInfos[block];
|
||||||
var removeIndexes = new List<int>(list.Count);
|
var removeIndexes = new List<int>(list.Count);
|
||||||
foreach (var info in list) {
|
foreach (var info in list) {
|
||||||
if (info.IsCall) {
|
if (info.IsCall) {
|
||||||
var opcode = info.DelegateInfo.callOpcode;
|
var opcode = info.DelegateInfo.callOpcode;
|
||||||
var newInstr = Instruction.Create(opcode, info.DelegateInfo.methodRef);
|
var newInstr = Instruction.Create(opcode, ReResolve(info.DelegateInfo.methodRef, gpContext));
|
||||||
block.Replace(info.Index, 1, newInstr);
|
block.Replace(info.Index, 1, newInstr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -174,6 +175,12 @@ namespace de4dot.code.deobfuscators {
|
||||||
|
|
||||||
return removeInfos.Count > 0;
|
return removeInfos.Count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IMethod ReResolve(IMethod method, GenericParamContext gpContext) {
|
||||||
|
if (method.IsMethodSpec || method.IsMemberRef)
|
||||||
|
method = module.ResolveToken(method.MDToken.Raw, gpContext) as IMethod ?? method;
|
||||||
|
return method;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fixes proxy calls that call the delegate inline in the code, eg.:
|
// Fixes proxy calls that call the delegate inline in the code, eg.:
|
||||||
|
@ -279,7 +286,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return FixProxyCalls(removeInfos);
|
return FixProxyCalls(blocks.Method, removeInfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual BlockInstr FindProxyCall(DelegateInfo di, Block block, int index) {
|
protected virtual BlockInstr FindProxyCall(DelegateInfo di, Block block, int index) {
|
||||||
|
@ -481,7 +488,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return FixProxyCalls(removeInfos);
|
return FixProxyCalls(blocks.Method, removeInfos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -239,7 +239,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
|
|
||||||
var attrs2 = new Dictionary<TypeDef, bool>();
|
var attrs2 = new Dictionary<TypeDef, bool>();
|
||||||
foreach (var cattr in cattrs) {
|
foreach (var cattr in cattrs) {
|
||||||
if (!DotNetUtils.IsMethod(cattr.Constructor as IMethod, "System.Void", "(System.Int32)"))
|
if (!DotNetUtils.IsMethod(cattr.Constructor, "System.Void", "(System.Int32)"))
|
||||||
continue;
|
continue;
|
||||||
var attrType = cattr.AttributeType as TypeDef;
|
var attrType = cattr.AttributeType as TypeDef;
|
||||||
if (attrType == null)
|
if (attrType == null)
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
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 dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
using dnlib.DotNet.Emit;
|
using dnlib.DotNet.Emit;
|
||||||
|
@ -83,12 +84,40 @@ namespace de4dot.code.deobfuscators.Spices_Net {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RenameResources() {
|
class ResourceDictionary {
|
||||||
if (resourceManagerType == null && componentResourceManagerType == null)
|
struct Key {
|
||||||
return;
|
public readonly uint hash;
|
||||||
|
public readonly string ns;
|
||||||
|
public Key(uint hash, string ns) {
|
||||||
|
this.hash = hash;
|
||||||
|
this.ns = ns;
|
||||||
|
}
|
||||||
|
|
||||||
var numToResource = new Dictionary<uint, Resource>(module.Resources.Count);
|
public override int GetHashCode() {
|
||||||
foreach (var resource in module.Resources) {
|
return (int)(hash ^ ns.GetHashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj) {
|
||||||
|
if (!(obj is Key))
|
||||||
|
return false;
|
||||||
|
var other = (Key)obj;
|
||||||
|
return hash == other.hash &&
|
||||||
|
ns == other.ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() {
|
||||||
|
if (ns == string.Empty)
|
||||||
|
return string.Format("{0}", hash);
|
||||||
|
return string.Format("{0}.{1}", ns, hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dictionary<Key, Resource> resources = new Dictionary<Key, Resource>();
|
||||||
|
|
||||||
|
public int Count {
|
||||||
|
get { return resources.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Add(Resource resource) {
|
||||||
var name = resource.Name.String;
|
var name = resource.Name.String;
|
||||||
int index = name.LastIndexOf('.');
|
int index = name.LastIndexOf('.');
|
||||||
string ext;
|
string ext;
|
||||||
|
@ -98,35 +127,55 @@ namespace de4dot.code.deobfuscators.Spices_Net {
|
||||||
ext = name.Substring(index + 1);
|
ext = name.Substring(index + 1);
|
||||||
uint extNum;
|
uint extNum;
|
||||||
if (!uint.TryParse(ext, out extNum))
|
if (!uint.TryParse(ext, out extNum))
|
||||||
continue;
|
return false;
|
||||||
numToResource[extNum] = resource;
|
var ns = index < 0 ? string.Empty : name.Substring(0, index);
|
||||||
|
|
||||||
|
resources.Add(new Key(extNum, ns), resource);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Resource GetAndRemove(uint hash, string ns) {
|
||||||
|
var key = new Key(hash, ns);
|
||||||
|
Resource resource;
|
||||||
|
if (resources.TryGetValue(key, out resource))
|
||||||
|
resources.Remove(key);
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RenameResources() {
|
||||||
|
if (resourceManagerType == null && componentResourceManagerType == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var rsrcDict = new ResourceDictionary();
|
||||||
|
foreach (var resource in module.Resources)
|
||||||
|
rsrcDict.Add(resource);
|
||||||
|
|
||||||
if (module.Assembly != null)
|
if (module.Assembly != null)
|
||||||
Rename(numToResource, "", module.Assembly.Name + ".g");
|
Rename(rsrcDict, "", module.Assembly.Name + ".g");
|
||||||
|
|
||||||
foreach (var type in callsResourceManager.Keys)
|
foreach (var type in callsResourceManager.Keys)
|
||||||
Rename(numToResource, type);
|
Rename(rsrcDict, type);
|
||||||
|
|
||||||
if (numToResource.Count != 0) {
|
if (rsrcDict.Count != 0) {
|
||||||
foreach (var type in module.GetTypes()) {
|
foreach (var type in module.GetTypes()) {
|
||||||
if (numToResource.Count == 0)
|
if (rsrcDict.Count == 0)
|
||||||
break;
|
break;
|
||||||
if (!IsWinFormType(type))
|
if (!IsWinFormType(type))
|
||||||
continue;
|
continue;
|
||||||
Rename(numToResource, type);
|
Rename(rsrcDict, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numToResource.Count != 0) {
|
if (rsrcDict.Count != 0) {
|
||||||
foreach (var type in module.GetTypes()) {
|
foreach (var type in module.GetTypes()) {
|
||||||
if (numToResource.Count == 0)
|
if (rsrcDict.Count == 0)
|
||||||
break;
|
break;
|
||||||
Rename(numToResource, type);
|
Rename(rsrcDict, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numToResource.Count != 0)
|
if (rsrcDict.Count != 0)
|
||||||
Logger.e("Couldn't restore all renamed resource names");
|
Logger.e("Couldn't restore all renamed resource names");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,18 +200,17 @@ namespace de4dot.code.deobfuscators.Spices_Net {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Rename(Dictionary<uint, Resource> numToResource, TypeDef type) {
|
static bool Rename(ResourceDictionary rsrcDict, TypeDef type) {
|
||||||
return Rename(numToResource, "", type.FullName) ||
|
if (!IsWinFormType(type) && Rename(rsrcDict, "", type.FullName))
|
||||||
Rename(numToResource, "", type.FullName + ".g") ||
|
return true;
|
||||||
Rename(numToResource, type.Namespace, type.Name) ||
|
return Rename(rsrcDict, type.Namespace, type.Name);
|
||||||
Rename(numToResource, type.Namespace, type.Name + ".g");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Rename(Dictionary<uint, Resource> numToResource, string ns, string name) {
|
static bool Rename(ResourceDictionary rsrcDict, string ns, string name) {
|
||||||
var resourceName = name + ".resources";
|
var resourceName = name + ".resources";
|
||||||
uint hash = GetResourceHash(resourceName);
|
uint hash = GetResourceHash(resourceName);
|
||||||
Resource resource;
|
var resource = rsrcDict.GetAndRemove(hash, ns);
|
||||||
if (!numToResource.TryGetValue(hash, out resource))
|
if (resource == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int index = resource.Name.String.LastIndexOf('.');
|
int index = resource.Name.String.LastIndexOf('.');
|
||||||
|
@ -176,13 +224,12 @@ namespace de4dot.code.deobfuscators.Spices_Net {
|
||||||
newName = resourceNamespace + "." + resourceName;
|
newName = resourceNamespace + "." + resourceName;
|
||||||
}
|
}
|
||||||
if (resourceNamespace != ns)
|
if (resourceNamespace != ns)
|
||||||
return false;
|
throw new ApplicationException("Invalid resource namespace");
|
||||||
|
|
||||||
Logger.v("Restoring resource name: '{0}' => '{1}'",
|
Logger.v("Restoring resource name: '{0}' => '{1}'",
|
||||||
Utils.RemoveNewlines(resource.Name),
|
Utils.RemoveNewlines(resource.Name),
|
||||||
Utils.RemoveNewlines(newName));
|
Utils.RemoveNewlines(newName));
|
||||||
resource.Name = newName;
|
resource.Name = newName;
|
||||||
numToResource.Remove(hash);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -333,6 +333,9 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (methodsDecrypter.DecrypterTypeVersion != DnrDecrypterType.V1)
|
||||||
|
return DeobfuscatorInfo.THE_NAME;
|
||||||
|
|
||||||
if (methodsDecrypter.Method == null) {
|
if (methodsDecrypter.Method == null) {
|
||||||
if (minVer >= 3800)
|
if (minVer >= 3800)
|
||||||
return DeobfuscatorInfo.THE_NAME + " >= 3.8";
|
return DeobfuscatorInfo.THE_NAME + " >= 3.8";
|
||||||
|
@ -361,6 +364,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
bool compileMethodHasConstant_0x70000000 = DeobUtils.HasInteger(compileMethod, 0x70000000); // 4.0-4.1
|
bool compileMethodHasConstant_0x70000000 = DeobUtils.HasInteger(compileMethod, 0x70000000); // 4.0-4.1
|
||||||
DeobfuscatedFile.Deobfuscate(methodsDecrypter.Method);
|
DeobfuscatedFile.Deobfuscate(methodsDecrypter.Method);
|
||||||
bool hasCorEnableProfilingString = FindString(methodsDecrypter.Method, "Cor_Enable_Profiling"); // 4.1-4.4
|
bool hasCorEnableProfilingString = FindString(methodsDecrypter.Method, "Cor_Enable_Profiling"); // 4.1-4.4
|
||||||
|
bool hasCatchString = FindString(methodsDecrypter.Method, "catch: "); // <= 4.7
|
||||||
|
|
||||||
if (compileMethodHasConstant_0x70000000) {
|
if (compileMethodHasConstant_0x70000000) {
|
||||||
if (hasCorEnableProfilingString)
|
if (hasCorEnableProfilingString)
|
||||||
|
@ -368,7 +372,6 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
return DeobfuscatorInfo.THE_NAME + " 4.0";
|
return DeobfuscatorInfo.THE_NAME + " 4.0";
|
||||||
}
|
}
|
||||||
if (!hasCorEnableProfilingString) {
|
if (!hasCorEnableProfilingString) {
|
||||||
// 4.x or 4.5 - 4.6
|
|
||||||
bool callsReverse = DotNetUtils.CallsMethod(methodsDecrypter.Method, "System.Void System.Array::Reverse(System.Array)");
|
bool callsReverse = DotNetUtils.CallsMethod(methodsDecrypter.Method, "System.Void System.Array::Reverse(System.Array)");
|
||||||
if (!callsReverse)
|
if (!callsReverse)
|
||||||
return DeobfuscatorInfo.THE_NAME + " 4.0 - 4.4";
|
return DeobfuscatorInfo.THE_NAME + " 4.0 - 4.4";
|
||||||
|
@ -382,7 +385,9 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
case 10:
|
case 10:
|
||||||
if (!hasSymmetricAlgorithm)
|
if (!hasSymmetricAlgorithm)
|
||||||
return DeobfuscatorInfo.THE_NAME + " 4.6";
|
return DeobfuscatorInfo.THE_NAME + " 4.6";
|
||||||
return DeobfuscatorInfo.THE_NAME + " 4.7";
|
if (hasCatchString)
|
||||||
|
return DeobfuscatorInfo.THE_NAME + " 4.7";
|
||||||
|
return DeobfuscatorInfo.THE_NAME + " 4.8";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -392,7 +397,9 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
case 9:
|
case 9:
|
||||||
if (!hasSymmetricAlgorithm)
|
if (!hasSymmetricAlgorithm)
|
||||||
return DeobfuscatorInfo.THE_NAME + " 4.6";
|
return DeobfuscatorInfo.THE_NAME + " 4.6";
|
||||||
return DeobfuscatorInfo.THE_NAME + " 4.7";
|
if (hasCatchString)
|
||||||
|
return DeobfuscatorInfo.THE_NAME + " 4.7";
|
||||||
|
return DeobfuscatorInfo.THE_NAME + " 4.8";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,13 +24,24 @@ using System.Security.Cryptography;
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
using dnlib.DotNet.Emit;
|
using dnlib.DotNet.Emit;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
using de4dot.blocks.cflow;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
|
enum DnrDecrypterType {
|
||||||
|
Unknown,
|
||||||
|
V1,
|
||||||
|
V2,
|
||||||
|
}
|
||||||
|
|
||||||
class EncryptedResource {
|
class EncryptedResource {
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
MethodDef resourceDecrypterMethod;
|
MethodDef resourceDecrypterMethod;
|
||||||
EmbeddedResource encryptedDataResource;
|
EmbeddedResource encryptedDataResource;
|
||||||
byte[] key, iv;
|
IDecrypter decrypter;
|
||||||
|
|
||||||
|
public DnrDecrypterType DecrypterTypeVersion {
|
||||||
|
get { return decrypter == null ? DnrDecrypterType.Unknown : decrypter.DecrypterType; }
|
||||||
|
}
|
||||||
|
|
||||||
public TypeDef Type {
|
public TypeDef Type {
|
||||||
get { return resourceDecrypterMethod == null ? null : resourceDecrypterMethod.DeclaringType; }
|
get { return resourceDecrypterMethod == null ? null : resourceDecrypterMethod.DeclaringType; }
|
||||||
|
@ -58,8 +69,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
resourceDecrypterMethod = Lookup(oldOne.resourceDecrypterMethod, "Could not find resource decrypter method");
|
resourceDecrypterMethod = Lookup(oldOne.resourceDecrypterMethod, "Could not find resource decrypter method");
|
||||||
if (oldOne.encryptedDataResource != null)
|
if (oldOne.encryptedDataResource != null)
|
||||||
encryptedDataResource = DotNetUtils.GetResource(module, oldOne.encryptedDataResource.Name.String) as EmbeddedResource;
|
encryptedDataResource = DotNetUtils.GetResource(module, oldOne.encryptedDataResource.Name.String) as EmbeddedResource;
|
||||||
key = oldOne.key;
|
this.decrypter = oldOne.decrypter;
|
||||||
iv = oldOne.iv;
|
|
||||||
|
|
||||||
if (encryptedDataResource == null && oldOne.encryptedDataResource != null)
|
if (encryptedDataResource == null && oldOne.encryptedDataResource != null)
|
||||||
throw new ApplicationException("Could not initialize EncryptedResource");
|
throw new ApplicationException("Could not initialize EncryptedResource");
|
||||||
|
@ -69,30 +79,12 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
return DeobUtils.Lookup(module, def, errorMessage);
|
return DeobUtils.Lookup(module, def, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CouldBeResourceDecrypter(MethodDef method, IEnumerable<string> additionalTypes) {
|
public bool CouldBeResourceDecrypter(MethodDef method, IList<string> additionalTypes) {
|
||||||
return CouldBeResourceDecrypter(method, additionalTypes, true);
|
return CouldBeResourceDecrypter(method, additionalTypes, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CouldBeResourceDecrypter(MethodDef method, IEnumerable<string> additionalTypes, bool checkResource) {
|
public bool CouldBeResourceDecrypter(MethodDef method, IList<string> additionalTypes, bool checkResource) {
|
||||||
if (!method.IsStatic)
|
if (GetDecrypterType(method, additionalTypes) == DnrDecrypterType.Unknown)
|
||||||
return false;
|
|
||||||
if (method.Body == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var localTypes = new LocalTypes(method);
|
|
||||||
var requiredTypes = new List<string> {
|
|
||||||
"System.Byte[]",
|
|
||||||
"System.IO.BinaryReader",
|
|
||||||
"System.IO.MemoryStream",
|
|
||||||
"System.Security.Cryptography.CryptoStream",
|
|
||||||
"System.Security.Cryptography.ICryptoTransform",
|
|
||||||
};
|
|
||||||
requiredTypes.AddRange(additionalTypes);
|
|
||||||
if (!localTypes.All(requiredTypes))
|
|
||||||
return false;
|
|
||||||
if (!localTypes.Exists("System.Security.Cryptography.RijndaelManaged") &&
|
|
||||||
!localTypes.Exists("System.Security.Cryptography.AesManaged") &&
|
|
||||||
!localTypes.Exists("System.Security.Cryptography.SymmetricAlgorithm"))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (checkResource && FindMethodsDecrypterResource(method) == null)
|
if (checkResource && FindMethodsDecrypterResource(method) == null)
|
||||||
|
@ -101,6 +93,24 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DnrDecrypterType GuessDecrypterType() {
|
||||||
|
return GetDecrypterType(resourceDecrypterMethod, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DnrDecrypterType GetDecrypterType(MethodDef method, IList<string> additionalTypes) {
|
||||||
|
if (method == null || !method.IsStatic || method.Body == null)
|
||||||
|
return DnrDecrypterType.Unknown;
|
||||||
|
|
||||||
|
if (additionalTypes == null)
|
||||||
|
additionalTypes = new string[0];
|
||||||
|
var localTypes = new LocalTypes(method);
|
||||||
|
if (DecrypterV1.CouldBeResourceDecrypter(method, localTypes, additionalTypes))
|
||||||
|
return DnrDecrypterType.V1;
|
||||||
|
else if (DecrypterV2.CouldBeResourceDecrypter(method, localTypes, additionalTypes))
|
||||||
|
return DnrDecrypterType.V2;
|
||||||
|
return DnrDecrypterType.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
public void Initialize(ISimpleDeobfuscator simpleDeobfuscator) {
|
public void Initialize(ISimpleDeobfuscator simpleDeobfuscator) {
|
||||||
if (resourceDecrypterMethod == null)
|
if (resourceDecrypterMethod == null)
|
||||||
return;
|
return;
|
||||||
|
@ -111,10 +121,10 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
if (encryptedDataResource == null)
|
if (encryptedDataResource == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
key = ArrayFinder.GetInitializedByteArray(resourceDecrypterMethod, 32);
|
var key = ArrayFinder.GetInitializedByteArray(resourceDecrypterMethod, 32);
|
||||||
if (key == null)
|
if (key == null)
|
||||||
throw new ApplicationException("Could not find resource decrypter key");
|
throw new ApplicationException("Could not find resource decrypter key");
|
||||||
iv = ArrayFinder.GetInitializedByteArray(resourceDecrypterMethod, 16);
|
var iv = ArrayFinder.GetInitializedByteArray(resourceDecrypterMethod, 16);
|
||||||
if (iv == null)
|
if (iv == null)
|
||||||
throw new ApplicationException("Could not find resource decrypter IV");
|
throw new ApplicationException("Could not find resource decrypter IV");
|
||||||
if (NeedReverse())
|
if (NeedReverse())
|
||||||
|
@ -126,6 +136,13 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
iv[i * 2 + 1] = publicKeyToken.Data[i];
|
iv[i * 2 + 1] = publicKeyToken.Data[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var decrypterType = GetDecrypterType(resourceDecrypterMethod, new string[0]);
|
||||||
|
switch (decrypterType) {
|
||||||
|
case DnrDecrypterType.V1: decrypter = new DecrypterV1(iv, key); break;
|
||||||
|
case DnrDecrypterType.V2: decrypter = new DecrypterV2(iv, key, resourceDecrypterMethod); break;
|
||||||
|
default: throw new ApplicationException("Unknown decrypter type");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int[] pktIndexes = new int[16] { 1, 0, 3, 1, 5, 2, 7, 3, 9, 4, 11, 5, 13, 6, 15, 7 };
|
static int[] pktIndexes = new int[16] { 1, 0, 3, 1, 5, 2, 7, 3, 9, 4, 11, 5, 13, 6, 15, 7 };
|
||||||
|
@ -162,22 +179,244 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Decrypt() {
|
interface IDecrypter {
|
||||||
if (encryptedDataResource == null || key == null || iv == null)
|
DnrDecrypterType DecrypterType { get; }
|
||||||
throw new ApplicationException("Can't decrypt resource");
|
byte[] Decrypt(EmbeddedResource resource);
|
||||||
|
byte[] Encrypt(byte[] data);
|
||||||
return DeobUtils.AesDecrypt(encryptedDataResource.GetResourceData(), key, iv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Encrypt(byte[] data) {
|
class DecrypterV1 : IDecrypter {
|
||||||
if (key == null || iv == null)
|
readonly byte[] key, iv;
|
||||||
throw new ApplicationException("Can't encrypt resource");
|
|
||||||
|
|
||||||
using (var aes = new RijndaelManaged { Mode = CipherMode.CBC }) {
|
public DnrDecrypterType DecrypterType {
|
||||||
using (var transform = aes.CreateEncryptor(key, iv)) {
|
get { return DnrDecrypterType.V1; }
|
||||||
return transform.TransformFinalBlock(data, 0, data.Length);
|
}
|
||||||
|
|
||||||
|
public DecrypterV1(byte[] iv, byte[] key) {
|
||||||
|
this.iv = iv;
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CouldBeResourceDecrypter(MethodDef method, LocalTypes localTypes, IList<string> additionalTypes) {
|
||||||
|
var requiredTypes = new List<string> {
|
||||||
|
"System.Byte[]",
|
||||||
|
"System.IO.BinaryReader",
|
||||||
|
"System.IO.MemoryStream",
|
||||||
|
"System.Security.Cryptography.CryptoStream",
|
||||||
|
"System.Security.Cryptography.ICryptoTransform",
|
||||||
|
};
|
||||||
|
requiredTypes.AddRange(additionalTypes);
|
||||||
|
if (!localTypes.All(requiredTypes))
|
||||||
|
return false;
|
||||||
|
if (!localTypes.Exists("System.Security.Cryptography.RijndaelManaged") &&
|
||||||
|
!localTypes.Exists("System.Security.Cryptography.AesManaged") &&
|
||||||
|
!localTypes.Exists("System.Security.Cryptography.SymmetricAlgorithm"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Decrypt(EmbeddedResource resource) {
|
||||||
|
return DeobUtils.AesDecrypt(resource.GetResourceData(), key, iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Encrypt(byte[] data) {
|
||||||
|
using (var aes = new RijndaelManaged { Mode = CipherMode.CBC }) {
|
||||||
|
using (var transform = aes.CreateEncryptor(key, iv)) {
|
||||||
|
return transform.TransformFinalBlock(data, 0, data.Length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DecrypterV2 : IDecrypter {
|
||||||
|
readonly byte[] key, iv;
|
||||||
|
readonly MethodDef method;
|
||||||
|
List<Instruction> instructions;
|
||||||
|
readonly List<Local> locals;
|
||||||
|
readonly InstructionEmulator instrEmulator = new InstructionEmulator();
|
||||||
|
Local emuLocal;
|
||||||
|
|
||||||
|
public DnrDecrypterType DecrypterType {
|
||||||
|
get { return DnrDecrypterType.V2; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public DecrypterV2(byte[] iv, byte[] key, MethodDef method) {
|
||||||
|
this.iv = iv;
|
||||||
|
this.key = key;
|
||||||
|
this.method = method;
|
||||||
|
this.locals = new List<Local>(method.Body.Variables);
|
||||||
|
if (!Initialize())
|
||||||
|
throw new ApplicationException("Could not initialize decrypter");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CouldBeResourceDecrypter(MethodDef method, LocalTypes localTypes, IList<string> additionalTypes) {
|
||||||
|
var requiredTypes = new List<string> {
|
||||||
|
"System.UInt32",
|
||||||
|
"System.String",
|
||||||
|
"System.Int32",
|
||||||
|
"System.Byte[]",
|
||||||
|
"System.IO.BinaryReader",
|
||||||
|
};
|
||||||
|
requiredTypes.AddRange(additionalTypes);
|
||||||
|
if (!localTypes.All(requiredTypes))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Initialize() {
|
||||||
|
for (int i = 0; i < iv.Length; i++)
|
||||||
|
key[i] ^= iv[i];
|
||||||
|
|
||||||
|
var origInstrs = method.Body.Instructions;
|
||||||
|
|
||||||
|
int emuStartIndex;
|
||||||
|
if (!FindStart(origInstrs, out emuStartIndex, out emuLocal))
|
||||||
|
return false;
|
||||||
|
int emuEndIndex;
|
||||||
|
if (!FindEnd(origInstrs, emuStartIndex, out emuEndIndex))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int count = emuEndIndex - emuStartIndex + 1;
|
||||||
|
instructions = new List<Instruction>(count);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
instructions.Add(origInstrs[emuStartIndex + i].Clone());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindStart(IList<Instruction> instrs, out int startIndex, out Local tmpLocal) {
|
||||||
|
for (int i = 0; i + 8 < instrs.Count; i++) {
|
||||||
|
if (instrs[i].OpCode.Code != Code.Conv_U)
|
||||||
|
continue;
|
||||||
|
if (instrs[i + 1].OpCode.Code != Code.Ldelem_U1)
|
||||||
|
continue;
|
||||||
|
if (instrs[i + 2].OpCode.Code != Code.Or)
|
||||||
|
continue;
|
||||||
|
if (CheckLocal(instrs[i + 3], false) == null)
|
||||||
|
continue;
|
||||||
|
Local local;
|
||||||
|
if ((local = CheckLocal(instrs[i + 4], true)) == null)
|
||||||
|
continue;
|
||||||
|
if (CheckLocal(instrs[i + 5], true) == null)
|
||||||
|
continue;
|
||||||
|
if (instrs[i + 6].OpCode.Code != Code.Add)
|
||||||
|
continue;
|
||||||
|
if (CheckLocal(instrs[i + 7], false) != local)
|
||||||
|
continue;
|
||||||
|
var instr = instrs[i + 8];
|
||||||
|
int newStartIndex = i + 8;
|
||||||
|
if (instr.IsBr()) {
|
||||||
|
instr = instr.Operand as Instruction;
|
||||||
|
newStartIndex = instrs.IndexOf(instr);
|
||||||
|
}
|
||||||
|
if (newStartIndex < 0 || instr == null)
|
||||||
|
continue;
|
||||||
|
if (CheckLocal(instr, true) != local)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
startIndex = newStartIndex;
|
||||||
|
tmpLocal = local;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
startIndex = 0;
|
||||||
|
tmpLocal = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindEnd(IList<Instruction> instrs, int startIndex, out int endIndex) {
|
||||||
|
for (int i = startIndex; i < instrs.Count; i++) {
|
||||||
|
var instr = instrs[i];
|
||||||
|
if (instr.OpCode.FlowControl != FlowControl.Next)
|
||||||
|
break;
|
||||||
|
if (instr.IsStloc() && instr.GetLocal(locals) == emuLocal) {
|
||||||
|
endIndex = i - 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
endIndex = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Local CheckLocal(Instruction instr, bool isLdloc) {
|
||||||
|
if (isLdloc && !instr.IsLdloc())
|
||||||
|
return null;
|
||||||
|
else if (!isLdloc && !instr.IsStloc())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return instr.GetLocal(locals);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Decrypt(EmbeddedResource resource) {
|
||||||
|
var encrypted = resource.GetResourceData();
|
||||||
|
var decrypted = new byte[encrypted.Length];
|
||||||
|
|
||||||
|
uint sum = 0;
|
||||||
|
for (int i = 0; i < encrypted.Length; i += 4) {
|
||||||
|
sum = CalculateMagic(sum + ReadUInt32(key, i % key.Length));
|
||||||
|
WriteUInt32(decrypted, i, sum ^ ReadUInt32(encrypted, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return decrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint CalculateMagic(uint input) {
|
||||||
|
instrEmulator.Initialize(method, method.Parameters, locals, method.Body.InitLocals, false);
|
||||||
|
instrEmulator.SetLocal(emuLocal, new Int32Value((int)input));
|
||||||
|
|
||||||
|
foreach (var instr in instructions)
|
||||||
|
instrEmulator.Emulate(instr);
|
||||||
|
|
||||||
|
var tos = instrEmulator.Pop() as Int32Value;
|
||||||
|
if (tos == null || !tos.AllBitsValid())
|
||||||
|
throw new ApplicationException("Couldn't calculate magic value");
|
||||||
|
return (uint)tos.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint ReadUInt32(byte[] ary, int index) {
|
||||||
|
int sizeLeft = ary.Length - index;
|
||||||
|
if (sizeLeft >= 4)
|
||||||
|
return BitConverter.ToUInt32(ary, index);
|
||||||
|
switch (sizeLeft) {
|
||||||
|
case 1: return ary[index];
|
||||||
|
case 2: return (uint)(ary[index] | (ary[index + 1] << 8));
|
||||||
|
case 3: return (uint)(ary[index] | (ary[index + 1] << 8) | (ary[index + 2] << 16));
|
||||||
|
default: throw new ApplicationException("Can't read data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteUInt32(byte[] ary, int index, uint value) {
|
||||||
|
int sizeLeft = ary.Length - index;
|
||||||
|
if (sizeLeft >= 1)
|
||||||
|
ary[index] = (byte)value;
|
||||||
|
if (sizeLeft >= 2)
|
||||||
|
ary[index + 1] = (byte)(value >> 8);
|
||||||
|
if (sizeLeft >= 3)
|
||||||
|
ary[index + 2] = (byte)(value >> 16);
|
||||||
|
if (sizeLeft >= 4)
|
||||||
|
ary[index + 3] = (byte)(value >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Encrypt(byte[] data) {
|
||||||
|
//TODO: Support re-encryption
|
||||||
|
Logger.e("Re-encryption is not supported. Assembly will probably crash at runtime.");
|
||||||
|
return (byte[])data.Clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Decrypt() {
|
||||||
|
if (encryptedDataResource == null || decrypter == null)
|
||||||
|
throw new ApplicationException("Can't decrypt resource");
|
||||||
|
return decrypter.Decrypt(encryptedDataResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Encrypt(byte[] data) {
|
||||||
|
if (decrypter == null)
|
||||||
|
throw new ApplicationException("Can't encrypt resource");
|
||||||
|
return decrypter.Encrypt(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
if (type == null)
|
if (type == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var gpContext = GenericParamContext.Create(blocks.Method);
|
||||||
foreach (var block in blocks.MethodBlocks.GetAllBlocks()) {
|
foreach (var block in blocks.MethodBlocks.GetAllBlocks()) {
|
||||||
var instrs = block.Instructions;
|
var instrs = block.Instructions;
|
||||||
for (int i = 0; i < instrs.Count - 1; i++) {
|
for (int i = 0; i < instrs.Count - 1; i++) {
|
||||||
|
@ -98,7 +99,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
|
|
||||||
uint token = (uint)(int)instrs[i].Operand;
|
uint token = (uint)(int)instrs[i].Operand;
|
||||||
instrs[i] = new Instr(OpCodes.Nop.ToInstruction());
|
instrs[i] = new Instr(OpCodes.Nop.ToInstruction());
|
||||||
instrs[i + 1] = new Instr(new Instruction(OpCodes.Ldtoken, module.ResolveToken(token) as ITokenOperand));
|
instrs[i + 1] = new Instr(new Instruction(OpCodes.Ldtoken, module.ResolveToken(token, gpContext) as ITokenOperand));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,10 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
get { return encryptedResource.Resource; }
|
get { return encryptedResource.Resource; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DnrDecrypterType DecrypterTypeVersion {
|
||||||
|
get { return encryptedResource.GuessDecrypterType(); }
|
||||||
|
}
|
||||||
|
|
||||||
public MethodsDecrypter(ModuleDefMD module) {
|
public MethodsDecrypter(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.encryptedResource = new EncryptedResource(module);
|
this.encryptedResource = new EncryptedResource(module);
|
||||||
|
@ -301,10 +305,10 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
if (instructions[i].OpCode.Code != Code.Ldind_I8)
|
if (instructions[i].OpCode.Code != Code.Ldind_I8)
|
||||||
continue;
|
continue;
|
||||||
var ldci4 = instructions[i + 1];
|
var ldci4 = instructions[i + 1];
|
||||||
if (!ldci4.IsLdcI4())
|
if (ldci4.IsLdcI4())
|
||||||
continue;
|
return ldci4.GetLdcI4Value();
|
||||||
|
if (ldci4.OpCode.Code == Code.Ldc_I8)
|
||||||
return ldci4.GetLdcI4Value();
|
return (long)ldci4.Operand;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,21 +70,37 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
if (!DotNetUtils.IsMethod(method, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)") &&
|
if (!DotNetUtils.IsMethod(method, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)") &&
|
||||||
!DotNetUtils.IsMethod(method, "System.Reflection.Assembly", "(System.Object,System.Object)"))
|
!DotNetUtils.IsMethod(method, "System.Reflection.Assembly", "(System.Object,System.Object)"))
|
||||||
continue;
|
continue;
|
||||||
if (!encryptedResource.CouldBeResourceDecrypter(method, additionalTypes, false))
|
var initMethod = GetResourceDecrypterInitMethod(method, additionalTypes, false);
|
||||||
|
if (initMethod == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
encryptedResource.Method = method;
|
encryptedResource.Method = initMethod;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MethodDef GetResourceDecrypterInitMethod(MethodDef method, string[] additionalTypes, bool checkResource) {
|
||||||
|
if (encryptedResource.CouldBeResourceDecrypter(method, additionalTypes, checkResource))
|
||||||
|
return method;
|
||||||
|
|
||||||
|
foreach (var calledMethod in DotNetUtils.GetCalledMethods(module, method)) {
|
||||||
|
if (!DotNetUtils.IsMethod(calledMethod, "System.Void", "()"))
|
||||||
|
continue;
|
||||||
|
if (encryptedResource.CouldBeResourceDecrypter(calledMethod, additionalTypes, checkResource))
|
||||||
|
return calledMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
bool CheckFields(IList<FieldDef> fields) {
|
bool CheckFields(IList<FieldDef> fields) {
|
||||||
if (fields.Count != 3)
|
if (fields.Count != 3 && fields.Count != 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
int numBools = fields.Count == 3 ? 1 : 2;
|
||||||
var fieldTypes = new FieldTypes(fields);
|
var fieldTypes = new FieldTypes(fields);
|
||||||
if (fieldTypes.Count("System.Boolean") != 1)
|
if (fieldTypes.Count("System.Boolean") != numBools)
|
||||||
return false;
|
return false;
|
||||||
if (fieldTypes.Count("System.Object") == 2)
|
if (fieldTypes.Count("System.Object") == 2)
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -40,6 +40,12 @@ namespace de4dot.code.renamer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Check(MTypeDef type) {
|
public bool Check(MTypeDef type) {
|
||||||
|
return Check(type, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Check(MTypeDef type, int recurseCount) {
|
||||||
|
if (recurseCount >= 100)
|
||||||
|
return false;
|
||||||
if (results.ContainsKey(type))
|
if (results.ContainsKey(type))
|
||||||
return results[type];
|
return results[type];
|
||||||
|
|
||||||
|
@ -53,7 +59,7 @@ namespace de4dot.code.renamer {
|
||||||
val = false;
|
val = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
val = Check(type.baseType.typeDef);
|
val = Check(type.baseType.typeDef, recurseCount + 1);
|
||||||
|
|
||||||
results[type] = val;
|
results[type] = val;
|
||||||
return val;
|
return val;
|
||||||
|
|
|
@ -62,6 +62,8 @@ namespace de4dot.code.renamer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Merge(ExistingNames other) {
|
public void Merge(ExistingNames other) {
|
||||||
|
if (this == other)
|
||||||
|
return;
|
||||||
foreach (var key in other.allNames.Keys)
|
foreach (var key in other.allNames.Keys)
|
||||||
allNames[key] = true;
|
allNames[key] = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1520,6 +1520,29 @@ namespace de4dot.code.renamer {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static ITypeDefOrRef GetScopeType(TypeSig typeSig) {
|
||||||
|
if (typeSig == null)
|
||||||
|
return null;
|
||||||
|
var scopeType = typeSig.ScopeType;
|
||||||
|
if (scopeType != null)
|
||||||
|
return scopeType;
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
var nls = typeSig as NonLeafSig;
|
||||||
|
if (nls == null)
|
||||||
|
break;
|
||||||
|
typeSig = nls.Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (typeSig.GetElementType()) {
|
||||||
|
case ElementType.MVar:
|
||||||
|
case ElementType.Var:
|
||||||
|
return new TypeSpecUser(typeSig);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string GetNewPropertyNamePrefix(MethodNameGroup group) {
|
string GetNewPropertyNamePrefix(MethodNameGroup group) {
|
||||||
const string defaultVal = "Prop_";
|
const string defaultVal = "Prop_";
|
||||||
|
|
||||||
|
@ -1527,7 +1550,7 @@ namespace de4dot.code.renamer {
|
||||||
if (propType == null)
|
if (propType == null)
|
||||||
return defaultVal;
|
return defaultVal;
|
||||||
|
|
||||||
var elementType = propType.ScopeType.ToTypeSig(false).RemovePinnedAndModifiers();
|
var elementType = GetScopeType(propType).ToTypeSig(false).RemovePinnedAndModifiers();
|
||||||
if (propType is GenericInstSig || elementType is GenericSig)
|
if (propType is GenericInstSig || elementType is GenericSig)
|
||||||
return defaultVal;
|
return defaultVal;
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace de4dot.code.renamer {
|
||||||
|
|
||||||
string prefix = GetPrefix(typeRef);
|
string prefix = GetPrefix(typeRef);
|
||||||
|
|
||||||
var elementType = typeRef.ScopeType;
|
var elementType = Renamer.GetScopeType(typeRef);
|
||||||
if (elementType == null && IsFnPtrSig(typeRef))
|
if (elementType == null && IsFnPtrSig(typeRef))
|
||||||
return fnPtrNameCreator.Create();
|
return fnPtrNameCreator.Create();
|
||||||
if (IsGenericParam(elementType))
|
if (IsGenericParam(elementType))
|
||||||
|
@ -113,6 +113,8 @@ namespace de4dot.code.renamer {
|
||||||
protected abstract string FixName(string prefix, string name);
|
protected abstract string FixName(string prefix, string name);
|
||||||
|
|
||||||
public virtual TypeNames Merge(TypeNames other) {
|
public virtual TypeNames Merge(TypeNames other) {
|
||||||
|
if (this == other)
|
||||||
|
return this;
|
||||||
foreach (var pair in other.typeNames) {
|
foreach (var pair in other.typeNames) {
|
||||||
NameCreator nc;
|
NameCreator nc;
|
||||||
if (typeNames.TryGetValue(pair.Key, out nc))
|
if (typeNames.TryGetValue(pair.Key, out nc))
|
||||||
|
|
|
@ -61,6 +61,8 @@ namespace de4dot.code.renamer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public VariableNameState Merge(VariableNameState other) {
|
public VariableNameState Merge(VariableNameState other) {
|
||||||
|
if (this == other)
|
||||||
|
return this;
|
||||||
existingVariableNames.Merge(other.existingVariableNames);
|
existingVariableNames.Merge(other.existingVariableNames);
|
||||||
existingMethodNames.Merge(other.existingMethodNames);
|
existingMethodNames.Merge(other.existingMethodNames);
|
||||||
existingPropertyNames.Merge(other.existingPropertyNames);
|
existingPropertyNames.Merge(other.existingPropertyNames);
|
||||||
|
|
|
@ -285,9 +285,44 @@ namespace de4dot.code.renamer.asmmodules {
|
||||||
void Add(DeclSecurity decl) {
|
void Add(DeclSecurity decl) {
|
||||||
if (decl == null)
|
if (decl == null)
|
||||||
return;
|
return;
|
||||||
|
Add(decl.SecurityAttributes);
|
||||||
Add(decl.CustomAttributes);
|
Add(decl.CustomAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Add(IEnumerable<SecurityAttribute> secAttrs) {
|
||||||
|
if (secAttrs == null)
|
||||||
|
return;
|
||||||
|
foreach (var secAttr in secAttrs)
|
||||||
|
Add(secAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Add(SecurityAttribute secAttr) {
|
||||||
|
if (secAttr == null)
|
||||||
|
return;
|
||||||
|
Add(secAttr.AttributeType);
|
||||||
|
Add(secAttr.NamedArguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Add(ITypeDefOrRef tdr) {
|
||||||
|
var td = tdr as TypeDef;
|
||||||
|
if (td != null) {
|
||||||
|
Add(td);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tr = tdr as TypeRef;
|
||||||
|
if (tr != null) {
|
||||||
|
Add(tr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ts = tdr as TypeSpec;
|
||||||
|
if (ts != null) {
|
||||||
|
Add(ts);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Add(IEnumerable<EventDef> eds) {
|
void Add(IEnumerable<EventDef> eds) {
|
||||||
if (eds == null)
|
if (eds == null)
|
||||||
return;
|
return;
|
||||||
|
@ -326,6 +361,7 @@ namespace de4dot.code.renamer.asmmodules {
|
||||||
Add(fd.CustomAttributes);
|
Add(fd.CustomAttributes);
|
||||||
Add(fd.Signature);
|
Add(fd.Signature);
|
||||||
Add(fd.DeclaringType);
|
Add(fd.DeclaringType);
|
||||||
|
Add(fd.MarshalType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Add(IEnumerable<GenericParam> gps) {
|
void Add(IEnumerable<GenericParam> gps) {
|
||||||
|
@ -489,6 +525,22 @@ namespace de4dot.code.renamer.asmmodules {
|
||||||
return;
|
return;
|
||||||
Add(pd.DeclaringMethod);
|
Add(pd.DeclaringMethod);
|
||||||
Add(pd.CustomAttributes);
|
Add(pd.CustomAttributes);
|
||||||
|
Add(pd.MarshalType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Add(MarshalType mt) {
|
||||||
|
if (mt == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (mt.NativeType) {
|
||||||
|
case NativeType.SafeArray:
|
||||||
|
Add(((SafeArrayMarshalType)mt).UserDefinedSubType);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NativeType.CustomMarshaler:
|
||||||
|
Add(((CustomMarshalType)mt).CustomMarshaler);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Add(IEnumerable<MethodOverride> mos) {
|
void Add(IEnumerable<MethodOverride> mos) {
|
||||||
|
|
|
@ -74,7 +74,7 @@ namespace de4dot.cui {
|
||||||
|
|
||||||
Logger.n("");
|
Logger.n("");
|
||||||
Logger.n("de4dot v{0} Copyright (C) 2011-2014 de4dot@gmail.com", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version);
|
Logger.n("de4dot v{0} Copyright (C) 2011-2014 de4dot@gmail.com", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version);
|
||||||
Logger.n("Latest version and source code: https://bitbucket.org/0xd4d/de4dot");
|
Logger.n("Latest version and source code: https://github.com/0xd4d/de4dot");
|
||||||
Logger.n("");
|
Logger.n("");
|
||||||
|
|
||||||
var options = new FilesDeobfuscator.Options();
|
var options = new FilesDeobfuscator.Options();
|
||||||
|
|
|
@ -30,7 +30,7 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
[assembly: InternalsVisibleTo("de4dot, PublicKey=00240000048000009400000006020000002400005253413100040000010001007b5ffd8f48f1397cd4e21c9e30a5cb36b2c013d6f20688c90e3f0c2d24e6d67cbeea7a6ec3faf9ba081f3d6b6fbe389677adbb8337d3a16187cd13b16a34008a22b89089da41c4a08fd35615c77de0827adcca6d49b08c0ed3e0404a1c44b7d083be614acb1779e4fb275e14427f3687f375d03f3b465c8a6cdeebd1f8c7f4ea")]
|
[assembly: InternalsVisibleTo("de4dot, PublicKey=00240000048000009400000006020000002400005253413100040000010001007b5ffd8f48f1397cd4e21c9e30a5cb36b2c013d6f20688c90e3f0c2d24e6d67cbeea7a6ec3faf9ba081f3d6b6fbe389677adbb8337d3a16187cd13b16a34008a22b89089da41c4a08fd35615c77de0827adcca6d49b08c0ed3e0404a1c44b7d083be614acb1779e4fb275e14427f3687f375d03f3b465c8a6cdeebd1f8c7f4ea")]
|
||||||
[assembly: InternalsVisibleTo("de4dot-x64, PublicKey=00240000048000009400000006020000002400005253413100040000010001007b5ffd8f48f1397cd4e21c9e30a5cb36b2c013d6f20688c90e3f0c2d24e6d67cbeea7a6ec3faf9ba081f3d6b6fbe389677adbb8337d3a16187cd13b16a34008a22b89089da41c4a08fd35615c77de0827adcca6d49b08c0ed3e0404a1c44b7d083be614acb1779e4fb275e14427f3687f375d03f3b465c8a6cdeebd1f8c7f4ea")]
|
[assembly: InternalsVisibleTo("de4dot-x64, PublicKey=00240000048000009400000006020000002400005253413100040000010001007b5ffd8f48f1397cd4e21c9e30a5cb36b2c013d6f20688c90e3f0c2d24e6d67cbeea7a6ec3faf9ba081f3d6b6fbe389677adbb8337d3a16187cd13b16a34008a22b89089da41c4a08fd35615c77de0827adcca6d49b08c0ed3e0404a1c44b7d083be614acb1779e4fb275e14427f3687f375d03f3b465c8a6cdeebd1f8c7f4ea")]
|
||||||
|
|
|
@ -596,6 +596,9 @@ namespace de4dot.mdecrypt {
|
||||||
new PatchInfo(0x000110A5, new byte[] { 0x33, 0xC0, 0xC2, 0x04, 0x00 }, new byte[] { 0xE9, 0x36, 0x3A, 0x00, 0x00 }),
|
new PatchInfo(0x000110A5, new byte[] { 0x33, 0xC0, 0xC2, 0x04, 0x00 }, new byte[] { 0xE9, 0x36, 0x3A, 0x00, 0x00 }),
|
||||||
new PatchInfo(0x000110AF, new byte[] { 0x33, 0xC0, 0xC2, 0x04, 0x00 }, new byte[] { 0xE9, 0x4C, 0x3C, 0x00, 0x00 }),
|
new PatchInfo(0x000110AF, new byte[] { 0x33, 0xC0, 0xC2, 0x04, 0x00 }, new byte[] { 0xE9, 0x4C, 0x3C, 0x00, 0x00 }),
|
||||||
new PatchInfo(0x000110AA, new byte[] { 0x33, 0xC0, 0xC2, 0x04, 0x00 }, new byte[] { 0xE9, 0xF1, 0x3A, 0x00, 0x00 }),
|
new PatchInfo(0x000110AA, new byte[] { 0x33, 0xC0, 0xC2, 0x04, 0x00 }, new byte[] { 0xE9, 0xF1, 0x3A, 0x00, 0x00 }),
|
||||||
|
new PatchInfo(0x00011019, new byte[] { 0x33, 0xC0, 0xC2, 0x04, 0x00 }, new byte[] { 0xE9, 0x12, 0x4B, 0x00, 0x00 }),
|
||||||
|
new PatchInfo(0x00011019, new byte[] { 0x33, 0xC0, 0xC2, 0x04, 0x00 }, new byte[] { 0xE9, 0x02, 0x4B, 0x00, 0x00 }),
|
||||||
|
new PatchInfo(0x00011019, new byte[] { 0x33, 0xC0, 0xC2, 0x04, 0x00 }, new byte[] { 0xE9, 0xA2, 0x4B, 0x00, 0x00 }),
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsafe bool PatchCM(IntPtr addr, IntPtr origValue, IntPtr newValue) {
|
static unsafe bool PatchCM(IntPtr addr, IntPtr origValue, IntPtr newValue) {
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
[assembly: AssemblyVersion("3.0.3.3405")]
|
[assembly: AssemblyVersion("3.1.41592.3405")]
|
||||||
[assembly: AssemblyFileVersion("3.0.3.3405")]
|
[assembly: AssemblyFileVersion("3.1.41592.3405")]
|
||||||
|
|
2
dnlib
2
dnlib
|
@ -1 +1 @@
|
||||||
Subproject commit d854e20b2d4245245efc19e676e6862cdbd162f6
|
Subproject commit 4abc5988d3cc4e8ae4cb7ac77f3018ffb54200c7
|
Loading…
Reference in New Issue
Block a user