Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #83, НОЯБРЬ 2005 г.

64-битный привет

Крис Касперски ака мыщъх

Хакер, номер #083, стр. 083-118-6


Ниже идет пример простейшей x86-64 программы, которая не делает ничего, только возвращает в регистре RAX значение 0.

; сообщаем FASM'у, что мы хотим программировать на x86-64

use64

xor r9,r9 ; обнуляем регистр r9

mov rax,r9 ; пересылаем в rax,r9 (можно сразу mov rax,0, но неинтересно)

ret ; выходим туда откуда пришли

Никаких дополнительных аргументов командной строки указывать не надо, просто сказать fasm file-name.asm и все! Через мгновение образуется файл file-name.bin, который в hex-представлении выглядит следующим образом:

[дизассемблерный листинг простейшей 64-битной программы]

4D 31 C9 xor r9, r9

4C 89 C8 mov rax, r9

C3 retn

Формально, это типичный com-файл, вот только запустить его не удастся (во всяком случае, ни одна популярная ось его не съест) и необходимо замутить законченный ELF или PE, в заголовке которого будет явно прописана нужная разрядность.

Начиная с версии 1.64, ассемблер FASM поддерживает специальную директиву format PE64", автоматически формирующую 64-разрядный PE-файл (директиву use64 в этом случае указывать уже не нужно), а в каталоге EXAMPLES можно найти готовый пример PE64DEMO, в котором показано, как ее использовать на практике.

Ниже приведен пример x86-64 программы hello, world" с комментариями:

[64-битное приложение "hello, world" под Windows на FASM'е]

; пример 64-битного PE файла

; для его выполнения необходимо иметь Windows XP 64-bit edition

; указываем формат

format PE64 GUI

; указываем точку входа

entry start

; создать кодовую секцию с атрибутами на чтение и исполнение

section '.code' code readable executable

start:

mov r9d,0 ; uType == MB_OK (кнопка по умолчанию)

; аргументы по соглашению x86-64

; передаются через регистры, не через стек!

; префикс d задает регистр размером в слово,

; можно использовать и mov r9,0, но тогда

; машинный код будет на байт длиннее

lea r8,[_caption] ; lpCaption передаем смещение

; команда lea занимает всего 7 байт,

; а mov reg, offset - целых 11, так что

; lea намного более предпочтительна

lea rdx,[_message] ; lpText передаем смещение выводимой строки

mov rcx,0 ; hWnd передам дескриптор окна владельца

; (можно также использовать xor rcx, rcx,

; что на три байта короче)

call [MessageBox] ; вызываем функцию MessageBox

mov ecx,eax ; заносим в ecx результат возврата

; (Функция ExitProcess ожидает 32-битный параметр

; можно использовать и mov rcx, rax, но это будет

; на байт длиннее)

call [ExitProcess] ; вызываем функцию ExitProcess

; создать секцию данных с атрибутами на чтение и запись

; (вообще-то в данном случае атрибут на запись необязателен,

; поскольку мы ничего не пишем, а только читаем)

section '.data' data readable writeable

_caption db 'PENUMBRA is awesome!',0 ; ASCIIZ-строка заголовка окна

_message db 'Hello World!',0 ; ASCIIZ-строка выводимая на экран

; создать секцию импорта с атрибутами на чтение и запись

; (здесь атрибут на запись обязателен, поскольку при загрузке PE-Файла

; в секцию импорта ; будут записываться фактические адреса API-функций)

Назад на стр. 083-118-5  Содержание  Вперед на стр. 083-118-7