【HGAME】easyasm
收获
- 汇编代码逻辑
思路
将文件拖入 Exeinfo PE 查看文件类型:
发现文件是一个 16位 的 MS-DOS 程序
拖入 IDA,对 start 函数 F5 反编译发现无法编译
可能是 IDA 无法反编译 16位 程序
直接查看汇编代码:
首先将 dseg
移入 ds
段,将 seg001
移入 es
段
dseg
的内容:hgame{Fill_in_your_flag}
seg001
的内容:[0x91, 0x61, 0x01, 0xC1, 0x41, 0xA0, 0x60, 0x41, 0xD1, 0x21, 0x14, 0xC1, 0x41, 0xE2, 0x50, 0xE1, 0xE2, 0x54, 0x20, 0xC1, 0xE2, 0x60, 0x14, 0x30, 0xD1, 0x51, 0xC0, 0x17, 0x00, 0x00, 0x00, 0x00]
初始时 si = 0
,根据:
loc_100DD: ; CODE XREF: start+38↓j
cmp si, 1Ch
jz short loc_10135
---------------------------------------------------------------
add si, 1
cmp al, es:[si-1]
jz short loc_100DD
mov ax, 0B800h
mov es, ax
assume es:nothing
mov byte ptr es:0, 77h ; 'w'
mov byte ptr es:2, 72h ; 'r'
mov byte ptr es:4, 6Fh ; 'o'
mov byte ptr es:6, 6Eh ; 'n'
mov byte ptr es:8, 67h ; 'g'
mov byte ptr es:0Ah, 21h ; '!'
---------------------------------------------------------------
loc_10135: ; CODE XREF: start+10↑j
mov ax, 0B800h
mov es, ax
mov byte ptr es:0, 72h ; 'r'
mov byte ptr es:2, 69h ; 'i'
mov byte ptr es:4, 67h ; 'g'
mov byte ptr es:6, 68h ; 'h'
mov byte ptr es:8, 74h ; 't'
mov byte ptr es:0Ah, 21h ; '!'
可知 loc_100DD
是一个循环,循环的次数由计数器 si
的值控制,每循环一次 si + 1
当 si = 1Ch
时,输出 “right!”
并且每一轮循环都必须满足 al = es:[si-1]
,否则就输出 “wrong!”
根据:
xor ax, ax
mov al, [si]
shl al, 1
shl al, 1
shl al, 1
shl al, 1
push ax
首先通过异或 xor ax, ax
将 ax
清零,然后将 si
中存放的值作为地址,取该地址上的值作为 [si]
(间接寻址,si
中存放的是操作数的地址)
将 [si]
的值存入 ax
,然后 4 个 shl al, 1
将 al
逻辑左移(低位补 0) 4 位后,将 ax
送入堆栈段
同理,根据:
xor ax, ax
mov al, [si]
shr al, 1
shr al, 1
shr al, 1
shr al, 1
首先通过异或 xor ax, ax
将 ax
清零,接着将 [si]
的值存入 ax
然后 4 个 shr al, 1
将 al
逻辑右移(高位补 0) 4 位
注意这里:
pop bx
add ax, bx
这里将刚刚 push ax
时入栈的 ax
出栈作为 bx
假设 [si] = xxxx yyyy
此时的 bx
应该为 yyyy 0000
,而此时 ax 的值为 0000 xxxx
因此 add ax, bx
后,ax = yyyy xxxx
即:此过程其实就是将 [si]
的高位和低位互换位置
根据:
xor ax, 17h
add si, 1
cmp al, es:[si-1]
jz short loc_100DD
这里将 ax
(互换高位和低位后的 [si]
) 与 0x17 异或,计数器 si
加一,然后将 al
与以 es
为段首址、以 si - 1
为偏移地址的地址处的值进行比较(ES
是附加数据段的段首址),如果相等就继续往下循环,否则就输出 “wrong!”
因此,程序逻辑就是将 flag 的每个字符的 前四位 和 后四位 进行置换,然后与 0x17 异或,再与 es
段的数据进行逐位比较
脚本
unk_10030 = [
0x91, 0x61, 0x01, 0xC1, 0x41, 0xA0, 0x60, 0x41, 0xD1, 0x21, 0x14, 0xC1, 0x41, 0xE2, 0x50, 0xE1,
0xE2, 0x54, 0x20, 0xC1, 0xE2, 0x60, 0x14, 0x30, 0xD1, 0x51, 0xC0, 0x17, 0x00, 0x00, 0x00, 0x00
]
for i in range(0x1c - 1):
key = unk_10030[i] ^ 0x17
key_h = int(key / 16)
key_l = key - key_h * 16
print(chr(key_l * 16 + key_h), end="")
结果
hgame{welc0me_to_4sm_w0rld}