windows环境下64位汇编语言程序设计
文章目录
进入x64时代用汇编写程序的越来越少了, 经常去的几个汇编论坛也越来越没人气. 也是,现在很少事情非得找到一个用汇编来写的理由了. 所以慢慢也就没落了.实际上32位汇编和x64汇编个人感觉差别也不大.为什么就没人用了呢..
作为一个看<
x32上罗牛用的是MASM32的开发包, MASM32是一个好东西, 里面已经收集起来了开发windows程序所需要的编译器和头文件, 也都经过了较为严格的测试,总之之前我用MASM32基本没有遇到什么问题.
x64上,目前还没有MASM32那样的牛人来给我们收集头文件, 编译器和其他东西, 一方面可能有一些版权方面的问题, 一方面可能现在x64也不火了.没人搞这方面的工作,所以导致x64上用汇编很麻烦..难倒了很多新人. 就我在将<
为了修改<
http://www.terraspace.co.uk/uasm.html
UASM是从之前的 JWasm 修改过来的, 这个汇编器还是开源的, 兼容MASM的语法. 另外头文件也是从JWasm那边搞过来的, 不过我加入了一些自己的私货. 比如C语言的头文件, 比如UNICODE支持. MASM32的时代我就已经找到了UNICODE支持中文办法, 不过一直没有推广出去. 如果你有幸看到这篇文章. 并且以后也会准备用汇编来写程序.. 一定不要再用老掉牙的ANSI编码, 而是要采用UNICODE来写.. 如果你用了附件我上传的开发包, 那么可以这样定义和使用UNICODE. 一种是在.const节里面定义字符串. 还有一种就向C语言一样定义字符串..
MASM支持中文UNICODE字符串定义
|
|
中文的完美支持. 依靠的就是unicode.inc 如果你下载附件的开发包,里面就已经自带了. 作者是陈浪涛. 也是个汇编高手. 有兴趣可以看看. 显然MASM的M不是Microsoft而是 Macro.. 用MASM的宏可以实现很多完全突破想象的功能, 这里有一个哥们就用MASM实现了面向对象. 有兴趣可以了解下.
关于附件中的例子编译方法和罗牛书上是一样的, 只是他用的是masm32 SDK包, 现在换成了UASM. UASM64压缩包解压到一个目录下, 运行目录下的set_path.bat就可以到各个例子目录下运行nmake了. 另外把TAB设置成8个BYTE. 这样显示出来的代码格式才正常.
下面是我修改例子程序的时候, 遇到的一些问题. 不过都已经被解决了..
无法接受和发送WM_COPYDATA消息, 原因是对齐方面的问题. COPYDATASTRUCT结构体必须按照16BYTE对齐. 我已经修改了winuser.inc文件, 将COPYDATASTRUCT结构体设置成了16BYTE对齐
C:\JASM64\luoyunbin\Chapter04\SendMessage-1
这个例子在win7 x64上已经试验不出效果了, 应该是win7的gdi画窗口的方式换了,不过虽然没有效果,我还是修改成了x64的版本.
C:\JASM64\luoyunbin\Chapter07\DcCopy
无法打开通用对话框 已修复OPENFILENAME对齐必须是16BYTE的. 所以我修改了系统的commdlg.inc后面的人就不会遇到这个坑了.
C:\JASM64\luoyunbin\Chapter09\Richedit
C:\JASM64\luoyunbin\Chapter10\FormatText
设置结构体对齐 pushcontext alignment option fieldalign:16 popcontext alignment
这些无法打开通用对话框的问题都是由于没有设置对齐引起的. 这个问题折腾了好久好久. 他们说现在用汇编和C差不多, 相信用C肯定不会遇到这种问题. 不禁又让我想起了以前用汇编写驱动的时候, DriverEntry写出来死活崩溃. 偶尔又不崩溃. 最好找了好久的问题才发现原来DriverEntry里面不能动ebx. 如果动了ebx就会出错, 想用的话就要push保存起来. 这些都是一路走来的坑…
工具栏有编译错误,解决
C:\JASM64\luoyunbin\Chapter09\Toolbar
工具栏有编译错误,已解决
C:\JASM64\luoyunbin\Chapter09\Wordpad
工具栏错误解决, 主要是因为CommCtrl.inc头文件定义的有问题, 看来WinInc208 jwasm的作者还是没有masm32作者那样做那么多的测试.只是s使用h2incx工具转换好了就不管了. 这个转换难免还是有不少问题的..
屌爆了, C:\JASM64\luoyunbin\Chapter10\FindFile 里面使用了COM接口也被我修改成了x64修改了不少的接口定义. 还修改了系统头文件的几个定义, 系统的ShlObj.INC里面关于SHBrowseForFolder等几个函数的名称粉碎方式定义错了..
这是只适用于32位的例子.关于内存申请方面测试的例子, 所以就不修改了
C:\JASM64\luoyunbin\Chapter10\Fragment
这个是在9x做进程隐藏的. 和x64也没有关系也就不修改了.
C:\JASM64\luoyunbin\Chapter13\HideProcess9x
因为之前罗牛也没有做PE文件的分析,所以这个Test程序在x64上要将PE文件的Relocation stripped勾选, 不然每次地址都不一样patch就无从谈起了, 不过例子程序里面的可以直接运行,如果自己编译的话, 记得勾选Relocation stripped就好了..
C:\JASM64\luoyunbin\Chapter13\Patch1
Patch2 里面的Test程序也是要勾选Relocation stripped.并且为了可以使upx加壳,我加了不少的nop
C:\JASM64\luoyunbin\Chapter13\Patch2
这个例子应该是罗牛书中最有技术含量的几个例子之一, 也是汇编相对C语言C语言还有一些做不到的事情之一,处理重定位问题和写_invoke宏花了不少时间.
C:\JASM64\luoyunbin\Chapter13\RemoteThread
异常始终不进去.经过调试发现,SetUnhandledExceptionFilter调用必须写在函数里面. 不能和32位一样,使用裸函数. 应该又是堆栈对齐方面的问题.
C:\JASM64\luoyunbin\Chapter14\TopHandler
SEH异常方面,x64完全变掉了, 现在变得更简单了.
C:\JASM64\luoyunbin\Chapter14\SEH01
C:\UASM64\luoyunbin\Chapter16\Chat-TCP
第16章关于网络这块的定义都有问题, 主要问题是出在SOCKET. 之前UASM的头文件定义成了 SOCKET typedef u_int 实际上翻看windows的winsock.h头文件中的定义, typedef UINT_PTR SOCKET;是一个64位的类型, 所以将头文件修改成 SOCKET typedef qword 就好了. 如果不修改所有和Socket有关的函数都会出问题. 另外fd_set结构体也要修改, 将对齐修改成8BYTE.
C:\UASM64\luoyunbin\Chapter17\AddCode
17章最复杂的几个例子之一, 但是代码层面的复杂度都被我搞定了, 程序也可以正常运行了, 不知道最后一步调用MessageBox为什么会出错.. 参数各方面都是正确的. 最后发现出错地址在MessageBox函数里面的movdqa指令上, 然后手册发现movdqa指令必须16BYTE对齐, 所以加入了以下指令来做对齐工作,
MOVDQA - 移动对齐的双四字
将双四字从源操作数(第二个操作数)移到目标操作数(第一个操作数)。此指令可以用于在 XMM 寄存器与 128 位内存位置之间移入/移出双四字,或是在两个 XMM 寄存器之间移动。源操作数或目标操作数是内存操作数时,操作数必须对齐 16 字节边界,否则将生成一般保护性异常 (#GP)。
在 16 位寻址模式中执行时,不允许 128 位数据访问的线性地址与 16 位段尾重叠,此时的行为定义成保留行为。在这种情形下,特定的处理器版本可能会生成 #GP 异常,也可能不会,并且,跨越段尾的地址可能会通过舍位变成段首地址,也可能不会。
另外Chapter17\AddCode总共有两种方式, 一种是在节表后面添加一个节,以为一个节的大小毕竟有限, 所以这种方式是目前的主流方式,另外一种方式是扫描代码段看看有没有空间可以插入代码,这种方式现在不流行了, 因为现在PE文件FileAlignment对齐一般都是0x200而随便写一点shell code都会超过0x200 BYTE.. 这个例子的shell code就有300个BYTE. 因为要放置GetProcAddress 和Get Kernel32 base的代码, 在x64情况下很容易就超了..所以要实验在代码节中添加代码的方式可以找VC6编译的程序, VC6的FileAlignment SectionAlignment都是0x1000比较容易找到空隙. 不然就自己编译代码在link的时候加上这两个选项.
#pragma comment(linker, “/ALIGN:0x1000”)
#pragma comment(linker, “/FILEALIGN:0x1000”)
一个是设置文件对齐大小, 一个是设置内存对齐大小的.
C:\UASM64\luoyunbin\Chapter17\Reloc
重定位显示的例子, 没有什么特别需要说的. 就是之前罗牛只处理了IMAGE_REL_BASED_HIGHLOW一种类型的重定位表, 这个在32位上也是没有错的, 但是x64上面的重定位表一般都是IMAGE_REL_BASED_DIR64, 我都给改过来了. 所以在看例子程序的时候需要注意一下.
C:\UASM64\luoyunbin\Chapter18\OdbcSample
这是一个使用odbc数据库的例子, 刚开始遇到问题就是没有找到odbc.inc. 后面发现使用的不是odbc.inc文件, 而是使用的sql.inc sqlext.inc两个头文件, 另外UASM自己的头文件也是有问题的, sql.inc里面的函数声明都是proto stdcall. 然后link的时候报错. 无法解析的外部符号 _SQLRowCount@16,一类的. 这个名字一看就是使用了stdcall的名称处理方式, 然后我在odbc32.lib里面里面看到的名称是没有做任何处理的, 所以翻看头文件发现函数的原型定义错了. 原版里面都有stdcall. 现在去掉. 默认使用x64的fastcall..
另外x64上面access的连接字符串也要修改一下.
32位: “Driver={Microsoft Access Driver (*.mdb)};dbq=path;”
64位: “Driver={Microsoft Access Driver (*.mdb,*.accdb)};dbq=path;“)
还有, 例子里面使用了ListView. 操作ListView需要一个结构体LVITEM. 这个结构体在x64上面也是16 BYTE对齐的. 所以如果你自己找的头文件需要注意这个问题. 当然我发出来的UASM已经被我修改好了.
//===========================================================================
最后, 所有的例子我修改完成以后都简单做了一下测试. 主要功能应该是没有什么问题的, 不过如果有什么隐藏的bug. 你可以报给我. [email protected] 当然也欢迎大家加群Q群127285697讨论技术问题.
编译环境的下载地址因为看雪附件上传限制. 我上传到了百度云. 请猛戳下载, 附件是修改的18章+3个附录.
文章作者 忆杰
上次更新 2017-06-08