Support AN 6.1

This commit is contained in:
de4dot 2012-07-22 18:37:14 +02:00
parent 2320c458cf
commit 09d5bd40ea

View File

@ -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;
}
}
}