Logo WP

你真的是大学生吗

一道8086逆向题的分析

![[DOSBox_icon.png]]

你是冤种大学生吗?

难度:easy

出题人:@dev1l

源文件{:download="______.EXE"}

扔进DIE(Detect It Easy)里

操作系统: MS-DOS(-)[8086, 16 位, EXE]

扔进IDA x32,分析程序

lea     dx, unk_10000   ; Load Effective Address
mov     ah, 9
int     21h             ; DOS - PRINT STRING
                        ; DS:DX -> string terminated by "$"
dseg:0000 unk_10000       db  0Dh                 ; DATA XREF: start+5↓o
dseg:0001                 db  0Ah
dseg:0002                 db  69h ; i
dseg:0003                 db  6Eh ; n
dseg:0004                 db  70h ; p
dseg:0005                 db  75h ; u
dseg:0006                 db  74h ; t
dseg:0007                 db  20h
dseg:0008                 db  73h ; s
dseg:0009                 db  74h ; t
dseg:000A                 db  72h ; r
dseg:000B                 db  69h ; i
dseg:000C                 db  6Eh ; n
dseg:000D                 db  67h ; g
dseg:000E                 db  3Ah ; :
dseg:000F                 db  24h ; $

0x0D 0x0A 是Windows的换行符,相当于\r\n

小知识#

  • 0x0D - \r 是“回车符” carriage return (CR)
  • 0x0A - \n 是“换行符” line feed (LF)

回车按键包含两个操作,字车归位,然后换行。

对应的计算机文本中的两个转义字符分别是\r和\n ,

对应它们的缩写(Carriage Return (CR)和Line Feed (LF)),合起来叫换行符。

Windows中是 \r\n,Mac或者类Unix是 \n,老Mac是 \r

8086中的字符串以 $ 结尾,IDA中按 A 自动转换成字符串

这里是传递字符串首字符地址给dx,然后调用系统的PRINT函数(21h号中断,9号子函数)

lea     dx, unk_1002D   ; Load Effective Address
mov     ah, 0Ah
int     21h             ; DOS - BUFFERED KEYBOARD INPUT
                        ; DS:DX -> buffer
unk_1002D       db  15h

经过Debug,这里的执行流程如下

  1. 读取 [dx],作为缓冲区最大值
    • 这里是15h,即最大输入14h个字符,最后一个字符需要保留—— \r
  2. 获取用户字符,以 [dx+2] 为起点存字符串,直到回车(即\r
    • 每收到一个按键都会放入缓冲区
  3. 字符串长度存到了 [dx+1]

小知识#

退格按键看起来删掉了字符,实际上缓冲区中的内容并没变

例如:输入11111,然后退格全删掉,再输入222,再删掉,再输入3和回车,最后缓冲区数据为:

33,0D,32,31,31 | 3.211

lea     dx, asc_10010
mov     ah, 9
int     21h

打印换行符

之后的代码逐步分析就OK,有几个需要注意的点

到底跳不跳转?#

cmp     al, bl          ; Compare Two Operands
jnz     short loc_100AA ; Jump if (Result is) Not Zero (ZF=0)

这里 CMP 相当于 al-bl,如果结果为0,就把ZF(Zero Flag,零标志位)置1

所以这里是不相等跳转

这是什么算法#

loc_1007C:
sub     si, 1           ; Integer Subtraction
xor     [si], al        ; Logical Exclusive OR
mov     al, [si]
dec     cx              ; Decrement by 1
cmp     cx, 0           ; Compare Two Operands
jnz     short loc_1007C ; Jump if Not Zero (ZF=0)

简单的异或运算,在纸上写几下就可以知道逆向算法是什么了

EXP#

# 加密后的数据
enc = [0x76,0x0E,0x77,0x14,0x60,0x06,0x7D,0x04,0x6B,0x1E,0x41,0x2A,0x44,0x2B,0x5C,0x03,0x3B,0x0B,0x33,0x05]
result = [0] * len(enc)

for i in range(len(enc) - 1):
    result[i] = enc[i] ^ enc[i+1]
result[len(enc) - 1] = result[0] ^ enc[len(enc) - 1]

r = ''
for v in result:
    r += chr(v)
print(r)