2

I want to call a function inside another process and send more then 1 argument through createremotethread.

Now, I could do that by sending inline asm but I don't know enough assembly in order to do it that way. Also I don't have any access to the remote process source-code.

I was thinking about using:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct RemoteThreadParams
{
    [MarshalAs(UnmanagedType.I4)]
    public int Param1;

    [MarshalAs(UnmanagedType.I4)]
    public int Param2;

}

but from what I understand, the remote process must know how to handle that.

Is there a easy way to send more then 1 argument to the remote process which doesn't include any assembly?

EDIT:

This is how I'm trying to solve it at the moment but i get out of memory exception and I really don't understand what I'm doing wrong.

We have our function ptr at 0x64D480 in the remote process, this is the assembly taken from IDA pro.

// FUNCTION PTR IS 0x64D480
.text:0064D480 sub_64D480      proc near               ; CODE XREF: sub_4DA7F0+3Ap
.text:0064D480                                         ; sub_64D550+Bp ...
.text:0064D480
.text:0064D480 var_C           = dword ptr -0Ch // arg1
.text:0064D480 arg_0           = dword ptr  4 // arg2
.text:0064D480
.text:0064D480                 push    esi
.text:0064D481                 push    edi
.text:0064D482                 mov     edi, [esp+8+arg_0]
.text:0064D486                 push    edi
.text:0064D487                 mov     esi, ecx
.text:0064D489                 call    sub_64D330
.text:0064D48E                 test    al, al
.text:0064D490                 jnz     short loc_64D497
.text:0064D492                 pop     edi
.text:0064D493                 pop     esi
.text:0064D494                 retn    4  

Shouldn't it be possible to call the function this way:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct RemoteThreadParams
{
    [MarshalAs(UnmanagedType.I4)]
    public int Param1;

    [MarshalAs(UnmanagedType.I4)]
    public int Param2;

}  

void CallFunction(IntPtr _functionPtr, RemoteThreadParams _parameters)
{
    // Allocate some native heap memory in your process big enough to store the parameter data
    IntPtr iptrtoparams = Marshal.AllocHGlobal(Marshal.SizeOf(_parameters));

    // Copies the data in your structure into the native heap memory just allocated
    Marshal.StructureToPtr(_parameters, iptrtoparams, false);
    // Use to alloc "committed" memory that is addressable by other process
    IntPtr iptrremoteallocatedmemory = VirtualAllocEx(this.handle, IntPtr.Zero, (uint)Marshal.SizeOf(_parameters), AllocationType.Commit, MemoryProtection.ExecuteReadWrite);
    UIntPtr bytesWritten = UIntPtr.Zero;
    // Copy from local process memory to the memory of the remote process
    WriteProcessMemory(this.handle, iptrremoteallocatedmemory, iptrtoparams, (uint)Marshal.SizeOf(_parameters), out bytesWritten);
    //Free up memory
    Marshal.FreeHGlobal(iptrtoparams);

    //thread id and return value in case we need it for later
    uint iThreadId;
    uint returnValue = 0;

    IntPtr hThread = CreateRemoteThread(this.handle, IntPtr.Zero, 0, _functionPtr, iptrtoparams, 0, out iThreadId);

    WaitForSingleObject(hThread, 0xFFFFFFFF);
    GetExitCodeThread(hThread, out returnValue);

    CloseHandle(hThread);
    CloseHandle(this.handle);
}  
basd bfnsa
  • 81
  • 1
  • 10
  • This is just routine injection. I cannot understand what's special. Pick an injection technique and move on. – David Heffernan Oct 09 '14 at 07:10
  • Ok lets say for example that i have a function pointer in the remote process at: 0x64D480 which takes two arguments: .text:0064D480 var_C = dword ptr -0Ch .text:0064D480 arg_0 = dword ptr 4 and the process is running unmanaged code, how can i call that function and send those two arguments from my C# app? – basd bfnsa Oct 09 '14 at 20:13
  • Mind sending me a link to one of those countless examples? :) – basd bfnsa Oct 09 '14 at 20:19
  • Care to take a look at the updated post? I don't want you to waste your time though :) thanks in advance – basd bfnsa Oct 09 '14 at 20:56
  • You aren't checking any return values, so your function calls may fail. Don't know what `this.handle` is. The function that you are calling doesn't have the correct signature. It expects two parameters, but a thread function is passed one. And I can't tell what the calling convention of the function is. Do you know? Why don't you do this in native code? Write a DLL that does what you need, and inject it. – David Heffernan Oct 09 '14 at 21:24

2 Answers2

1

I dont think that this will help but:

You can actually call native methods (as you may already know) using e.g.

public static extern Foo (Bar argument);
public void Main()
{
    Foo(new Bar());
}

Furthermore you actually can do is read and manipulate the data an application is storing in the RAM this is what most "Game trainers" do so this might help you: http://forum.cheatengine.org/viewtopic.php?t=530207

M4GNV5
  • 59
  • 2
  • 8
  • But using native methods requires DLL imports from the process doesn't it? – basd bfnsa Oct 08 '14 at 20:45
  • No Afaik you cannot import not-.net-dlls (.dll files that are native etc. and dont contain a managed .net assembly) EDIT: wait do you mean the [DllImport] yes it requires you to programatically import dlls but not set them as a reference to your project what i meant above. Also see http://msdn.microsoft.com/en-us/library/e59b22c5.aspx – M4GNV5 Oct 08 '14 at 20:48
1

There is no easy way. The easiest way is to do this with LoadLibrary and unmanaged code. You need two versions: 32-bit dll and 64-bit dll, you choose which one to inject based on the target process "bitness".

CreateRemoteThread(....., Address of LoadLibrary,   "location of your unmanaged dll");

you'll find the references in Internet when you google C# CreateRemoteThread LoadLibrary.

After that, you then want the custom dll to do function calling:

#include "stdafx.h"

typedef void (__stdcall *MyCustomFunc)(int param1, int param2);

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        {
            // this code is executed arbitrarily. 
            // this is just a test,
            // you're better off writing a separate function in a DLL
            // and export it, so you can later call it from C#, once DLL is injected.
            MyCustomFunc test = 0x64D480;
            test(2, 4);
        }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

ps, you also need FreeLibrary if needed. It's also important to get the calling convention right. I am going out on a limb here, and say that it looks like __stdcall, but it might be __cdecl, or __fastcall, or whatever. See: http://www.codeproject.com/Articles/1388/Calling-Conventions-Demystified for more info.

Erti-Chris Eelmaa
  • 25,338
  • 6
  • 61
  • 78