64-битный привет Крис Касперски ака мыщъх Хакер, номер #083, стр. 083-118-7 section '.idata' import data readable writeable dd 0,0,0,RVA kernel_name,RVA kernel_table dd 0,0,0,RVA user_name,RVA user_table dd 0,0,0,0,0 ; завершаем список двумя 64-разряными нулеми!!! kernel_table: ExitProcess dq RVA _ExitProcess dq 0 ; завершаем список 64-разряным нулем!!! user_table: MessageBox dq RVA _MessageBoxA dq 0 kernel_name db 'KERNEL32.DLL',0 user_name db 'USER32.DLL',0 _ExitProcess dw 0 db 'ExitProcess',0 _MessageBoxA dw 0 db 'MessageBoxA',0 Ассемблируем файл (fasm PE64DEMO.ASM) и запустим образовавшийся EXE на выполнение. Под 32-разрядной Windows он, естественно, не запустится. Вдоволь наигравшись нашем первым x86-64 файлом, загрузим его в дизассемблер (например, в IDA Pro 4.7. Она хоть и материться, предлагая использовать специальную 64-битную версию, но при нажатии на yes все корректно дизассемблирует, во всяком случае до тех пор, пока не столкнется с подлинным 64-битным адресом или операндом, с которым произойдет обрезание, в частности, mov r9,1234567890h дизассемблируется, как mov r9, 34567890h, так что переход на 64-битную версию IDA все же очень желателен, тем более, что начиная с IDA 4.9 она входит в базовую поставку). Посмотрим, что у нашей программы внутри? [дизассемблерный листинг 64-битного приложения hello, world!] .code:0000000000401000 41 B9 00 00 00 00 mov r9d, 0 .code:0000000000401006 4C 8D 05 F3 0F 00 00 lea r8, aPENUMBRA .code:000000000040100D 48 8D 15 03 10 00 00 lea rdx, aHelloWorld ; "Hello World!" .code:0000000000401014 48 C7 C1 00 00 00 00 mov rcx, 0 .code:000000000040101B FF 15 2B 20 00 00 call cs:MessageBoxA .code:0000000000401021 89 C1 mov ecx, eax .code:0000000000401023 FF 15 13 20 00 00 call cs:ExitProcess Что ж, довольно громоздко, объемно и концептуально. Для сравнения, дизассемблированный листинг аналогичного 32-разрядного файла приведен ниже. Старый x86 код в 1,6 раз короче! А ведь это только демонстрационная программа из нескольких строк! На полновесных приложениях разрыв будет только нарастать! Так что не стоит злоупотреблять 64-разрядным кодом без необходимости. Его следует использовать только там, где 64-битная арифметика и 8 дополнительных регистров действительно дают ощутимый выигрыш. Например, в математических задачах или программах для вскрытия паролей. [дизассемблерный листинг 32-битного приложения hello, world!] code:00401000 6A 00 push 0 code:00401002 68 00 20 40 00 push offset aPENUMBRA code:00401007 68 17 20 40 00 push offset aHelloWorld code:0040100C 6A 00 push 0 code:0040100E FF 15 44 30 40 00 call ds:MessageBoxA code:00401014 6A 00 push 0 code:00401016 FF 15 3C 30 40 00 call ds:ExitProcess В качестве заключительного упражнения перепишем наше приложение в стиле MASM, поклонников которого нужно не бить, а уважать. Никаких радикальных отличий не наблюдается: [64-битное приложение hello, world под Windows на MASM'е] ; объявляем внешние API-функции, которые мы будем вызывать extrn MessageBoxA: PROC extrn ExitProcess: PROC ; секция данных с атрибутами по умолчанию (чтение и запись) |