Search code examples
c++winapiparametersrpccreateremotethread

Calling a function in another process with parameters using CreateRemoteThread


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.


Solution

  • 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;
        ......
    }