在堆栈顶部搜索线程启动参数

时间:2010-10-26 09:41:38

标签: c++ assembly windows-server-2008

我继承了一些适用于Windows 2000的代码,它使用一小段汇编代码来定位堆栈的基址,然后使用偏移量来获取传递给线程启动函数的参数值。

但是,这在Windows 2008 Server中不起作用。偏移明显不同。

#define TEB_OFFSET 4
    DWORD * pStackBase;
    __asm { mov eax,fs:[TEB_OFFSET]}
    __asm { mov pStackBase,eax}

    // Read the parameter off the stack
#define PARAM_0_OF_BASE_THEAD_START_OFFSET -3
    g_dwCtrlRoutineAddr = pStackBase[PARAM_0_OF_BASE_THEAD_START_OFFSET];

经过实验,我修改了代码以查找堆栈,直到找到第一个非NULL值。的

DWORD* pStack = pStackBase;
do
{
    pStack--;
}
while (*pStack == NULL);

// Read the parameter off the stack
g_dwCtrlRoutineAddr = *pStack; 

它的作品!但我想要一个'正确的'解决方案。

有谁知道在Windows 2008 Server上将参数传递给线程的起始函数更安全/更好的解决方案?

线程启动功能是ntdll!_RtlUserThreadStart

我想找到的第一个参数是函数kernel32的地址!CtrlRoutine

3 个答案:

答案 0 :(得分:1)

怪异。查看调试器,线程堆栈上的第一个非空值是参数的值,即CreateThread的第4个参数。当您编写如下的线程程序时,会在银盘上交给您:

DWORD WINAPI threadProc(void* arg) {
    // arg is the value you are looking for
    // etc..
}

不确定这与“kernel32!CtrlRoutine”有什么关系,除非这是服务中使用的线程。

答案 1 :(得分:0)

要获取kernel32!CtrlRoutine的地址,您可以通过RVA使用包含所有(kernel32版本,CtrlRoutine RVA)对的表来获取它。这是最可靠的方式。

答案 2 :(得分:0)