From 09d5bd40ea01d9a58c154cbac44373a86882e075 Mon Sep 17 00:00:00 2001 From: de4dot Date: Sun, 22 Jul 2012 18:37:14 +0200 Subject: [PATCH] Support AN 6.1 --- de4dot.mdecrypt/DynamicMethodsDecrypter.cs | 83 +++++++++++++--------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/de4dot.mdecrypt/DynamicMethodsDecrypter.cs b/de4dot.mdecrypt/DynamicMethodsDecrypter.cs index 84dc7136..4c24861e 100644 --- a/de4dot.mdecrypt/DynamicMethodsDecrypter.cs +++ b/de4dot.mdecrypt/DynamicMethodsDecrypter.cs @@ -89,6 +89,7 @@ namespace de4dot.mdecrypt { IntPtr hInstModule; IntPtr ourCompMem; bool compileMethodIsThisCall; + IntPtr ourCodeAddr; de4dot.PE.MetadataType methodDefTable; IntPtr methodDefTablePtr; @@ -127,7 +128,7 @@ namespace de4dot.mdecrypt { const uint PAGE_EXECUTE_READWRITE = 0x40; [DllImport("kernel32")] - static extern void DebugBreak(); + static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, uint flAllocationType, uint flProtect); delegate IntPtr GetJit(); delegate int CompileMethod(IntPtr jitter, IntPtr comp, IntPtr info, uint flags, IntPtr nativeEntry, IntPtr nativeSizeOfCode, out bool handled); @@ -199,13 +200,17 @@ namespace de4dot.mdecrypt { prepareMethods(); initializeDelegateFunctionPointers(); - installOurCode(createOurCode(origCompileMethod)); + createOurCode(); callMethodDelegate = (CallMethod)Marshal.GetDelegateForFunctionPointer(callMethod, typeof(CallMethod)); + writeCompileMethod(ourCompileMethodInfo.ptrInDll); + } + + unsafe void writeCompileMethod(IntPtr newCompileMethod) { uint oldProtect; if (!VirtualProtect(jitterVtbl, IntPtr.Size, PAGE_EXECUTE_READWRITE, out oldProtect)) throw new ApplicationException("Could not enable write access to jitter vtbl"); - *(IntPtr*)jitterVtbl = ourCompileMethodInfo.ptrInDll; + *(IntPtr*)jitterVtbl = newCompileMethod; VirtualProtect(jitterVtbl, IntPtr.Size, oldProtect, out oldProtect); } @@ -265,17 +270,11 @@ namespace de4dot.mdecrypt { RuntimeHelpers.PrepareMethod(methodInfo.MethodHandle); } - unsafe byte[] createOurCode(IntPtr compileMethod) { + unsafe void createOurCode() { var code = new NativeCodeGenerator(); - var origCode = new byte[0x60]; - Marshal.Copy(compileMethod, origCode, 0, origCode.Length); - // our compileMethod() func int compileMethodOffset = code.Size; - code.writeByte(0xE9); - code.writeDword((uint)origCode.Length); - writeOriginalCode(code, origCode, compileMethod); int numPushedArgs = compileMethodIsThisCall ? 5 : 6; @@ -318,12 +317,14 @@ namespace de4dot.mdecrypt { code.writeCall(returnNameOfMethodInfo.ptr); code.writeBytes(0xC2, (ushort)(IntPtr.Size * 3)); - IntPtr baseAddr = new IntPtr((byte*)jitterTextFreeMem - code.Size); + ourCodeAddr = VirtualAlloc(IntPtr.Zero, new UIntPtr((ulong)code.Size), 0x00001000, PAGE_EXECUTE_READWRITE); + IntPtr baseAddr = ourCodeAddr; ourCompileMethodInfo.ptrInDll = new IntPtr((byte*)baseAddr + compileMethodOffset); callMethod = new IntPtr((byte*)baseAddr + callMethodOffset); returnMethodTokenInfo.ptrInDll = new IntPtr((byte*)baseAddr + getMethodTokenOffset); returnNameOfMethodInfo.ptrInDll = new IntPtr((byte*)baseAddr + getMethodNameOffset); - return code.getCode(baseAddr); + byte[] theCode = code.getCode(baseAddr); + Marshal.Copy(theCode, 0, baseAddr, theCode.Length); } // Writes push dword ptr [esp+displ] @@ -332,28 +333,6 @@ namespace de4dot.mdecrypt { code.writeBytes(0x24, (byte)displ); } - static void writeOriginalCode(NativeCodeGenerator code, byte[] origCode, IntPtr origAddr) { - for (int i = 0; i < origCode.Length; i++) { - byte b = origCode[i]; - if (b != 0xE8 || i + 5 >= origCode.Length) { - code.writeByte(b); - continue; - } - - IntPtr dest = new IntPtr(origAddr.ToInt64() + i + 5 + BitConverter.ToInt32(origCode, i + 1)); - code.writeCall(dest); - i += 4; - } - } - - void installOurCode(byte[] ourCode) { - uint oldProtect; - if (!VirtualProtect(ourCompileMethodInfo.ptrInDll, ourCode.Length, PAGE_EXECUTE_READWRITE, out oldProtect)) - throw new ApplicationException("Could not enable write access to jitter DLL"); - Marshal.Copy(ourCode, 0, ourCompileMethodInfo.ptrInDll, ourCode.Length); - VirtualProtect(ourCompileMethodInfo.ptrInDll, ourCode.Length, oldProtect, out oldProtect); - } - static IntPtr getJitterDllHandle() { var hJitterDll = GetModuleHandle("mscorjit"); if (hJitterDll == IntPtr.Zero) @@ -392,6 +371,7 @@ namespace de4dot.mdecrypt { uint codeRva = (uint)((byte*)info2->ILCode - (byte*)hInstModule); if (decryptMethodsInfo.moduleCctorBytes != null && moduleCctorCodeRva != 0 && moduleCctorCodeRva == codeRva) { fixed (byte* newIlCodeBytes = &decryptMethodsInfo.moduleCctorBytes[0]) { + writeCompileMethod(origCompileMethod); info2->ILCode = new IntPtr(newIlCodeBytes); info2->ILCodeSize = (uint)decryptMethodsInfo.moduleCctorBytes.Length; handled = true; @@ -470,6 +450,10 @@ namespace de4dot.mdecrypt { } public DumpedMethods decryptMethods() { + if (!canDecryptMethods()) + throw new ApplicationException("Can't decrypt methods since compileMethod() isn't hooked yet"); + installCompileMethod2(); + var dumpedMethods = new DumpedMethods(); if (decryptMethodsInfo.methodsToDecrypt == null) { @@ -561,5 +545,36 @@ namespace de4dot.mdecrypt { mem[13] = returnMethodTokenInfo.ptrInDll; // .NET 2.0 mem[14] = returnMethodTokenInfo.ptrInDll; // .NET 4.0 } + + bool hasInstalledCompileMethod2 = false; + unsafe void installCompileMethod2() { + if (hasInstalledCompileMethod2) + return; + + if (!patchDword(*(IntPtr*)jitterVtbl, 0x30000, origCompileMethod, ourCompileMethodInfo.ptrInDll)) + throw new ApplicationException("Couldn't patch compileMethod"); + + hasInstalledCompileMethod2 = true; + return; + } + + unsafe bool patchDword(IntPtr addr, int size, IntPtr origValue, IntPtr newValue) { + addr = new IntPtr(addr.ToInt64() & ~0xFFF); + var endAddr = new IntPtr(addr.ToInt64() + size); + for (; addr.ToPointer() < endAddr.ToPointer(); addr = new IntPtr(addr.ToInt64() + 0x1000)) { + try { + for (int i = 0; i < 0x1000; i += IntPtr.Size) { + var addr2 = (IntPtr*)((byte*)addr + i); + if (*addr2 == origValue) { + *addr2 = newValue; + return true; + } + } + } + catch { + } + } + return false; + } } }