| //pop ecx,Proc已压栈,弹出Proc到ecx thunk->Code[0] = 0x59; //pop ecx //mov dword ptr [esp+0x4],this //Proc已弹出,栈顶是返回地址,紧接着就是HWND了。 //[esp+0x4]就是HWND thunk->Code[1] = 0xC7; // mov thunk->Code[2] = 0x44; // dword ptr thunk->Code[3] = 0x24; // disp8[esp] thunk->Code[4] = 0x04; // +4 thunk->Window = this; //偷梁换柱成功!跳转到Proc //jmp [ecx] thunk->Jmp = 0xFF; // jmp [r/m]32 thunk->ECX = 0x21; // [ecx] m_thunk = (WNDPROC)thunk; return m_thunk; } |
这样m_thunk虽然是一个结构,但其数据是一段可执行的代码,而其类型又是WNDPROC,系统就会忠实地按窗口过程规则调用这段代码,m_thunk就把Window字段里记录的this指针替换掉堆栈中的hWnd参数,然后跳转到静态的stdProc:
| //本回调函数的HWND调用之前已由m_thunk替换为对象指针 LRESULT WINAPI CMyWnd::stdProc(HWND hWnd,UINT uMsg,UINT wParam,LONG lParam) { CMyWnd* w = (CMyWnd*)hWnd; return w->WindowProc(uMsg,wParam,lParam); } |
这样就把窗口过程转向到了类成员函数WindowProc,当然这样还有一个问题,就是窗口句柄hWnd还没来得及记录,因此一开始的窗口过程应该先定位到静态的InitProc,CreateWindow的时候给最后一个参数,即初始化参数赋值为this指针:
| CreateWindowEx( dwExStyle, szClass, szTitle, dwStyle, x, y, width, height, hParentWnd, hMenu, hInst, |
|