【问题标题】:Could I create a function based on another function at runtime?我可以在运行时基于另一个函数创建一个函数吗?
【发布时间】:2011-04-16 14:30:37
【问题描述】:

我在玩微软的Detours去hook api,比如我可以改变MessageBoxA时发生的事情 是这样调用的:

  int (WINAPI* pMessageBoxA)(HWND, LPCTSTR, LPCTSTR, UINT) = MessageBoxA;

  int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
  {
      printf("A function is called here!\n");
      return pMessageBoxA(hWnd, lpText, lpCaption, uType);  // call the regular MessageBoxA
  }

  DetourTransactionBegin();
  DetourUpdateThread(GetCurrentThread());
  DetourAttach(&(PVOID&)pMessageBoxA, MyMessageBoxA); 

所以当你打电话给MessageBoxA时,你实际上是在打电话给MyMessageBoxA
现在我想写一个函数Hook(),它会做上面的代码在运行时做的事情。例如,如果我将函数指针 MessageBoxA 传递给函数,它将完全按照上面的代码执行。
当然,我也可以将其他函数指针传递给它。
那么有一个问题,当我在Hook中得到一个函数指针时,如何定义一个与给定函数具有相同返回值和参数的函数(本例中为MessageBoxAint WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType))然后填充函数的函数体?

【问题讨论】:

  • 听起来您正在寻找 eval() - 动态类型语言的圣杯。但它在 C++ 中不可用。当然,您可以将函数写入文件,调用编译器以生成可加载库,加载它,获取指向函数的指针。
  • 听起来你想挂钩整个 Win32 API。要使用 Detours 做到这一点,您需要为每个 API 函数生成存根。您可以在运行时执行此操作,但它会涉及运行时代码生成。这是可能的,但在 C++ 中自然比在 Python、.net 等中要困难一些。由于您不想为所有 API 函数生成存根,因此您陷入了僵局。也许你可以告诉我们你的最终目标。例如,您是否尝试检测您的应用对 Win32 API 的使用?
  • @David 我想要做什么:首先,从程序的 exe 文件中获取程序将使用的所有 api,然后将这些函数与将打印函数名称的新函数挂钩,所以我可以得到程序中如何调用api的序列,然后利用这些信息做一些安全检查
  • @wong2 如何获得程序使用的所有 API?并非所有函数都在导入表中。你将如何挂钩那些你不知道调用约定和参数列表的函数?
  • @David 是的,这是一个大问题......但我认为恶意软件总是会调用系统 API 来执行诸如扫描磁盘、连接到网络等操作,所以我认为可能只是挂钩系统api就足够了。你怎么看?

标签: c++ windows detours


【解决方案1】:

在 C++ 中,函数不是 first-class object,这意味着它们不能在运行时创建。

但是,您可以使用函数指针数组,每个指针指向一个已定义的函数,并在运行时根据某些条件选择适当的函数指针,然后调用它。看起来您已经在 code-sn-p 中使用了函数指针。

【讨论】:

  • 我无法创建一个预定义的函数指针数组……API函数太多了……
  • @wong2:你的问题不够清楚。根据我对您问题的措辞的理解,我只能说不能在运行时用 C++ 创建函数。
【解决方案2】:

这并不完全正确。您可以轻松地存储一个(成员)函数引用,这样您就可以让一个函数调用另一个函数(可在运行时确定)。

您还可以使用functor,它是一个结构/类,用于加载 () 运算符。然后,这可以使用类的状态来记住要调用的实际函数。一个仿函数的例子:

STL 有一个<functional> 标头,其中包含大量有用的实用程序,可以使处理(成员)函数引用“更容易”(稍微)。来自cplusplus.com的随机示例:

// mem_fun example
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

int main () 
{
  vector <string*> numbers;

  // populate vector of pointers:
  numbers.push_back ( new string ("one") );
  numbers.push_back ( new string ("two") );
  numbers.push_back ( new string ("three") );
  numbers.push_back ( new string ("four") );
  numbers.push_back ( new string ("five") );

  vector <int> lengths ( numbers.size() );

  transform (numbers.begin(), numbers.end(), lengths.begin(), mem_fun(&string::length));

  for (int i=0; i<5; i++) {
      cout << *numbers[i] << " has " << lengths[i] << " letters.\n";
  }
  return 0;
}

c++0x 有很多漂亮的新功能(包括“自动”类型推断和 lambda 表达式),这将使这一切变得更容易

【讨论】:

    猜你喜欢
    • 2010-10-17
    • 2020-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多