Это очень легко. Мы должны
Это очень легко. Мы должны использовать функцию API "MessageBoxA", поэтому мы определяем ее с помощью команды "extrn", а затем помещаем параметры в стек и вызываем эту функцию. Обратите внимание, что строки должны быть в формате ASCIIZ (ASCII, 0). Помните, что параметры должны помещаться в стек в перевернутом порядке.
;---[ CUT HERE ]-------------------------------------------------------------
.386 ; Процессор (386+) .model flat ; Использует 32-х битные ; регистры
extrn ExitProcess:proc ; Функции API, которые extrn MessageBoxA:proc ; использует программа
;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; ; С помощью директивы "extrn" мы указываем, какие API мы будем использовать; ; ExitProcess возвращает контроль операционной системе, а MessageBoxA ; ; показывает классическое виндовозное сообщение. ; ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·;
.data szMessage db "Hello World!",0 ; Message for MsgBox szTitle db "Win32 rocks!",0 ; Title of that MsgBox
;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; ; Здесь мы не будем помещать данные настоящего вируса. Фактически, только ; ; из-за того, что TASM отказывается ассемблировать код, если мы не поместим; ; здесь какие-нибудь данные. Как бы то ни было... Помещайте здесь данные ; ; 1-го поколения носителя вашего вируса. ; ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·;
.code ; Поехали!
HelloWorld: push 00000000h ; Стиль MessageBox push offset szTitle ; Заголовок MessageBox push offset szMessage ; Само сообщение push 00000000h ; Хэндл владельца
call MessageBoxA ; Вызов функции
;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; ; int MessageBox( ; ; HWND hWnd, // хэндл окна-владельца ; ; LPCTSTR lpText, // адрес текста сообщения ; ; LPCTSTR lpCaption, // адрес заголовка MessageBox'а ; ; UINT uType // стиль MessageBox'а ; ; ); ; ; ; ; Мы помещаем параметры в стек до вызова самой API-функции, и если вы ; ; помните, стек построен согласно принципу LIFO (Last In First Out), ; ; поэтому мы должны помещать параметры в перевернутом порядке (при всем ; ; уважении к автору данного туториала, я должен сказать, что он не прав ; ; вовсе не поэтому мы должны помещать данные в перевернутом порядке - прим.; ; пер.). Давайте посмотрим на краткое описание каждого из параметров этой ; ; функции: ; ; ; ; ¦ hWnd: идентифицирует окно-владельца messagebox'а, который должен быть ; ; создан. Если этот параметр равняется NULL, у окна с сообщением не будет; ; владельца. ; ; ¦ lpText: указывает на ASCIIZ-строку, содержащую сообщение, которое нужно; ; отобразить. ; ; ¦ lpCaption: указывает на ASCIIZ-строку, содержащую заголовок окна ; ; сообщения. Если этот параметр равен NULL, будет использован заголовок ; ; по умолчанию. ; ; ¦ uType: задает флаги, которые определяют содержимое и поведение ; ; диалогового окна. Это параметр может быть комбинацией флагов. ; ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·;
push 00000000h call ExitProcess
;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·; ; VOID ExitProcess( ; ; UINT uExitCode // код выхода для всех ветвей ; ; ); ; ; ; ; Эта функция эквивалентна хорошо известному Int 20h или функциям 00, 4С ; ; Int 21h. Она просто завершает выполнение текущего процесса. У нее только ; ; один параметр: ; ; ; ; ¦ uExitcode: задает код выхода для процесса и всех ветвей, выполнение ; ; которых будет прервано вызовом данной функции. Используйте функцию ; ; GetExitCodeProcess, чтобы получить код возврата процесса, а функцию ; ; GetExitCodeThread, чтобы получить код возврата треда. ; ;-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·;
end HelloWorld
;---[ CUT HERE ]-------------------------------------------------------------
Как вы можете видеть, это все очень просто программируется. а теперь, когда вы знаете, как сделать "Hello, world!", вы можете заразить весь мир ;).