【问题标题】:Thunking __stdcall function with stack adjustment带有堆栈调整的 __stdcall 函数
【发布时间】:2016-12-07 11:23:31
【问题描述】:

我想 thunk(通过调整堆栈)__stdcall 函数。例如,调用者 think is 有一个指向回调函数的指针,其原型如下:

int Func(int a);

我想编写一个 thunk(将作为回调传递)来调整对以下函数原型的调用:

int Func(char* ptr, int a);

我知道当我的 thunk 将被调用时,堆栈布局是:

------------------
|       a        |
------------------
| return address | <-- Top of the stack
------------------

我想将卡住调整为:

------------------
|       a        |
------------------
------------------
|       ptr      |
------------------
| return address | <-- Top of the stack
------------------

然后相对跳转到相关函数(这样当被调用函数返回时栈是平衡的)

这是我最后的工作(当然它必须被打包并动态加载到可执行内存),感谢 Jester 帮助汇编十六进制代码以获得所需的指令!

struct Thunk
{
    BYTE    m_popRet;
    BYTE    m_pushPtr;          
    DWORD   m_ptr;         
    BYTE    m_pushRet;         
    BYTE    m_jmp;          
    DWORD   m_relProc;      
    BOOL Init(DWORD_PTR proc, void* ptr)
    {
        m_popRet  = 0x58;       
        m_pushPtr = 0x68; 
        m_ptr     = PtrToUlong(ptr);
        m_pushRet = 0x50;
        m_jmp     = 0xE9;
        m_relProc = DWORD((INT_PTR)proc - ((INT_PTR)this + sizeof Thunk));
        return TRUE;
    }
}

【问题讨论】:

    标签: c++ assembly x86 calling-convention


    【解决方案1】:

    由于您描述了堆栈布局,因此不确定您有什么问题。 无论如何,如果您想使用JMP,您的代码可能如下所示:

    pop eax  ; 58             return address
    push ptr ; 68 xx xx xx xx
    push eax ; 50             put return address back
    jmp proc ; E9 xx xx xx xx
    

    请注意,这会改变堆栈对齐方式,因此如果您处于重要的环境中,则必须调整代码。更文明的版本可能是:

    push edx     ; 52             align stack
    push [esp+8] ; FF 74 24 08    "a"
    push ptr     ; 68 xx xx xx xx
    call proc    ; E9 xx xx xx xx
    pop edx      ; 5A
    ret 4        ; C2 04 00
    

    【讨论】:

    • 这个问题看起来很有趣,但我不明白要问什么。既然您以某种方式确定了这一点,您可能需要编辑问题。
    • @anatolyg 不确定需要清理什么?他说他想创建一个 thunk 函数,它可以作为具有原型 int Func(int a); 的回调传递,然后应该调用另一个函数 int Func(char* ptr, int a); 要做到这一点,您需要根据提供的图表 OP 更改堆栈布局。他基本上是想创建int thunk(int a) { return proc(ptr, a); }
    • 所以问题是“我的代码有什么问题”,答案是“对齐”,对吧?
    • @anatolyg 问题是我需要帮助编写 thunk 的十六进制代码才能解决问题。我的目标是做 Jester 答案的第一个变体,但我不知道如何获取给定程序集的十六进制代码
    • 当然是通过汇编程序运行它。再说一次,手动查找pushpop 的操作码也很简单。
    猜你喜欢
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    • 2019-11-22
    • 1970-01-01
    • 2014-11-13
    • 1970-01-01
    相关资源
    最近更新 更多