Nuitka 已經不再安全? Nuitka/Cython 打包應用逆向工具 -- pymodhook

pymodhook是一個記錄任意對Python模塊的調用的庫,用于Python逆向分析。
pymodhook庫類似于Android的xposed框架,但不僅能記錄函數的調用參數和返回值,還能記錄模塊的類的任意方法調用,以及任意派生對象的訪問,基于pyobject.objproxy庫實現。
備注:請勿用本工具注入未授權的商業軟件!

GitHub: qfcy/PyModuleHook

目錄

    • DLL注入工具
        • 1.復制模塊文件
        • 2.修改 `__hook__.py`
        • 3.注入DLL
        • 4.獲取注入結果
    • 附:pymodhook庫的用法
        • 示例
        • 詳細用法
        • 工作原理

DLL注入工具

由于只依賴于加載的python3x.dll,工具支持記錄Nuitka/Cython打包的應用的模塊調用,而不僅僅是PyInstaller。

1.復制模塊文件

首先用pip install pymodhook安裝pymodhook及其依賴的pyobject包,
再打開<Python安裝目錄>/Lib/site-packages文件夾(Python安裝目錄視環境而異),將pyobject包,pymodhook.pypymodhook-patches目錄,和__hook__.py復制到目錄下:

另外如果是Python 3.8或以下的版本,還需要復制astor模塊。

2.修改 __hook__.py

__hook__.py是注入的DLL執行的第一段Python代碼,默認的__hook__.py是:

# 放入打包程序目錄的__hook__.py的模板
import atexit, pprint, tracebackCODE_FILE = "hook_output.py"
OPTIMIZED_CODE_FILE = "optimized_hook_output.py"
VAR_DUMP_FILE = "var_dump.txt"
ERR_FILE = "hooktool_err.log"def export_code():try:with open(CODE_FILE, "w", encoding="utf-8") as f:f.write(get_code())with open(VAR_DUMP_FILE, "w", encoding="utf-8") as f:dump_scope(file=f)with open(OPTIMIZED_CODE_FILE, "w", encoding="utf-8") as f:f.write(get_optimized_code())except Exception:with open(ERR_FILE, "w", encoding="utf-8") as f:traceback.print_exc(file=f)try:from pymodhook import *from pyobject.objproxy import ReprFormatProxyinit_hook()hook_modules("wx","matplotlib.pyplot","requests",deep_hook=True) # 本行可修改atexit.register(export_code)
except Exception:with open(ERR_FILE, "w", encoding="utf-8") as f:traceback.print_exc(file=f)

一般只需要將調用hook_modules()的這行,修改成自定義的其他模塊即可。deep_hook=True選項一般用于Cython/Nuitka打包的應用,對于普通應用deep_hook是可選的。
另外對于特定庫,可能還需要自行修改pymodhook-patches目錄。

3.注入DLL

在項目的Release頁面下載DLLInject_win_amd64.zip。
下載后解壓并運行hook_win32.exe,搜索目標進程并選中,再點擊"Inject DLL"按鈕:

如果注入成功,會看到這個提示:

4.獲取注入結果

注入成功后如果程序退出(非強制終止進程),模塊hook的結果hook_output.py, optimized_hook_output.pyvar_dump.txt會在被注入進程的工作目錄生成。
hook_output.py是原始的詳細調用記錄,optimized_hook_output.py是簡化后的模塊調用代碼,var_dump.txt為所有變量的轉儲。
如果結果生成失敗,還會額外生成一個文件hooktool_err.log,記錄錯誤消息。

optimized_hook_output.py的示例:

import tkinter as tk
Canvas = tk.Canvas
import matplotlib.pyplot as plt
import requests
var0 = tk.Tk()
ex_var1 = int(tk.wantobjects)
var15 = var0.tk
var0.title('Tk')
var0.withdraw()
var0.iconbitmap('paint.ico')
var0.geometry('400x300')
var0.overrideredirect(ex_var1)
var43 = Frame(var0, bg='gray92')
var43._last_child_ids = {}
var28 = Canvas(var43, bg='#d0d0d0', fg='#000000')
var28.pack(expand=ex_var1, fill='x')
var28._last_child_ids = {}
# external var53: <function object at 0x000001F3F0A27180>
var0.bind('<Button-1>', var53)
var0.mainloop()
...

var_dump.txt的示例:

{...,'ex_var855': True,'ex_var860': True,'ex_var875': True,...'var123': <function BaseWidget.__init__ at 0x04616B28>,'var124': <tkinter.ttk.Button object .!frame.!button3>,'var125': {'command': <bound method Painter.save of <painter.Painter object at 0x047298F0>>,'text': '保存','width': 4},'var126': None,'var127': <function BaseWidget._setup at 0x04616AE0>,'var128': {'command': <bound method Painter.save of <painter.Painter object at 0x047298F0>>,'text': '保存','width': 4},...'var146': '.!frame.!button3','var147': <built-in method call of _tkinter.tkapp object at 0x048C3890>,'var148': '','var152': <function BaseWidget.__init__ at 0x04616B28>,'var153': <tkinter.ttk.Button object .!frame.!button4>,'var154': {'command': <bound method Painter.clear of <painter.Painter object at 0x047298F0>>,'text': '清除','width': 4},...
}

附:pymodhook庫的用法

運行命令pip install pymodhook,即可安裝pymodhook庫。

示例

hook了numpymatplotlib庫的示例:

from pymodhook import *
init_hook()
hook_modules("numpy", "matplotlib.pyplot", for_=["__main__"]) # 記錄numpy和matplotlib的調用
enable_hook()
import numpy as np
import matplotlib.pyplot as plt
arr = np.array(range(1,11))
arr_squared = arr ** 2
mean = np.mean(arr)
std_dev = np.std(arr)
print(mean, std_dev)plt.plot(arr, arr_squared)
plt.show()# 顯示記錄的代碼
print(f"原始調用記錄:\n{get_code()}\n")
print(f"優化后的代碼:\n{get_optimized_code()}")

運行后會出現類似IDA等工具生成的代碼:

原始調用記錄:
import numpy as np
matplotlib = __import__('matplotlib.pyplot')
var0 = matplotlib.pyplot
var1 = np.array
var2 = var1(range(1, 11))
var3 = var2 ** 2
var4 = np.mean
var5 = var4(var2)
var6 = var2.mean
var7 = var6(axis=None, dtype=None, out=None)
var8 = np.std
var9 = var8(var2)
var10 = var2.std
var11 = var10(axis=None, dtype=None, out=None, ddof=0)
ex_var12 = str(var5)
ex_var13 = str(var9)
var14 = var0.plot
var15 = var14(var2, var3)
var16 = var2.shape
var17 = var2.shape
var18 = var2[(slice(None, None, None), None)]
var19 = var18.ndim
var20 = var3.shape
var21 = var3.shape
var22 = var3[(slice(None, None, None), None)]
var23 = var22.ndim
var24 = var2.values
var25 = var2._data
var26 = var2.__array_struct__
var27 = var3.values
...
var51 = var41.__array_struct__
var52 = var0.show
var53 = var52()優化后的代碼:
import numpy as np
import matplotlib.pyplot as plt
var2 = np.array(range(1, 11))
plt.plot(var2, var2 ** 2)
plt.show()
詳細用法
  • init_hook(export_trivial_obj=True, hook_method_call=False, **kw)
    初始化模塊hook,需要在調用hook_module()hook_modules()之前調用。

    • export_trivial_obj:是否不繼續hook模塊函數返回的基本類型(如整數、列表、字典等)。
    • hook_method_call:是否hook模塊類實例的方法內部調用(即方法的self傳入的是ProxiedObj而不是原先的對象)
    • 其它參數通過**kw傳遞給ObjChain
  • hook_module(module_name, for_=None, hook_once=False, deep_hook=False, deep_hook_internal=False, hook_reload=True)
    鉤住(hook)一個模塊,后續導入這個模塊時會返回hook后的模塊。

    • module_name:要hook的模塊名(如"numpy")。
    • for_:只有從特定模塊(如["__main__"])導入時才應用hook,能避免底層模塊之間相互依賴導致的報錯。如果不提供,默認對所有模塊全局應用hook。
    • hook_once:只在首次導入時返回hook后的庫,后續直接返回原模塊。
    • deep_hook:是否hook模塊中的每個函數和類,而不是模塊本身。deep_hookTrue時模塊始終被hook,for_hook_onceenable_hook不起作用。
    • deep_hook_internaldeep_hookTrue時,是否hook以下劃線開頭的對象(雙下劃線對象如__loader__除外)。
    • hook_reload:是否繼續hook通過importlib.reload()返回的同一新模塊。
  • hook_modules(*modules, **kw)
    一次hook多個模塊,如hook_modules("numpy","matplotlib"),關鍵字參數的其他用法同hook_module函數。

  • unhook_module(module_name)
    取消對指定模塊的hook,包括deep_hook后的模塊。

    • module_name:要撤銷hook的模塊名。
  • enable_hook()
    啟用模塊hook的全局開關(默認關閉)。啟用后,導入被hook的模塊時才會返回hook對象。deep_hookTrue時不需要手動調用enable_hook

  • disable_hook()
    禁用模塊hook的全局開關。禁用時不會導入hook后的模塊,除非使用了deep_hook=True

  • import_module(module_name)
    導入并返回子模塊對象,而不是根模塊。

    • module_name:如"matplotlib.pyplot",會返回pyplot子模塊對象。
  • get_code(*args, **kw)
    生成模塊原始調用記錄的Python代碼,可用于重現當前對象依賴關系,以及庫調用歷史。

  • get_optimized_code(*args, **kw)
    生成優化后的代碼,同get_code用法。(代碼優化在內部使用了有向無環圖(DAG),詳細優化原理見pyobject庫)

  • get_scope_dump()
    返回當前hook鏈的變量命名空間(作用域)字典的淺拷貝,用于調試和分析。

  • dump_scope(file=None)
    將整個變量命名空間字典用pprint輸出到流file,某個對象的__repr__()方法出錯時輸出不會中斷。file默認為sys.stdout

  • getchain()
    返回用于hook模塊的全局pyobject.ObjChain實例,用于手動操作ObjChain。如果尚未調用init_hook(),返回None

pymodhook-patches目錄

pymodhook-patches目錄內部包含了多個以模塊名命名的json文件,包含不能hook的自定義的屬性和函數名,用于兼容特定的Python庫。
matplotlib.pyplot.json的格式如下:

{// 每個鍵是可選的"export_attrs":["attr"], // 要導出的屬性名(即plt.attr返回原始對象,而不是pyobject.ProxiedObj)"export_funcs":["plot","show"], // 要導出的函數名(即函數的調用返回值是原始對象,而不是pyobject.ProxiedObj)"alias_name":"plt" // 模塊的常用別名,用于控制代碼生成格式(如import matplotlib.pyplot as plt)
}
工作原理

庫在底層使用了pyobject.objproxy庫中的ObjChain,用于動態代碼生成,而本pymodhook庫是pyobject.objproxy的高層封裝。詳細原理參見pyobject.objproxy的文檔。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/80799.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/80799.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/80799.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

path環境變量滿了如何處理,分割 PATH 到 Path1 和 Path2

要正確設置 Path1 的值&#xff0c;你需要將現有的 PATH 環境變量 中的部分路徑復制到 Path1 和 Path2 中。以下是詳細步驟&#xff1a; 步驟 1&#xff1a;獲取當前 PATH 的值 打開環境變量窗口&#xff1a; 按 Win R&#xff0c;輸入 sysdm.cpl&#xff0c;點擊 確定。在 系…

SEMI E40-0200 STANDARD FOR PROCESSING MANAGEMENT(加工管理標準)-(一)

1 目的 物料(例如晶圓)加工在設備中的自動化管理與控制是實現工廠自動化的關鍵要素。本標準針對半導體制造環境中與設備內部物料處理相關的通信需求進行了規范。本標準規定了在加工單元接收到的指定材料所應適用的加工方法(例如Etch腔室需要Run哪支Recipe)。它闡述了物料加工的…

【Hadoop】集群搭建實戰:超詳細保姆級教程

&#x1f407;明明跟你說過&#xff1a;個人主頁 &#x1f3c5;個人專欄&#xff1a;《大數據前沿&#xff1a;技術與應用并進》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目錄 一、引言 1、Hadoop簡介 2、Hadoop集群概念 3、 Hadoop 集…

阿里云人工智能大模型通義千問Qwen3開發部署

本文主要描述阿里云人工智能大模型開源社區ModelScope提供的通義千問Qwen3開發部署。 與阿里云一起 輕松實現數智化 讓算力成為公共服務&#xff1a;用大規模的通用計算&#xff0c;幫助客戶做從前不能做的事情&#xff0c;做從前做不到的規模。讓數據成為生產資料&#xff1a;…

24.(vue3.x+vite)引入組件并動態掛載(mount)

示例截圖 組件代碼: <template><div><div>{{message }}</div>

《Python星球日記》 第56天:循環神經網絡(RNN)入門

名人說:路漫漫其修遠兮,吾將上下而求索。—— 屈原《離騷》 創作者:Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder??) 目錄 一、序列數據的特點與挑戰1. 什么是序列數據?2. 序列數據的挑戰二、RNN 的基本結構與前向傳播1. RNN的核心理念2. RNN的數學表達3. RNN的前向傳…

手寫 vue 源碼 === computed 實現

目錄 計算屬性的基本概念 計算屬性的核心實現 ComputedRefImpl 類的實現 ReactiveEffect 與計算屬性的關系 計算屬性的工作流程 1. 創建計算屬性 2. 依賴收集過程 3. 嵌套 effect 的處理 4. 更新過程 嵌套 effect 關系圖解 依賴關系建立過程 代碼實現分析 1. 創建…

【Lattice FPGA 開發】Diamond在線調試Reveal邏輯亂跳的解決

在Vivado中在always塊中寫邏輯時如果出現always塊中的異步復位敏感詞在塊內部未使用的情況&#xff0c;如下例的rst&#xff1a; always (posedge clk or posedge rst) begin if(~tx_sense_flag)o_rd_adr < d1;else if((o_rd_adr d94) & (bit_cnt d7))o_rd_adr <…

【hadoop】Sqoop數據遷移工具的安裝部署

一、Sqoop安裝與配置 步驟&#xff1a; 1、使用XFTP將Sqoop安裝包sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz發送到master機器的主目錄。 2、解壓安裝包&#xff1a; tar -zxvf ~/sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz 3、修改文件夾的名字&#xff0c;將其改為s…

BUUCTF——PYWebsite

BUUCTF——PYWebsite 進入靶場 看看基本信息 沒有什么信息 掃個目錄看看 http://node5.buuoj.cn:28115/.DS_Store http://node5.buuoj.cn:28115/flag.php http://node5.buuoj.cn:28115/index.html訪問flag.php 提示保存購買者的IP 抓包看看 直接XFF偽造一下 X-Forwarded-F…

基于Qt開發的多線程TCP服務端

目錄 一、Qt TCP服務端開發環境準備1. 項目配置2. 核心類說明二、服務端搭建步驟詳解步驟1:初始化服務端對象步驟2:啟動端口監聽步驟3:處理客戶端連接三、數據通信與狀態管理1. 數據收發實現2. 客戶端狀態監控四、進階功能擴展1. 多客戶端并發處理2. 心跳檢測機制五、調試與…

【Tools】VScode使用CMake構建項目

這里寫目錄標題 vscode 使用 CMake**安裝插件**新建CMake項目 vscode 使用 CMake 安裝插件 CMake和CMake Tools c等等 CMake插件主要功能是CMake語法高亮、自動補全CMake Tools的功能主要是結合VSCode IDE使用CMake這個工具&#xff0c;比如生成CMake項目、構建CMake項目等…

neo4j圖數據庫基本概念和向量使用

一.節點 1.新建節點 create (n:GroupProduct {name:都邦高保額團意險,description: "保險產品名稱"} ) return n CREATE&#xff1a;Neo4j 的關鍵字&#xff0c;用于創建新節點或關系。 (n:GroupProduct)&#xff1a; n 是節點的臨時別名&#xff08;變量名&#…

2025年滲透測試面試題總結-滲透測試紅隊面試八(題目+回答)

網絡安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。 目錄 滲透測試紅隊面試八 二百一十一、常見中間件解析漏洞利用方式 二百一十二、MySQL用戶密碼存儲與加密 …

大語言模型主流架構解析:從 Transformer 到 GPT、BERT

&#x1f4cc; 友情提示&#xff1a; 本文內容由銀河易創AI&#xff08;https://ai.eaigx.com&#xff09;創作平臺的gpt-4-turbo模型生成&#xff0c;旨在提供技術參考與靈感啟發。文中觀點或代碼示例需結合實際情況驗證&#xff0c;建議讀者通過官方文檔或實踐進一步確認其準…

Java設計模式之裝飾器模式:從基礎到高級的全面解析(萬字解析)

裝飾器模式(Decorator Pattern)是一種結構型設計模式,它允許向一個現有的對象添加新的功能,同時又不改變其結構。這種模式創建了一個裝飾類,用來包裝原有的類,并在保持類方法簽名完整性的前提下,提供了額外的功能。 一、裝飾器模式基礎概念 1.1 什么是裝飾器模式 裝飾…

RN 鴻蒙混合開發實踐(踩坑)

#三方框架# #React Native # 1 。環境配置&#xff1b; 安裝 DevEco 開發工具&#xff1b; Node 版本16&#xff1b; hdc環境配置 hdc 是 OpenHarmony 為開發人員提供的用于調試的命令行工具&#xff0c;鴻蒙 React Native 工程使用 hdc 進行真機調試。hdc 工具通過 OpenHa…

動態網站 LNMP

一、名詞解釋&#xff1a; LNMP&#xff1a; L : 代表 Linux 操作系統&#xff0c;為網站提供了可靠的運行環境N : 代表 Nginx&#xff0c;它是一款輕量級的高性能 Web 服務器&#xff0c;能夠快速處理大量并 發連接&#xff0c;有效提升網站的訪問速度和性能 M : 代表…

DAY04:Vue.js 指令與事件處理深度解析之從基礎到實戰

1. 指令系統核心概念 1.1 插值表達式與基礎指令 Vue.js 的指令系統是其響應式編程模型的核心&#xff0c;我們首先從最基礎的插值表達式開始&#xff1a; <div id"app"><!-- 基礎文本插值 --><p>{{ message }}</p><!-- JavaScript 表達…

12配置Hadoop集群-集群配置

&#xff08;一&#xff09;Hadoop的組成 對普通用戶來說&#xff0c; Hadoop就是一個東西&#xff0c;一個整體&#xff0c;它能給我們提供無限的磁盤用來保存文件&#xff0c;可以使用提供強大的計算能力。 在Hadoop3.X中&#xff0c;hadoop一共有三個組成部…