Support ILProtector 2.0.13.0 - 2.0.13.1

This commit is contained in:
de4dot 2014-04-01 08:20:38 +02:00
parent 27694eb19c
commit 978c2a7e31
2 changed files with 224 additions and 17 deletions

View File

@ -40,6 +40,50 @@ namespace de4dot.code.deobfuscators.ILProtector {
IDecrypter decrypter;
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 {
byte[] Decrypt(int methodId, uint rid);
}
@ -323,7 +367,7 @@ namespace de4dot.code.deobfuscators.ILProtector {
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;
foreach (var fi in obj.GetType().GetFields(flags)) {
if (fi.FieldType == typeof(IntPtr))
@ -335,7 +379,6 @@ namespace de4dot.code.deobfuscators.ILProtector {
public byte[] Decrypt(int methodId, uint rid) {
decryptedData = null;
currentILBytes = dmd.reflectionModule.ResolveMethod(0x06000000 + (int)rid).GetMethodBody().GetILAsByteArray();
invoker.DynamicInvoke(new object[1] { methodId });
return decryptedData;
}
@ -358,7 +401,7 @@ namespace de4dot.code.deobfuscators.ILProtector {
public unsafe DecrypterV2_0_12_0(DynamicMethodsDecrypter dmd)
: base(dmd) {
getCallerMethodAsILByteArrayDelegate = GetCallerMethodAsILByteArray;
decryptCallbackDelegate = MyDecryptCallback;
decryptCallbackDelegate = DecryptCallback;
*(IntPtr*)pGetILBytes = Marshal.GetFunctionPointerForDelegate(getCallerMethodAsILByteArrayDelegate);
*(IntPtr*)pDecryptCallback = Marshal.GetFunctionPointerForDelegate(decryptCallbackDelegate);
@ -368,7 +411,7 @@ namespace de4dot.code.deobfuscators.ILProtector {
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);
return true;
}
@ -386,7 +429,7 @@ namespace de4dot.code.deobfuscators.ILProtector {
public unsafe DecrypterV2_0_12_3(DynamicMethodsDecrypter dmd)
: base(dmd) {
getCallerMethodAsILByteArrayDelegate = GetCallerMethodAsILByteArray;
decryptCallbackDelegate = MyDecryptCallback;
decryptCallbackDelegate = DecryptCallback;
*(IntPtr*)pGetILBytes = Marshal.GetFunctionPointerForDelegate(getCallerMethodAsILByteArrayDelegate);
*(IntPtr*)pDecryptCallback = Marshal.GetFunctionPointerForDelegate(decryptCallbackDelegate);
@ -396,12 +439,176 @@ namespace de4dot.code.deobfuscators.ILProtector {
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);
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 {
get { return methodReaderHasDelegateTypeFlag; }
}
@ -456,9 +663,13 @@ namespace de4dot.code.deobfuscators.ILProtector {
methodReaderHasDelegateTypeFlag = true;
if (version < new Version(2, 0, 12, 3))
return CreateDecrypterV2_0_12_0();
if (version < new Version(2, 0, 12, 4))
return CreateDecrypterV2_0_12_3();
return new DecrypterV2_0_12_0(this);
if (version == new Version(2, 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;
}
@ -503,14 +714,6 @@ namespace de4dot.code.deobfuscators.ILProtector {
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 Assembly GetProtectAssembly() {
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) {

View File

@ -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, 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, 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[] {
@ -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, 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, 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) {