Игра в сокс по-программерски

19 Вересня 2009

За сьогодні це 3-тій пост в блог. Трохи забагато ;). Але річ в тім, що завтра їду в Ялту на наукову конференцію, та й буду там пропадати десь з тиждень. Тому зараз опублікую багатенько, що вам було що читати в мою відсутність. Хоча ВайФай в мене буде, тому на декілька хвилин в день сможу бувати в інтернеті, то може ще й буду щось публікувати з Ялти.

Отже, ще одна стаття з 8-мого випуска журнала Хакер. І як завжди тут повний оригінал зі всіми помилками, що є невідємною частиною мого стилю ;)


Методы не стандартного использования socks-сервера

Хакер от обычного человека отличается способом мышления - у нас мозги "направлены" в иную сторону. Хакеры это не нормальные люди. И я горжусь, когда меня кто-то так называет. Давайте используем эту способность и попробуем посмотреть не нормальным взглядом на socks-сервер.

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

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

После появления браузера Google Chrome я почти полностью перешел на него, и не жалею. Но столкнулся с его ограниченным функционалом и отсутствием плагинов. Исходя из этого, он теоретически для хакинга не подходит. И тут на помощь придет Чип и Дейл локальный socks-сервер, через который можно направлять весь трафик Chrome'a. Это нам дает возможность безгранично увеличить функциональность браузера. Например, изменять заголовки http-запросов и в том числе user-agent на маленький шел, что часто используется при локальных инклудах. Или можно показывать кукисы, параметры, что передавались скрипту, а также их в каком-то автоматическом режиме модифицировать для каких-то действий. Плюс можно б указать сохранять все ресурсы, что загружает браузер, и если немного изменять http-формы, то получиться автоматический создатель фейков. Развивать эту тему можно еще очень много, и конечном итоге реализовать навороченный хак-socks-сервер.

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

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

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

Все вышеперечисленные примеры относятся к прокачке лишь одной программы - браузера, но ведь и другие можно усилить подключив через socks-сервер. Возьмем для практического примера Аську. Я прям уже слышу, как продвинутые поют поминальный песню аське. Но она же живучая, прям как динозавр. Когда открываю свой многопротокольный месенджер, то там больше половины на аське сидит. И еще долго будет сидеть :(

В аське много недостатков, первый и может главный для меня, что все сообщения передаются на сервак в открытом виде. И поэтому если у тебя локалка, то сосед может читать все твои сообщения. Также сообщения пересылаются через сервак, где, конечно же, логируются. Помню даже писалось про эксперимент, что посылали через аську линк, который никто не знал кроме пересылающих, а потом оказалось что кто-то неизвестный на линк все равно заходил. Может это и не правда, но думаю все равно по запросу с ФСБ они будут сохранять все сообщения. Мы конечно с тобой честные, но все же не очень нравится, что сообщения к соседке эротического содержания прочитают левые чувачки. Поэтому вариант защиты лишь один - шифровать сообщения. Для этой цели есть бесплатный продукт Sipt, который по сути - socks-сервер, что шифрует сообщения RSA-ключами. Все это почти полностью автоматически происходит. Но мне в свое время не понравился Sipt своим размером. Хотелось чего-то сверх простого. И это простое, но мощное средство сейчас замутим конечно на Python'е.

Короче, Склихосовский

Хватит уже теории... Перейдем к написанию socks-сервера, что сможет шифровать сообщения аськи которые мы пишем, и расшифровывать те которые нам приходят. Методом шифрования пусть будет симметрический DES. Также будем (де)шифровать абсолютно все сообщения ото всех юзеров. Это конечно уменьшает универсальность, но учитывая, что для секретных разговором лучше использовать отдельную аську, то это не критично.

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

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-сервер.

Шифрование

Чтобы шифровать сообщения нашел чудный модуль для Python'a 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] == '\x2a\x02' and data[6:10] == '\x00\x04\x00\x06': #определяем длину номера аськи 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 + '\x00\x02\x00\x00' + 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:] Как видим что мы используем 2 и 3 строчки (деление и взятие остатка от деления), чтобы преобразовать число с десятичного значение в hex-значение. На этом часть по отсылки готова, вторая часть по приему и расшифровке еще проще, поэтому ее сам сможешь написать, ну иль подсмотреть на диске.

Напутствие

Вот и рассмотрели некоторые случаи в которых обычный socks-сервер легко превращается в интереснейшие программы. Конечно не всегда все так просто как описано. Например, при рассмотрении socks'а для браузера я не упоминал о варианте что браузер будет работать по https. И это во много усложняет нашу задачу, но все же выход есть, а поскольку эта тема очень обширна и никак не поместиться в этой статье, то лишь дам в пример скрипт, на основе которого возможен обход этого ограничения - sslstrip, что был описан в 125 номере нашего журнала.

Надеюсь, что ты тоже считаешь себя хакером, и сможешь замечать в незначительных и обыденных вещах - второе дно.


Демонстрация

Шифрування Аськ from presidentua on Vimeo.

 
 
 
Роман Хоменко aka PresidentUA
mail/jabber: spirt40@gmail.com