汇编语言字符串加密代码分析(2)

来源:互联网 发布:国家食药监局数据查询 编辑:程序博客网 时间:2024/05/03 12:26

来自于《Intel汇编语言程序设计》(第四版)第六章。

 

这个例子利用了XOR(异或)指令的一个特性(即对操作数两次异或之后操作效果抵消),对字符串进行加密。

 

书中代码:

 

 

TITLE Encryption Program     (Encrypt.asm)

 

INCLUDE Irvine32.inc

KEY = 239                                       ; any value between 1-255

BUFMAX = 128                                ; maximum buffer size

 

.data

sPrompt BYTE "Enter the plain text : ",0

sEncrypt BYTE "Cypher text :             ",0

sDecrypt BYTE "Decrypted :               ",0

buffer BYTE BUFMAX dup(0)

bufsize DWORD ?

 

.code

main PROC

       call  InputTheString                    ; input  the plain text

       call TranslateBuffer                     ; encrypt the buffer

       mov edx , OFFSET sEncrypt        ; display encrypted message

       call DisplayMessage

       call TranslateBuffer                    ; decrypt the buffer

       mov edx , OFFSET sDecrypt        ; display decrypted message

       call DisplayMessage

 

       exit

main ENDP

 

 

;------------------------------------------------------------------

InputTheString PROC

;

; Asks the user to enter a string from the

; keyboard Saves the string and its length

; in variables.

; Receives : nothing

; Returns : nothing

;------------------------------------------------------------------

        pushad

        mov edx , OFFSET sPrompt        ;display a prompt           

        call WriteString

        mov ecx,BUFMAX                        ; maximum character count

        mov edx,OFFSET buffer              ; point to the buffer

        call ReadString                           ; input the string

        mov bufsize , eax                       ; save length

        call Crlf

        popad

        ret

InputTheString ENDP

 

 

;------------------------------------------------------------------

DisplayMessage PROC

;

; Display the encrypted or decrypted message

; Receives : EDX points to the message

; Returns : nothing

;------------------------------------------------------------------

         pushad

         call WriteString

         mov edx , OFFSET buffer            ;display the buffer

         call WriteString

         call Crlf

         call Crlf

         popad

         ret

DisplayMessage ENDP

 

 

;------------------------------------------------------------------

TranslateBuffer PROC

;

; Translate the string by exclusive-ORing each

; byte with the same integer .

; Receives : nothing

; Returns : nothing

;------------------------------------------------------------------

          pushad

          mov ecx , bufsize                        ; loop counter

          mov esi , 0                                  ; index 0 in buffer

L1:

          xor buffer[esi] , KEY                    ; translate a byte

          inc esi                                         ; point to next byte

          loop L1

          popad

          ret

TranslateBuffer ENDP

END main

 

 

 让我们来逐句分析这段程序的代码:

 

首先,程序包含了作者的一个inc文件,里面有一些常量的定义,随后定义了一个用来加密的数字,这里是239,和一个缓冲长度值,这里是128:

 

INCLUDE Irvine32.inc

KEY = 239                                       ; any value between 1-255

BUFMAX = 128                                ; maximum buffer size

 

随后,数据段如下:

 

.data

sPrompt BYTE "Enter the plain text : ",0

sEncrypt BYTE "Cypher text :             ",0

sDecrypt BYTE "Decrypted :               ",0

buffer BYTE BUFMAX dup(0)

bufsize DWORD ?

 

定义了三个字符串,用于程序中的显示,一个buffer数组,还有一个用来存储长度的bufsize变量

 

接下来的是主程序段,这里有一个main函数和三个子函数,分别是:

 

InputTheString

DisplayMessage

TranslateBuffer

 

让我们先看一下三个子函数。

 

首先是InputTheString ,这个函数用来提示用户输入值,并且将值保存到buffer中,看一下代码:

 

 

        pushad                                      ; 首先保存所有寄存器的值

        mov edx , OFFSET sPrompt        ; 将sPrompt的地址赋给edx(用于下面的显示)

        call WriteString                          ; 显示edx中的值

        mov ecx,BUFMAX                        ; 将字符串的数量赋给ecx,因为ecx将用于循环的计数器

        mov edx,OFFSET buffer              ; 将edx寄存器指向buffer数组的地址

        call ReadString                           ; 读取用户输入的字符串到buffer中

        mov bufsize , eax                       ; 将用户输入字符串的长度值(此时保存在eax寄存器中),赋值给bufsize

        call Crlf                                       ; 将光标输出到下一行的开始

        popad                                        ; 重新得到所有寄存器的值

        ret                                              ; EIP 跳回

 

整个过程很简单。

 

然后我们再来看DisplayMessage :

 

 

 

         pushad                                       ; 首先保存所有寄存器的值

         call WriteString                           ; 显示edx寄存器中的值,显然这需要在调用函数之前对edx赋值

         mov edx , OFFSET buffer            ; 将buffer 中保存的值赋值到edx中准备显示

         call WriteString                           ; 显示edx中的值

         call Crlf                                        ; 将光标输出到下一行的开始

         call Crlf                                        ; 将光标输出到下一行的开始

         popad                                         ; 重新得到所有寄存器的值

         ret                                               ; EIP 跳回

 

 

 

然后再来看一下 TranslateBuffer  :

 

          pushad                                       ; 首先保存所有寄存器的值

          mov ecx , bufsize                        ; 将长度赋值给ecx,用于循环计数

          mov esi , 0                                  ; esi作为数组的index值,从零开始

L1:

          xor buffer[esi] , KEY                    ; 使用key值对每一个字节进行异或操作

          inc esi                                         ; 将index值加1

          loop L1                                        ; 重复执行L1,此时ecx值自减1

          popad                                         ; 异或操作完成后,重新得到所有寄存器的值

          ret                                               ; EIP 跳回

 

此函数时比较核心的部分,用于执行异或操作。

 

最后让我们看一下main函数:

 

 

       call  InputTheString                    ; 得到用户的输入,放到buffer数组中

       call TranslateBuffer                     ; 将buffer数组中的每一个字节进行异或操作,即“加密”操作

       mov edx , OFFSET sEncrypt        ; 因为DisplayMessage需要用到edx值,所以为edx赋值

       call DisplayMessage                   ; 显示用户输入字符串的加密值

       call TranslateBuffer                     ; 对buffer数组进行第二次异或操作,即“解密”操作

       mov edx , OFFSET sDecrypt        ; 为edx赋值

       call DisplayMessage                   ; 显示解密后的字符串

 

       exit                                             ; 退出(此函数并不是MASM伪指令,而是作者库中的函数)

 

 

 以上便是最简单的汇编加密程序的代码分析。