;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