Брутимо дедіки по-новому свіжий підхід до програмування RDP-брутфорсерів
Зміст статті
У наші дні тільки лінивий не пробував лаяти дедики — благо, тулз для цієї справи написано достатньо. Найбільш відомі tss-brute від metal і ActiveX-based брутфорси, початок еволюції яких поклали ми з Dizz'ом минулого року. Всі інші брутфорси базуються на цих двох - будучи фронт-ендами tss-brute (RDP Brute by Dizz) або клонами мого R&D Brute. Цього року я знайшов новий спосіб викрадення серверів на Windows. Хочеш дізнатися, як читай далі!
Здавалося б, все добре — безліч брутфорсів, вибирай-не хочу, але всі вони не позбавлені недоліків.
Отже, сьогодні я розповім тобі, як мені вдалося написати брутфорс, який працює на будь-якій ОС сімейства Windows NT, при цьому не використовуючи ніяких зовнішніх компонентів - фактично працюючи прямо з протоколом RDP версії 5!
Розбір польотів
Восени 2009 року я серйозно замислився над написанням нового брутфорсу. Я почав шукати документацію по протоколу RDP, і, само собою, нічого не знайшов. І тоді я згадав, що існує такий проект, як rdesktop — RDP-клієнт під нікси, що працює з X-сервером і вміє автоматично вводити логін і пароль. Я скачав вихідники і почав їх вивчати. Взяти і просто скопіювати кілька функцій неможливо через своєрідну структуру програми, тому я вирішив переписати їх у потрібному мені вигляді. Витративши приблизно тиждень, я забив на цю справу. Через деякий час один мій іноземний знайомий, зацікавлений у написанні мною хорошого брутфорсу, скинув мені цікаву інформацію — патч, що перетворює rdesktop на брутфорс. Начебто б, ось воно, щастя, та не тут-то було! Брут виходив однопоточним, за спискомпаролів, і працював він тільки під лінуксом, що нас зовсім не влаштовувало. Вкотре на проект було забито. Через кілька місяців я наткнувся на pudn.com на winRDesktop — порт rdesktop'a на Windows, у вигляді проекту для MS Visual Studio. Це було саме те, що мені потрібно, і я взявся за перетворення невинної софтинки на забійний брутфорс.
Для початку нам необхідно визначитися, як саме виглядатиме наша прога. Розглянувши безліч варіантів, я зупинився на одному - брутфорс складається з двох частин:
- Модифікований winrdesktop, якому передаються логін, пароль та IP сервера. Він намагається залогінитися та повертає результат.
- 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++ 2008Express, але Professional має більш крутий компілятор, тому раджу використовувати саме його, тим більше якщо ти студент — можеш отримати його безкоштовно по DreamsPark), і відкриваємо наш проект. Проект спочатку призначений для VC 9, тому без танців з бубном у версіях молодше VS2008 він не запрацює.
Спочатку додамо кілька констант у файл rdesktop.h, які допоможуть програмі розпізнавати результат введення пароля. До речі, в патчі є функція брутфорсу серверів під Win 2k, але він використовує четверту версію протоколу, яка не підтримує автологін, тому пас вбивається емуляцією кнопок. Нас таке не влаштовує, тому Win 2000 ми підтримувати не будемо.
Як же працює розпізнавання? Дуже просто — пакет , що прийшов клієнту, побайтово порівнюється з деякими сигнатурами, і на підставі цих сигнатур робиться висновок про успіх/невдачу при підборі пароля. Наприклад, #define LOGON_AUTH_FAILED"\xfe\x00\x00" означає, що пароль введено неправильно. Інші константи ти можеш піддивитися в коді. Значення констант має бути зрозуміле з назви. Якщо ні, то навіщо ти читаєш? 🙂
Далі ми патчімо процедурку process_text2() з файлу orders.c. У ній і відбувається розпізнавання результату введення пароля. Хоча, насправді, не тільки в ній — найчастіше при успішному логіні сервер надсилає пакет з повідомленням про це — PDU_LOGON.
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-проект з одним віджетом. Дизайн - особиста справа кожного, на скріншоті ти можеш побачити те. що вийшло у мене.
Для початку – накидаємо невеликий план.
- Головний потік запускає допоміжний потік.
- Допоміжний потік запускає .exe-шник, який ми написали раніше, і чекає результату.
- Коли виконання брутфорсу закінчується, потік випускає сигнал, який обробляється головним потоком, беренаступні логін та пароль, і переходить до кроку 2.
Для допоміжних потоків я написав клас BruteThread, який, по суті, не є потоком, оскільки не успадковується від QThread, але використовує тільки асинхронні методи для виконання дій, що займають тривалий час. BruteThread займається запуском нашого модифікованого winRDesktop'a за допомогою об'єкта process класу QProcess. Клас QProcess створений для запуску зовнішніх додатків, і може запускати додаток, направляти його виведення в консоль (то, що виводиться через printf або cout, наприклад), відстежувати зміну стану і завершення процесу. Нас цікавлять тільки запуск і завершення програми — якщо відбувається одна з цих подій, випускаються сигнали void started() і void finished(int exitCode) відповідно. Зверніть увагу на останній сигнал - у ньому як параметр передається код, з яким програма була завершена - і цей параметр нам дуже знадобиться. Обробляти ми тільки другий сигнал, і код слота ти можеш побачити на врізці "Сигнал onFinished()". У ньому потік випускає відповідні сигнали, і переходить до наступної комбінації логін;пароль.
Сам запуск процесу виглядає так:
Запуск процесу бруту
QStringList slArgs; slArgs
Як бачиш, аргументи процесу передаються QStringList, що дуже зручно :). Ну і, звичайно ж, не забудь у конструкторі класу відразу приєднати сигнал до слоту:
Ось так виглядає слот головного потоку, який обробляє результати:
Обробляємо результати у головному потоці
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++; >
От і все! Решту ти маєш доробити сам, а якщо не зможеш — сміливо дивись у мої вихідники на диску. Тільки не сподівайся, що зможеш відкрити проект, змінити назви кнопочок і заробити на Хаммер, продаючи новий брут — у ньому є кілька елементарних хитрощів, і, якщо ти скрипт-кідді, то скомпилити проект у тебе не вийде. Ну, а якщо вмієш хоча б базово працювати з С, то, я думаю, проблем воно тобі не завдасть :).
До цього рішення я прийшов після масової перекомпіляції мого R&D P Brute, після викладання його вихідників, школотою (не плутати зі школярами!), які при найменших проблемах здійснювали дії сексуального характеру з моїм мозком (" А у мене не та версія mstscax.dll, що робити??", "А що означає ShowMessage(). "). Один з індивідуумів, до речі, сам зізнався, що brain.dll і hands.lib у нього відсутні (спасибі sslBot за лог, поржав від душі). Ну, та ми відволіклися.
У нас залишилися невирішеними дві проблеми, усунення яких я доручаю тобі:
- Споживання ресурсів.
- Підтримка кирилиці (чисто спортивний інтерес, ще раз повторюю — не бруть українські сервери).
На цьому дозволь відкланятися. Вдалого кодингу!
Подяки
Хотілося б подякувати наступним людям за допомогу, надану при написанні бруту: