【问题标题】:Calling a function in another process with parameters using CreateRemoteThread使用 CreateRemoteThread 在另一个进程中使用参数调用函数
【发布时间】:2021-07-05 10:03:53
【问题描述】:

我想在同一个进程的上下文中用参数调用另一个进程中的函数。为此,CreateRemoteThread() 函数似乎可以完成这项工作。可以找到一个代码示例,例如here.

注意:我不想实施其他提供的解决方案,因为这个解决方案看起来不错且切中要害。

在向函数传递参数时,参数仅作为垃圾接收。

我的函数采用intdouble 作为参数:

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);
}

据我了解,需要定义一个struct 来保存参数,然后像这样传递struct 的地址:

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);

消息框非常清楚地显示了错误值,但我导出的DLL函数实现正确:

代码是否有任何问题,或者是否有推荐的方法来在程序集级别上调试此问题?寄存器不包含正确的值。

【问题讨论】:

  • 您的 show_message_dialog 函数没有 struct my_parameters * 作为其(唯一)参数。
  • 我不明白这个结构是如何变成两个参数的。您似乎省略了相当多的代码。
  • 注入器需要将 DLL 加载到目标进程中,然后将结构数据复制到远程进程,然后调用可以将该结构数据移动到调用堆栈的远程函数,然后调用目标DLL函数。完成所有这些工作需要做很多工作。比这个问题所暗示的要多得多。
  • @DavidHeffernan:我没有省略任何相关代码,我指的是上面链接上发布的RemoteLibraryFunction()。它处理将参数写入目标进程。如果这还不够或不正确,最好有一个完整的例子,将结构数据写入调用堆栈。如果不支持像我的示例导出函数中的多个参数,那也很高兴知道。我只想拥有一个具有参数支持的通用远程库函数,以至少涵盖基本参数类型。我不明白投反对票的原因。
  • 您了解函数调用是如何在您设想的目标架构上实现的吗?

标签: c++ winapi parameters rpc createremotethread


【解决方案1】:

消息框产生不正确的值。 cmets中提到,不能修改函数的参数列表,可以使用类似如下的代码:

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);
}

但我仍然想支持任何类型的具有多个参数的函数

你没有更好的办法,需要将添加的参数添加到struct,然后通过函数中的结构体获取对应的其他数据。

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

【讨论】:

    【解决方案2】:

    我发现的另一种允许您真正指定任意数量的参数的方法是实现 shellcode 以设置参数和调用函数地址,同时当然尊重 calling conventions of the platform 然后 shellcode 将成为函数由CreateRemoteThread() 执行,而不是实际的目标函数。这种方法完全实现起来比较痛苦,但对于一些“边缘情况”来说可能是相当可行的,比如只需要integer arguments

    【讨论】:

    • 很高兴您得到了解决方案,感谢您的分享,如果您将它们标记为答案,我将不胜感激,这将对其他社区有益。
    猜你喜欢
    • 1970-01-01
    • 2013-03-23
    • 1970-01-01
    • 2020-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多