книги хакеры / журнал хакер / 119_Optimized
.pdf
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
||
|
|
|
C |
|
E |
|
|
|
|
|
|
C |
|
E |
|
|
|
||||||
|
|
X |
|
|
|
|
|
|
|
|
X |
|
|
|
|
|
|
||||||
|
- |
|
|
|
|
|
d |
|
|
- |
|
|
|
|
|
d |
|
||||||
|
F |
|
|
|
|
|
|
|
i |
|
|
F |
|
|
|
|
|
|
|
i |
|
||
|
|
|
|
|
|
|
|
t |
|
|
|
|
|
|
|
|
|
t |
|
||||
P |
D |
|
|
|
|
|
|
|
|
o |
P |
D |
|
|
|
|
|
|
|
|
o |
||
|
|
|
|
NOW! |
r |
|
|
|
|
NOW! |
r |
||||||||||||
|
|
|
|
|
BUY |
|
|
|
|
|
|
|
BUY |
|
|
||||||||
|
|
|
|
to |
|
|
|
|
|
|
|
|
|
|
to |
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
w |
|
|
|
|
|
|
|
|
|
m |
w |
|
|
|
|
|
|
|
|
|
m |
||
w Click |
|
|
|
|
|
|
o |
w Click |
|
|
|
|
|
|
o |
||||||||
|
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
||
|
. |
|
|
|
|
|
|
.c |
|
|
. |
|
|
|
|
|
|
.c |
|
||||
|
|
p |
df |
|
|
|
|
e |
|
|
|
p |
df |
|
|
|
|
e |
|
||||
|
|
|
|
|
g |
|
|
|
|
|
|
|
|
g |
|
|
|
||||||
|
|
|
|
|
n |
|
|
|
|
|
|
|
|
|
n |
|
|
|
|
||||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
|
-x cha |
|
|
|
|
|
||||
|
|
|
|
|
|
SennheiserE815-S |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
Отличный |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
микрофон |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
дляподкастеров |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
Выборхорошегомикрофона—настоящаяголовнаябольдлялюбого |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
начинающегоподкастера.Тозвукхрипит,иголосполучается,какуСтаса |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
Барецкого,товнешнийшумпробиваетсявэфиризабиваетдиалог.Привыбо- |
|
|
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
рекачественногомикрофонасамоеважное—доверитьсяпроверенному |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
временемпроизводителю,вкачествепродукциикоторогоможно |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
несомневаться. |
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
Sennheiser E815-S — идеальный вариант для |
Технические характеристики |
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
начинающего подкастера. Это микрофон с |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
Диаграмма направленности: Cardioid |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
кардиоидной диаграммой направленности, |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
Чувствительность в свободном поле, без нагрузки (1 кГц): 1,5 мВ/Па |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
что означает наибольшую его чувствитель- |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
Номинальный импеданс: 350 Ом |
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
ность к звуку, идущему спереди и почти полное |
Минимальный согласованный импеданс: 1000 Ом |
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
игнорирование внешнего шума и сторонних |
Вес: 330 г |
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
звуков. Ты также можешь не переживать о |
Длина кабеля: 5 м |
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
взрывоподобном эффекте при произнесении |
Размеры: 48 x 180 мм |
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
буквы «п» и шипении букв «ш», «ф» и «с» |
Диапазон воспроизводимых частот: 80 – 12.000 Гц |
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
— благодаря специальному пористому филь- |
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
трующему покрытию головки E815 все эти |
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
звуки будут восприняты максимально точно и |
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
без нелепых искажений. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
E |
|
|
||||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
NOW! |
o |
||||
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
||||
w Click |
to BUY |
|
>> coding |
|||||||
|
|
|
|
|
|
m |
||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
ородин
/ www.dreamboss.ru /
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
Сагаовикинге Эрланге
Высоконаучный брутфорс на практике
На дворе XXI век. Хакер, разбирающий дампы вручную — такой же анахренизм (© Не помню, кто), как и хакер, пытающийся сбрутить пасс в один поток. Напомню, что в прошлом номере мы начали знакомство с викингом Эрлангом. Сегодня тебя ждет продолжение рассказа о языке программирования, рожденном для многопоточной работы в мультипроцессорной монолитной или распределенной среде.
Erlang: Стать подмастерьем
С языком Erlang я тебя познакомил, да вот беда, не успел рассказать, как программировать с его помощью. Чтобы постичь Дао Erlang программиста, тебе придется познать четыре великих секрета:
• конкурентное программирование. Не заморачиваясь на нюансах, можно сказать, что процесс написания конкурентного кода выглядит несколько сложнее, чем процесс написания традиционного последовательного кода. Зачастую приходится совмещать несовместимое — реализовать последовательный алгоритм, обеспечивая возможность его параллельного выполнения. То еще удовольствие, особенно при неправильном подходе. Большинство кодеров пытаются решить проблему в лоб — реализовать в одном программном модуле и параллельную, и последовательную обработку данных. Я покажу тебе, как правильно структурировать код, распределив его по двум модулям — один для параллельной обработки, а другой — для последовательной; • обработка ошибок. Ты уже понял, что в этом языке все делается через
ж..., в смысле — не так, как в других языках программирования. Спешу тебя обрадовать: отстреливание и обработка ошибок — не исключение. Уф, какой лингвистический выверт у меня получился — errors exception is not exception!
• процессы первичны, остальное вторично. Надеюсь, ты еще не забыл главную фишку Erlang’а, согласно которой все — процессы? Сегодня ты убедишься в этом на практике!
• преднамеренноепрограммирование.«Чтозамуть?»,спросишьты—ая отвечу:этотакойстилькодинга,прикоторомкодер,очнувшисьотвчерашнейбурнойвечеринки,непытаетсяпостигнутьсмыслбытия(написанного имжеднемранеекода).Емуненадоизовсехсилстаратьсяпонять,что жеемусегоднянаписать,чтобычертовпроектнаконец-топролезчерез
компилятор,невыплюнувниоднойкритическойошибки.Онпростосадится ипишет,так,будтоонпросветленныйБудда.Секреткроетсявтомсамом преднамеренномпрограммировании,согласнокоторомууженаписанный кодопределяеткод,которыйдолженбытьнаписан.Кстати,фишкаэта достаточнопочтенноговозраста.Erlang—функциональныйязык.Акакой функциональныйязыккручеСолнцаивсехостальныхязыковпрограм- мированиявместевзятых?Правильно—Lisp.ИименновLisp’евпервые появиласьидеяпрограмм,которыепишутдругиепрограммы(еслитебеэто интересноитынамеренкопнутьглубже—копайвсторонуLisp-макросов).
Конкурентное программирование
Давай вспомним матчасть — а именно, клиент-серверную архитектуру. На всякий случай, я со своим атрофированным чувством прекрас-
110 |
xàêåð 11 /119/ 08 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
E |
|
|
||||
|
|
|
X |
|
|
|
|
|
|||
|
|
- |
|
|
|
|
|
d |
|
||
|
|
F |
|
|
|
|
|
|
t |
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
|
P |
|
|
|
|
|
NOW! |
o |
|||
|
>> codingto BUY |
|
|
||||||||
|
|
|
|
|
|
||||||
|
w Click |
|
|
|
|
|
|
m |
|||
|
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
|
-x cha |
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Erlang плагин в IDE NetBeans
Тестирование производительности Erlang в сравнении с другими технологиями
|
ного попытался изобразить эту шведскую семейку на |
|
Страшно? А никто и не обещал, что сбрутить пассы через |
|
|
|
картинке («Три плюс один»). |
|
распределенку будет легко. Это тебе не формочки в дельфях |
|
|
|
Модель клиент-сервер отличается от прочих тем, что в |
|
клепать. Но на самом деле, разобраться вполне реаль- |
|
|
|
ней есть некий центральный узел (такой весь на рас- |
|
но. Клиент осуществляет RPC-запрос (строки с 13 по 17), |
|
|
|
пальцовке сервачок), к которому подключены несколько |
|
отправляя сообщение серверу (строка 14) и ожидая от |
|
|
|
дремучих провинциалов-неудачников. Что им нужно от |
|
него ответ (строки с 15 по 17). Сервер получает посланный |
warning |
|
|
сервера? Очевидно, эти кровососы вовсю юзают один |
|
клиентом запрос (строка 23), формирует ответ и, меняя свое |
Описанные подхо- |
|
|
из его ресурсов. По максимуму упростив модель, всю |
|
состояние, прокручивает ответ через хвостовую рекурсию |
ды не могут быть |
|
|
выполняемую сервером работу можно представить в виде |
|
(строка 26). |
использованы для |
|
|
некоторой функции F. |
|
Почему я выбрал именно этот пример с клиент-серверной |
несанкционирован- |
|
|
Теперь представь, что у нашего сервера есть несколько |
|
архитектурой? Потому что он неплохо иллюстрирует хорошо |
ных действий! |
|
|
возможных состояний — State (упал под DDOSом, обраба- |
|
распараллеливаемый алгоритм — для обработки каждого |
В случае таковых ни |
|
|
тывает спам-лист, брутит пассы). Наш сервачок постоян- |
|
запроса запускается свой поток. Теперь допустим, что наш |
автор, ни редакция |
|
|
но тревожат клиенты своими запросами (Query). Серверу |
|
сервер нужно обвесить разными рюшечками, не предпо- |
за твои поступки |
|
|
не позавидуешь, потому что пока он жив, он обязан |
|
лагающими параллельной обработки: например, написать |
не несут никакой |
|
|
отвечать на все поступившие запросы (Replay), поменяв |
|
функцию, которая будет сбрасывать сбрученный пароль в |
ответственности. |
|
|
свое текущее состояние со State на State 1. Все это можно |
|
текстовик. Это будет уже последовательная операция (пока |
|
|
|
сжато и емко выразить с помощью синтаксиса Erlang: |
|
пароль не найден — в файл лить нечего) и глупо пихать ее |
|
|
|
|
|
в один модуль с распараллеленным алгоритмом. Логичнее |
|
|
|
{State1, Replay} = F(Query, State) |
|
создать новый модуль, подключив к нему те, что поддаются |
|
|
|
|
|
распараллеливанию: |
|
|
|
А теперь перейдем от теории к практике — напишем свой |
|
|||
|
|
|
|
|
|
|
первый сервер: |
|
|
— import (server1, [start/3, stop/1, rpc/2]). |
info |
|
|
|
|
— import (dict, [new/0, store/3, find/2]). |
Статья преследует |
|
-module(server1). |
|
|
|
цель показать новые |
|
|
А что произойдет, если наш сервер, в ожидании хэша рутов- |
|||
|
-export([start/3, stop/1, rpc/2]). |
|
направления в ауди- |
||
|
start(Name, F, State) -> |
|
ского пасса, словит нечто неперевариваемое? К примеру, |
те информационной |
|
|
register(Name, |
|
горе-хакер решит сбрутить CRC, приняв его за вожделен- |
безопасности, |
|
|
spawn(fun() -> |
|
ный пароль от админки местечкового порнохранилища. |
в частности — знако- |
|
|
loop(Name, F, State) |
|
Каким-то образом наша чудо-цифродробилка должна |
мит с эффективными |
|
|
end)). |
|
отреагировать на такую внештатную ситуацию. Об этом |
средствами проверки |
|
|
stop(Name) -> Name ! Stop. |
|
— буквально в следующем абзаце. |
качества исполь- |
|
|
rpc(Name, Query) -> |
|
|
|
зуемых паролей на |
|
Name ! {self(), Query}, |
|
|
Сапер ошибается дважды |
сопротивляемость |
|
|
|
|||
|
|
|
|||
|
receive |
|
Пользуясь случаем, хочу передать пламенный привет сиш- |
прямому перебору. |
|
|
{Name, Replay} -> Reply |
|
ным кодерам, отстрелившим себе не только обе ноги, но и |
|
|
|
end. |
|
то, что так мешало им танцевать полечку на костях функцио- |
|
|
|
loop(Name, F, State) -> |
|
нальной парадигмы программирования. |
|
|
|
receive |
|
Среди парней, что паяют компьютерное железо в промыш- |
|
|
|
stop -> |
|
ленных масштабах в ходу термин «fault-tolerance». Это же |
|
|
|
void; |
|
понятие можно встретить в идеологии Erlang’a. |
|
|
|
{Pid, Query} -> |
|
Сравни два фрагмента кода: |
|
|
|
{Reply, State1} = F(Query, State), |
|
|
|
|
|
Pid ! {Name, Replay}, |
|
|
rpc(Name, Query) -> |
|
|
loop(Name, F, State1) |
|
|
Name ! {self(), Query}, |
|
|
end. |
|
|
receive |
|
|
|
|
|
|
|
|
|
|
|
|
|
xàêåð 11 /119/ 08 |
111 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
C |
E |
|
|
|||
|
|
X |
|
|
|
|
|||
|
- |
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|||
w Click |
to BUY |
|
>> coding |
||||||
|
|
|
|
|
m |
||||
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
g |
|
|
|
|
|
|
df |
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
Главное в Erlang — его модель легковесных процессов. Перефразируя для Erlang слоган текущего дня — «Everything is an object» («Все является объектом»), можно сказать: «Everything is a process» («Все является процессом»).
Процессы дешевы, а их создание занимает не больше ресурсов, чем вызов функции. Единственным способом взаимодействия процессов является асинхронный обмен сообщениями.
Процесс при желании может или установить связь (link) с другими процессами (по выбору), или получить сообщение об их смерти с указанием причины, или разделить их участь. Процесс имеет свой «почтовый ящик», откуда может выборочно читать сообщения. В этом очень помогает сопоставление по шаблону; код проверки «ящика» чем-то похож на программу awk. Нужное выгребается и обрабатывается, остальное остается или выбрасывается.
Клиент
Сервер
Клиент
Клиент
Три плюс один, или милый групповичок
|
наш сервер лежит без чувств, сраженный безжалостным |
{Name, crash} -> exit(rpc); |
DDOSом. Чтобы такое ожидание не длилось вечно, нужно |
{Name, ok, Replay} -> Reply |
предусмотреть возможность отстрела ошибок и на стороне |
end. |
клиента: |
|
|
|
|
И второй вариант: |
|
|
rpc(Name, Query) -> |
Логотип Erlang |
|
||||
|
|
|
|
Name ! {self(), Query}, |
|
|
|
|
|
|
|
|
|
case (catch F(Query, State)) of |
|
|
receive |
|
|
{'EXIT', Why} -> |
|
|
{Name, crash} -> exit(rpc); |
|
|
log_error(Name, Query, Why), |
|
|
{Name, ok, Reply} -> Reply |
|
|
From ! {Name, crash}, |
|
|
after 10000 -> |
|
|
loop(Name, F, State); |
|
|
exit(timeout) |
|
|
{Replay, State1} -> |
|
|
end. |
|
|
From ! {Name, ok, Replay}, |
|
|
|
|
|
loop(Name, F, State1) |
|
Думаю, решение очевидно. За исключением одного |
|
|
|
end. |
|
маленького, но принципиального вопроса — как долго |
|
|
|
|
|
ждать ответ от сервера, прежде чем начинать панико- |
|
|
|
Надеюсь, ты уже успел заметить ключевые отличия первого |
|||
|
|
|
вать? Ткнув пальцем в небо, я написал: десять тысяч |
||
|
|
фрагмента от второго, встретив там до боли знакомое |
|
миллисекунд. При грамотном подходе (если ты хочешь |
|
|
|
словечко catch. Но не будем торопиться и рассмотрим обра- |
|
показать кому-то всю свою невозможную крутость) |
|
|
|
ботку ошибок в Erlang по шагам. |
|
клиент вовсе не должен проверять работоспособность |
|
|
|
1.Хорошим тоном среди крутых Erlang пацанов считается |
|
сервера. Не барское это дело! Для такого случая, соглас- |
|
|
|
журналировать все пойманные ошибки. В нашем варианте |
|
но идеологии Erlang, нужно создать отдельный процесс |
|
|
|
мы просто печатаем сообщение об ошибке, хотя правильнее |
|
(перевожу на русский — написать отдельный програм- |
|
|
|
было бы записать его в журнал. |
|
мный модуль), называемый гипервизором (Hypervisor). |
|
|
|
2.Соответствующее уведомление должно быть отправлено |
|
Задача гипервизора состоит в том, чтобы с заданной пе- |
|
|
|
клиенту, чтобы он, отправив кривой запрос, не питал иллю- |
|
риодичностью проверять состояние сервера и сообщать |
|
links |
зий по поводу ответа. |
|
о нем клиентам. |
||
• www.erlang.org |
3.Сервер продолжает свою работу со старым значением пе- |
|
|
|
|
— Open Sources реа- |
ременной (или переменных), описывающей его состояние. |
|
|
Чужие секреты |
|
|
|
||||
|
|
||||
лизация. |
Получается интересная штуковина: RPC как бы подчиняется |
|
Ты уже достаточно много знаешь о языке программиро- |
||
|
|
транзакционной семантике, которая в свою очередь опре- |
|
вания Erlang. Не исключено, что у тебя уже появились |
|
• erlang.dmitriid.com |
деляется состоянием сервера — если состояние сервера |
|
свои собственные идеи, как можно было бы организо- |
||
— Erlang по-русски. |
изменилось, значит, все ОК. Если нет — случился страшный |
|
вать систему распределенного брутфорса. Но один воп- |
||
www.erlang-projects. |
писец и нужно срочно принимать меры по спасению все- |
|
рос по-прежнему не раскрыт, и возможно, не дает тебе |
||
org — список проек- |
ленной от последствий роковой ошибки. |
|
спокойно заснуть с любимым журналом под подушкой. |
||
тов, использующих |
Приведенная схема прекрасно работает в том случае, |
|
Собственно, это вопрос о том, каким образом можно |
||
Erlang в качестве |
если нужно урезонить клиентов, отправляющих серверу |
|
реализовать криптографические инструменты средс- |
||
основного языка |
невменяемые запросы. А теперь представь такую ситуацию: |
|
твами Erlang. Не волновайся, как говаривала добрая |
||
разработки. |
клиент отправляет серверу корректный запрос и вполне на |
|
бабушка в одном бездарном российском блокбастере. |
||
|
|
законных основаниях ожидает от него ответ. Тем временем |
|
Среди разнообразных библиотек, поставляемых вместе |
112 |
xàêåð 11 /119/ 08 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
C |
E |
|
|
|||
|
|
X |
|
|
|
|
|||
|
- |
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
NOW! |
o |
|||
>> codingto BUY |
|
|
|||||||
|
|
|
|
|
|||||
w Click |
|
|
|
|
|
m |
|||
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
g |
|
|
|
|
|
|
df |
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
Мощностьсвязки«Процессы+сообщения»неменьше,чему «Объекты+Интерфейсы+Наследование».Нозачастуюона приводиткболеекомпактнымипонятнымрешениям.Устранить конкуренциютакжепросто,какисоздать.Нетнеобходимости блокироватьдоступксостояниюпроцессадлясинхронизации взаимодействия,иэтосильнооблегчаетжизнь.Дляконкурентного ресурсаобычнопростосоздаетсяпроцесс-монитор,черезкоторый осуществляетсявзаимодействиесресурсом.
Веб-сервер Yaws, написанный на Erlang vs. Apache httpd
с самим языком, криптографических инструментов присутствует достаточно.
Как решать с помощью этих инструментов конкретную задачу, ты и сам прекрасно разберешься, покурив хорошенько документацию. Я, в силу ограниченного журнального пространства, покажу тебе лишь общее направление на простом примере использования алгоритма MD5.
На всякий случай напомню, что алгоритм MD5 для своего аргумента вычисляет уникальное 32-разрядное число (обычно представляемое в шестнадцатеричной нотации). Для вычисления MD5 в Erlang есть специальная встроенная функция, возвращающая хэш в виде структуры чисел:
>erlang:md5("hello"). <<93,65,64,42,188,75,42,118,185,113,157,145,16,23,197 ,146>>
Однако, это не совсем то, что мы привыкли видеть, и не совсем то, что мы ожидаем получить от функции md5()! Чаще всего результат работы алгоритма MD5 фигурирует в виде шестнадцатеричной строки. Поэтому после вычисления значения хэш-функции есть смысл воспользоваться функцией конвертирования binary_to_list():
>binary_to_list(<<93,65,64,42,188,75,42,118,185,113,15 7,145,16,23,197,146>>). [93,65,64,42,188,75,42,118,185,113,157,145,16,23,197, 146]
Следующий шаг — преобразование каждого целого числа в списке в его шестнадцатеричный эквивалент. Как бы ты это сделал, не имея под рукой компьютера? С помощью разложения на множители по модулю 16! Реализация этого алгоритма на любом языке — задача для школьника. Такое преобразование нужно выполнить для каждого элемента списка. Я бы тебе порекомендовал воспользоваться для
xàêåð 11 /119/ 08
defin.ru — сайт, посвященный функциональному программированию
этого стандартной функцией lists:map, пропустив через нее преобразование каждого десятичного числа к его шестнадцатеричной нотации:
>lists:map(fun(X) -> int_to_hex(X) end, L).
Врезультате должен получиться список целых чисел в шестнадцатеричной нотации. Последнее, что осталось сделать — привести список к одному значению. Весь алгоритм в сборе будет примерно таким:
— module(md5). — export([md5_hex/1]).
md5_hex(S) ->
Md5_bin = erlang:md5(S),
Md5_list = binary_to_list(Md5_bin), lists:flatten(list_to_hex(Md5_list)).
list_to_hex(L)->
lists:map(fun(X) -> int_to_hex(X) end, L).
int_to_hex(N) when N < 256 -> [hex(N div 16), hex(N rem 16)].
hex(N) when N < 10 -> $0+N;
hex(N) when N >= 10, N < 16 -> $a + (N-10).
И — результат работы:
>md5:md5_hex("hello"). "5d41402abc4b2a76b9719d911017c592"
Finita la comedia
Возможно, кто-то разочаруется, так и не обнаружив в статье готового решения. Но, согласись, это было бы, мягко говоря, не по тру-хакерски. Мое дело — дать тебе удочку, а с рыбой ты как-нибудь сам справишься. За эти две статьи, посвященные языку программирования Erlang, мы успели познакомиться с основами синтаксиса языка, его основополагающими идеями, основными приемами, техникой создания процессов и даже затронули криптографическую библиотеку. Тебе осталось собрать кусочки мозаики. Вот за этим занятием разреши тебя и оставить. А если будут вопросы — пиши, не стесняйся. Только не забудь вложить в письмо пустой конверт и пятьдесят американских рублей, на канцелярские, так сказать, расходы. Ариведерчи! z
113
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
NOW! |
o |
||||
|
|
|
|
|
|
|||||
|
|
|
|
to BUY |
|
|
||||
w Click |
|
|
|
>> coding |
||||||
|
|
|
|
|
|
m |
||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
n |
e |
|
|||
|
|
|
|
-xcha |
|
|
|
|
Крис Касперски
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
трюки открыса
Борьба с хакерами на высоком сишном уровне (без ассемблерных вставок!) продолжается. Сегодня мы рассмотрим технику обфускации указателей на данные и функции, продемонстрировав системно-независимые подходы — легкие в реализации, но устойчивые к взлому.
01Обфускацияуказателейнаданные
Дизассемблеры и отладчики поддерживают мощные механизмы реконструкции перекрестных ссылок, опутывающих всю программу и образующих своеобразный несущий каркас, на который уже навешивается все остальное. Перекрестные ссылки — это артерии, автомагистрали и нити, связывающие крошечные лоскуты кода воедино.
Допустим, у нас есть строка «wrong serial mumber» или «trial expired».
Достаточно всего одного щелчка мыши, чтобы найти код, выводящий ее на экран. Следующий щелчок перенесет нас в материнскую функцию, осуществляющую проверку серийного номера/срока действия программы. Чтобы воспрепятствовать анализу алгоритма, достаточно ослепить механизм реконструкции перекрестных ссылок. Тогда программа распадется на ряд крошечных лоскутов, неизвестно каким образом связанных друг с другом.
Возьмем, к примеру, вариацию на тему «hello, world»:
Исходныйтекстнезащищеннойпрограммы
char s1[] = "j.a.n.g.a.n b.e.r.u.m.a.h d.i t.e.p.i p.a.n.t.a.i j.i.k.a";
char s2[] = "do not bulild a house on near the beach if afraid of being hit by waves";
main() { MessageBox(0, s1, s2, MB_OK); }
А теперь посмотрим, как выглядит ее дизассемблерный листинг, сгенерированный IDA Pro:
Дизассемблерныйлистингнезащищеннойпрограммы
.text:00401000 _main:
.text:00401000 |
push 0 |
|
.text:00401002 |
push offset Caption |
; "do not build a house on near |
the"... |
|
|
.text:00401007 |
push offset Text |
; "j.a.n.g.a.n b.e.r.u.m.a.h |
d.i"... |
|
.text:0040100C |
push 0 |
.text:0040100E |
call ds:MessageBoxA |
.text:00401014 |
retn |
...
.data:00405030 ; char Text[]
; DATA XREF: .text:00401007
.data:00405030 Text db 'j.a.n.g.a.n b.e.r.u.m.a.h d.i t.e.p.i p.a.n.t.a.i'
.data:00405030
.data:0040508C ; char Caption[]
; DATA XREF: .text:00401002?o
.data:0040508C Caption db 'do not bulild a house on near the beach if afraid of'
Как мы видим, IDA Pro автоматически реконструировала перекрестные ссылки на строки, упростив анализ программы до предела. Как этому помешать? Во-первых, мы должны предотвратить попадание незашифрованных указателей в код, сгенерированный компилятором. А во-вторых,
— расшифровать указатели в манере, которую не поддерживают ни IDA Pro, ни популярные отладчики.
Первая фаза решается тривиально. Оптимизирующие компиляторы поддерживают ряд математических операций (типа сложения и вычитания), вычисляя их еще на стадии трансляции. В результате, в код попадают зашифрованные указатели. Демонстрируется это в следующем примере:
Очевидное,нонеправильноерешение
#define _KEY_ 0x666999
main()
{
char* p1 = s1 + _KEY_; char* p2 = s2 + _KEY_;
114 |
xàêåð 11 /119/ 08 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
C |
E |
|
|
|||
|
|
X |
|
|
|
|
|||
|
- |
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
NOW! |
o |
|||
>> coding to BUY |
|
|
|||||||
|
|
|
|
|
|||||
w Click |
|
|
|
|
|
m |
|||
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
g |
|
|
|
|
|
|
df |
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
MessageBox(0, p1 — _KEY_, p2 — _KEY_, MB_OK);
}
Компилируем файл, загружаем его в IDA Pro и видим:
Оптимизирующиекомпиляторыстремятся выполнитьавтоматическуюдеобфускацию указателейвсегда,когдатольковозможно
.text:00401000 _main:
|
|
; CODE XREF: start+AF |
.text:00401000 |
push 0 |
|
.text:00401002 |
push offset Caption |
|
; "do not bulild a house on near the"... |
|
|
.text:00401007 |
push offset Text |
; "j.a.n.g.a.n b.e.r.u.m.a.h |
d.i"... |
|
|
.text:0040100C |
push 0 |
|
.text:0040100E |
call ds:MessageBoxA |
|
.text:00401014 |
retn |
|
Вот так сюрприз! А где же наши зашифрованные указатели?! Программа осталась в первозданном виде. Оказывается, оптимизирующий компилятор, вычисливший значение «s1 + _KEY_» на стадии трансляции, вычислил и значение «s1 - _KEY_», автоматически расшифровав указатель s1. Как запретить это компилятору — причем, не какому-то одному отдельно взятому, а всем оптимизаторам сразу? Очень просто: достаточно раскрыть ANSI C и прочитать, что трансляторы не оптимизируют статические и глобальные переменные. Следовательно, для достижения полученного результата, первый проход шифрования надо осуществлять с константой, а второй — с глобальной/статической переменной. Законченный (в смысле, окончательный) пример реализации приведен ниже:
Реальноработающаяобфускацияуказателей
main()
{
char* p1 = s1 + _KEY_; char* p2 = s2 + _KEY_; static _key_ = _KEY_;
MessageBox(0, p1 — _key_, p2 — _key_, MB_OK);
}
Программа незначительно усложнилась, зато результат превзошел все ожидания (дизассемблерный листинг ты можешь посмотреть в
исходнике на диске). Получается, IDA Pro не только не реконструировала перекрестные ссылки, но и распознала указатели на s1и s2, оставив их в зашифрованном виде. И хотя расшифровать значение указателя
вполне возможно (достаточно проанализировать дизассемблерный код),
— на это уходит время и, кроме того, все средства для постройки графов тушатся на корню. Достигается все — без применения ассемблерных вставок и прочих нестандартных извращений!
02Обфускацияуказателейнафункции
Зашифровать указатели на функции намного сложнее, поскольку оптимизаторы не поддерживают математических преобразований над ними. Почему? А потому, что их не поддерживает стандарт. Тот самый, позволяющий законными средствами получить указатель на функцию, но сужающий меню доступных действий только до присвоения нуля
— естественно, это не входит в наши планы.
Запрет на математические преобразования легко обходится кастингом. В частности, 32 битные операционные системы (Windows 9x/NT, Linux, FreeBSD) используют плоскую модель адресного пространства и 32 битные указатели на код, которыми можно оперировать так же, как
и целочисленным типом DWORD (unsigned int). В других случаях разрядность указателя может отличаться от обозначенной. Более того, он вообще может представлять собой сложную структуру, состоящую из селектора и смещения, а потому кастинг — уже хак. Но этот хак работает! Главное, вынести физический тип указателя на код в отдельный define, зависящий от платформы.
Кастинг снимает защиту на математические операции с указателями на функции, но все преобразования выполняются на стадии выполнения программы, а вовсе не на стадии компиляции. В итоге, указатели «благополучно» переживают оптимизацию, попадая в машинный код целевого файла, где их распознает IDA Pro вместе с отладчиками.
Проблема кажется неразрешимой, но… кто нам мешает доработать откомпилированный код уже после трансляции, зашифровав указатели непосредственно в двоичном файле и выполняя расшифровку уже в самой программе? Перед нами встает проблема поиска указателей в откомпилированном коде. Каково же будет наше решение? Самое простое
—загнать указатели в структуру, предваренную специальным маркером
—текстовой строкой или константой с уникальным содержимым. После чего нам остается только найти этот маркер в программе и зашифровать следующие за ним указатели. Это можно сделать как вручную в HIEW’е, так и автоматически, с помощью несложной программы. Но довольно слов, больше дела:
Обфускацияуказателейнафункции
#define p DWORD
#define _KEY_ 0x66666666
baz(char* s1, char* s2){ MessageBox(0, s1, s2, MB_OK); }
struct FF |
|
{ |
|
p am; |
// <<-- marker |
p f1; |
// <<-- list of func. pointers |
}ff = { 0xEFBEADDE, (p) &baz};
main()
{
char* p1 = s1 + _KEY_; char* p2 = s2 + _KEY_; static _key_ = _KEY_;
int (*foo)(char*, char*);
foo = (int (*)(char*, char*)) (ff.f1 ^ pk);
foo((char*) p1 — pk, (char*) p2 + pk);
}
После компиляции программы мы должны найти в исполняемом файле «магическую» последовательность 0xDEADBEEF, наложив на следующее за ней двойное слово ключ шифрования 0x66666666 по XOR. Убедившись, что все выполнено правильно и программа работает, а не падает, загружаем ее в дизассемблер (смотри листинг из исходника на диске) и видим убийственный результат обфускации указателей на код и данные. Полный хаос и теперь сам черт не разберет, что это за код и какого он там делает! Да, конечно, при прогоне программы под отладчиком (или плагином-эмулятором для IDA Pro) хакер узнает значение регистра EAX, определив, какая функция тут вызывается. Но… наглядность дизассемблерного листинга необратимо утеряна. Механизмы реконструкции потока управления тихо курят в сторонке, высаживая хакера на измену и увеличивая время анализа программы на порядок-другой. z
xàêåð 11 /119/ 08 |
115 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
C |
E |
|
|
|||
|
|
X |
|
|
|
|
|||
|
- |
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
||||
|
|
|
|
to BUY |
|
|
|||
w Click |
|
|
>> phreaking |
||||||
|
|
|
|
|
m |
||||
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
g |
|
|
|
|
|
|
df |
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
Артемий «Di Halt» Исламов
/ di_halt@mail.ru /
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
Домашний
терминатор
>>Мастерим собственного киборга
Роботывторгаютсявнашмир!Уженикогонеудивишьмеханическимируками,
аробопсывовсюшастаютпоквартирам.Ксожалению,поканеунас.Нопочему?
,чтоли,изготовитьдомашнегоробота?По-твоему,этоподсилутолько гигантувродеSony?Вовсенет!Сейчасярасскажутебе,как
терминатора-убийцувдомашнихусловиях.