用于简单编码/解码字符串混淆的汇编代码?

时间:2016-08-22 13:36:41

标签: pointers assembly encoding x86

我正在学习考试,我对这个汇编代码很困惑。这是一个程序,其中第一个用户输入一个字符串,而不是该字符串被编码和打印,而不是解码和打印。

令我困惑的是(De)编码部分。因此,使用“LEA bx,MyString”MyString的内存地址保存在寄存器bx中。现在编码发生了。这是什么目的?

INC bx
MOV cl, [bx]
XOR ch, ch

coding:
    INC bx
    MOV dl, [bx]
    XOR dl, ah
    MOV [bx], dl
LOOP coding

为什么增加内存地址?这不是改变地址吗?为什么再次在循环中增加bx。这些指针让我很困惑。我得到了一个部分,其中地址bx中的字符移动到dl而不是使用掩码编码而不是放回到dl。我对内存地址的增加感到困惑。这是否意味着它首先从第3个字符开始?用掩码编码字符串的3个以上字符?前两个比什么更好?对不起,如果问题很愚蠢,谢谢!

以下是完整代码:

.MODEL small
.DATA
    STR_LENGTH EQU 30
    BUFF_LENGTH EQU STR_LENGTH + 3
    MyString DB BUFF_LENGTH DUP (0)
    Coder_Mask DB 128
.STACK
.CODE

NewLine MACRO
    MOV dl, 10
    MOV ah, 02h
    INT 21h
    MOV dl, 13
    MOV ah, 02h
    INT 21h
ENDM    

DeCode MACRO bx, ah
LOCAL coding

    INC bx
    MOV cl, [bx]
    XOR ch, ch

    coding:
        INC bx
        MOV dl, [bx]
        XOR dl, ah
        MOV [bx], dl
    LOOP coding
ENDM

WriteString MACRO bx
LOCAL writing

    INC bx
    MOV cl, [bx]
    XOR ch, ch

    writing:
        INC bx
        MOV dl, [bx]
        MOV ah, 02h
        INT 21h
    LOOP writing
ENDM

Start:
    MOV ax, @DATA
    MOV ds, ax

    LEA bx, MyString
    MOV cl, BUFF_LENGTH
    MOV [bx], cl
    LEA dx, MyString
    MOV ah, 0Ah
    INT 21h

    NewLine
    LEA bx, MyString
    WriteString bx

    LEA bx, MyString
    MOV ah, Coder_Mask
    DeCode bx, ah

    NewLine
    LEA bx, MyString
    WriteString bx

    NewLine

    LEA bx, MyString
    MOV ah, Coder_Mask
    DeCode bx, ah

    NewLine
    LEA bx, MyString
    WriteString bx

    MOV ax, 4C00h
    INT 21h
END Start

2 个答案:

答案 0 :(得分:3)

您需要了解内存的结构,字符串的存储方式。

教师的代码缺少任何评论,所以要么弄清楚(而你失败了),或者由于外交原因,我不会再对你的老师发表评论。

字符串缓冲区的结构是MS-DOS用于0Ahdescription)的函数int 21h的结构:

MyString:
    db string_maximum_size     ; maximum characters to store into buffer
    db character_actually_read ; characters read by INT 21h: 0Ah function
    db string_maximum_size DUP (0)  ; the string characters

因此,通过输入字符串“hello”,地址MyString的内存将设置为:
33, 5, 104 ('h'), 101 ('e'), 108 ('l'), 108 ('l'), 111 ('o')后跟26个零(DUP (0)的结果)。

实际上我认为你的代码有bug,设置最大大小为总缓冲区大小BUFF_LENGTH EQU STR_LENGTH + 3,而从中断描述我希望第一个字节只包含STR_LENGTH。您可以通过尝试输入33个字符长的字符串来验证这一点,并检查调试器是否在MyString缓冲区之后覆盖了内存。此外,+3没有多大意义,因为只有+2字节用于最大尺寸和实际尺寸。

现在代码发生了这个:

LEA bx,[MyString]   ; bx = address of first byte of buffer (contains maximum size)
INC bx              ; bx now points to actual size
; instead LEA bx,[MyString+1] could have been used, skipping one INC bx
MOV cl,[bx]         ; cl = actual string size
XOR ch,ch           ; ch = 0 (extending 8 bit value in cl to unsigned 16 bit in cx)
; other option on 386+ CPU is MOVZX cx,BYTE PTR [bx]
; or XOR cx,cx  MOV cl,[bx]
INC bx              ; bx now points to the first character

然后随时随地使用[bx]内容,在循环期间再次递增bx以访问下一个字符,直到cx计数器到达0

你绝对应该启动调试器,逐步通过指令执行该代码指令,并将内存窗口指向MyString并观察bx如何用于访问那里的特定字节,以及这些INC bx如何int 21h 1}}适合那个。

这将解释它比其他任何东西都好。

编辑:

还有一件事。我实际上对自己保守了一个秘密,这是你问题中不可或缺的一部分。

所以“我怎么知道?”:你应该总是记得,计算机是计算机器。你把一些程序放入(指令列表),你输入一些数字,让它执行指令,并得到结果数字。

我有代码(说明)。我在你的代码中寻找的下一件事是“你如何定义字符串”。我发现它是由用户输入的,由set cinoptions+=#1s 函数读取。所以我用Google搜索了函数,它是如何工作的,它返回了什么数据。 snap :突然之间一切都有意义了(除了max size bug,我认为这只是你的lector中的bug,即使是经验丰富的程序员也很容易在ASM中做一些bug)。

因此,请务必了解所有说明,并了解输入数据(其结构和值)。然后,您可以像在CPU上一样运行脑中的所有内容,以了解这些输入数据如何转换为输出数据。这是一个纯粹确定性的计算过程,你需要猜测任何东西,它准确定义了计算的每个阶段接下来会发生什么。

如果您确切地知道这些定义是什么,它实际上比任何高级抽象的东西简单易行,更容易,而且更加繁琐。

当你是ASM的新手时,在调试器中观察这种情况要容易得多(而且它也可以帮助你更快地理解ASM),而不是在头脑中进行。

答案 1 :(得分:0)

说明:

INC bx   ; increment bx, skip this byte (why ?)
MOV cl, [bx]  ; get number of characters of the string
XOR ch, ch    ; quick way to set ch to zero, so cx == cl for the loop

coding:
    INC bx    ; next address
    MOV dl, [bx]  ; get character value
    XOR dl, ah    ; decode it with XOR key in ah
    MOV [bx], dl  ; store in the same memory value
LOOP coding       ; decrement cl and goto coding if cx > 0

字符串的格式似乎" custom",当然不是NULL终止但是首先包含大小(是Pascal吗?Ada使用这种系统)

  • 那里似乎忽略了第一个字节。
  • 第二个字节包含以下字符串的长度
  • 其余数据是字符串本身

请注意,在这种情况下,编码和解码是相同的,因为使用了XOR屏蔽。