2014-01-23 120 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