2014-01-23 83 views
1

我在Win32上编写了一个模拟可执行程序的X86应用程序级模拟器,并将它的API调用挂接,并将它们转发给我的回调函数。 在这些回调我打印一些调试东西,然后调用实际的API,每个回调是一样的东西:模拟printf堆栈弹出

int hook_MessageBoxA(emu_t *emu, mem_t *mem) 
{ 
    char *pszText, *pszTitle; 
    DWORD hwnd, text, title, button; 

    // pop arguments from the stack 
    STACK_POP(emu, &hwnd); 
    STACK_POP(emu, &text); 
    STACK_POP(emu, &title); 
    STACK_POP(emu, &button); 

    // read actual strings from process memory 
    mem_read(mem, text, &pszText, 256); 
    mem_read(mem, title, &pszTitle, 256); 

    printf("* MessageBoxA(%p, %s, %s, %d)\n", hwnd, pszText, pszTitle, button); 

    // call the real API 
    int ret = MessageBoxA(hwnd, pszText, pszTitle, button); 

    // store return value into EAX register 
    emu->regs->eax = ret; 

    return 0; 
} 

这是工作完美每一个API,但我有挂钩里面MSVCRT的的printf API,因为问题除了szFormat之外,我不知道有多少参数需要从堆栈中弹出。 如何确定我必须弹出的参数数量? printf的东西如何工作低水平?

感谢

回答

3

你不需要弹出printf()的论点,如果你不把它们堆在首位。

无论调用约定,所有可变参数函数都是调用者清理的,所以他们读取它们的参数而不会弹出它们。

+0

好的,一半的问题解决了,那么我怎么知道有多少参数被压入堆栈,所以我可以读取它们(没有弹出,这只是一个regs-> esp + = 4;)并将它们打印出来用于调试目的? –

+2

@SimoneMargaritelli你必须以同样的方式做printf - 通过检查其各种%元素的格式字符串。 – mah

+2

为此,恐怕唯一的办法就是像printf()那样做:解析格式字符串。请记住,“long long”和“double”参数需要两个单词,因此您不能只计算未转义的百分号:您实际上必须读取格式才能确定类型。 – Medinoc