SOCKET PYTHON. Пишем client-server приложение.

SOCKET PYTHON. Пишем client-server приложение.

moderator E7

Всем привет ! В этой статье обсудим модуль socket и напишем своё клиент-серверное приложение


PYTHON SOCKET , коротко о сетях.

Программистам на Python доступен целый ряд сторонних инструментов для создания серверов и клиентов, работающих по сети, но все они основаны на одном модуле — socket . Этот модуль предоставляет доступ ко всем необходимым компонентам для быстрого написания клиентов и серверов, взаимодействующих по TCP (Transmission Control Protocol — протокол управления передачей) и UDP (User Datagram Protocol — протокол пользовательских датаграмм), применения сырых сокетов и т. п. На самом деле этого модуля вполне достаточно, для того чтобы получить или поддерживать несанкционированный доступ к атакуемым компьютерам. Для начала создадим простые клиентские и серверные программы — два вида сетевых скриптов, которые вам придется писать чаще всего.


TCP-клиент

Бывает, что приходится на скорую руку написать TCP-клиент для проверки сервисов, отправки бессмысленных данных, проведения фаззинга или выполнения каких-либо других задач. Если вы работаете внутри крупного корпоративного окружения, у вас не будет такой роскоши, как сетевые инструменты или компиляторы, а иногда вы будете лишены даже самого элементарного, например возможности копирования/вставки информации или подключения к интернету. Именно в таких условиях способность быстро создать TCP-клиент чрезвычайно полезна. Но хватит болтать — давайте писать код! Вот простой TCP-клиент:


import socket
target_host = "www.google.com"
target_port = 80
# создаем объект сокета
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

# подключаем клиент
client.connect((target_host,target_port)) 

# отправляем какие-нибудь данные
client.send(b"GET / HTTP/1.1\r\nHost: google.com\r\n\r\n") 

# принимаем какие-нибудь данные
response = client.recv(4096) 
print(response.decode())

client.close()


Сначала создаем объект сокета с параметрами AF_INET и SOCK_STREAM . Параметр AF_INET говорит о том, что мы будем использовать стандартный адрес IPv4 или сетевое имя, а SOCK_STREAM означает, что клиент будет работать по TCP. Затем подключаемся к серверу и отправляем ему какие-то данные в виде байтов. Последний шаг состоит в получении и выводе ответа , после чего сокет можно закрыть. Это простейший вариант TCP-клиента, но вы будете писать его чаще всего.

В этом фрагменте кода делаются серьезные допущения насчет сокетов, и вам определенно нужно о них знать. Первое допущение — соединение всегда остается стабильным, второе — сервер ждет, когда мы первыми отправим данные (некоторые серверы сначала шлют данные, а затем ожидают от вас ответа). Третье предположение заключается в том, что сервер всегда и вовремя возвращает данные. Все это в основном продиктовано желанием упростить код. В программистской среде существуют разные мнения о том, как работать с блокирующими сокетами, обрабатывать их исключения и т. п. , однако пентестеры довольно редко реализуют такие тонкости в своих инструментах , написанных на скорую руку для сбора данных или эксплуатации удаленных компьютеров, поэтому в данной главе мы их тоже проигнорируем.


UDP-клиент

В Python UDP-клиент мало отличается от TCP-клиента, нам нужно внести всего два небольших изменения, чтобы он мог отправлять пакеты в формате UDP:



import socket
target_host = "127.0.0.1"
target_port = 9997

# создаем объект сокета
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 

# отправляем какие-нибудь данные
client.sendto(b"AAABBBCCC",(target_host,target_port)) 

# принимаем какие-нибудь данные
data, addr = client.recvfrom(4096)
print(data.decode())
client.close()

Как видите, при создании объекта сокета мы поменяли его тип на SOCK_DGRAM . Дальше нужно просто вызвать функцию sendto() и передать ей данные и сервер, которому вы хотите их отправить. Поскольку протокол UDP не поддерживает соединения, перед взаимодействием нет вызова connect().

В конце нужно вызвать recvfrom() , чтобы получить ответные UDP-данные. Вы можете заметить, что вместе с данными этот вызов возвращает информацию об удаленном адресе и порте. И вновь мы не пытаемся быть превосходными сетевыми программистами — нам нужен быстрый, простой и надежный способ писать инструменты для выполнения повседневных хакерских задач. Давайте перейдем к созданию простых серверных программ.


TCP-сервер

В Python TCP-серверы создаются так же просто, как и клиенты. Собственный TCP-сервер может пригодиться при написании командных оболочек или прокси-серверов (и то, и другое мы реализуем позже). Для начала создадим стандартный многопоточный TCP-сервер. Наберите в своем редакторе следующий код:



import socket
import threading
IP = '0.0.0.0'
PORT = 9998
def main():
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind((IP, PORT)) 
    server.listen(5) 
    print(f'[*] Listening on {IP}:{PORT}')
    
    while True:
        client, address = server.accept() 
        print(f'[*] Accepted connection from {address[0]}{address[1]}')
        client_handler = threading.Thread(target=handle_client,
                                            args=(client,))
        client_handler.start() 

def handle_client(client_socket): 
    with client_socket as sock:
    request = sock.recv(1024)
    print(f'[*] Received: {request.decode("utf-8")}')
    sock.send(b'ACK')

if __name__ == '__main__':
    main()

Вначале мы передаем IP-адрес и порт, который должен прослушивать наш сервер. Затем просим сервер начать прослушивание, указав, что отложенных соединений должно быть не больше пяти. Затем сервер входит в свой главный цикл, в котором ждет входящее соединение. При подключении клиента мы получаем клиентский сокет в переменной client и подробности обудаленном соединении в переменной address . Затем создаем объект нового потока, который указывает на нашу функцию handle_client , и передаем этой функции клиентское соединение. В этот момент главный цикл сервера освобождается для обработки следующего входящего соединения. Функция andle_client выполняет вызов recv() , после чего возвращает клиенту простое сообщение. Если воспользоваться TCP-клиентом, который мы создали ранее, можно послать серверу несколько проверочных пакетов. Вы должны увидеть следующий вывод:


[*] Listening on 0.0.0.0:9998
[*] Accepted connection from: 127.0.0.1:62512
[*] Received: ABCDEF

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




С любовью от E7TEAM ;)

Report Page