Windows X86-64位汇编语言入门教学内容.doc

上传人:1595****071 文档编号:51557394 上传时间:2022-10-18 格式:DOC 页数:26 大小:485.50KB
返回 下载 相关 举报
Windows X86-64位汇编语言入门教学内容.doc_第1页
第1页 / 共26页
Windows X86-64位汇编语言入门教学内容.doc_第2页
第2页 / 共26页
点击查看更多>>
资源描述

《Windows X86-64位汇编语言入门教学内容.doc》由会员分享,可在线阅读,更多相关《Windows X86-64位汇编语言入门教学内容.doc(26页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、Good is good, but better carries it.精益求精,善益求善。Windows X86-64位汇编语言入门-WindowsX86-64位汇编语言入门WindowsX64汇编入门(1)最近断断续续接触了些64位汇编的知识,这里小结一下,一是阶段学习的回顾,二是希望对64位汇编新手有所帮助。我也是刚接触这方面知识,文中肯定有错误之处,大家多指正。文章的标题包含了本文的四方面主要内容:(1)Windows:本文是在windows环境下的汇编程序设计,调试环境为WindowsVista64位版,调用的均为windowsAPI。(2)X64:本文讨论的是x64汇编,这里的x6

2、4表示AMD64和Intel的EM64T,而不包括IA64。至于三者间的区别,可自行搜索。(3)汇编:顾名思义,本文讨论的编程语言是汇编,其它高级语言的64位编程均不属于讨论范畴。(4)入门:既是入门,便不会很全。其一,文中有很多知识仅仅点到为止,更深入的学习留待日后努力。其二,便于类似我这样刚接触x64汇编的新手入门。本文所有代码的调试环境:WindowsVistax64,IntelCore2Duo。1.建立开发环境1.1编译器的选择对应于不同的x64汇编工具,开发环境也有所不同。最普遍的要算微软的MASM,在x64环境中,相应的编译器已经更名为ml64.exe,随VisualStudio2

3、005一起发布。因此,如果你是微软的忠实fans,直接安装VS2005既可。运行时,只需打开相应的64位命令行窗口(图1),便可以用ml64进行编译了。第二个推荐的编译器是GoASM,共包含三个文件:GoASM编译器、GoLINK链接器和GoRC资源编译器,且自带了Include目录。它的最大好外是小,不用为了学习64位汇编安装几个G的VS。因此,本文的代码就在GoASM下编译。第三个Yasm,因为不熟,所以不再赘述,感兴趣的朋友自行测试吧。不同的编译器,语法会有一定差别,这在下面再说。1.2IDE的选择搜遍了Internet也没有找到支持asm64的IDE,甚至连个Editor都没有。因此,

4、最简单的方法是自行修改EditPlus的masm语法文件,这也是我采用的方法,至少可以得到语法高亮。当然,如果你懒得动手,那就用notepad吧。没有IDE,每次编译时都要手动输入不少参数和选项,做个批处理就行了。1.3硬件与操作系统硬件要求就是64位的CPU。操作系统也必须是64位的,如果在64位的CPU上安装了32位的操作系统,就算编译成功也无法运行程序。2.寄存器的改变汇编是直接与寄存器打交道的语言,因此硬件对语言影响很大。先来看看x64与x32相比在硬件上多了什么,变了什么(图2)。X64多了8个通用寄存器:R8、R9、R10、R11、R12、R13、R14、R15,当然,它们都是64

5、位的。另外还增加了8个128位XMM寄存器,不过通常用不着。X32中原有的寄存器在X64中均为扩展为64位,且名称的第一个字母从E改为R。不过我们还是可以在64位程序中调用32位的寄存器,如RAX(64位)、EAX(低32)、AX(低16位)、AL(低8位)、AH(8到15位),相应的有R8、R8D、R8W和R8B。不过不要在程序中使用如AH之类的寄存器,因为在AMD的CPU上这种用法会与某些指令产生冲突。3.第一个x64汇编程序本节,我们开始编写自己的第一个x64汇编程序。在这之前,先讲一下callingconvention的改变。3.1API调用方式把Callingconvention放在

6、第一个讲,代表它的重要性。在32位汇编中,我们调用一个API时,采用的是stdcall,它有两个特点:一是所有参数入栈,通过椎栈传递;二是被调用的API负责栈指针(ESP)的恢复,我们在调用MessageBox后不用addesp,14h,因为MessageBox已经恢复过了。而在x64汇编中,两方面都发生了变化。一是前四个参数分析通过四个寄存器传递:RCX、RDX、R8、R9,如果还有更多的参数,才通过椎栈传递。二是调用者负责椎栈空间的分配与回收。下面给出一段代码,功能是显示一个简单的MessageBox,注意对RSP的操作:代码:;示例代码1.asm;语法:GoASMDATASECTIONt

7、extdbHellox64!,0captiondbMyFirstx64Application,0CODESECTIONSTART:subrsp,28hxorr9d,r9dlear8,captionleardx,textxorrcx,rcxcallMessageBoxAaddrsp,28hret这段代码是在GoASM中编译,指令部分GoASM与ML64差不多,关键是一些宏的定义有差别。比如masm中的.code,在这里就成了CODESECTION。下面再说区别,先编译。GoASM中编译分两步:(1)编译:goasm/x641.asm(2)链接:golink1.objuser32.dll如果一些正

8、常,命令行中应显示图3的内容。运行一下,我们的第一个64位windows程序就运行了。GoASM还有一个特点是支持宏:ARG和INVOKE,使用这两个宏可以免除程序员自己对椎栈进行操作。不过初学吗,还是从基础掌握比较好。下面的一段代码相同的功能的MASM代码,注意看看区别。ML64至今仍不支持宏,所以每一步工作都要自己做。代码:;示例代码2.asm;语法:ML64extrnMessageBoxA:proc.datatextdbHellox64!,0captiondbMyFirstx64Application,0.codeMainprocsubrsp,28hxorr9d,r9dlear8,cap

9、tionleardx,textxorrcx,rcxcallMessageBoxAaddrsp,28hretMainENDPend编译这段代码的命令行是:ml642.asm/link/subsystem:windows/entry:Mainuser32.lib。如果正常,应该如图5显示那样。很有意思吧,在64位系统下,我们仍然调用user32的API。可能是名称用习惯了,微软自己都懒得改了吧。3.264位的椎栈代码中还有一处值得注意,那就是subrsp,28h和addrsp,28h。28h这个数值是怎么来的呢?首先,x64中椎栈被扩展为64位;其次,我们在调用MessageBoxA时,要给四个参

10、数外加一个返回地址留空间,因此8(位)*5=40=28h。另外一些小问题要注意,AMD64不支持push32bit寄存器的指令,最好的方法就是push和pop都用64位寄存器。EM64T如何?看了下Intel的开发手册,各个指令都分三种情况:纯32位、纯64位和32与64位混合。下面是手册的片段:Opcode*Instruction64-BitModeCompat/LegModeDescriptionFF/6PUSHr/m16ValidValidPushr/m16.FF/6PUSHr/m32N.E.ValidPushr/m32.FF/6PUSHr/m64ValidN.E.Pushr/m64.D

11、efaultoperandsize64-bits.没别的好方法,使用中多注意,尽量在64位程序中保用64位寄存器。L4.一些参考资料写完了第一个helloworld,本文就此打住。本还想写一些内容,但掌握不深,留待下回吧。感觉有些资料不得不在第一篇文章中放出来,因为它们是现有学习x64汇编的最好教材了,文中很多代码和知识点也来自于这些资料。(1)MovingtoWindowsx64,出自:(2)GoASM的帮助文档,目前最好的64位汇编教程。出自:www.jorgon.freeserve.co.uk(3)开始进行64位Windows系统编程之前需要了解的所有信息,出自:(4)来自CodeGur

12、us的两篇文章Assembler&Win64,http:/www.codegurus.be/codegurus/Programming/assembler&win64_en.htmboutRIPrelativeaddressinghttp:/www.codegurus.be/codegurus/Programming/riprelativeaddressing_en.htm(5)AMD开发手册(6)Intel开发手册,注意是新的ntel64andIA-32ArchitecturessoftwareDevelopersManualWindowsX64汇编入门(2)五一长假就要结束了,总算有时间好

13、好睡了几个懒觉。今天醒来后想到的第一件事就是,该写第二篇了。64位技术现在还不成熟,没有好调试器,但是我们搞技术的总是对新东西充满了好奇和热情。这个理由就足够我们现在开始学习64位汇编了!OK,Letsgoon。1.再说Callingconvention关于API的调用方式,在入门(1)中说了一些,不过感觉有必要再讲两点。一是在调用API时椎栈的框架,也就是StackFrame,二是利用反汇编64位C/C+程序来研究callingconvention。先说StackFrame。图1是一个通用的椎栈框架。在一个使用STDCALL的32位程序中,stackframe的四项工作:(1)传入参数的调用

14、;(2)在返回caller时,callee要负责平衡椎栈;(3)给局部变量提供空间;(4)保证ebx、esi、edi和ebp四个寄存器的值不变(这种寄存器被称为non-volatile)。在64位环境中,少了一个平衡椎栈的任务,因为平衡椎栈的工作由caller负责了,因此callee的stackframe只剩下三项工作:(1)将寄存器传入的参数和其它超过4个以上的参数在椎栈上保存(入栈);(2)给局部变量提供空间;(3)保证non-volatile寄存器的值不变,包括ebp、ebx、rdi、rsi、r12到r15,xmm6到xmm15。所以,在一个函数的开始往往有如下代码:MOVRSP+8h,

15、RCXMOVRSP+10h,RDXMOVRSP+18h,R8MOVRSP+20h,R9PUSHRBPMOVRBP,RSP而在返回时会有如下代码:LEARSP,RBPPOPRBPRET图2摘自GoASM的帮助文档,上文描述的情况在图中一目了然。如果能在VC中编译64位C/C+程序,再用IDA反汇编,不是挺好的吗?正确,这正是我们玩儿逆向工程的人喜欢的方法。VisualStudio2005的64位开发环境设置网上有,这里不多说了。以一个C/C+的代码为例:代码:/Messagehandlerforaboutbox.INT_PTRCALLBACKAbout(HWNDhDlg,UINTmessage,

16、WPARAMwParam,LPARAMlParam)UNREFERENCED_PARAMETER(lParam);switch(message)caseWM_INITDIALOG:return(INT_PTR)TRUE;caseWM_COMMAND:if(LOWORD(wParam)=IDOK|LOWORD(wParam)=IDCANCEL)EndDialog(hDlg,LOWORD(wParam);return(INT_PTR)TRUE;break;return(INT_PTR)FALSE;这段代码是一个地球人都知道的窗口消息处理代码,在编译为64位程序后,用ida64看一下它的反汇编。这样

17、,熟悉而又有点陌生的64位汇编代码就出来了,包括消息的判断,EndDialog的调用等,确实很方便。2.第二个汇编例子:SMC在入门(1)中我们写了第一个64位的汇编程序,这里我们开始写第二个。当然,代码本身还是有点意思的,这就是SelfModifyCode。让我们试一试SMC在64位下进行的如何?这还牵涉到vista的特性。代码来自修改过的参考资料AboutRIPrelativeaddressing。DATASECTIONtestzerodbeax值为0,0testnonzerodbeax值不为0!,0testtitledb测试oreax,eax指令,0oldprotectdd?CODESE

18、CTIONStart:;改变当前内存页的保护为可写subrsp,28hlear9,oldprotect;R9=lpflOldProtectmovr8d,40h;R8D=flNewProtectmovrdx,1;RDX=dwSizelearcx,modifyhere;RCX=lpAddresscallVirtualProtectaddrsp,28hlearax,modifyhereincBraxxoreax,eaxoreax,eax;如果eax为0,则or指令会使jz跳转learax,testzeromodifyhere:jz.skip;这个是GoASM的语法,号表示后面代码中的labellea

19、rax,testnonzero.skip;GoASM中的label这样定义;显示结果subrsp,28hmovr9d,0;R9D=UINTuTypelear8,testtitle;R8=LPCTSTRlpCaptionmovrdx,rax;RDX=LPCSTRlpTextmovrcx,0;RCX=HWNDhWndcallMessageBoxAmovecx,eax;ECX=UINTuExitCodecallExitProcessaddrsp,28hret代码的执行流程如下:将eax赋0,然后进行oreax,eax,如果不修改代码,则jz处会跳转,结果会显示“eax值为0”。我们的任务就是把jz改

20、为jnz。jz的十六进制编码为74,jnz为75。编译一下:GoASM/x64“2.1.asm”GoLink“2.1.obj”kernel32.dlluser32.dll因为我们加入了下面两句代码:learax,modifyhereincBrax所以jz为in为jnz了。结果显示如下图所示。注意,GoASM中byteptr简写为B。当然,你可以把上面两句指令删除,那出来的就完全是另一个结果了。3.资源文件本文的最后一节来讲下带资源的程序编译。由于GoASM有自己的编译器GoRC,而visualstudio中是rc,因此我们将分别用两种语法编写,看一下两个编译器中的相同与不同。先按下面的代码建立

21、MainDlg.rc,这个rc文件是两个例子通用的,代码来自RadASM的32位默认模板代码,其实就是一个对话框,没有添加任何控件:代码:#defineIDD_DLG11000IDD_DLG1DIALOGEX6,6,194,106CAPTION我的第一个DialogBoxFONT8,MSSansSerifSTYLE0x10CF0000EXSTYLE0x00000000BEGINEND来看一下GoASM语法的文件,其中用了很多GoASM的宏语法,不熟悉的可以看下帮助文件。我们把它保存为2.2.asm。;#;DIALOGAPP;#;暂时没有完整的include文件,我们把要用的自己添加进来#Def

22、ineWM_INITDIALOG00110H#DefineWM_DESTROY00002H#DefineWM_COMMAND00111H#DefineWM_CLOSE00010H#IFNDEFFALSE#DefineFALSE0#ENDIF#IFNDEFTRUE#DefineTRUE1#ENDIFCONSTSECTIONIDD_DLG1equ1000DATASECTIONhInstanceDQ?CODESECTIONStart:;invoke是GoASM调用API的宏,用不着我们自己进行stackframe了invokeGetModuleHandleA,0movhInstance,raxinv

23、okeInitCommonControlsinvokeDialogBoxParamA,hInstance,IDD_DLG1,0,ADDRDlgProc,0invokeExitProcess,0;FRAME是GoASM的宏DlgProcFRAMEhwnd,uMsg,wParam,lParammoveax,uMsgcmpeax,WM_INITDIALOGjne.WMCOMMANDjmp.EXIT.WMCOMMANDcmpeax,WM_COMMANDjne.WMCLOSEjmp.EXIT.WMCLOSEcmpeax,WM_CLOSEjne.DEFPROCINVOKEEndDialog,hwnd,0.

24、DEFPROCmoveax,FALSEret.EXITmoveax,TRUEretENDF编译时有个很奇怪的问题,就是要把资源文件编译成.obj格式才能顺利链接。命令行如下:GoRC/machinex64/omaindlg.rcGoASM/x642.2.asmGoLink“2.2.obj”maindlg.objkernel32.dlluser32.dllcomctl32.dll生成了2.2.exe后,运行,如下图所示:下面,看一下ml64的编译过程。rc文件不变,把下面的代码保存为2.3.asm。;#;DIALOGAPP;#extrnGetModuleHandleA:procextrnMess

25、ageBoxA:procextrnInitCommonControls:procextrnDialogBoxParamA:procextrnDestroyWindow:procextrnExitProcess:procextrnEndDialog:proc.constWM_INITDIALOGequ00110HWM_DESTROYequ00002HWM_COMMANDequ00111HWM_CLOSEequ00010HFALSEequ0TRUEequ1IDD_DLG1equ1000.data?hInstanceqword?.codeMainproc;invode是GoASM调用API的宏,用不

26、着我们自己进行stackframe了subrsp,30hxorrcx,rcxcallGetModuleHandleAmovhInstance,raxcallInitCommonControlsmovrcx,hInstancemovrdx,IDD_DLG1xorr8,r8lear9,DlgProcpush0callDialogBoxParamAxorrcx,rcxcallExitProcessaddrsp,30hretMainendp;DlgProcFRAMEhwnd,uMsg,wParam,lParamDlgProc:movrsp+8,rcxmovrsp+10h,rdxmovrsp+18h,r

27、8movrsp+20h,r9pushrbpmovrbp,rspmoveax,edxcmpeax,WM_INITDIALOGjneWMCOMMANDjmpEXITWMCOMMAND:cmpeax,WM_COMMANDjneWMCLOSEjmpEXITWMCLOSE:cmpeax,WM_CLOSEjneDEFPROCsubrsp,18hxorrdx,rdx;注意,这里第一个参数rcx未变。按理应该是由rbp定位movrcx,rbp+10hcallEndDialogaddrsp,18hDEFPROC:poprbpmoveax,FALSEretEXIT:poprbpmoveax,TRUEretend编

28、译命令行为:rcmaindlg.rcml642.3.asm/link/subsystem:windows/entry:Mainkernel32.libuser32.libcomctl32.libmaindlg.res如果你编译正确了,应该和2.2.exe的运行结果一样。和GoASM的宏比起来,ml64的语法显得更低级,也更基础。不过要注意的是,在2.3.asm中,很多语法我并没有写得很规范,要想知道最规范的代码,便是逆向高级语言或GoASM生成的exe文件。OK,第二篇就到这里了。五一长假将在今晚结束,明天上班喽。备注:标题:【原创】WindowsX64汇编入门(1)作者:tankaiha时间:2007-05-05,23:31链接:-

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁