Самый маленький эльф Крис Касперски ака мыщъх Хакер, номер #090, стр. 090-110-5 xorl %ebx,%ebx ; // код возврата int $0x80 ; // exit(0); .data msg: .ascii "hello,elf\n" len = . - msg Пара замечаний к программе. Инструкция "MOVL $1,%EBX" занимает пять байт, но при желании ее можно ужать до трех: "XORL %EBX,%EBX", "INCL %EBX", однако, учитывая размер служебных полей elf-файла, выигрыш не составит и доли процента, так что над оптимизацией кода можно не напрягаться. Сборка для всех систем осуществляется следующим образом: $ as -о elf_80h.o elf_80h.S $ ld -s -o elf_80h elf_80h.o Под Linux'ом размер файла составляет всего 388 байт, под FreeBSD слегка отстает — 452 байта (сказываются разные версии трансляторов и линкеров). Под Linux файл запускается сразу же и без вопросов, а вот под FreeBSD требует предварительной эмуляции: $ brandelf -t Linux elf_80h $ ./elf_80h hello,elf Кстати, под Linux'ом существует альтернативный вариант автоматической сборки при помощи все того же gcc, запущенного с ключом "-nostartfiles", но в этом случае размер полученного файла (даже после стрипа) будет составлять 928 байт, а это плохо (тем не менее, все равно меньше, чем с использованием libc). Конструирование elf'а Программирование без libc значительно сокращает размер программ, однако полученные файлы все равно остаются большими и толстыми. Самый крошечный эльф, который нам только удалось получить, весит целых 388 байт, и это притом, что он не насчитывает и десятка ассемблерных команд. Что же в нем такое содержится? Возьмем любой hex-редактор и посмотрим. Нашему взору представится одна вода, то есть нули, "заботливо" вставленные тупым линкером. А что если отказаться от услуг линкера и попробовать соорудить elf-файл голыми руками? Для этого нам, во-первых, потребуется подробное описание всех служебных структур elf'а (последний draft лежит здесь www.caldera.com/developers/gabi/), а во-вторых, транслятор, умеющий генерировать двоичные файлы, например NASM, входящий в большинство Linux-дистрибутивов, но, к сожалению, не в BSD. Во всяком случае, его всегда можно скачать с "родной" страницы проекта: nasm.sf.net. Исполняемый elf-файл нуждается в двух структурах: elf-header'e, описывающим основные параметры файла (платформа, адрес точки входа и т.д.) и program header table, перечисляющего все сегменты. Как минимум, должен быть один сегмент с правами на чтение, запись и исполнение. Наконец, чтобы elf заработал, требуется добавить "боевую начинку", то есть непосредственно сам ассемблерный код. Минимальный адрес, с которого в UNIX-системах может загружаться elf, равен 8048000h, поэтому нам понадобится директива ORG, задающая начальное смещение в файле. Остается только изучить документацию и заполнить все служебные структуры соответствующим образом: Ассемблерный файл elf_tiny.asm, сконструированный голыми руками BITS 32 org 8048000h ... _start: mov eax,4 ; // системный вызов #4 "write" xor ebx,ebx inc ebx ; // 1 - STDOUT push ebx mov ecx,msg ; // смещение выводимой строки mov edx,msg_end-msg ; // длина строки int 80h ; // write(stdout, msg, len); pop eax ; // системный вызов #1 "exit" |