-
-
[原创]Windows X64汇编入门(2)
-
发表于:
2007-5-7 22:51
30052
-
tankaiha
五一长假就要结束了,总算有时间好好睡了几个懒觉。今天醒来后想到的第一件事就是,该写第二篇了。
64位技术现在还不成熟,没有好调试器,但是我们搞技术的总是对新东西充满了好奇和热情。这个理由就足够我们现在开始学习64位汇编了!OK,Let’s go on。
1. 再说Calling convention
关于API的调用方式,在入门(1)中说了一些,不过感觉有必要再讲两点。一是在调用API时椎栈的框架,也就是Stack Frame,二是利用反汇编64位C/C++程序来研究calling convention。
先说Stack Frame。图1是一个通用的椎栈框架。
在一个使用STDCALL的32位程序中,stack frame的四项工作:
(1) 传入参数的调用;
(2) 在返回caller时,callee要负责平衡椎栈;
(3) 给局部变量提供空间;
(4) 保证ebx、esi、edi和ebp四个寄存器的值不变(这种寄存器被称为non-volatile)。
在64位环境中,少了一个平衡椎栈的任务,因为平衡椎栈的工作由caller负责了,因此callee的stack frame只剩下三项工作:
(1) 将寄存器传入的参数和其它超过4个以上的参数在椎栈上保存(入栈);
(2) 给局部变量提供空间;
(3) 保证non-volatile寄存器的值不变,包括ebp、ebx、rdi、rsi、r12到r15,xmm6到xmm15。
所以,在一个函数的开始往往有如下代码:
MOV [RSP+8h],RCX
MOV [RSP+10h],RDX
MOV [RSP+18h],R8
MOV [RSP+20h],R9
PUSH RBP
MOV RBP,RSP
而在返回时会有如下代码:
LEA RSP,[RBP]
POP RBP
RET
图2摘自GoASM的帮助文档,上文描述的情况在图中一目了然。
如果能在VC中编译64位C/C++程序,再用IDA反汇编,不是挺好的吗?正确,这正是我们玩儿逆向工程的人喜欢的方法。Visual Studio 2005的64位开发环境设置网上有,这里不多说了。以一个C/C++的代码为例:
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!