• 标 题:一个最简单的SMC例子
  • 作 者:RoBa
  • 时 间:2004-1-24 周六, 下午4:01
  • 链 接:http://bbs.pediy.com

; 从MASM32的例子里找到的,我写了中文的注释,希望对广大菜鸟同胞理解SMC有所帮助。
;
; #########################################################################
;
;   这是一个读写PE文件代码段的例程。在这个例子里有两个过程,第一个先被调用,
;   第二个被读取并写入第一个过程里面,然后第一个过程被再次调用,前后的代码
;   已经改变了。
;   链接时应把参数设为"/section:.text,RWE",也就是说把代码段设为可读可写可执
;   行。(非常重要,不然您就等着"非法操作"吧。)
;
; #########################################################################

      .386
      .model flat, stdcall
      option casemap :none   ; case sensitive

; #########################################################################

      include masm32includewindows.inc
      include masm32includeuser32.inc
      include masm32includekernel32.inc

      includelib masm32libuser32.lib
      includelib masm32libkernel32.lib

      CalledProc PROTO         ;过程1
      ReplaceMentProc  PROTO   ;过程2

; #########################################################################

    .data
        lnth1       dd 0
        szDlgTitle  db "SMC example",0
        Phony       db "This is 1st call of proc",0
        Replc       db "This is 2nd call of proc",0
        ttl1        db "Original Code",0
        ttl2        db "Replacement Code",0

; #########################################################################
    
    .code

start:

    invoke CalledProc   ; 调用第一个过程,这时的代码还是原来的,因此显示This is 1st call of proc
    
    lea eax, rpEnd      ; 找找rpEnd在哪里,原来是在第二个过程末尾
    lea edx, rpStart    ; 第二个过程的开始处
    sub eax, edx        ; 这两个LABEL的偏移量相减是什么呢
    mov lnth1, eax      ; 得到了第二个过程的代码长度,放在lnth1

    lea esi, rpStart    ; rpStart,这是第二个过程的开始处 ->ESI
    lea edi, ppStart    ; ppStart,这是第一个过程的开始处 ->EDI
    mov ecx, lnth1      ; 把长度放在ECX
    rep movsb           ; 这个指令的作用是把ECX个字节从EDI处搬到ESI处(大概就是这意思),详情请查手册。
                        ; 执行完后会怎么样呢,你一定猜到了,这时过程1实际上已经是过程2的内容了

    invoke CalledProc   ; 再调用第一个过程,结果呢,显示出来的是This is 2st call of proc

    invoke ExitProcess,0; 退出

; #########################################################################

CalledProc proc

    ppStart::   ;两个冒号表示这个LABEL是全局的,因为默认时LABEL只能在本过程内使用

    invoke MessageBox,0,ADDR Phony,ADDR ttl1,MB_OK  ;对话框显示This is 1st call of proc

    ppEnd::

  ; ------------------------------------------------------
  ; 下面的NOP是为了给复制过来的过程2留下地方,每个NOP可以占一个字节
  ; ------------------------------------------------------

    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop

    ret

CalledProc endp

; #########################################################################

ReplaceMentProc proc

    ; -----------------------------------
    ; 这个过程2永远不会被执行,但它的代码
    ; 却被复制了过去
    ; -----------------------------------

    rpStart::
    
    push MB_OK or MB_ICONEXCLAMATION
    lea eax, ttl2
    push eax
    lea eax, Replc
    push eax
    push 0
    lea eax, MessageBox
    call eax              ;对话框显示This is 2st call of proc

    rpEnd::

    ret

ReplaceMentProc endp

; #########################################################################

end start