28

Continuing my reverse engineering education I've often wanted to be able to copy portions of x86 assembly code and call it from a high level language of my choice for testing.

Does anyone know of a method of calling a sequence of x86 instructions from within a C# method? I know that this can be done using C++ but I'm curious if it can be done in C#?

Note: I'm not talking about executing MSIL instructions. I'm talking about executing a series of raw x86 assembly instructions.

0

5 Answers 5

49

Just to counter Brian's claim, rewritten code from leppie's answer link:

using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace DynamicX86 { class Program { const uint PAGE_EXECUTE_READWRITE = 0x40; const uint MEM_COMMIT = 0x1000; [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); private delegate int IntReturner(); static void Main(string[] args) { List<byte> bodyBuilder = new List<byte>(); bodyBuilder.Add(0xb8); bodyBuilder.AddRange(BitConverter.GetBytes(42)); bodyBuilder.Add(0xc3); byte[] body = bodyBuilder.ToArray(); IntPtr buf = VirtualAlloc(IntPtr.Zero, (uint)body.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE); Marshal.Copy(body, 0, buf, body.Length); IntReturner ptr = (IntReturner)Marshal.GetDelegateForFunctionPointer(buf, typeof(IntReturner)); Console.WriteLine(ptr()); } } } 
Sign up to request clarification or add additional context in comments.

6 Comments

Cool! I was thinking an external dll would still be needed, but I stand corrected :)
Make sure to use a Finally block to free the memory, but that works (and is terrifying :) )
I wanted to keep example as small as possible.
Wow, nice. I think Cthulon's method is easier, though.
@radashk my Windows 7 based system doesn't restrict it. Try to exec program with administration rights. Author, thank you for intresting code, question to favourites)
|
6

Yes, see my detailed answer here
The main part is: (Without any P/Invoke or external reference)

public static unsafe int? InjectAndRunX86ASM(this Func<int> del, byte[] asm) { if (del != null) fixed (byte* ptr = &asm[0]) { FieldInfo _methodPtr = typeof(Delegate).GetField("_methodPtr", BindingFlags.NonPublic | BindingFlags.Instance); FieldInfo _methodPtrAux = typeof(Delegate).GetField("_methodPtrAux", BindingFlags.NonPublic | BindingFlags.Instance); _methodPtr.SetValue(del, ptr); _methodPtrAux.SetValue(del, ptr); return del(); } else return null; } 

Which can be used as follows:

Func<int> del = () => 0; byte[] asm_bytes = new byte[] { 0xb8, 0x15, 0x03, 0x00, 0x00, 0xbb, 0x42, 0x00, 0x00, 0x00, 0x03, 0xc3 }; // mov eax, 315h // mov ebx, 42h // add eax, ebx // ret int? res = del.InjectAndRunX86ASM(asm_bytes); // should be 789 + 66 = 855 

EDIT: The newest version of C# (C#9) introduces the concept of 'delegate pointers', which allows you to do the following:

byte[] asm = { 0x8D, 0x04, 0x11, // lea eax, [rcx+rdx] 0xC3 // ret }; void* buffer = VirtualAlloc(null, asm.Length, 0x1000, 4); var func = (delegate*<int, int, int>)buffer; int dummy; Marshal.Copy(asm, 0, (nint)buffer, asm.Length); VirtualProtect(buffer, asm.Length, 0x20, &dummy); Console.WriteLine(func(42, 378)); // call 'func' with (42, 378), which computes '420' VirtualFree(buffer, 0, 0x8000); 

You can find a complete example here: https://gist.github.com/Unknown6656/a42a810d4283208c3c21c632fb16c3f9

3 Comments

Are the Virtual* calls really necessary? Could the POH be used, instead?
I think they are necessary as you need to allocate a dedicated memory page and flag it as 'executable'. That's not possible to do using a simple heap- or stack allocation. Thus, you cannot simply use a fixed array, stackalloc, or the POH.
It makes sense that arbitrary bytes cannot just be executed. It's just that InjectAndRunX86ASM method appears to not have this limitation.
0

I believe, you can add a managed C++ project to your solution and expose method with usage of asm instructions. You can reference that project from any .Net project (not just C#), so you can call that method from there.

Comments

0

Yes.

Just use P/Invoke on winapi functions.

WriteProcessMemory or find the pointer to your buffer. Enable the execute bit on page (don't remember the function for this).

CreateThread on the pointer. WaitForObject (if you want it to be single threaded).

Comments

-1

No, but you can write assembly in C++ and call it from C#. See this example.

2 Comments

If you can write an unmanaged C++ assembly and call it from c#, could you not also call assembly from the c++ assembly? OMG I've got a headache...
Ummm, isn't that what I just said?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.