;WINPASS.ASM - графическое Win32-приложение демонстрирующее защиту программы паролем
;компиляция MASM:
;ml /c /coff /Cp WinPass.asm
;rc /r WinPass.rc
;link32 WinPass.obj WinPass.res /subsystem:windows
;программа использует файл ресурсов WinPass.rc
;// стили для диалога
;#define DS_CENTER 0x0800L
;#define DS_MODALFRAME 0x80L
;#define DS_3DLOOK 0x0004L
;// стили для окон
;#define WS_SYSMENU 0x00080000L
;#define WS_OVERLAPPED 0x00000000L
;// стили для редактора
;#define ES_AUTOHSCROLL 0x80L
;#define ES_LEFT 0
;#define ES_PASSWORD 0x0020L
;// идентификаторы контролов диалога
;#define IDC_EDIT 0
;#define IDC_BUTTON 1
;#define IDC_STATIC -1
;#define IDOK 1
;denta2000 DIALOG 10,10,150,40 // x, y, ширина,высота
;STYLE DS_CENTER | DS_MODALFRAME | DS_3DLOOK | WS_SYSMENU | WS_OVERLAPPED
;CAPTION "denta2000" //заголовок
;FONT 8, "MS Sans Serif" //шрифт
;BEGIN // начало списка контролов
; LTEXT "Введите пароль:",IDC_STATIC,15,2,90,8
; EDITTEXT IDC_EDIT,15,12,111,13,ES_AUTOHSCROLL | ES_LEFT | ES_PASSWORD
;END
;Идентификаторы элементов диалога(CONTROL)
IDC_EDIT equ 0
IDC_BUTTON equ 1
IDC_EXIT equ 2
IDOK equ 1
;включаемые файлы,содержащие,используемые в программе структуры,определения,константы
include struc.inc
include const.inc
include Win32API.inc
include mac.inc
.386
.model flat
.data
dialog_name db "denta2000",0 ; имя диалога в ресурсах
error db "Ошибка!",0 ; заголовок для MessageBox
pass db 'asM',0 ; слово-пароль
string db "Неправильный пароль,",0dh ;сообщение для MessageBox
db "повторите ввод пароля",0
URL db 'http://www.chat.ru/~denta2000/stomat02.htm',0
class_name db 'window class 1',0
window_name db 'DENTA2000(denta2000@chat.ru)',0
txt_1 db 'ПАРОЛЬ ВВЕДЕН' ;0 в конце не обязателен т.к. мы задаем длину строки
Mes_txt_1 = $-txt_1 ;длина строки
pa_ss db 9eh,8ch,0b2h ; "asM" в перевернутом виде
txt_2 db 'ПРАВИЛЬНО !'
Mes_txt_2 = $-txt_2
txt_3 db 'Если Вы хотите поддержать развитие'
Mes_txt_3 = $-txt_3
txt_4 db 'нашей странички, щелкните в окне'
Mes_txt_4 = $-txt_4
txt_5 db 'левой кнопкой мышки и посетите'
Mes_txt_5 = $-txt_5
txt_6 db 'наших спонсеров...'
Mes_txt_6 equ $-txt_6
ps PAINTSTRUCT <> ;структура,которая заполняеться после BeginPaint (см. файл struc.inc)
; структура описывающая класс окна
wc WNDCLASSEX <4*12,CS_HREDRAW or CS_VREDRAW,offset win_proc,0,0,?,?,?,COLOR_WINDOW+1,0,offset class_name,0>
;сегмент неинициализированных даных:
.data?
msg_ MSG <?,?,?,?,?,?> ; структура,к которой возвращаеться сообщение после GetMessage
buffer db 12 dup(?) ; буфер для вводимого текста
wmclose dd ? ; переменная для WM_CLOSE
.code
_start:
xor ebx,ebx ;в EBX будет 0 для команд push 0
; определить идентификатор нашей программы
push ebx
call GetModuleHandle
mov esi,eax ; и сохранить его в ESI
;запустить диалог
push ebx ; значение,которое перейдет как параметр WM_INITDIALOG
push offset dialog_proc ; адрес процедуры типа DialogProc
push ebx ;идентификатор окна-предка (0 - ничей диалог)
push offset dialog_name ; адрес имени диалога в ресурсах
push eax ; идентификатор программы,в ресурсах которой
; находится диалог (наш идентификатор в EAX)
call DialogBoxParam
cmp wmclose,WM_CLOSE ;если диалог был закрыт после обработки WM_CLOSE
je exit_msg_loop ;выйти из программы
; заполнить и зарегистрировать класс
mov dword ptr wc.hInstance,eax ; идентификатор предка
; выбрать иконку
push ebx ; идентификатор иконки
push ebx ; идентификатор модуля с иконкой(здесь 0 - значит объект предопределен)
call LoadIcon
mov wc.hIcon,eax ; идентификатор иконки для нашего класса
; выбрать форму курсора
push IDC_ARROW ; стандартная стрелка
push ebx ;идентификатор модуля с курсором(0 - предопределен)
call LoadCursor
mov wc.hCursor,eax ;идентификатор курсора для нашего класса
push offset wc
call RegisterClassEx ;зарегистрировать класс
;создать окно
mov ecx,CW_USEDEFAULT ; push ecx короче push N в пять раз
push ebx ; адрес структуры CREATESTRUCT (здесь NULL)
push esi ;идентификатор процесса,который будет получать сообщения от окна(т.е.наш)
push ebx ; идентификатор меню или окна-потомка
push ebx ; идентификатор окна-предка
push 430 ; высота(CW_USEDEFAULT - по умолчанию)
push 300 ; ширина
push 150 ; y-координата
push 250 ; x-координата
push 000800000 ;стиль окна WS_SYSMENU
push offset window_name ;заголовок окна
push offset class_name ; любой зарегистрированный класс
push ebx ; дополнительный стиль
call CreateWindowEx ;создать окно(EAX - идентификатор окна)
push eax ; идентификатор для UpdateWindow
push SW_SHOWNORMAL ; тип показа для ShowWindow
push eax ; идентификатор для ShowWindow
;больше идентификатор окна нам не потребуеться
call ShowWindow ;показать окно
call UpdateWindow ; и послать ему сообщение WM_PAINT
;основной цикл - проверка сообщений от окна и выход по WM_QUIT
mov edi,offset msg_ ; push edi короче push N в 5 раз
message_loop:
push ebx ; последнее сообщение
push ebx ; первое сообщение
push ebx ; идентификатор окна (0 - любое наше окно)
push edi ; адрес структуры MSG
call GetMessage ; получить сообщение от окна с ожиданием - не забывайте использовать
; PeekMessage,если нужно в этом цикле что-то выполнять
test eax,eax ; если получено WM_QUIT
jz exit_msg_loop ; выйти
push edi ;иначе преобразовать сообщения типа WM_KEYUP в сообщение типа WM_CHAR
call TranslateMessage
push edi
call DispatchMessage ; и послать их процедуре окна(иначе его нельзя будет закрыть)
jmp short message_loop ; продолжить цикл
exit_msg_loop:
;выход из программы
push ebx
call ExitProcess
; ДИАЛОГОВАЯ ПРОЦЕДУРА
; процедура dialog_proc
;вызываеться диалогом каждый раз,когда в нем что-нибуть происходит
;здесь - заложена основная логика прграммы
;процедура не должна изменять EBP,EDI,ESI и EBX !
;
dialog_proc proc near
;так как мы получаем параметры в стеке,построим стековый кадр
push ebp
mov ebp,esp
;поцедура типа DialogProc вызываеться со следующими параметрами:
dp_hWnd equ dword ptr [ebp+08h] ;идентификатор диалога
dp_uMsg equ dword ptr [ebp+0Ch] ; номер сообщения
dp_wParam equ dword ptr [ebp+10h] ; первый параметр
dp_lParam equ dword ptr [ebp+14h] ; второй параметр
mov ebx,dp_hWnd ; ЕВХ будет хранить идентификатор диалога
mov eax,dp_uMsg ; EAX - номер сообщения
cmp eax,WM_INITDIALOG ; если мы получили WM_INITDIALOG
jne not_initdialog
push IDC_EDIT
push ebx
call GetDlgItem ;определить идентификатор
push eax ; окна редактирования текста
call SetFocus ; и передать ему фокус
not_initdialog:
cmp eax,WM_CLOSE ; если мы получили WM_CLOSE
jne not_close
mov wmclose,eax ; сообщение WM_CLOSE сохранить в переменной для условного перехода
push 0
push ebx
call EndDialog ;закрыть диалог
not_close:
cmp eax,WM_COMMAND ; если мы получили WM_COMMAND
jne not_command
mov eax,dp_wParam ; EAX = wParam (номер сообщения)
cmp ax,IDC_BUTTON ; если это IDC_BUTTON
jne not_exit
push 512 ; размер буфера
push offset buffer ; адрес буфера
push IDC_EDIT ; номер контрола редактирования
push ebx
call GetDlgItemText ; считать текст в buffer
;сравнение строк байтов:
cld ;направление возрастания адресов(df=0)
mov esi,offset pass ;цепочку-источник в ESI
mov edi,offset buffer ;цепочку-приемник в EDI
mov ecx,3 ;второй операнд равен кол. символов в строке,на которую указывает pass
repe cmpsb ;сравнивать пока: не встретились разные элементы или ECX не стал равным 0
je end_dialog ;переход,если равно
push MB_OK
push offset error
push offset string ;неправильный пароль
push dp_hWnd
call MessageBox ; показать текст в MessageBox
cmp eax,IDOK ;была нажата OK?
jne not_exit
push 0 ; NULL
push IDC_EDIT ; номер контрола
push dp_hWnd
call SetDlgItemText ; установить новый текст
push IDC_EDIT
push dp_hWnd
call GetDlgItem
push eax
call SetFocus ;передать ему фокус
jmp not_close
end_dialog:
push 0
push dp_hWnd
call EndDialog ;закрыть диалог
not_exit:
xor eax,eax ; после обработки команды
inc eax ; DialogProc должен возвращать TRUE (eax=1)
mov esp, ebp
pop ebp ; восстановить ebp
ret 16 ; конец процедуры
not_command: ; сюда передается управление,если мы получили,
; какое-то незнакомое сообщение
xor eax,eax ; код возврата FALSE (eax=0)
mov esp, ebp
pop ebp ; восстановить ebp
ret 16 ; конец процедуры
dialog_proc endp
; ОКОННАЯ ПРОЦЕДУРА
; процедура win_proc
; вызываеться каждый раз, когда окно получает какое-то сообщение
; процедура не должна изменять регистры EBP,EDI,ESI и EBX !
win_proc proc
;так-как мы получаем параметры в стеке построить стековый кадр
push ebp
mov ebp,esp
pusha ;сохранить все регистры
xor ebx, ebx ;в EBX будет 0 для команд push 0
mov edx, wp_hWnd ;для команд push hWnd
mov eax, wp_uMsg ;номер сообщения в eax
;процедура типа WindowProc вызываеться со следующими параметрами:
wp_hWnd equ dword ptr [ebp+08h] ; идентификатор окна
wp_uMsg equ dword ptr [ebp+0Ch] ; номер сообщения
wp_wParam equ dword ptr [ebp+10h] ; первый параметр
wp_lParam equ dword ptr [ebp+14h] ; второй параметр
hdc equ dword ptr [ebp-04h] ; локальная переменная для hDC
;обработка сообщений
cmp eax, WM_DESTROY ;сообщение WM_DESTROY? (окно удалили с экрана)
je wmdestroy ;если равно - переход на обработку сообщения WM_DESTROY
cmp eax, WM_PAINT ; сообщение WM_PAINT? (перерисовать содержимое окна)
je wmpaint ;если равно - переход на метку wmpaint
cmp eax, WM_LBUTTONDOWN ; нажата левая кнопка мыши
je wmlbuttondown
jmp default ; обработчик по умолчанию
;обработка сообщения WM_PAINT:
wmpaint:
;получение контекста устройства
push offset ps ;адрес структуры PAINTSTRUCT
push edx ;идентификатор окна
call BeginPaint
mov hdc, eax ;сохраняем его в переменной
;вывод строки в заданное место окна,используем макрокоманду string_out (см.файл mac.inc)
string_out Mes_txt_1, txt_1,50,70
string_out Mes_txt_2, txt_2,90,80
string_out Mes_txt_3, txt_3,160,10
string_out Mes_txt_4, txt_4,185,10
string_out Mes_txt_5, txt_5,210,10
string_out Mes_txt_6, txt_6,235,10
;освободить контекст
push offset ps
push hdc ;контекст устройства
call EndPaint
jmp short end_procedure
;нажата левая кнопка мыши:
wmlbuttondown:
;запускает,установленный по умолчанию броузер,по адресу,указанному в URL
xor ebx,ebx
push ebx ; для исполнимых файлов - способ показа
push ebx ; рабочая директория
push ebx ; командная строка
push offset URL ; имя файла с путем
push ebx ; операция open
push ebx ; идентификатор окна,которое получит сообщения
call ShellExecute
jmp short end_procedure
;уничтожение окна
wmdestroy:
push ebx ; код выхода (здесь 0)
call PostQuitMessage ; послать WM_QUIT
mov eax, 0
jmp short end_procedure ; выйти из процедуры
default:
;обработчик по умолчанию
popa ;восстановить все регистры
mov esp, ebp
pop ebp ; восстановить ebp
jmp DefWindowProc ; и вызвать DefWindowProc с нашими параметрами и адресом возврата
; в стеке
;конец процедуры
end_procedure:
popa ;восстановить все регистры
mov esp, ebp
pop ebp ;весстановить ebp
ret ; и вернуться самим, очистив стек от параметров
win_proc endp
end _start