⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 crc32_test.asm

📁 CRC原理及源程序
💻 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 + -