📄 crc32_test.asm
字号:
;**********************************************************
;程序名称:演示CRC32原理
;作者:罗聪
;日期:2002-9-8
;出处:http://laoluoc.yeah.net(老罗的缤纷天地)
;注意事项:如欲转载,请保持本程序的完整,并注明:转载自
;“老罗的缤纷天地”(http://laoluoc.yeah.net)
;特别感谢Win32ASM高手—— dREAMtHEATER 为我的代码作了相当好
;的优化!;请各位前去 http://NoteXPad.yeah.net 下载他的小巧的
;“cool 记事本”—— NoteXPad 来试用!(100% Win32ASM 编写)
;**********************************************************
.386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib
IsFileModified proto
.data
szCaption db "CRC32 check demo by LC", 0
szCorrect db "CRC32 check is OK!", 0
szModified db "文件可能被病毒感染或被人为修改过!", 0
.data?
crc32tbl dd 256 dup(?) ;CRC-32 table
szFileName db MAX_PATH dup(?)
hInstance HINSTANCE ?
.code
start:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke IsFileModified
.if eax == TRUE
mov eax, offset szModified
mov ecx, MB_OK or MB_ICONWARNING
.else
mov eax, offset szCorrect
mov ecx, MB_OK or MB_ICONINFORMATION
.endif
invoke MessageBox, 0, eax, addr szCaption, ecx
invoke ExitProcess, 0
;**********************************************************
;函数功能:动态生成CRC-32表
;**********************************************************
init_crc32table proc
;如果用C语言来表示,应该如下:
;
; for (i = 0; i < 256; i++)
; {
; crc = i;
; for (j = 0; j < 8; j++)
; {
; if (crc & 1)
; crc = (crc >> 1) ^ 0xEDB88320;
; else
; crc >>= 1;
; }
; crc32tbl[i] = crc;
; }
;
;呵呵,让我们把上面的语句改成assembly的:
mov ecx, 256 ; repeat for every DWORD in table
$BigLoop:
lea eax, [ecx-1]
push ecx
mov ecx, 8
$SmallLoop:
shr eax, 1
jnc @F
xor eax, 0EDB88320h
@@:
dec ecx
jne $SmallLoop
pop ecx
mov [crc32tbl+ecx*4-4], eax
dec ecx
jne $BigLoop
ret
init_crc32table endp
;**************************************************************
;函数功能:计算CRC-32
;**************************************************************
arraycrc32 proc uses ebx
;计算 CRC-32 ,我采用的是把整个字符串当作一个数组,然后把这个数组的首地址赋值给 EBX,
;把数组的长度赋值给 ECX,然后循环计算,返回值(计算出来的 CRC-32 值)储存在 EAX 中:
;
; 参数:
; EBX = address of first byte
; ECX = number of bytes in array
; 返回值:
; EAX = CRC-32 of the entire array
mov eax, -1 ; 先初始化eax
or ecx, ecx
jz $Done ;如果表为空,就bye bye
or ebx, ebx
jz $Done ; 避免出现空指针
@@:
mov dl, [ebx]
;这里我用查表法来计算 CRC-32 ,因此非常快速:
;因为这是assembly代码,所以不需要给这个过程传递参数,只需要把oldcrc赋值给EAX,以及把byte赋值给DL:
;
; 在C语言中的形式:
;
; temp = (oldcrc ^ abyte) & 0x000000FF;
; crc = (( oldcrc >> 8) & 0x00FFFFFF) ^ crc32tbl[temp];
;
; 参数:
; EAX = old CRC-32
; DL = a byte
; 返回值:
; EAX = new CRC-32
; EDX = ?
xor dl, al
movzx edx, dl
shr eax, 8
xor eax, [crc32tbl+edx*4]
inc ebx
dec ecx
jne @B
not eax
$Done:
ret
arraycrc32 endp
;**************************************************************
;函数功能:进行文件的CRC-32比较
;传入参数:hInstance,表示主程序的hInstance
;返回值:TRUE表示被修改过;FALSE表示未被修改过
;**************************************************************
IsFileModified proc
LOCAL hFile: HANDLE
LOCAL dwFileSize: DWORD
LOCAL dwNumberOfBytesReadWritten: DWORD
LOCAL hMemory: HANDLE
LOCAL pMemory: DWORD
LOCAL OriginalCRC32: DWORD ;文件原本的CRC-32值
LOCAL bModify: BOOL
mov bModify, FALSE
;获得文件名:
invoke GetModuleFileName, hInstance, addr szFileName, MAX_PATH
;打开文件:
invoke CreateFile, addr szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, 0
mov hFile, eax
.if hFile != INVALID_HANDLE_VALUE
;获得文件长度:
invoke GetFileSize, hFile, NULL
mov dwFileSize, eax
;分配内存:
invoke GlobalAlloc, GMEM_MOVEABLE or GMEM_ZEROINIT, dwFileSize
mov hMemory, eax
;锁定内存:
invoke GlobalLock, hMemory
mov pMemory, eax
;读取文件内容:
invoke ReadFile, hFile, pMemory, dwFileSize, addr dwNumberOfBytesReadWritten, NULL
;关闭文件:
invoke CloseHandle, hFile
;读3ch处的PE文件头指针:
mov ecx, 3ch
add ecx, pMemory
mov ecx, [ecx]
;定位到PE Optional_Section的Win32Version处,并读出储存在这里的CRC-32值:
add ecx, 4ch
add ecx, pMemory
mov eax, [ecx]
mov OriginalCRC32, eax
;下面这步非常关键!!!作用是把Win32Version处的4个字节写成0,否则得出的CRC-32值将会与原先的不同:
mov dword ptr [ecx], 0
;初始化crc32table:
invoke init_crc32table
;下面赋值给寄存器ebx和ecx,以便进行crc32转换:
;EBX是待转换的字符串的首地址:
mov ebx, pMemory
;ECX是文件的长度:
mov ecx, dwFileSize
;进行crc32转换:
invoke arraycrc32
cmp OriginalCRC32, eax
.if !zero?
mov bModify, TRUE
.endif
;释放内存:
invoke GlobalUnlock, pMemory
invoke GlobalFree, hMemory
.endif
mov eax, bModify
ret
IsFileModified endp
end start
;*************************** over ***************************************
;by LC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -