Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР 128, АВГУСТ 2009 г.

Игра в сокс по-программерски. Прокачиваем аську и браузеры с использованием socks-сервера на Python’e

Роман «predidentua» Хоменко (http://tutamc.com)

Для обычного человека socks-сервер – это просто штука, которая позволяет менять IP. Но хакеру она готова раскрыть еще несколько секретов: например, как слушать и видоизменять трафик, добавляя функционал к любым программам.

Вариант 1. Прокачаем браузер

После появления браузера Google Chrome я почти полностью перешел на него. Бродилка хороша всем, но огорчает ограниченный функционал и отсутствие плагинов. Значит, теоретически для хакинга он не подходит. Спокойно! На помощь придет локальный socks-сервер, через который можно направлять весь трафик Chrome'a. Это даст возможность безгранично увеличивать функциональность браузера. Так, мы сможем изменять заголовки http-запросов (в том числе, user-agent) на маленький шелл, который часто используется при локальных инклудах. И показывать кукисы, параметры, которые передавались скрипту, модифицируя их в автоматическом режиме. Кроме того, станет возможно сохранять все загружаемые браузером ресурсы.

Вариант 2. Храним секрет среди паблика

Об этом методе нестандартного использования соксов я узнал после вступления в FOA Group. Для внутренних нужд группой был написан socks-сервер, который во всех POST-запросах искал заданные маркеры и, в случае нахождения, шифровал текст между ними с использованием AES и BASE64. Стало реально писать на любом сайте, ощущая полную уверенность, что левые люди этот текст не прочитают. До шифрования текст выглядит так: [FOA]secure text[/FOA], а socks-сервер переделывает его во что-то вроде [FOA]BASE64==[/FOA]. При загрузке html-страниц он автоматически выполняет обратное преобразование. Если увидишь где-то на форумах среди обычного текста непонятную base64-строку, – есть вероятность, что она содержит какую-либо секретную информацию.

Вариант 3. Шифрование аськи

Само собой, прокачиванием браузера польза от сокс-серверов не ограничивается. Обратим взоры на аську (несмотря на происки жабберастов, она остается живее всех живых). Асечка – продукт небезопасный, сообщения передаются в явном виде и могут быть отсниффаны злобными соседями по локале. Передавать интимную информацию в объятия любопытных чуваков из интернетов в наши планы не входит, поэтому попробуем пофиксить ситуацию. Во-первых, для этой цели существует бесплатный продукт Simp, представляющий собой socks-сервер, который автоматически шифрует сообщения RSA-ключами. А во-вторых, мне он не нравится :). Поэтому мы с тобой рассмотрим создание более легкой и элегантной версии подобного софта. Разумеется, с реализацией на Python'е.

Выбор socks-сервера и внедрение в него

Socks - протокол несложный и хорошо документированный. При желании сервер можно закодить самому за три четверти часа, но мы поступим по-хакерски, внедрившись в существующий сокс-сервер. Мне больше всего нравится socks-сервер от Xavier Lagraula. Он представляет собой набор скриптов, основными среди которых являются PySocks.py (главная программа), и socks.conf (конфиг). Зайдем в конфиг и выставим два параметра:

bind_address : 127.000.000.001
bind_port : 1080

Здесь мы определяем IP-шник и порт, на котором будет висеть socks-сервер. Теперь можно запустить PySocks.py и попробовать его в работе. Кстати, при запуске сервера ты наверняка заметил черное консольное окошко, которое портит внешний вид твоей новой Windows7? Чтобы убрать его, измени расширение файла PySocks с py на pyw.

Затем найдем место внедрения нашего кода. Для этого нужно знать, что для чтения данных с сокета есть функция recv. Если мы откроем файл PySocks.py и попробуем поискать название функции, то сразу же найдем следующий код (без выделенного жирным шрифтом):

data = readable_sock.recv(self.server)

if data:

if readable_sock == client_sock:
my_type = 1
else:
my_type = 2
data = my_hack.my_hack(my_type,data)

writeableslist[0].send(data)
if readable_sock == client_sock:
octets_out += len(data)
else:
octets_in += len(data)
else:
raise Connection_Closed

Этот код читает данные с одного сокета и записывает их в другой. Именно в этот участок мы и присунем свой код (он как раз выделен). Здесь по значению client_sock мы узнаем, в какую сторону идет информация, и передаем ее в нашу функцию my_hack. Она будет находиться в одноименном модуле. То есть, все данные после нашего внедрения начнут проходить через my_hack, в котором мы, соответственно, и получим полную власть над информацией.

Минимальный вариант модуля my_hack.py, который должен размещаться в каталоге с остальными файлами socks-сервера, таков:

def my_hack(type,data):
return data

Как видим, эта функция (my_hack) лишь возвращает то, что ей передали, и поэтому никак не влияет на socks-сервер.

Шифрование

Для реализации функции шифрования я нашел чудесный модуль - pyDes.py, сделанный добрыми руками человека по имени Todd Whiteman. Для шифрования или расшифровки с помощью модуля нужно создать объект и передать ему пароль и установить параметр padmode=pyDes.PAD_PKCS5. Дальше все просто - используем функцию encrypt для шифрования и decrypt для расшифровки.

Ниже приведен пример двух функций, которые упрощают процесс шифровки-дешифровки. Эти функции мы позже будем использовать для шифрования сообщений аськи:

import pyDes
#функция для шифрования
def encode(password,data):
k = pyDes.des(pass,padmode=pyDes.PAD_PKCS5)
return k.encrypt(data)
#функция для расшифровки
def decode(password,data):
k = pyDes.des(pass,padmode=pyDes.PAD_PKCS5)
return k.decrypt(data)

Мы используем DES-шифрование, но этот модуль также поддерживает надежный 3DES. А если захочешь использовать AES, то тут я могу посоветовать использовать Python Cryptography Toolkit.

Протокол аськи

Самый сложный момент - разобраться с протоколом аськи. Я честно начал вкуривать в документацию и даже прочел пару страницу, но затем мотивация иссякла, я бросил теорию и перешел к изучению протокола методом проб и ошибок. Для анализа протокола сохраним несколько сообщений. Тут подойдет такой код в нашей функции my_hack:

#если исходящее соединение
if type == 1:
file = open('q.txt.', 'w+')
file.write(data)
file.close()

При просмотре сохраненных сообщений стало ясно, что во всех них вначале идет 0x2a02, далее - 2 байта (число, которое увеличивается на единицу при каждом следующем обмене данными с сервером). Следующими идут 2 байта, которые обозначают длину всего блока данных, без учета первых 6 байт. После заголовка идет блок данных; для исходящих сообщений он всегда начинается с 0x00040006.

В блоке данных важным полем является байт с номером 26. В нем содержится размер номера аськи. Размер номера запомним обязательно, ведь при расчете остальных смещений нужно учитывать длину номера. Слово по адресу 39 помещает в себе размер сообщения + 4 байта. Само сообщение начинается с адреса 45 + длина_номера аськи. Теперь у нас достаточно информации, чтобы считать сообщение для последующего шифрования:

if type == 1:
#отбираем только исходящие сообщения аськи
if data[0:2] == 'x2ax02'
and data[6:10] == 'x00x04x00x06':
#определяем длину номера аськи
len_num = ord(data[26])
#определяем длину сообщения
len_msg = ord(data[39+len_num])*256
+ord(data[40+len_num])-4
#читаем сообщение
msg = data[45+len_num:45+len_num+len_msg]

Итак, что здесь происходит? Мы отбираем только исходящие сообщения, определяем длину номера аськи, длину сообщения и само сообщение.
Теперь сообщение нужно зашифровать и подготовить к отправке, закодируя его в base64 и используя встроенный модуль base64, чтобы избавиться от спецсимволов, которые могли появиться при шифровании DES и повлиять на передачу сообщения:

enc_msg = encode(pass, msg)
enc_msg = base64.encodestring(enc_msg)

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

#определяем длину сообщения
len_enc_msg = len(enc_msg)+4
len_num_1 = chr(len_enc_msg / 256)
len_num_2 = chr(len_enc_msg % 256)

#создаем исходящий пакет данных
data = data[0:39+len_num] + len_num_1
+ len_num_2 + 'x00x02x00x00'
+ enc_msg + data[45+len_num+len_msg:]

Осталось лишь подкорректировать 5-й и 6-й байт, которые отвечают за размер всего пакета данных:

#определяем длину пакета данных
len_all = len(data)-6
len_all_1 = chr(len_all / 256)
len_all_2 = chr(len_all % 256)

#формируем полностью готовый к отправке пакет
data = data[0:4]+len_all_1 + len_all_2 + data[6:]

Здесь мы используем вторую и третью строчки (деление и взятие остатка от деления), чтобы преобразовать число из десятичного значения в hex.
На этом часть, посвященная исходящим сообщениям, завершена. Дешифровочную мы приводить здесь и не будем. Во-первых, ты сможешь написать все самостоятельно, интуитивно ориентируясь на предыдущий код, а во-вторых, ее можно просто списать из исходника на диске.

Отнюдь не миф

Мы рассмотрели несколько интересных примеров, которые наглядно демонстрируют, что прокачка обычных программ с помощью сокс-сервера – вовсе не миф. Правда, в разделе, посвященном прокачке броузера мы не коснулись ситуации, когда ему приходится работать по https. Ситуация довольно сложная, и решение ее в статье не поместится, поэтому я ограничусь намеком на скрипт, позволяющий обходить ограничение. Имя ему sslstrip, и он был описан в 12-м номере нашего журнала.

Кстати, мы все ждем от тебя обратной связи! Что тебе интересно? Какие темы ты нам предложишь раскрыть? Мы – твои рабы, приказывай, повинуемся :). Конечно, идей у нас с Лозовским еще вагон, но хотелось бы иметь представление о том, что интересно именно тебе. Ждем писем: spirt40@gmail.com!

OSCAR

OSCAR — открытый, но не свободный сетевой протокол, обеспечивающий обмен мгновенными и оффлайновыми текстовыми сообщениями. В данный момент используется для двух систем компании AOL (сейчас Time Warner): ICQ и AIM. AOL открыла спецификации протокола 5 марта 2008 года и разрешила создание альтернативных клиентов. Конечно же, не без ограничений.

CD

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

INFO

SOCKS — сетевой протокол, который позволяет клиент-серверным приложениям прозрачно использовать сервисы за межсетевыми экранами (файрволами). «SOCKS» — это сокращение от «SOCKetS» (сокеты, гнезда).

VIDEO

Без демонстрационного видео я тебя не оставлю - смотри его с нашего диска!

WWW

Содержание
ttfb: 481.13894462585 ms