如何在C ++中的另一个地址空间中调用函数

时间:2011-11-29 08:49:31

标签: c++ security

我知道这可能导致的线程问题及其危险,但我需要知道如何为我在学校做的安全项目做这件事。我需要知道如何使用参数调用给定调用约定的远程地址空间中的函数 - 最好是恢复远程函数返回的数据,尽管我真的不需要它。

如果我可以在编译时从远程函数的函数原型获取细节,我将能够使这个方法工作。我需要知道参数有多大以及参数是否明确声明为指针(void*, char*, int*, etc...)

即如我定义了一个函数原型,如:

typedef void (__cdecl *testFunc_t)(int* pData);

在编译时,我需要至少获得参数的大小,如果可以的话,哪些是指针或不是。在这里,我们假设远程功能是stdcall_cdecl呼叫。

我使用的IDE是Microsoft Visual Studio 2007,以防该解决方案特定于特定产品。

这是我的计划:

  1. 在想要调用的函数的原点使用CreateRemoteThread在远程进程中创建一个线程,但我会在挂起状态下执行此操作。

  2. 我会设置堆栈,使得返回地址是在调用ExitThread(eax)的进程内部分配的代码存根的地址 - 因为这将使用函数的返回值退出线程 - I然后通过使用GetExitCodeThread

  3. 来恢复它
  4. 我还会将函数调用的参数从我的本地堆栈复制到新创建的线程 - 我需要知道函数参数是指针和参数的大小。

  5. 恢复线程并等待它退出,此时我将返回调用者,线程退出代码。

  6. 我知道这应该在编译时可行但是编译器是否有一些我可以使用的方法,我不确定。我也知道所有这些数据都可以从编译代码后创建的PDB文件中轻松恢复,并且如果编译器执行优化,参数的大小可能会改变。我不需要被告知这是多么危险,因为我完全了解它,但这不是商业产品,而是我必须为学校做的一个小项目。

    问题: 如果我有一个功能原型,如 typedef void(__ cdecl testFunc_t)(int pData);

    无论如何,我可以在编译时获得这个原型参数的大小(即在上面的例子中,参数总和为sizeof(int *)的总大小。例如,我有一个类似的函数:

    template<typename T> unsigned long getPrototypeArgLength<T>()
    { 
       //would return size of arguments described in the prototype T 
    } 
    
    //when called as
    
    getPrototypeArgLength<testFunc>()
    

2 个答案:

答案 0 :(得分:1)

这看起来像是一个学校项目...

  1. 对于第3步,您可以使用ReadProcessMemory / WriteProcessMemory(其中之一)。例如,新线程可以在线程创建期间接收开始(开始和结束)上的参数的地址(在调用进程上)。然后它可以从该区域读取调用者进程内存并将其复制到自己的堆栈。

  2. 您是否考虑过将COM用于整个事情?如果你使用专门为此设计的机制,你可能会更容易完成任务。

答案 1 :(得分:1)

好吧,我发现我可以使用BOOST库在编译时获取大量类型信息。具体来说,我使用boost :: function_traits但是,如果你环顾一下boost库,你会发现你可以恢复很多信息。以下是我编写的一些代码,用于演示如何获取函数原型的参数数量。

(实际上,我没有测试下面的代码,它只是我从另一个我制作和测试的函数中抛出的东西。)

template<typename T>
unsigned long getArgCount()
{
    return boost::function_traits<boost::remove_pointer<T>::type>::arity;
}

void (*pFunc)(int, int);

2 = getArgCount<BOOST_TYPEOF(pFunc)>();