/// <summary> /// See base class documentation. /// </summary> /// <param name="anILOpInfo">See base class documentation.</param> /// <param name="aScannerState">See base class documentation.</param> /// <returns>See base class documentation.</returns> public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState) { StringBuilder result = new StringBuilder(); //Load the metadata token used to get the type info int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0); //Get the type info for the element type Type elementType = aScannerState.CurrentILChunk.Method.Module.ResolveType(metadataToken); //New array must: // - Allocate memory on the heap for the object // - If no memory is left, throw a panic attack because we're out of memory... // - Call the specified constructor //The label to jump to if allocated memory isn't null //i.e. not out of memory. string NotNullLabel = string.Format("{0}.IL_{1}_NotNullMem", aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method), anILOpInfo.Position); //Attempt to allocate memory on the heap for the new array //This involves: // - (Number of elements is already on the stack) // - Pushing the element type reference onto the stack // - Calling GC NewArr method // - Check the pointer == 0, if so, out of memory //Push type reference string typeIdStr = aScannerState.GetTypeIdString(aScannerState.GetTypeID(elementType)); result.AppendLine(string.Format("push dword {0}", typeIdStr)); //Push a dword for return value (i.e. new array pointer) result.AppendLine("push dword 0"); //Get the GC.NewArr method ID (i.e. ASM label) string methodLabel = aScannerState.GetMethodID(aScannerState.NewArrMethod); //Call GC.NewArr result.AppendLine(string.Format("call {0}", methodLabel)); //Pop the return value (i.e. new array pointer) result.AppendLine("pop dword eax"); //Remove args from stack result.AppendLine("add esp, 8"); //Check if pointer == 0? result.AppendLine("cmp eax, 0"); //If it isn't 0, not out of memory so continue execution result.AppendLine(string.Format("jnz {0}", NotNullLabel)); //If we are out of memory, we have a massive problem //Because it means we don't have space to create a new exception object //So ultimately we just have to throw a kernel panic //Throw a panic attack... ( :/ ) by calling kernel Halt(uint lastAddress) //result.AppendLine("call GetEIP"); //result.AppendLine("push dword esp"); //result.AppendLine("push dword ebp"); //result.AppendLine("pushad"); //result.AppendLine("mov dword eax, 0xDEADBEEF"); //result.AppendLine("mov dword ebx, 0x2"); //result.AppendLine("mov dword ecx, 1"); //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_GC_Enabled], 1"); //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_Heap_PreventAllocation], 0"); //result.AppendLine("jmp method_System_Void_RETEND_Kernel_PreReqs_DECLEND_PageFaultDetection_NAMEEND___Fail"); result.AppendLine("call GetEIP"); result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.HaltMethod))); //Insert the not null label result.AppendLine(NotNullLabel + ":"); //Push new array pointer result.AppendLine("push dword eax"); aScannerState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isNewGCObject = true, isGCManaged = true }); return result.ToString().Trim(); }
/// <summary> /// See base class documentation. /// </summary> /// <param name="anILOpInfo">See base class documentation.</param> /// <param name="aScannerState">See base class documentation.</param> /// <returns>See base class documentation.</returns> public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState) { StringBuilder result = new StringBuilder(); MethodBase constructorMethod = anILOpInfo.MethodToCall; Type objectType = constructorMethod.DeclaringType; //New obj must: // - Ignore for creation of Delegates // - Allocate memory on the heap for the object // - If no memory is left, throw a panic attack because we're out of memory... // - Call the specified constructor if (typeof(Delegate).IsAssignableFrom(objectType)) { result.AppendLine("; Ignore newobj calls for Delegates"); //Still need to: // - Remove the "object" param but preserve the "function pointer" GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", 0, (OpCodes)anILOpInfo.opCode.Value); result.AppendLine("mov dword eax, [esp]"); GlobalMethods.InsertPageFaultDetection(result, aScannerState, "esp", 4, (OpCodes)anILOpInfo.opCode.Value); result.AppendLine("mov dword [esp+4], eax"); result.AppendLine("add esp, 4"); return result.ToString().Trim(); } //The label to jump to if allocated memory isn't null //i.e. not out of memory. string NotNullLabel = string.Format("{0}.IL_{1}_NotNullMem", aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method), anILOpInfo.Position); //Attempt to allocate memory on the heap for the new object //This involves: // - Pushing the type reference onto the stack // - Calling GC NewObj method // - Check the pointer == 0, if so, out of memory //Push type reference string typeIdStr = aScannerState.GetTypeIdString(aScannerState.GetTypeID(objectType)); result.AppendLine(string.Format("push dword {0}", typeIdStr)); //Push a dword for return value (i.e. new object pointer) result.AppendLine("push dword 0"); //Get the GC.NewObj method ID (i.e. ASM label) string methodLabel = aScannerState.GetMethodID(aScannerState.NewObjMethod); //Call GC.NewObj result.AppendLine(string.Format("call {0}", methodLabel)); //Pop the return value (i.e. new object pointer) result.AppendLine("pop dword eax"); //Remove arg 0 from stack result.AppendLine("add esp, 4"); //Check if pointer == 0? result.AppendLine("cmp eax, 0"); //If it isn't 0, not out of memory so continue execution result.AppendLine(string.Format("jnz {0}", NotNullLabel)); //If we are out of memory, we have a massive problem //Because it means we don't have space to create a new exception object //So ultimately we just have to throw a kernel panic //Throw a panic attack... ( :/ ) by calling kernel Halt(uint lastAddress) //result.AppendLine("call GetEIP"); //result.AppendLine("push dword esp"); //result.AppendLine("push dword ebp"); //result.AppendLine("pushad"); //result.AppendLine("mov dword eax, 0xDEADBEEF"); //result.AppendLine("mov dword ebx, 0x1"); //result.AppendLine("mov dword ecx, 1"); //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_GC_Enabled], 1"); //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_Heap_PreventAllocation], 0"); //result.AppendLine("jmp method_System_Void_RETEND_Kernel_PreReqs_DECLEND_PageFaultDetection_NAMEEND___Fail"); result.AppendLine("call GetEIP"); result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(aScannerState.HaltMethod))); //Insert the not null label result.AppendLine(NotNullLabel + ":"); //Call the specified constructor //This involves: // - Push empty dword onto stack // - Move all args down by one dword // - Move object reference into dword as first arg // - Call constructor result.AppendLine("push dword 0"); int sizeOfArgs = 0; ParameterInfo[] allParams = constructorMethod.GetParameters(); foreach(ParameterInfo aParam in allParams) { sizeOfArgs += Utils.GetNumBytesForType(aParam.ParameterType); aScannerState.CurrentStackFrame.Stack.Pop(); } result.AppendLine("mov dword ebx, esp"); if (sizeOfArgs > 0) { if (sizeOfArgs % 4 != 0) { throw new InvalidOperationException("sizeOfArgs not exact multiple of 4!"); } result.AppendLine(string.Format("mov dword ecx, {0}", sizeOfArgs / 4)); string ShiftArgsLoopLabel = string.Format("{0}.IL_{1}_ShiftArgsLoop", aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method), anILOpInfo.Position); result.AppendLine(ShiftArgsLoopLabel + ":"); GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", 4, (OpCodes)anILOpInfo.opCode.Value); result.AppendLine("mov dword edx, [ebx+4]"); GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", 0, (OpCodes)anILOpInfo.opCode.Value); result.AppendLine("mov dword [ebx], edx"); result.AppendLine("add ebx, 4"); result.AppendLine(string.Format("loop {0}", ShiftArgsLoopLabel)); } GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", 0, (OpCodes)anILOpInfo.opCode.Value); result.AppendLine("mov dword [ebx], eax"); result.AppendLine(string.Format("call {0}", aScannerState.GetMethodID(constructorMethod))); //Only remove args from stack - we want the object pointer to remain on the stack result.AppendLine(string.Format("add esp, {0}", sizeOfArgs)); aScannerState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isNewGCObject = true, isGCManaged = true }); return result.ToString().Trim(); }
/// <summary> /// See base class documentation. /// </summary> /// <param name="anILOpInfo">See base class documentation.</param> /// <param name="aScannerState">See base class documentation.</param> /// <returns>See base class documentation.</returns> public override string Convert(ILOpInfo anILOpInfo, ILScannerState aScannerState) { StringBuilder result = new StringBuilder(); string Label_3 = string.Format("{0}.IL_{1}_Point3", aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method), anILOpInfo.Position); string Label_False1 = string.Format("{0}.IL_{1}_False1", aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method), anILOpInfo.Position); string Label_False2 = string.Format("{0}.IL_{1}_False2", aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method), anILOpInfo.Position); string Label_End = string.Format("{0}.IL_{1}_End", aScannerState.GetMethodID(aScannerState.CurrentILChunk.Method), anILOpInfo.Position); // Test if the object provided inherits from the specified class // 1. Pop object ref // 1.1. Test if object ref is null: // 1.1.1 True: Push null and continue // 1.1.2 False: Go to 2 // 2. Load object type // 3. Test if object type == provided type: // 3.1 True: Push object ref and continue // 3.2 False: // 3.2.1. Move to base type // 3.2.2. Test if base type null: // 3.2.2.1 True: Push null and continue // 3.2.2.2 False: Jump back to (3) // 1. Pop object ref result.AppendLine("pop dword eax"); // 1.1. Test if object ref is null: result.AppendLine("cmp eax, 0"); result.AppendLine("jne " + Label_False1); // 1.1.1 True: Push null and continue result.AppendLine("push dword 0"); result.AppendLine("jmp " + Label_End); // 1.1.2 False: Go to 2 result.AppendLine(Label_False1 + ":"); // 2. Load object type GlobalMethods.InsertPageFaultDetection(result, aScannerState, "eax", 0, (OpCodes)anILOpInfo.opCode.Value); result.AppendLine("mov dword ebx, [eax]"); // 3. Test if object type == provided type: int metadataToken = Utils.ReadInt32(anILOpInfo.ValueBytes, 0); Type theType = aScannerState.CurrentILChunk.Method.Module.ResolveType(metadataToken); string TestTypeId = aScannerState.GetTypeIdString(aScannerState.GetTypeID(theType)); result.AppendLine("mov dword ecx, " + TestTypeId); result.AppendLine(Label_3 + ":"); result.AppendLine("cmp ebx, ecx"); result.AppendLine("jne " + Label_False2); // 3.1 True: Push object ref and continue result.AppendLine("push dword eax"); result.AppendLine("jmp " + Label_End); // 3.2 False: result.AppendLine(Label_False2 + ":"); // 3.2.1. Move to base type int baseTypeOffset = aScannerState.GetTypeFieldOffset("TheBaseType"); GlobalMethods.InsertPageFaultDetection(result, aScannerState, "ebx", baseTypeOffset, (OpCodes)anILOpInfo.opCode.Value); result.AppendLine(string.Format("mov dword ebx, [ebx+{0}]", baseTypeOffset)); // 3.2.2. Test if base type null: result.AppendLine("cmp ebx, 0"); // 3.2.2.2 False: Jump back to (3) result.AppendLine("jne " + Label_3); // 3.2.2.1 True: Push null and continue result.AppendLine("push dword 0"); result.AppendLine(Label_End + ":"); return result.ToString().Trim(); }