📄 attach.asm
字号:
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 + -