调试用 x86 16 位程序集编写的校验和算法
Debug checksum algorithm written in x86 16-bit assembly
我目前正在对一个软件进行逆向工程,该软件可以为给定的数据缓冲区计算 2 字节宽的校验和。代码来自一个 16 位 DLL(NE 格式),使用 Borland C++ 编译。我怀疑校验和是具有 0x8408 多边形的 CRC-16,但我没有机会计算出相同的 CRC,所以我想知道实现是否是 "CRC16 standard"。
下面是程序集实现:
crc_cal proc far
var_4= word ptr -4
arg_0= word ptr 6
arg_2= dword ptr 8
mov ax, seg dseg37
inc bp
push bp
mov bp, sp
push ds
mov ds, ax
sub sp, 2
push si
push di
xor cx, cx
mov dx, 0FFFFh
mov [bp+var_4], 8408h
loc_42646:
les bx, [bp+arg_2]
add bx, cx
mov al, es:[bx]
xor al, dl
mov dl, al
inc cx
xor di, di
jmp short loc_42672
loc_42657:
mov si, dx
dec si
mov ax, si
shr ax, 1
mov si, ax
mov ax, dx
shr ax, 1
mov dx, ax
cmp si, dx
jnz short loc_42671
mov ax, dx
xor ax, [bp+var_4]
mov dx, ax
loc_42671:
inc di
loc_42672:
cmp di, 8
jb short loc_42657
cmp cx, [bp+arg_0]
jb short loc_42646
mov ax, dx
not ax
mov dx, ax
les bx, [bp+arg_2]
add bx, cx
mov es:[bx], dl
inc cx
mov ax, dx
shr ax, 8
mov dx, ax
les bx, [bp+arg_2]
add bx, cx
mov es:[bx], dl
inc cx
pop di
pop si
pop cx
pop ds
pop bp
dec bp
retf
crc_cal endp
以及软件计算出的带有相关 CRC(最后两个字节)的一些数据:
| DATA |Inc|CRC|
|----------------------------------------------------------|---|---|
00 00 00 00 00 00 01 ef f7 fe ef ff fd ef fb fa fd a2 aa 21 01 f4 e0
00 00 00 00 00 00 01 ef f7 fd ef ff fd fe fb fa fd a2 aa 21 02 f4 d1
00 00 00 00 00 00 01 f7 fe fd fd ff fd df ff fb fd a2 aa 21 03 f4 cd
00 00 00 00 00 00 01 f7 fe fe fd ff f7 ef ff fa fd a2 aa 21 04 f4 c2
00 00 00 00 00 00 01 ef f7 fe ef ff fe ef fb fa fd a2 aa 21 05 f4 db
00 00 00 00 00 00 01 ef f7 fe ef ff fd ef fb fa fd a2 aa 21 06 f4 db
显示的数据与 crc 不对应,如之前的回答所述:
该代码是右移 CRC(在 dx 中)的过于复杂的实现,poly = 0x8408,初始值 = 0xffff,xor out = 0xffff。检查每行之后的下 2 个字节以查看是否是附加 CRC 的位置。
带有注释的问题代码。感谢 Ross Ridge 解释 "inc bp" 用于指示涉及远调用,以防堆栈需要回溯(最后的 "dec bp" 用于撤消 "inc bp"在开头)。
crc_cal proc far
var_4 = word ptr -4 ; used to store poly
arg_0 = word ptr 6 ; number of bytes of data
arg_2 = dword ptr 8 ; far pointer to data
mov ax, seg dseg37 ; for ds that is never used
inc bp ; bp += 1, (bp&1 == far call indicator)
push bp ; save bp+1
mov bp, sp ; bp = sp, base for the equated offsets
push ds ; save ds
mov ds, ax ; ds = dseg37 (never used)
sub sp, 2 ; allocate space for poly (var_4)
push si ; save si, di
push di
xor cx, cx ; cx = offset to data
mov dx, 0FFFFh ; dx = initial crc
mov [bp+var_4], 8408h ;store poly
loc_42646:
les bx, [bp+arg_2] ; al = next byte of data
add bx, cx
mov al, es:[bx]
xor al, dl ; crclo ^= data
mov dl, al
inc cx ; increment offset to data
xor di, di ; di = bit counter (0 to 7)
jmp short loc_42672
loc_42657:
mov si, dx ; si = (crc-1)>>1
dec si ; if lsb was 0, then
mov ax, si ; si != dx later on
shr ax, 1
mov si, ax
mov ax, dx ; dx = (crc)>>1
shr ax, 1
mov dx, ax
cmp si, dx ; br if prior lsb of crc was 0
jnz short loc_42671
mov ax, dx ; crc ^= 0x8408
xor ax, [bp+var_4]
mov dx, ax
loc_42671:
inc di ; increment bit counter
loc_42672:
cmp di, 8 ; loop till byte done
jb short loc_42657
cmp cx, [bp+arg_0] ; loop till all bytes done
jb short loc_42646
mov ax, dx ; dx = ~ crc
not ax
mov dx, ax
les bx, [bp+arg_2] ; append crc to data, lsbyte first
add bx, cx
mov es:[bx], dl
inc cx
mov ax, dx
shr ax, 8
mov dx, ax
les bx, [bp+arg_2]
add bx, cx
mov es:[bx], dl
inc cx ; useless, cx gets overwritten below
pop di ; restore di, si
pop si
pop cx ; cx = poly
pop ds ; restore ds, bp
pop bp
dec bp ; bp -= 1 (undo inc bp from above)
retf
crc_cal endp
我目前正在对一个软件进行逆向工程,该软件可以为给定的数据缓冲区计算 2 字节宽的校验和。代码来自一个 16 位 DLL(NE 格式),使用 Borland C++ 编译。我怀疑校验和是具有 0x8408 多边形的 CRC-16,但我没有机会计算出相同的 CRC,所以我想知道实现是否是 "CRC16 standard"。
下面是程序集实现:
crc_cal proc far
var_4= word ptr -4
arg_0= word ptr 6
arg_2= dword ptr 8
mov ax, seg dseg37
inc bp
push bp
mov bp, sp
push ds
mov ds, ax
sub sp, 2
push si
push di
xor cx, cx
mov dx, 0FFFFh
mov [bp+var_4], 8408h
loc_42646:
les bx, [bp+arg_2]
add bx, cx
mov al, es:[bx]
xor al, dl
mov dl, al
inc cx
xor di, di
jmp short loc_42672
loc_42657:
mov si, dx
dec si
mov ax, si
shr ax, 1
mov si, ax
mov ax, dx
shr ax, 1
mov dx, ax
cmp si, dx
jnz short loc_42671
mov ax, dx
xor ax, [bp+var_4]
mov dx, ax
loc_42671:
inc di
loc_42672:
cmp di, 8
jb short loc_42657
cmp cx, [bp+arg_0]
jb short loc_42646
mov ax, dx
not ax
mov dx, ax
les bx, [bp+arg_2]
add bx, cx
mov es:[bx], dl
inc cx
mov ax, dx
shr ax, 8
mov dx, ax
les bx, [bp+arg_2]
add bx, cx
mov es:[bx], dl
inc cx
pop di
pop si
pop cx
pop ds
pop bp
dec bp
retf
crc_cal endp
以及软件计算出的带有相关 CRC(最后两个字节)的一些数据:
| DATA |Inc|CRC|
|----------------------------------------------------------|---|---|
00 00 00 00 00 00 01 ef f7 fe ef ff fd ef fb fa fd a2 aa 21 01 f4 e0
00 00 00 00 00 00 01 ef f7 fd ef ff fd fe fb fa fd a2 aa 21 02 f4 d1
00 00 00 00 00 00 01 f7 fe fd fd ff fd df ff fb fd a2 aa 21 03 f4 cd
00 00 00 00 00 00 01 f7 fe fe fd ff f7 ef ff fa fd a2 aa 21 04 f4 c2
00 00 00 00 00 00 01 ef f7 fe ef ff fe ef fb fa fd a2 aa 21 05 f4 db
00 00 00 00 00 00 01 ef f7 fe ef ff fd ef fb fa fd a2 aa 21 06 f4 db
显示的数据与 crc 不对应,如之前的回答所述:
该代码是右移 CRC(在 dx 中)的过于复杂的实现,poly = 0x8408,初始值 = 0xffff,xor out = 0xffff。检查每行之后的下 2 个字节以查看是否是附加 CRC 的位置。
带有注释的问题代码。感谢 Ross Ridge 解释 "inc bp" 用于指示涉及远调用,以防堆栈需要回溯(最后的 "dec bp" 用于撤消 "inc bp"在开头)。
crc_cal proc far
var_4 = word ptr -4 ; used to store poly
arg_0 = word ptr 6 ; number of bytes of data
arg_2 = dword ptr 8 ; far pointer to data
mov ax, seg dseg37 ; for ds that is never used
inc bp ; bp += 1, (bp&1 == far call indicator)
push bp ; save bp+1
mov bp, sp ; bp = sp, base for the equated offsets
push ds ; save ds
mov ds, ax ; ds = dseg37 (never used)
sub sp, 2 ; allocate space for poly (var_4)
push si ; save si, di
push di
xor cx, cx ; cx = offset to data
mov dx, 0FFFFh ; dx = initial crc
mov [bp+var_4], 8408h ;store poly
loc_42646:
les bx, [bp+arg_2] ; al = next byte of data
add bx, cx
mov al, es:[bx]
xor al, dl ; crclo ^= data
mov dl, al
inc cx ; increment offset to data
xor di, di ; di = bit counter (0 to 7)
jmp short loc_42672
loc_42657:
mov si, dx ; si = (crc-1)>>1
dec si ; if lsb was 0, then
mov ax, si ; si != dx later on
shr ax, 1
mov si, ax
mov ax, dx ; dx = (crc)>>1
shr ax, 1
mov dx, ax
cmp si, dx ; br if prior lsb of crc was 0
jnz short loc_42671
mov ax, dx ; crc ^= 0x8408
xor ax, [bp+var_4]
mov dx, ax
loc_42671:
inc di ; increment bit counter
loc_42672:
cmp di, 8 ; loop till byte done
jb short loc_42657
cmp cx, [bp+arg_0] ; loop till all bytes done
jb short loc_42646
mov ax, dx ; dx = ~ crc
not ax
mov dx, ax
les bx, [bp+arg_2] ; append crc to data, lsbyte first
add bx, cx
mov es:[bx], dl
inc cx
mov ax, dx
shr ax, 8
mov dx, ax
les bx, [bp+arg_2]
add bx, cx
mov es:[bx], dl
inc cx ; useless, cx gets overwritten below
pop di ; restore di, si
pop si
pop cx ; cx = poly
pop ds ; restore ds, bp
pop bp
dec bp ; bp -= 1 (undo inc bp from above)
retf
crc_cal endp