Calling a function in another process with parameters using CreateRemoteThread

719 views Asked by At

I want to call a function in another process in the context of the same process with parameters. For this, the CreateRemoteThread() function seems to do the job. A code example can be found e.g. here.

Note: I don't want to implement the other provided solution since this one seems nice and to the point.

When it comes to passing parameters to the function, the parameters are only received as garbage.

My function takes an int and a double as parameters:

DLL_EXPORT void show_message_dialog(const int first_value, const double second_value)
{
    const auto text = std::to_string(first_value);
    const auto caption = std::to_string(second_value);
    MessageBoxA(nullptr, text.c_str(), caption.c_str(), MB_ICONINFORMATION);
}

As far as I understood it, one needs to define a struct holding the parameters and then passing the address of the struct like this:

struct my_parameters
{
    int i;
    double d;
};

auto params = my_parameters{3, 1.1};
const auto process_id = get_process_id_from_process_name("...");
auto * const process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id);
RemoteLibraryFunction(process_handle, "my_injected_dll.dll", "show_message_dialog", &params, sizeof(my_parameters), nullptr);

The message box quite clearly shows the wrong values but my exported DLL function is implemented correctly:

Is there anything wrong with the code or is there a recommended approach to debug this issue on an assembly level? The registers do not contain the right values.

2

There are 2 answers

0
Zeus On BEST ANSWER

The message box produces incorrect values. As mentioned in the comments, you cannot modify the parameter list of the function, but use code similar to the following:

DLL_EXPORT void show_message_dialog(LPVOID *myparam)
{
    my_parameters *p = (my_parameters *)myparam
    const auto text = std::to_string(p->i);
    const auto caption = std::to_string(p->d);
    MessageBoxA(nullptr, text.c_str(), caption.c_str(), MB_ICONINFORMATION);
}

but I still want to support any type of function with multiple arguments

You don't have a better way, you need to add the added parameters to the struct, and then get the corresponding other data through the structure in the function.

struct my_parameters
{
    int i;
    double d;
    char c;
    std::string s;
    //other data
};

DLL_EXPORT void show_message_dialog(LPVOID *myparam)
{
    my_parameters* p = (my_parameters*)myparam;
    int i = p->i;
    double d = p->d;
    char c = p->c;
    std::string s = p->s;
    ......
}
1
BullyWiiPlaza On

Another way I found which allows you to truly specify any amount of parameters is to implement shellcode for setting up the parameters and the call to the function address while of course respecting the calling conventions of the platform and then the shellcode will be the function to be executed by CreateRemoteThread() instead of the actual target function. This method is more painful to fully implement but may be quite viable for some "edge cases" like only needing integer arguments.