做app 的模板下载网站,巩义专业网站建设公司,河北中保建设集团网站首页,优质外链平台今天让我们来看Win32ASM里面的高级一点的技术——SMC#xff08;当当当当……#xff09;#xff01;#xff01;#xff01;SMC是什么意思#xff1f;它的英文名叫“Self Modifying Code”#xff0c;顾名思义#xff0c;就是“代码自修改”#xff08;#xff1f;当当当当……SMC是什么意思它的英文名叫“Self Modifying Code”顾名思义就是“代码自修改”不好意思小弟的英语六级还没过只能翻译成这样啦……“代码自修改”哇好高深啊其实不然……我们知道Win32应用程序是运行在保护模式下的每个Win32应用程序都有相互独立的4GB地址空间并且已经摒弃了16位时代的把代码分为Data、Code等段的内存模式的做法现在它们只有一种内存模式即FLAT模式意思是“平坦”的内存模式——再也没有烦人的64KB的段大小限制啦。如此一来所有的Win32应用程序都能各自运行在一个连续、平坦、巨大的4GB空间中作为程序员也不用再跟段寄存器打交道您可以用任意的段寄存器寻址任意的地址空间是不是很方便呢不过且慢Win32时代的编程虽然比之Win16时代已经方便了不止一个数量级但是毕竟还有一些规则是需要遵守的。最明显的之一就是不能在程序运行的过程中随便更改代码段咦刚刚不是说了Win32里面没有段的概念了吗怎么这里又来了一个“代码段”了别急请听我细细道来……虽然Win32下已经没有了“段”但是您还是可以给自己的程序分成不同的“段”一个“分段”的开始即是上一个“分段”的结束。Win32只有两种性质的分段Data和Code。实际上在Win32里面的分段并不是像DOS下一样为不同的段分别指出不同的段寄存器因为Windows下只有一个4GB的段Windows程序中的分段表现在当程序装载时赋予不同的段不同的属性比如说当你的程序加载时对于Ring3程序来说.code段是不可写的而.data段是可写的如果你尝试像在DOS下一样写自己的代码部分你将会得到一个“很cool”的蓝屏错误。怎么样头晕了吗如果没有的话让我们继续^_^上面已经提到代码段是不能在程序运行途中更改的了那么怎么又来了一个“SMC”技术呢它是如何实现的其实关键就在于链接时的参数只要指定了代码段的属性是可写的那么就OK啦默认的参数是不可写的。也就是说我们在编译、链接带有SMC的Win32ASM时应该这样做
ml /c /coff %1.asmlink /subsystem:windows /section:.text,RWE %1.obj
怎么样明白了吗 /section:.text,RWE 这句指定了代码段.text的属性是RWE含义是RReadAbleWWriteAbleEExecuteAble也就是“可读可写可执行”。这样我们的程序就可以在运行途中自己改写自己的代码段啦怎么样是不是很爽呢下面给出了一个完整的带有SMC技术的Win32ASM例子很容易理解的记得要用上面的方法来编译和链接哦
;***********************************************;程序名称演示SMC原理;作者罗聪;日期2002-10-2;出处http://laoluoc.yeah.net老罗的缤纷天地;注意事项如欲转载请保持本程序的完整并注明;转载自“老罗的缤纷天地”http://laoluoc.yeah.net;***********************************************.386.model flat, stdcalloption casemap:noneinclude /masm32/include/windows.incinclude /masm32/include/kernel32.incinclude /masm32/include/user32.incincludelib /masm32/lib/kernel32.libincludelib /masm32/lib/user32.libShowMessage protoReplaceMent proto.dataszMsg1 db 这是未执行SMC之前的代码, 0szMsg2 db SMC已经执行, 0szCaption db SMC demo by LC, 2002, 0Replace_Len dd 0.codemain: ;第一次执行子程序ShowMessage此时还没执行SMC操作 invoke ShowMessage lea eax, ReplaceMentEnd ;标号ReplaceMent的结束 lea edx, ReplaceMentStart ;标号ReplaceMent的开始 sub eax, edx ;标号ReplaceMent的长度 mov Replace_Len, eax ;把长度储存起来 ;关键代码 lea esi, ReplaceMentStart ;标号ReplaceMent的开始 lea edi, ShowMessageStart ;原程序ShowMessage的标号的开始 mov ecx, Replace_Len ;标号ReplaceMent的长度 rep movsb ;这里是最关键的语句执行SMC操作 ;第二次执行子程序ShowMessage此时已经执行了SMC操作。 ;换句话说ShowMessage的内容已经不是第一次运行时的内容了 invoke ShowMessage invoke ExitProcess, 0ShowMessage proc ;这里用“::”的话就能够使标号成为全局性的 ShowMessageStart:: invoke MessageBox, NULL, addr szMsg1, addr szCaption, MB_OK ShowMessageEnd:: ;用nop来预留空间以便后面的SMC能够成功执行 ;否则如果空间不够将有可能产生不可预测的错误 nop nop nop nop nop nop nop nop retShowMessage endpReplaceMent proc ;将要用来SMC的代码 ReplaceMentStart:: ;invoke MessageBox, NULL, addr szMsg2, addr szCaption, MB_OK or MB_ICONINFORMATION push MB_OK or MB_ICONINFORMATION lea eax, szCaption push eax lea eax, szMsg2 push eax push NULL lea eax, MessageBox call eax ReplaceMentEnd:: retReplaceMent endpend main