Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Низкоуровневое программирование для дZeнствующих #0040


Информационный Канал Subscribe.Ru

Нiзкоуровнђвое программiрованiе для Дzђnствующих
#0028h

|| wasm.ru || forum || Пролог || Гарри Поттер || Ассемблер в Unix || Ассеблер в *nix ||Эпилог ||

# Пролог


FatMoon / HI-TECH

 


Marlyn

Ассемблер в Unix

#Введение

Так исторически сложилось, что программирование на ассемблере под unix почти не востребовано, и занимаются им только кодеры-маньяки, дзен-буддисты и прочие настоящие ассемблерщики.

Настоящий ассемблерщик - зверь крайне редкий, практически нигде и не встретишь его, разве что в заповеднике - wasm.ru. Unix-ассемблерщик еще более редкий подвид, практически вымерший, если не считать, западный, linuxassembly.org.

Для исправления такой плачевной ситуации, и была написана эта статья, а точнее цикл статей, которые по задумке автора, должны привлечь в ряды адептов-юникс-дзена множество новых членов.

В первой части (которую вы сейчас читаете) я имею честь познакомить вас с прекрасным миром unix-программирования, что выльется в написание простейшего helloworld. В следующей части - мы разберем несколько, более сложных примеров. И под конец, наверное, будет программирование под x-windows.

#Инструменты

Для нормально функционирования нам понадобятся следующие вещи:

  1. Собственно какая-либо unix-совместимая ось. (например linux, или лучше FreeBSD ),
  2. Компилятор fasm. ( www.flatassembler.net )
  3. Линкер ld ( есть почти в любом дистрибутиве unix ),
  4. Особый склад ума, причем последнее - самое главное. Если у вас этого нет, то ни один, даже самый последний RedHat на пару со свежим fasm'ом вам не поможет.

И еще, о компиляторах - в unix обычно используются AS с AT&T синтаксисом, который для многих людей, выросших на tasm'е и masm'е, кажется полной абракадаброй. Поэтому, для начала, мы будем использовать привычные компиляторы с Intel'овским синтаксисом (fasm или nasm). Хотя позже, если найдутся желающие, можно будет рассмотреть и AT&T asm.

#Общие сведения

Unix, который мы будем использовать - 32 битная система, работающая в защищенном режиме, и использующая плоскую модель памяти.

Как и большинство операционных систем, Unix предоставляет программе набор различных функций (по другому - Api). Но, в отличие от, например, WinAPI, где вызовы производятся с помощью call'ов, в unix - больше свободы: можно вызывать функция ядра напрямую, а можно использовать многочисленные библиотеки. Рассмотрим для начала первый способ.

Системный вызов производится с помощью прерывания 0x80 (чаще всего). К сожалению, (а может и к счастью) существует несколько конвенций вызова, что приводит к несовместимости кода между многими unix-like осями. Я рассмотрю только две, самые популярные платформы: Linux и *BSD.

FreeBSD (а также OpenBSD и NetBSD)

Эта система использует традиционную unix конвенцию вызова: номер функции помещается в eax, параметры в стек, вызов производится с помощью функции содержащей int 0x80, а результат возвращается в eax.
Наверное, понятнее будет, если рассмотреть это на примере:

 sys_call:
int 0x80
ret
start:
push msg_len ; размер строки
push msg ; адрес строки
push 1 ; stdout
mov eax,4 ; номер системной функции - sys_write
call sys_call
add esp,4*3 ; очищаем за собой стек

Впрочем, от функции sys_call можно отказаться, достаточно просто помещать в стек лишний dword:

start:
push msg_len ; размер строки
push msg ; адрес строки
push 1 ; stdout
mov eax,4 ; номер системной функции - sys_write
push eax ; все что угодно
int 0x80
add esp,4*3 ; очищаем за собой стек

Также FreeBSD поддерживает конвенцию вызова, применяемую в linux. Для это необходимо включить linux emulation. Еще эта эмуляция потребуется для запуска fasm. А еще нужна утилита brandelf (наверняка она у вас есть). Дело в том, что пока не существует версии fasm’а конкретно для BSD систем. Но это легко исправить, вот так:

Brandelf –t Linux fasm

Если это не сработает (а такое возможно из-за не совместимости форматов), придется перекомпилировать fasm, заменив формат файла “format PE executable” на простой “format ELF”, а потом слинковать ld.

 

Linux
В линуксе используется fastcall конвенция. Номер функции, все так же,
помещается в eax, а вот параметры, вместо стека, помещаются в регистры. Пример:

              mov  edx,msg_len
mov ecx,msg
mov ebx,1
mov eax,4
int 0x80

Порядок размещения параметров такой:

№ параметра Регистры
1
ebx
2 ecx
3 edx
4
esi
5
edi
6 ebp

Как видите максимальное количество параметров - 6. Если их больше,
приходиться помещать все параметры в структуру и передавать ее адрес в ebx.

 

#Описание системных функций

После того как вы разобрались с вызовом функций, будет логичным вопрос: "А где взять описание этих самых функций?".

Ничего похожего на msdn, в unix среде к сожалению не существует, но не нужно забывать: unix - система с открытым исходном кодом и все нужное, можно найти там.

Для linux:
arch/i386/kernel/entry.S
include/asm-i386/unistd.h
include/linux/sys.h
Для FreeBSD:
i386/i386/exception.s
i386/i386/trap.c
sys/syscall.h

Для каждой функции можно посмотреть описание, используя man(2).

 

#Пример программы. Hello world

Пришло время написать, тот самый, жутко всем надоевший - HelloWorld.

Я приведу пример только FreeBSD версии, переписать это под linux - будет вашим домашним заданием. (для самых ленивых - см. примеры к статье)

------------------[cut]-----------------------------------

format ELF 
section '.text' executable 
public _start
_start: 
              push msg_len   ; size of message             
              push msg       ; offset of message 
              push 1         ; stdout
              mov  eax,4     ; 4 =  sys_write
              push eax       
              int  0x80      
              add  esp,4*3   ; очищаем за собой стэк

              xor  eax,eax
              push eax       ; код выхода
              inc  eax       ; 1 = sys_exit
              int  0x80               

section '.data' writeable 

              msg db "Hello world",0
              msg_len = $-msg

------------------[end cut]-------------------------------
      

Сборка.
Сначала скомпилируем файл, вот так:

  fasm hello.asm hello.o

А потом слинкуем:

  ld -o hello hello.o

А теперь посмотрите на размер. 600 байт, впечатляет?! ( размер можно еще очень сильно уменьшить, но об этом, как-нибудь в другой раз)

 

#Использование библиотеки libc

Некрасивый и совсем не дзенский способ, но все же мы его рассмотрим - для полноты картины.

Итак, libc (c library) - это стандартная библиотека с для UNIX. Она содержит в себе кучу полезных функций, типа printf, и используется почти во всех обычных программах (кстати сказать, многие функции этой библиотеки - простые обертки над вызовами ядра).

В FASMе существуют удобные макросы, для вызова си функций..., но я не буду их использовать, отдав предпочтение чистому ассемблеру.

Пример:


------------------[cut]-----------------------------------
format ELF
section '.text' executable

extrn printf

public main
main:
        push msg
        call printf
        add  esp,4
        ret

section '.data' writeable

        msg db "Hello world!\n",0 
------------------[end cut]-------------------------------
      

Компилируется это дело так:

   fasm hellolib.asm hellolib.o
   gcc -o hellolib hellolib.o

Заключение.

Ну вот вы и написали свою первую программу на ассемблере под UNIX.

Все на много проще чем кажется, неправда ли?

Eсли у вас возникнут какие-либо вопросы, пишите мне на adain@mail.ru, или на форум WASM.RU.

До встречи.

(c) 2003, marlyn adain@mail.ru


Broken Sword / [HI-TECH]

Ассеблер в *nix – удел извращенца..?

A lot of people ask me..
stupid fuckin questions.
A lot of people think that..
ассемблера в *nix не существует.
(С) типа Eminem

Да, асм в *nix таки существует. Просто многие в это почему-то отказываются верить. Данная статья скромно претендует развеять все мифы и загадки вокруг этого загадочного явления. Не ищите здесь подробного описания AT&T синтаксиса и системных вызовов – я просто попробую описать те трудности и невзгоды, которые обязательно придется преодолеть смельчаку, желающему полностью овладеть *nix-ом через асм (в смысле - научиться программировать на асме под *nix, прим. для CyberManiac-а :) ).

Миф I:

“Синтаксис асма под *nix в корне отличается от оного под DOS/WIN, он кривой и к нему невозможно привыкнуть”.

Действительно, синтаксис, предложенный компанией AT&T, немного (безусловно, в лучшую сторону) отличается от Intel’овского. Но это ничего не значит. На самом деле, если бы все еще с детства начали кодировать, используя AT&T синтаксис, то интеловский очень скоро загнулся бы и не дожил до наших дней. Просто AT&T в свое время не стремилась делать свои поделки достоянием народных масс, это прерогатива MS и Intel (а вообще у AT&T уже существовала своя развитая культура и традиции, когда MS и Intel только спускались с деревьев :) ).

А уж если кто-то переборол свои страхи и все же перешел к AT&T с Intel, того точно уже за уши не оттянешь назад. По этому поводу когда-то даже родился проект DJGPP (GNU Binutils) - асм с AT&T синтаксисом под DOS (http://www.delorie.com/djgpp/). Однако в силу непонятных причин проект не прижился.

Если все эти доводы кому-то показались слишком хлипкими и невразумительными, то нет ничего проще - http://sf.net/projects/nasm/. Качайте себе NASM под *nix и будьте с Intel «вместе навсегда».

Миф II:

“Асм под *nix никому не нужен и вообще все это изврат, С – вот единственная дорога в светлое будущее”.

Существует известная в широких кругах поговорка: «Линукс писан программистами для программистов». На самом деле полностью она звучит так: «Линукс писан сишными программистами для сишных программистов». И с этим никто не спорит. Дело в том, что любому, кто попытается сунуться в такой монастырь как *nix со своим уставом (асм), тому суждено упереться в огненные стены и рвы с крокодилами (об этом ниже). Однако не все так трагично – уменьшение размера кода в сто и более раз, увеличение производительности в десятки раз, да и чего греха таить, – само удовольствие, которое может доставить только кодинг на живом языке - все это стоит того чтобы научиться асму под *nix.

Теперь, возможно это кого-то сильно удивит, но программирование на асме под *nix по своему стилю очень напоминает... программирование на оном под DOS (да! Именно под DOS). Многие скажут: *nix – полностью 32-х разрядная ОС, и работает в защищенном режиме, используя flat-модель памяти. При чем здесь 16-битная ОС реального режима DOS? Про такого с уверенностью можно сказать: он просто никогда не писал на асме под *nix. На самом деле можно сделать еще более шокирующее заявление: писать программы на асме в *nix НАМНОГО проще чем под DOS... Самое важное – не сойти “с пути истинного” в самом начале его...

#1: когда только начинаешь писать на асме под *nix то возникает интересное ощущение: вроде бы ты попал в грязный пятибаксовый мотель (из тех, возле которых обязательно проходит метро и когда едет поезд на потолке дрожит дешевая люстра и мигает свет); здесь давно нет горячей воды, обои уродливыми клочьями свисают со стен, с потолка капает какая то мерзкая гадость и пахнет плесенью, все удобства – во дворе... На мотеле (подпертые кем-то неизвестным) стоят уже давно покосившиеся со временем неоновые буквы «*NIX для ассемблерщиков» (половина букв давно не горит, а половина с треском догорает). У мотеля нет своих постояльцев. Сюда заезжают лишь переночевать, чтобы на следующее утро убраться подальше...

Самое мерзкое во всем этом то, что через единственное окно в этой конуре, через дорогу, как будто специально, вырос семизвездочный отель, весь в рекламе, бассейнах и пальмах... Прямо над входом (к которому то и дело поминутно подъезжают все более и более крутые тачки) сверкает золотом надпись: “*NIX для сишников”. Вон видно как по террасам ходят пузатые мужики в обнимку с дорогими бабами, потягивая коктейли и куря сигары, им прислуживает армия официантов и слуг; все они смеются и живут.

Всем им наплевать на мотель напротив...

Но в миру ходят легенды, что в том самом мотельчике существует некая потайная дверь, которая открывает путь в Вечное... Ради этой двери мотель и стоит. По крайней мере, ручеек из желающих приобщиться к Вечности никогда не пересыхает.

Я говорю к тому, что ассеблерщик, сунувшийся в *nix не найдет практически никакой документации, описывающей системные вызовы на низком уровне. Здесь (http://www.lxhp.in-berlin.de/lhpsyscal.html) об этом можно получить кое-какую захудалую информацию, но многие функции описаны неправильно, либо вообще не описаны. Иногда порядок расположения параметров в регистрах при передаче в ту или иную функцию приходиться подбирать буквально вручную, методом научного тыка. Но на самом деле настоящего асм-кодера все это может только раззадорить..

Для вызова любой системной функции используется команда INT 80h (вспомните DOS – там для этой цели использовался INT 21h). Параметры передаются через регистры. Номер функции – в АХ. Вся проблема в том, что найти полное описание того, в каком регистре какой параметр и для чего передается крайне проблематично, ресурс, указанный выше частично решает эту проблему.

Когда я говорил про все неземные блага, которые предоставляются для сишников, я имел ввиду полную документированность любой запятой, с которой только можно встретиться в увлекательном процессе программирования на С под *nix.

#2: вот это действительно самый большой фак: за всю историю существования *NIX никто не написал ни одного стоящего отладчика асм-кода (а может и написал, но не захотел поделиться с общественностью). Все что удалось найти (был перерыт буквально весь Интернет и опрошены десятки знающих людей) – ALD (Assembly Linux Debugger). Все что про него можно сказать – да, он действительно чем-то круче MS debug-а. Вот только чем именно - сказать довольно сложно. Все остальные отладчики дальше С-шного кода ничерта не видят. Писать программы без отладчика (а тем более на асме) – это верх извращенческого гения.

Конечно, существует еще и скромный аналог сайса под Линукс – PrivateICE (http://sourceforge.net/projects/pice). Единственная проблемка – на последних версиях ядер Линукса он не компилируется (вот вам и переносимость С).

Прим.: 9 июня 2003 года на sourceforge появился новый билд pice-а. Однако вот что пишет сам автор:

Since this project was abandoned a few years ago there is no active maintainence. [skipped]. The files provided here are as it is and there is no garuantee that they will compile. [skipped]. Of course you are welcome to send in bug reports or comments on this code, just don't expect that they can be compiled out of the box. :) These sources will compile on 2.4.18. They might give problems with non-SMP enabled kernels.

Скомпилировать так ничего и не удалось :). Если кто-то вдруг найдет заклинание, по которому pice можно скомпилировать под последние ASP, Mandrake или RedHat– сообщите плз на ящик внизу.

#3: проблема заголовочных файлов. Чуть ли не большую часть времени желающему покодить на асме в *nix придется провести за увлекательным поиском необходимой информации по заголовочным файлам. Искать придется практически все буквенные названия, которые могут встретиться в процессе (это и названия самих системных вызовов, и параметров, передаваемых в них, и вообще любых переменных). Все они как будто специально порастасканы по тысячам *.h – файлов, которые находятся в самых неожиданных местах. Сишнику в семизвездочном отеле достаточно всего лишь щелкнуть пальцем и сделать include ….h – все работает. Ассемблерщику в мотелишке напротив – сначала понять к чему тот или иной параметр, затем устроить поиск по всем системным директориям, найти заголовочный файл, содержащий этот параметр, затем скопировать его в «свой», который будет понимать GAS или NASM (или, если ассемблерщик попался реальный, то запомнить его, и везде использовать численные значения параметров ?), а в довершение еще и усадить в правильный регистр перед отправкой в недра функции.

#4: прога, написанная для *nix на асме теряет переносимость на другие *nix-платформы. Для перекомпиляции под другую *nix платформу придется изрядно повозиться, в некоторых случаях проще переписать заново весь код, чем переделывать старый с Linux под BSD. Но BSD пока не так распространен, а самые попсовые версии линуксов (Red Hat, Mandrake, ASP) используют одно и то же ядро, и данный фак вообщем-то не так уж страшен как его малюют.

Ну вот, а теперь вы сами убедитесь, что писать программы на асме под Линукс не сложнее чем под DOS, а может даже и проще.

Рассмотрим пример написания простейшего клиент-серверного приложения, использующего в качестве взаимодействия стек протоколов TCP/IP (подразумевается, что вы более-менее знакомы с сетевым программированием, и знаете хотя бы, что такое сокет).

Клиентское приложение посылает серверу символьную строку; Сервер шифрует символьную строку по следующему алгоритму шифрования: выполняет замену одного символа – буквы, на символ располагающийся на две позиции правее в алфавите, для последнего и предпоследнего символов в алфавите выполняется кольцевой сдвиг, например, для «Y» это будет буква «А» для «Z» - «В» (это шифр Цезаря). Сервер отправляет зашифрованное сообщение обратно; Клиент выбирает шифрограмму и выводит на экран.

Сообщения, подлежащие шифрованию, вводятся с клавиатуры. Программа сервера работает в бесконечном цикле.

Ну что ж, начнем с сервера. Я по ходу пьесы попытаюсь максимально комментировать происходящее. Начну с того, что наш сервер будет демоном (для пущего понту). Что такое демон? Демон на языке DOS-ассемблерщиков – резидент. Все. Так что ничего страшного.

# *******************************************************
# Server (daemon)
# by Broken Sword [HI-TECH]
# (for Linux based on Intel x86 only)

# brokensword@mail.ru
# www.wasm.ru

# Compile Instructions:
# -------------------------------------------------------
# as server.s
# ld --strip-all -o server a.out
# *******************************************************

# *******************************************************

# этот файлик содержит выдранные из какого-то файла
# определения системных вызовов (см. FUCK #3)
 .include  "syscalls.inc"  
# а этот – все остальные, которые только могут 
# встретиться

 .include  "def.inc"          
  .text         # начало сегмента кода
# метка, с которой все начинается (нужно чтоб она была 
# глобальной)
  .globl  _start    

_start:       
# итак, начинаем лепить нашего демона
# процесс создания демона в *.nix и создание резидента в DOS в корне различаются
# начинается любой демон с того, что нужно создать дочерний процесс.
# Создать дочерний процесс в линуксе проще 
# пареной репы – достаточно поместить номер сис.
# вызова в EAX и сделать «а-ля int 21h», т.е. int 80h
  movl  $SYS_fork,%EAX
  int  $0x80  
# все. 
# Теперь у нас параллельно сосуществуют ДВА процесса:
# родительский (в котором исполнялись все предыдущие 
# команды) и дочерний. Что же содержит дочерний код? 
# А все то же самое, что и родительский.
# Т.е. важно понять, что # весь нижеследующий (и выше тоже)
# код находиться в памяти в ДВУХ разных местах.
# Как процессор переключается между 
# ними (и всеми остальными живыми процессами) 
# – читайте «Переключение задач» в интеловском мануале. 
test  %EAX,%EAX  
# вот эту команду необходимо осознать.
# Прежде всего, важно понять, что данная команда
# существует и в родительском 
# и в дочернем процессах (об этом выше).
# Следовательно выполниться она и там и там.
# Все дело в том, что после 
# int 80h родительскому процессу вернется PID сына
# (в EAX ессесно, вообще все возвращается в EAX, как и в винде)
# а что же вернется сыне? Правильно, нолик.
# Именно поэтому следующий jmp будет выполнен
# в дочернем процессе и 
# не будет выполнен в родительском.

# ребенок улетает на метку _cont1
  jz  _cont1   
# ...а в это время, в родительском процессе:
  xorl  %EBX,%EBX  # EBX=status code
  xorl  %EAX,%EAX  #
  incl  %EAX   # SYS_exit 
# завершаем родительский процесс.
  int  $0x80   

# Теперь все дети 
# управляются процессом INIT


_cont1:
  movl  $SYS_setsid,%EAX
# сделаем нашего ребенка главным в группе
  int  $0x80   
  
  movl  $1,%EBX   # SIGHUP
  movl  $1,%ECX   # SIG_IGN
  movl  $SYS_signal,%EAX
# далее сигнал SIGHUP будет игнорироваться
  int  $0x80   
       
  movl  $SYS_fork,%EAX
# наш ребенок уже подрос и теперь сам может родить сына
  int  $0x80   
# (по сути – это уже внук нашему изначальному 
# родительскому процессу)

# EAX=0 в дочернем и EAX=PIDдочернего в родительском

  test  %EAX,%EAX  

jz  _cont2   

# внук нашего родительского (которого уже давно нет в 
# живых) улетает на метку _cont2, однако отец все еще 
# жив!!! (все как в мексиканском сериале)
  
  xorl  %EBX,%EBX  # EBX=status code
  xorl  %EAX,%EAX  #
  incl  %EAX   # SYS_exit
  int         $0x80   

# вот уже и отец отправлен к деду на небеса (да, 
# злостная программка, недаром демоном зовется)

# ..а в это время внучок получает все наследство и 

_cont2:

# продолжает жить
# далее, после того,
# как все кровавые разборки и отцеубийства благополучно завершены,
# внучок,продавший душу демону, 
# преспокойно создает сокет.
# Дело в том, что в линуксе есть такие системные вызовы,
# для вызова которых их номер не 
# помещается в EAX.
# Вместо этого в EAX помещается номер функции-мультиплексора,
# реализующий вызов конкретной 
# функции номер которой помещается в EBX.
# Так, например, происходит при вызове IPC и SOCKET-функций.
# Кроме того, 
# при вызове SOCKET-функций параметры располагаются не в регистрах,
# а в стеке. Смотри как все просто:

  pushl  $0   # протокол
  pushl  $SOCK_STREAM  # тип

  pushl  $AF_INET   # домен
# ECX должен указывать на кадр в стеке, содержащий 
  movl  %ESP,%ECX  
# параметры, такая уж у него судьба...
  movl  $SYS_SOCKET,%EBX  
# а вот это уже номер той самой конкретной функции
# SOCKET – создать сокет
       
  movl  $SYS_socketcall,%EAX
 
# в EAX - номер функции мультиплексора (по сути он 
# просто перенаправит вызов в функцию, указанную в EBX
  
       int         $0x80

# сокет создан! Ура товарищи. В EAX возвратиться его дескриптор.

# «очистим» стек (по сути это выражение придумано специально
# для HL-программистов, на самом деле ничего не 
# очищается, данную операцию необходимо производить только
# для того чтобы в дальнейшем не произошло переполнение 
# стека, но в таких маленьких программках это делать вовсе
# не обязательно):

  addl  $0xC,%ESP

  movl  %EAX,(sockfd)  

# сохраним дескриптор созданного сокета в переменной
# sockfd

# далее необходимо осуществить операцию BIND,
# которая называется «привязка имени сокету»,
# хотя суть этого названия 
# слабо отражает смысл происходящего на самом деле.
# На самом деле BIND просто назначает конкретному сокету IP-
# адрес и порт, через который с ним можно взаимодействовать:

# размер передаваемой структуры (вообще подобран 
  pushl  $0x10
# методом тыка, потому что логически непонятно почему 
# именно 16)

# указатель на структуру sockaddr_in

       pushl  $sockaddr_in
# дескриптор нашего сокета
  pushl  %EAX   
# ECX указывает на параметры в стеке
  movl  %ESP,%ECX  
# номер функции BIND – в EBX
  movl  $SYS_BIND,%EBX
# функция-мультиплексор
  movl  $SYS_socketcall,%EAX
  int  $0x80
# теперь сокет «привязан» к конкретному IP-шнику и порту
# поднимем ESP на место
  addl  $0xC,%ESP  
# далее что-либо подробно описывать я не вижу смысла,
# любой желающий сам без труда разберется, опираясь на 
# полученные выше знания.
  pushl  $0   # backlog
  movl  (sockfd),%EAX
  pushl  %EAX
  movl  %ESP,%ECX
  movl  $SYS_LISTEN,%EBX
  movl  $SYS_socketcall,%EAX
  int         $0x80
  addl  $0x8,%ESP

_wait_next_client:
  pushl  $0   # addrlen
  pushl  $0   # cliaddr
  movl  (sockfd),%EAX
  pushl  %EAX   # sockfd
  movl  %ESP,%ECX
  movl  $SYS_ACCEPT,%EBX
  movl  $SYS_socketcall,%EAX
  int  $0x80
  addl  $0xC,%ESP

  movl  %EAX,(connfd)
  
  movl  $SYS_fork,%EAX
  int  $0x80   # create child process
  test  %EAX,%EAX
  jnz  _wait_next_client

_next_plain_text:
  movl  (connfd),%EBX
  movl  $buf,%ECX  # ECX->buf
  movl  $1024,%EDX  # 1024 bytes
  movl  $SYS_read,%EAX
  int  $0x80   # wait plain_text

  movl  $buf,%ESI
  movl  %ESI,%EDI
  movl  %EAX,%ECX
  movl  %EAX,%EDX
_encrypt:
  lodsb
  cmp  $0x41,%AL  # A
  jb  _next
  cmp  $0x5A,%AL  # Z
  ja  _maybe_small
  incb  %AL
  incb  %AL   # encryption ;)
  cmp  $0x5A,%AL
  jle  _next
  sub  $26,%AL
_maybe_small:
  cmp  $0x61,%AL  # a
  jb  _next
  cmp  $0x7A,%AL  # z
  ja  _next
  incb  %AL
  incb  %AL   # encryption ;)
  cmp  $0x7A,%AL
  jle  _next
  sub  $26,%AL
_next:
  stosb
  loop  _encrypt
  
  movl  (connfd),%EBX
  movl  $buf,%ECX  # ECX->chiper_text
  movl  $SYS_write,%EAX
  int  $0x80   # send plain_text
  
  jmp  _next_plain_text
# *****************************************************
  .data
sockfd:  .long  0
connfd:  .long  0
sockaddr_in: 
sin_family: .word  AF_INET
sin_port: .word  0x3930   # port:12345
sin_addr: .long  0   # INADDR_ANY
buf:
# *****************************************************



#Клиент пишется по аналогии с сервером,
# думаю сами без труда разберетесь:


# *********************************************************
# Client
# by Broken Sword [HI-TECH]
# (for Linux based on Intel x86 only)

# brokensword@mail.ru
# www.wasm.ru

# Compile Instructions:
# ---------------------------------------------------------
# as client.s
# ld --strip-all -o client a.out
# *********************************************************

# *********************************************************  
       .include  "syscalls.inc"
  .include  "def.inc"
  .text
  .globl  _start
_start:
  pushl  $0   # protocol
  pushl  $SOCK_STREAM  # type
  pushl  $AF_INET   # domain
  movl  %ESP,%ECX
  movl  $SYS_SOCKET,%EBX
  movl  $SYS_socketcall,%EAX
  int  $0x80
  addl  $0xC,%ESP

  movl  %EAX,(sockfd)

  pushl  $0x10   # addrlen
  pushl  $sockaddr_in
  pushl  %EAX   # sockfd
  movl  %ESP,%ECX
  movl  $SYS_CONNECT,%EBX
  movl  $SYS_socketcall,%EAX
  int  $0x80
  addl  $0xC,%ESP

_next_plain_text:
  xorl  %EBX,%EBX  # stdin
  movl  $buf,%ECX  # ECX->buf
  movl  $1024,%EDX  # 1024 bytes
  movl  $SYS_read,%EAX
  int  $0x80   # read from stdin

  movl  (sockfd),%EBX
  movl  $buf,%ECX  # ECX->plain_text
  movl  %EAX,%EDX  # bytes read
  movl  $SYS_write,%EAX
  int  $0x80   # send plain_text

  movl  $SYS_read,%EAX
  int  $0x80   # wait chiper_text
  
  xorl  %EBX,%EBX
  incl  %EBX   # EBX=1 (stdout)
  movl  $SYS_write,%EAX
  int  $0x80   # disp chiper_text
  
  jmp  _next_plain_text
# *********************************************************
  .data
sockfd:  .long  0
sockaddr_in: 
sin_family: .word  AF_INET
sin_port: .word  0x3930   # port:12345
sin_addr: .long  0x0100007F  # 127.0.0.1
buf:
# *********************************************************

Вот так вот все просто (вся сложность на самом деле заключена в понимании стека TCP/IP, а не в том, как закодировать все эти действия на асме).

Все - запускайте бесов server, а за ним client.

p.s. использовать данное приложение для шифрования важных данных на диске не рекомендуется ).


Благодарности (в алфавитном порядке :)):


Aquila [HI-TECH]
CyberManiac [HI-TECH]
Edmond [HI-TECH]
Vladimir [HI-TECH]

...и всей группе HI-TECH! Держитесь, ребята!


Broken Sword [HI-TECH]

 


# Эпилог


###########################################################################
Оригинальное всТупление
вЁрстка
Контактный email
 
Edmond / HI-TECH
Edmond / HI-TECH
wasm@wasm.ru
-------------
Жаждущие опубликовать свои статьи обращайтесь Edmond@wasm.ru
Статьи присылаются в форматах RTF, DOC (желательно).
###########################################################################
Рассылка составлена HI-TECH GROUP 29 августа 2003 года.
(c) wasm.ru 2002-2003

 



http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное