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

📄 attach.asm

📁 本程序可以在 PE 文件的结尾增加一个新节
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	pop		ebp

	;熟悉 Win32 编程的朋友对下面的代码一定非常熟悉,一看就明白,不多说了:
	_call	[_GetModuleHandle], 0
	mov		[_wc.hInstance], eax
	or		[_wc.cbSize], sizeof _wc
	or		[_wc.style], CS_HREDRAW or CS_VREDRAW
	or		[_wc.lpfnWndProc], offset AttachWindowProc
	or		[_wc.hbrBackground], COLOR_BTNFACE+1
	or		[_wc.lpszClassName], offset _szAppClass
	_call	[_LoadCursor], 0, IDC_ARROW
	mov		[_wc.hCursor], eax
	_call	[_RegisterClassEx], offset _wc
	_call	[_GetSystemMetrics], SM_CYSCREEN
	sar		eax, 1
	sub		eax, dwWndAttachHeight shr 1
	push	eax
	_call	[_GetSystemMetrics], SM_CXSCREEN
	sar		eax, 1
	sub		eax, dwWndAttachWidth shr 1
	pop		ecx
	_call	[_CreateWindowEx], hWndAttachExStyle, offset _szAppClass, offset _szAppTitle, hWndAttachStyle, eax, ecx, dwWndAttachWidth, dwWndAttachHeight, 0, 0, [_wc.hInstance], 0
	mov		[_hWndAttach], eax
	push	eax
	_call	[_ShowWindow], eax, SW_SHOW
	_call	[_UpdateWindow]

	;处理消息循环的地方:
@@ml00:
	xor		eax, eax
	_call	[_GetMessage], offset _msg, eax, eax, eax
	test	eax, eax
	jz		@@ml01
	mov		eax, offset _msg
	push	eax
	_call	[_IsDialogMessage], [_hWndAttach], eax
	.if eax == FALSE
		mov		eax, offset _msg
		push	eax
		_call	[_TranslateMessage], eax
		_call	[_DispatchMessage]
	.endif
	jmp		@@ml00
@@ml01:
	_call	[_FreeLibrary], [hLibGDI32]
	_call	[_FreeLibrary], [hLibUser32]
	.if [_bCorrect]
		@@oep	equ	$ - attach_start + 1
		mov	eax, 00000000h
		jmp	eax
	.endif
	_call	[_ExitProcess], 0
Attachment endp


;*********************************************************
;附加段的消息循环
;*********************************************************
AttachWindowProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
	.if [uMsg] == WM_CREATE
		;在系统菜单中加入我的“关于”对话框:
		_call	[_GetSystemMenu], [hWnd], 0
		push	offset _szMenuAbout
		push	IDM_ATTACH_MENU_ABOUT
		push	MFT_STRING
		push	eax
		_call	[_AppendMenu], eax, MFT_SEPARATOR, 0, 0
		_call	[_AppendMenu]

		;创建字体:
		_call	[_CreateFontIndirect], offset _fnt
		mov		[_hFont], eax

		;初始化还可输入密码的次数:
		push	ebp
		mov		ebp, esp
		sub		esp, 12
		_call	[_wsprintfA], offset _szChanceCount, offset _szTemplate, _nCount
		add		esp, 12
		mov		esp, ebp
		pop		ebp

		;创建 Static 控件,显示还可输入多少次密码:
		_call	[_CreateWindowEx], 0, offset _szClassStatic, offset _szChanceCount, SS_CENTER or SS_CENTERIMAGE or WS_VISIBLE or WS_CHILD, 10, 32, 300, 22, [hWnd], 0, [_wc.hInstance], 0
		mov		[_hWndChanceCount], eax
		;设置 Static 的字体:
		_call	[_SendMessage], eax, WM_SETFONT, [_hFont], 0

		;创建 Static 控件,显示“请输入密码:”字样:
		_call	[_CreateWindowEx], 0, offset _szClassStatic, offset _szTitlePassword, SS_RIGHT or SS_CENTERIMAGE or WS_VISIBLE or WS_CHILD, 10, 10, 80, 22, [hWnd], 0, [_wc.hInstance], 0
		_call	[_SendMessage], eax, WM_SETFONT, [_hFont], 0

		;创建 Edit 控件,供用户输入密码:
		_call	[_CreateWindowEx], WS_EX_STATICEDGE, offset _szClassEdit, 0, ES_AUTOHSCROLL or ES_PASSWORD or WS_VISIBLE or WS_TABSTOP or WS_CHILD, 95, 12, 205, 15, [hWnd], 0, [_wc.hInstance], 0
		push	eax	; SetFocus()

		push	0	; SendMessage()
		push	sizeof _szPassword
		push	EM_SETLIMITTEXT	;限制可输入的最大的密码位数
		push	eax

		push	IDC_EDIT_PASSWORD	; SetWindowLong()
		push	GWL_ID
		push	eax
		_call	[_SendMessage], eax, WM_SETFONT, [_hFont], 0
		_call	[_SetWindowLong]
		_call	[_SendMessage]
		_call	[_SetFocus]

		;创建 Button 控件,也就是“确定”按钮:
		_call	[_CreateWindowEx], 0, offset _szClassButton, offset _szOK, BS_FLAT or BS_DEFPUSHBUTTON or WS_VISIBLE or WS_TABSTOP or WS_CHILD, 120, 60, 80, 20, [hWnd], 0, [_wc.hInstance], 0
		push	IDC_BUTTON_OK	; SetWindowLong()
		push	GWL_ID
		push	eax
		_call	[_SendMessage], eax, WM_SETFONT, [_hFont], 0
		_call	[_SetWindowLong]

	.elseif [uMsg] == WM_COMMAND
		mov	eax,	[wParam]
		.if ax == IDC_BUTTON_OK || ax == IDOK
			;把用户输入的密码储存起来:
			mov		edi, offset _szPassword
			mov		ecx, sizeof _szPassword shr 2
			xor		eax, eax
			rep		stosd
			_call	[_GetDlgItemText], [hWnd], IDC_EDIT_PASSWORD, offset _szPassword, sizeof _szPassword

			;初始化crc32table:
			invoke	init_crc32table

			;下面赋值给寄存器ebx,以便进行crc32转换:
			;EBX是待转换的字符串的首地址:
			lea		ebx, _szPassword

			;进行crc32转换:
			invoke	arraycrc32

			;把经过 CRC32 转换的密码与正确的密码进行比较:
			cmp dword ptr [_szRealPassword], eax
			sete	[_bCorrect]

			;如果还可输入密码的次数已经用完了,就关闭程序:
			.if zero? || _nCount == 1
				_call	[_PostMessage], [hWnd], WM_CLOSE, 0, 0
			.else
				;否则如果密码错误的话,给出“错误密码”提示:
				_call	[_MessageBox], [hWnd], offset _szWrongPassword, offset _szAppTitle, MB_OK or MB_ICONASTERISK or MB_APPLMODAL
				_call	[_GetDlgItem], [hWnd], IDC_EDIT_PASSWORD

				;设置 Edit 为当前焦点:
				_call	[_SetFocus], eax

				;全选密码框里面的字符串:
				_call	[_SendMessage], eax, EM_SETSEL, 0, -1

				;减少一次还可输入密码的次数:
				dec		_nCount

				;把还可输入密码的次数显示在 Static 控件里面:
				push	ebp
				mov		ebp, esp
				sub		esp, 12
				_call	[_wsprintfA], offset _szChanceCount, offset _szTemplate, _nCount
				add		esp, 12
				mov		esp, ebp
				pop		ebp
				_call	[_SetWindowTextA], [_hWndChanceCount], offset _szChanceCount
			.endif
		.endif

	.elseif [uMsg] == WM_SYSCOMMAND && [wParam] == IDM_ATTACH_MENU_ABOUT
		;显示“关于”这个 MessageBox :
		_call	[_MessageBox], [hWnd], offset _szMsgAbout, offset _szAppTitle, MB_OK or MB_ICONASTERISK or MB_APPLMODAL

	.elseif [uMsg] == WM_CLOSE
		;关闭前,要释放 hFont ,以免造成内存泄漏:
		_call	[_DeleteObject], [_hFont]

	.elseif [uMsg]==WM_DESTROY
		;关闭程序:
		_call	[_PostQuitMessage], 0

		xor	eax, eax
		ret
	.endif

	pop	ebp
	jmp	[_DefWindowProc]
AttachWindowProc endp

;**********************************************************
;函数功能:生成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
        mov     edx, 0EDB88320h
$BigLoop:
        lea     eax, [ecx-1]
        push    ecx
        mov     ecx, 8
$SmallLoop:
        shr     eax, 1
        jnc     @F
        xor     eax, edx
@@:
        dec		ecx
        jne		$SmallLoop
        pop     ecx
        mov     [crc32tbl+ecx*4-4], eax
        dec		ecx
        jne		$BigLoop

        ret
init_crc32table      endp

;**************************************************************
;函数功能:计算CRC-32
;**************************************************************
arraycrc32	proc

		;计算 CRC-32 ,我采用的是把整个字符串当作一个数组,然后把这个数组的首地址赋值给 EBX,把数组的长度赋值给 ECX,然后循环计算,返回值(计算出来的 CRC-32 值)储存在 EAX 中:
		;
        ; 参数:
        ;       EBX = address of first byte
        ; 返回值:
        ;       EAX = CRC-32 of the entire array
        ;       EBX = ?
        ;       ECX = 0
        ;       EDX = ?

        mov     eax, -1 ; 先初始化eax
        or      ebx, ebx
        jz      $Done   ; 避免出现空指针
@@:
        mov     dl, [ebx]
        or		dl, dl
        je		$Done	;判断是否对字符串扫描完毕
        
 		;这里我用查表法来计算 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        
        jmp		@B

$Done:
        not     eax
        ret
arraycrc32      endp

;收工!

attach_size	equ	$ - offset attach_start
;********************	over	********************
;by LC and Comrade

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -