飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 4573|回复: 3

[求助] 菜菜地问一句:什么是SMC技术(SMC法)

[复制链接]

该用户从未签到

发表于 2007-8-12 15:20:10 | 显示全部楼层 |阅读模式
如题。
在网上找了半天也没找到一个合适的解释,请朋友们指点。
SMC技术具体是什么。有相关的教程吗?
PYG19周年生日快乐!

该用户从未签到

发表于 2007-8-12 18:24:11 | 显示全部楼层
转贴一篇文章/:001

浅析SMC技术作者:kine 日期:2007-04-19
字体大小: 小 中 大  
今天让我们来看Win32ASM里面的高级一点的技术——SMC(当当当当……)!!!

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.asm
link /subsystem:windows /section:.text,RWE %1.obj


怎么样?明白了吗? /section:.text,RWE 这句指定了代码段(.text)的属性是RWE,含义是:R(ReadAble),W(WriteAble),E(ExecuteAble),也就是“可读可写可执行”。这样我们的程序就可以在运行途中自己改写自己的代码段啦,怎么样?是不是很爽呢?

下面给出了一个完整的带有SMC技术的Win32ASM例子,很容易理解的,记得要用上面的方法来编译和链接哦!


;***********************************************
;程序名称:演示SMC原理
;作者:罗聪
;日期:2002-10-2
;出处:http://laoluoc.yeah.net(老罗的缤纷天地)
;注意事项:如欲转载,请保持本程序的完整,并注明:
;转载自“老罗的缤纷天地”(http://laoluoc.yeah.net
;***********************************************

.386
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib

ShowMessage   proto
ReplaceMent   proto

.data
szMsg1     db   "这是未执行SMC之前的代码!", 0
szMsg2     db   "SMC已经执行!", 0
szCaption   db   "SMC demo by LC, 2002", 0
Replace_Len   dd   0

.code
main:
  ;第一次执行子程序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, 0

ShowMessage   proc
  ;这里用“::”的话,就能够使标号成为全局性的
  ShowMessageStart::
    invoke MessageBox, NULL, addr szMsg1, addr szCaption, MB_OK
  ShowMessageEnd::

  ;用nop来预留空间,以便后面的SMC能够成功执行;
  ;否则如果空间不够,将有可能产生不可预测的错误:
  nop
  nop
  nop
  nop
  nop
  nop
  nop
  nop

  ret
ShowMessage   endp

ReplaceMent   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::

  ret
ReplaceMent endp

end main
PYG19周年生日快乐!

该用户从未签到

 楼主| 发表于 2007-8-12 21:11:12 | 显示全部楼层
大体上了解了。谢谢楼上的朋友。
PYG19周年生日快乐!

该用户从未签到

发表于 2007-8-18 22:24:19 | 显示全部楼层
简单一句就是不脱壳搞破解~ 相应的文章论坛上有~
PYG19周年生日快乐!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表