0

My problem is in calling shellcode in C#. I alloc memory in the process, write there my bytes and try to call it with Marshal.GetDelegateFromFunctionPointer(). It seems working, but, only if my function doesn't have parameters. If there's any parameter there then it's value equals {Unable to read memory}. In C++ I just need to typedef func, cast it, and call. How to do this properly in C#? (Shellcode performs jump to another C# func)

8
  • Have you tried casting to a specific type of function e.g. Func<YourResponse, YourParam1, YourParam2>? Commented Jul 19, 2020 at 9:53
  • I can't cast that to Func<> with Marshal.GetDelegateFromFunctionPointer() so i cast it to delegate type, which is identical to my func public delegate void Funcd(string a); public void Func(string a) Commented Jul 19, 2020 at 10:02
  • How about with unsafe via IntPtr? Commented Jul 19, 2020 at 11:55
  • Sorry, i don't understand what u mean. I can't cast unsafe pointer to managed type (including delegates) so i use Marshal.GetDelegateFromFunctionPointer() Commented Jul 19, 2020 at 12:09
  • 1
    This sounds as a xy problem: xyproblem.info. Please explain what the goal is (x and not y) Commented Jul 19, 2020 at 12:15

1 Answer 1

1

First of all in C# you have to declare delegate with all required parameters and calling convension. When you use GetDelegateForFunctionPointer ptr is converted to a delegate that invokes the unmanaged method using the __stdcall calling convention on Windows, or the __cdecl calling convention on Linux and macOS. You can set the calling convention by applying the UnmanagedFunctionPointerAttribute to the delegate. Also you need indicate how to marshal parameters between managed and unmanaged code to achieve this you should use MarshalAsAttribute

See remarks section of Marshal.GetDelegateForFunctionPointer

and UnmanagedFunctionPointerAttribute

and MarshalAsAttribute

Example:

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern IntPtr LoadLibraryW([MarshalAs(UnmanagedType.LPWStr)] string libFileName);

[DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName);

const int MEM_COMMIT = 0x00001000;

const int PAGE_READWRITE = 0x04;

const int PAGE_EXECUTE_READ = 0x20;

[DllImport("kernel32.dll", ExactSpelling = true)]
private static extern IntPtr VirtualAlloc(IntPtr address, IntPtr size, int allocationType, int protect);

[DllImport("kernel32.dll", ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool VirtualProtect(IntPtr address, IntPtr size, int newProtect, out int oldProtect);

private delegate int GetTempPath(int nBufferLength, [MarshalAs(UnmanagedType.LPStr)] StringBuilder buffer);

static void Main(string[] args)
{
    IntPtr hModule = LoadLibraryW("c:\\windows\\system32\\kernel32.dll");

    IntPtr procAddress = GetProcAddress(hModule, "GetTempPathA");

    // allocate page with read/write access
    IntPtr page = VirtualAlloc(IntPtr.Zero, new IntPtr(4096), MEM_COMMIT, PAGE_READWRITE);
    // write to allocated memory
    // mov r11, procAddress
    Marshal.WriteByte(page, 0, 0x49);
    Marshal.WriteByte(page, 1, 0xBB);
    Marshal.WriteInt64(page, 2, procAddress.ToInt64());
    // jmp r11
    Marshal.WriteByte(page, 0xA, 0x41);
    Marshal.WriteByte(page, 0xB, 0xFF);
    Marshal.WriteByte(page, 0xC, 0xE3);
    // protect memory to allow execute code
    bool result = VirtualProtect(page, new IntPtr(4096), PAGE_EXECUTE_READ, out int oldProtect);

    var getTempPathTrampoline = Marshal.GetDelegateForFunctionPointer<GetTempPath>(page);

    StringBuilder builder = new StringBuilder(1024);

    getTempPathTrampoline(1024, builder);

    Console.WriteLine(builder.ToString());
}

Example (call managed code)

static void Main(string[] args)
{
    GetTempPath delegateToManaged = ManagedMethod;

    IntPtr managedPtr = Marshal.GetFunctionPointerForDelegate(delegateToManaged);

    // allocate page with read/write access
    IntPtr page = VirtualAlloc(IntPtr.Zero, new IntPtr(4096), MEM_COMMIT, PAGE_READWRITE);
    // write to allocated memory
    // mov r11, procAddress
    Marshal.WriteByte(page, 0, 0x49);
    Marshal.WriteByte(page, 1, 0xBB);
    Marshal.WriteInt64(page, 2, managedPtr.ToInt64());
    // jmp r11
    Marshal.WriteByte(page, 0xA, 0x41);
    Marshal.WriteByte(page, 0xB, 0xFF);
    Marshal.WriteByte(page, 0xC, 0xE3);
    // protect memory to allow execute code
    bool result = VirtualProtect(page, new IntPtr(4096), PAGE_EXECUTE_READ, out int oldProtect);

    var getTempPathTrampoline = Marshal.GetDelegateForFunctionPointer<GetTempPath>(page);

    StringBuilder builder = new StringBuilder(1024);

    getTempPathTrampoline(1024, builder);

    Console.WriteLine(builder.ToString());
}

public static int ManagedMethod(int nBufferLength, StringBuilder buffer)
{
    buffer.Append("Hello World");
    return 0;
}
Sign up to request clarification or add additional context in comments.

11 Comments

I set calling convention via UnmanagedFunctionPointer class to __stdcall and it's not working. Even __cdecl or __thiscall don't work.. [MarshalAsAttribute] doesn't works too.
@blastpolak please see example above, I hope this example helps
I don't import function, i create func by shellcode and do exactly as u say. Still doesn't works..
@blastpolak to allocate executable memory you should VirdualAlloc data page with READWRITE access, after that you should VirtualProtect the page with EXECUTE_READ access. Can you write more details how you create func?
Yes, i allocate memory and write there my shellcode then i VirtualProtect page with 0x20 (EXECUTE_READ). Shellcode (most important part of it and r11 is free): movabs r11, absoluteAddressOf1Function jmp r11
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.