靜態補丁腳本 - 修改 libtolua.so

直接改arm64的so, 使用python腳本。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
靜態補丁腳本 - 修改 libtolua.so
主要功能:
1. 修改 luaL_loadbuffer 函數,將跳轉目標從 luaL_loadbufferx 改為 luaL_loadfilex
2. 在 luaL_loadfilex 函數中實現跳轉到自定義的 my_custom_luaL_loadbufferx 函數
"""import struct
import os
import shutil
from pathlib import Pathclass LibtoluaPatcher:def __init__(self, target_so_path, custom_so_path):self.target_so_path = Path(target_so_path)self.custom_so_path = Path(custom_so_path)self.backup_path = self.target_so_path.with_suffix('.so.backup')# 關鍵地址定義 (基于提供的信息)self.luaL_loadbuffer_offset = 0x8A728  # luaL_loadbuffer 函數偏移self.luaL_loadfilex_offset = 0x8A530   # luaL_loadfilex 函數偏移 (未使用的函數)def backup_original(self):"""備份原始文件"""if not self.backup_path.exists():shutil.copy2(self.target_so_path, self.backup_path)print(f"已備份原始文件到: {self.backup_path}")else:print(f"備份文件已存在: {self.backup_path}")def calculate_branch_instruction(self, from_addr, to_addr):"""計算ARM64分支指令"""# 計算相對偏移offset = to_addr - from_addr# 檢查是否在B指令范圍內 (±128MB)if abs(offset) < (1 << 27):# 使用B指令 (無條件分支)# B指令格式: 0x14000000 | ((offset >> 2) & 0x3FFFFFF)offset_encoded = (offset >> 2) & 0x3FFFFFFinstruction = 0x14000000 | offset_encodedreturn struct.pack('<I', instruction)else:# 超出B指令范圍,需要使用間接跳轉raise ValueError(f"分支距離太遠: {offset}, 需要使用間接跳轉")def patch_luaL_loadbuffer(self, data):"""修改 luaL_loadbuffer 函數"""print("正在修改 luaL_loadbuffer 函數...")# 原始代碼:# .text:000000000008A728  MOV X4, #0# .text:000000000008A72C  B   luaL_loadbufferx# 新代碼:# .text:000000000008A728  MOV X4, #0  (保持不變)# .text:000000000008A72C  B   luaL_loadfilex  (修改跳轉目標)# 計算從 luaL_loadbuffer+4 到 luaL_loadfilex 的分支指令from_addr = self.luaL_loadbuffer_offset + 4  # +4 因為要修改第二條指令to_addr = self.luaL_loadfilex_offsettry:branch_instruction = self.calculate_branch_instruction(from_addr, to_addr)# 修改數據patch_offset = self.luaL_loadbuffer_offset + 4data[patch_offset:patch_offset+4] = branch_instructionprint(f"已修改 luaL_loadbuffer+4 (0x{patch_offset:X}) 的跳轉目標")except ValueError as e:print(f"修改 luaL_loadbuffer 失敗: {e}")return Falsereturn Truedef patch_luaL_loadfilex(self, data):"""在 luaL_loadfilex 函數中實現跳轉到自定義函數"""print("正在修改 luaL_loadfilex 函數...")# 創建一個簡化的hook代碼,直接跳轉到我們預設的地址# 在實際應用中,這個地址需要通過運行時解析獲得# 創建hook代碼樁stub_code = self.create_dynamic_dlopen_dlsym_and_call_stub()# 將代碼寫入 luaL_loadfilex 位置patch_offset = self.luaL_loadfilex_offsetif len(stub_code) <= 0x1F8:  # 確保不超出函數空間 (到下一個函數的距離)data[patch_offset:patch_offset+len(stub_code)] = stub_codeprint(f"已在 luaL_loadfilex (0x{patch_offset:X}) 處植入hook代碼")return Trueelse:print(f"Hook代碼太長 ({len(stub_code)} 字節),超出可用空間")return False# def create_dynamic_loader_stub(self):#     """創建SVC系統調用代碼樁"""#     # 使用SVC指令調用自定義的lua_loadbuffer系統調用#     # 根據lua_file_writer.c中的定義:SVC_LUA_LOADBUFFER = 0x1001#     instructions = []#     # 函數參數已經在X0-X4寄存器中:#     # X0 = lua_State *L#     # X1 = const char *buff  #     # X2 = size_t sz#     # X3 = const char *name#     # X4 = const char *mode#     # 直接調用SVC指令,無需保存/恢復寄存器#     # SVC #0x1001 (SVC_LUA_LOADBUFFER)#     svc_num = 0x1001#     svc_instruction = 0xD4000001 | (svc_num << 5)#     instructions.append(struct.pack('<I', svc_instruction))#     # 返回到調用者#     # RET#     instructions.append(struct.pack('<I', 0xD65F03C0))#     return b''.join(instructions)def create_dynamic_dlopen_dlsym_and_call_stub(self):"""創建動態加載和調用代碼樁"""# 這個函數生成ARM64匯編代碼,實現:# 1. dlopen("liblua_file_writer.so", RTLD_LAZY)# 2. dlsym(handle, "my_custom_luaL_loadbufferx")# 3. 跳轉到獲取的函數地址instructions = []#000000000008A6FC             luaL_loadbufferx                        ; CODE XREF: sub_C1B80+110↓p
#000000000008A530 F4 FF FF 17                 B luaL_loadbufferx (從0x00000000008A530跳轉到0x8A6FC)# 正確計算從0x8A530跳轉到0x8A6FC的B指令# 偏移量:0x8A6FC - 0x8A530 = 0x1CC = 460字節# 指令偏移:460 / 4 = 115# B指令編碼:0x14000000 | 115 = 0x14000073#instructions.append(struct.pack('<I', 0x14000073))  # B luaL_loadbufferx#     => 0x0000007f3d352530 <+0>:	sub	sp, sp, #0x80
#    0x0000007f3d352534 <+4>:	stp	x24, x23, [sp]
#    0x0000007f3d352538 <+8>:	stp	x22, x21, [sp,#16]
#    0x0000007f3d35253c <+12>:	stp	x20, x19, [sp,#32]
#    0x0000007f3d352540 <+16>:	stp	x29, x30, [sp,#48]
#    0x0000007f3d352544 <+20>:	str	x5, [sp,#56]# 保存參數寄存器 X0-X4 (逐個保存到不同棧位置)instructions.append(struct.pack('<I',0xD102C3FF))     # FF C3 02 D1                         SUB             SP, SP, #0xB0 instructions.append(struct.pack('<I',0xA9005FF8))     #F8 5F 00 A9                             STP             X24, X23, [SP]instructions.append(struct.pack('<I',0xA90157F6))     #F6 57 01 A9                             STP             X22, X21, [SP,#0x10]instructions.append(struct.pack('<I',0xA9024FF4))     #F4 4F 02 A9                             STP             X20, X19, [SP,#0x30]instructions.append(struct.pack('<I',0xA9037BFD))     #FD 7B 03 A9                             STP             X29, X30, [SP,#0x40]instructions.append(struct.pack('<I',0xF90057E5))     #E5 57 00 F9                             STR             X5, [SP,#0xA8]instructions.append(struct.pack('<I',0xAA0203F5))     #F5 03 02 AA                             MOV             X21, X2instructions.append(struct.pack('<I',0xAA0103F6))     #F6 03 01 AA                             MOV             X22, X1instructions.append(struct.pack('<I',0xAA0003F7))     #F7 03 00 AA                             MOV             X23, X0instructions.append(struct.pack('<I',0xAA0403F3))     #F3 03 04 AA                             MOV             X19, X4instructions.append(struct.pack('<I',0xAA0303F4))     #F4 03 03 AA                             MOV             X20, X3# 準備dlopen參數# 需要將"liblua_file_writer.so"字符串地址加載到X0# RTLD_LAZY (1) 加載到X1# 使用原始SO文件中已存在的字符串# "liblua_file_writer.so" 在 0x133C20# 當前函數在 0x8A530,計算相對偏移lib_string_addr = 0x133C20#0000000000133C68# GROUP#  lib_string_addr = 0x00DD668current_addr = self.luaL_loadfilex_offset + (len(instructions) * 4)lib_offset = lib_string_addr - current_addr# ADR X0, #lib_offset  ; 獲取"liblua_file_writer.so"地址if abs(lib_offset) < (1 << 20):  # ADR指令范圍檢查adr_instruction = 0x10000000 | ((lib_offset >> 2) & 0x7FFFF) << 5instructions.append(struct.pack('<I', adr_instruction))else:# 如果超出ADR范圍,使用ADRP+ADD組合page_offset = (lib_offset >> 12) & 0x1FFFFFadrp_instruction = 0x90000000 | (page_offset << 5)instructions.append(struct.pack('<I', adrp_instruction))# ADD X0, X0, #(lib_offset & 0xFFF)add_instruction = 0x91000000 | ((lib_offset & 0xFFF) << 10)instructions.append(struct.pack('<I', add_instruction))# MOV X1, #1  ; RTLD_LAZYinstructions.append(struct.pack('<I', 0xD2800021))# 調用dlopen# 這里需要通過GOT表調用dlopen,簡化處理:# 假設dlopen在已知偏移處,實際應該通過PLT調用# BL dlopen  ; 計算到dlopen的偏移# dlopen在.plt:0x17980,當前位置大約在0xB8AC0附近dlopen_plt_addr = 0x17980current_bl_addr = self.luaL_loadfilex_offset + (len(instructions) * 4)dlopen_offset = dlopen_plt_addr - current_bl_addr# BL指令格式: 0x94000000 | ((offset >> 2) & 0x3FFFFFF)bl_instruction = 0x94000000 | ((dlopen_offset >> 2) & 0x3FFFFFF)instructions.append(struct.pack('<I', bl_instruction))# 檢查dlopen返回值,如果不為空則跳過異常觸發指令# CBNZ X0, #8  ; 如果X0不為0,跳過下一條指令instructions.append(struct.pack('<I', 0xB5000040))# LDR X16, [X0]  ; 如果X0為0,這里會觸發空指針異常instructions.append(struct.pack('<I', 0xF9400010))# 準備dlsym參數# X0已經是handle,需要設置X1為符號名# "luaL_loadbufferx" 在 0x1336DEsymbol_string_addr = 0x1336DE;current_addr2 = self.luaL_loadfilex_offset + (len(instructions) * 4)symbol_offset = symbol_string_addr - current_addr2 +2# ADR X1, #symbol_offset  ; 獲取"luaL_loadbufferx"地址if abs(symbol_offset) < (1 << 20):  # ADR指令范圍檢查adr_instruction2 = 0x10000000 | ((symbol_offset >> 2) & 0x7FFFF) << 5 | 1  # 目標寄存器X1instructions.append(struct.pack('<I', adr_instruction2))else:# 如果超出ADR范圍,使用ADRP+ADD組合page_offset2 = (symbol_offset >> 12) & 0x1FFFFFadrp_instruction2 = 0x90000000 | (page_offset2 << 5) | 1  # 目標寄存器X1instructions.append(struct.pack('<I', adrp_instruction2))# ADD X1, X1, #(symbol_offset & 0xFFF)add_instruction2 = 0x91000000 | ((symbol_offset & 0xFFF) << 10) | (1 << 5) | 1instructions.append(struct.pack('<I', add_instruction2))# 調用dlsym# BL dlsym  ; 計算到dlsym的偏移# dlsym在.plt:0x17A40dlsym_plt_addr = 0x17A40current_bl_addr2 = self.luaL_loadfilex_offset + (len(instructions) * 4)dlsym_offset = dlsym_plt_addr - current_bl_addr2# BL指令格式: 0x94000000 | ((offset >> 2) & 0x3FFFFFF)bl_instruction2 = 0x94000000 | ((dlsym_offset >> 2) & 0x3FFFFFF)instructions.append(struct.pack('<I', bl_instruction2))# 檢查dlopen返回值,如果為空則訪問其指針值造成異常# CBNZ X0, #8  ; 如果X0不為0,跳過下一條指令instructions.append(struct.pack('<I', 0xB5000040))# LDR X16, [X0]  ; 如果X0為0,這里會觸發空指針異常instructions.append(struct.pack('<I', 0xF9400010))# 保存dlsym返回的函數地址到X16# MOV X17, X0instructions.append(struct.pack('<I', 0xAA0003F1))instructions.append(struct.pack('<I',0xAA1703E0))     #E0 03 17 AA                             MOV             X0, X23instructions.append(struct.pack('<I',0xAA1603E1))     #E1 03 16 AA                             MOV             X1, X22instructions.append(struct.pack('<I',0xAA1503E2))     #E2 03 15 AA                             MOV             X2, X21instructions.append(struct.pack('<I',0xAA1403E3))     #E3 03 14 AA                             MOV             X3, X20instructions.append(struct.pack('<I',0xAA1303E4))     #E4 03 13 AA                             MOV             X4, X19# 跳轉到目標函數instructions.append(struct.pack('<I',0xA9424FF4))     #F4 4F 42 A9                             LDP             X20, X19, [SP,#0x30+var_10]instructions.append(struct.pack('<I',0xA94157F6))     #F6 57 41 A9                             LDP             X22, X21, [SP,#0x30+var_20]instructions.append(struct.pack('<I',0xA9405FF8))     #F8 5F 40 A9                             LDP             X24, X23, [SP]instructions.append(struct.pack('<I',0xA9437BFD))     #FD 7B 43 A9                             LDP             X29, X30, [SP,#0x30+var_s0]instructions.append(struct.pack('<I',0xF9401FE5))     #E5 1F 40 F9                             LDR             X5, [SP,#0x38]instructions.append(struct.pack('<I',0x9102C3FF))     #FF C3 02 91                 ADD             SP, SP, #0xB0 ;instructions.append(struct.pack('<I', 0xD61F0220))    #20 02 1F D6                               BR              X17  return b''.join(instructions)def apply_patches(self):"""應用所有補丁"""# 讀取目標文件with open(self.target_so_path, 'rb') as f:data = bytearray(f.read())print(f"文件大小: {len(data)} 字節")# 應用補丁success = Trueif not self.patch_luaL_loadbuffer(data):success = Falseif not self.patch_luaL_loadfilex(data):success = Falseif success:# 寫回修改后的文件with open(self.target_so_path, 'wb') as f:f.write(data)print(f"補丁應用成功!修改后的文件: {self.target_so_path}")else:print("補丁應用失敗!")return successdef restore_backup(self):"""恢復備份文件"""if self.backup_path.exists():shutil.copy2(self.backup_path, self.target_so_path)print(f"已恢復備份文件: {self.target_so_path}")else:print("備份文件不存在!")def main():# 文件路徑target_so = "libtolua.so"custom_so = "iblua_file_writer.so"# 檢查文件是否存在if not os.path.exists(target_so):print(f"目標文件不存在: {target_so}")returnif not os.path.exists(custom_so):print(f"自定義SO文件不存在: {custom_so}")return# 創建補丁器patcher = LibtoluaPatcher(target_so, custom_so)# 應用補丁if patcher.apply_patches():print("\n補丁應用完成!")print("使用說明:")print("1. 修改后的libtolua.so會在luaL_loadbuffer調用時跳轉到我們的hook函數")print("2. 如需恢復原始文件,請運行: patcher.restore_backup()")else:print("\n補丁應用失敗!")if __name__ == "__main__":main()

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

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

相關文章

2-大語言模型—理論基礎:詳解Transformer架構的實現(2)

目錄 1-大語言模型—理論基礎&#xff1a;詳解Transformer架構的實現(1)-CSDN博客https://blog.csdn.net/wh1236666/article/details/149443139?spm1001.2014.3001.5502 2.3、殘差連接和層歸一化 2.3.1、什么是層歸一化&#xff1f; 2.3.2、層歸一化的核心特點&#xff08…

SmartX 用戶建云實踐|富士康:基于榫卯企業云平臺構建分布式云,支撐全球多地工廠重要產線

作為全球最大的電子科技智造服務商&#xff0c;富士康集團在全球范圍內構建生產制造網絡。為實現多廠區統一管理與降本增效&#xff0c;在逐步替代 VMware 虛擬化架構的過程中&#xff0c;富士康對比了自研 OpenStack Ceph 平臺和 SmartX 超融合方案&#xff0c;最終選擇基于 …

ADC選型設計

1、最大擺伏FSR&#xff1a; 0 ~ 4.096V&#xff0c;一般Vref要等于FSR 2、最大頻率&#xff1a;根據奈奎斯特采樣定理大于2倍的信號頻率才夠還原信號&#xff0c;所以選擇20/50倍更好&#xff0c; 3、最小精度&#xff0c;對于一給定模擬輸入&#xff0c;實際數字輸出與理論預…

基于深度學習的火災智能檢測系統設計與實現

在各類安全事故中&#xff0c;火災因其突發性強、破壞力大&#xff0c;一直是威脅人們生命財產安全的重大隱患。傳統的火災檢測方式多依賴煙霧傳感器、溫度傳感器等&#xff0c;存在響應滯后、易受環境干擾等問題。隨著深度學習技術的飛速發展&#xff0c;基于計算機視覺的火災…

HIVE實戰處理(二十四)留存用戶數

留存概念: 次X日活躍留存&#xff0c;次X日新增留存&#xff0c;也就是看今天的新增或活躍用戶在后續幾天的留存情況一、留存表的生成邏輯 因為用戶活躍日期和留存的日期無法對齊所以搞了2級分區&#xff08;dt,static_day&#xff09; 1&#xff09;首先獲得計算日D、根據要出…

W3C XHTML 活動:標準化的未來與交互式體驗

W3C XHTML 活動:標準化的未來與交互式體驗 概述 W3C(World Wide Web Consortium)是全球領先的互聯網技術標準制定組織。XHTML,作為W3C推薦的標準之一,是一種基于XML的標記語言,旨在提供一個更加結構化、兼容性和可擴展性更高的網頁內容表示方式。本文將圍繞W3C的XHTML活…

Java-數構鏈表

1.鏈表 1.1鏈表的概念和結構 鏈表是一種物理存儲結構上非連續存儲結構&#xff0c;數據元素的邏輯順序是通過鏈表中引用鏈接次序實現的。 這里大多討論無頭單向非循環鏈表。這種結構&#xff0c;結構簡單&#xff0c;一般與其他數據結構結合&#xff0c;作為其他數據結構的子…

Windows系統軟件游戲丟失找不到mgmtapi.dll修復解決方法

在使用電腦系統時經常會出現丟失找不到某些文件的情況&#xff0c;由于很多常用軟件都是采用 Microsoft Visual Studio 編寫的&#xff0c;所以這類軟件的運行需要依賴微軟Visual C運行庫&#xff0c;比如像 QQ、迅雷、Adobe 軟件等等&#xff0c;如果沒有安裝VC運行庫或者安裝…

初識C++——開啟新旅途

從今天開始主包也是掉入C這個深坑&#xff0c;上完課也是跟沒上一樣&#xff0c;所以寫好博客復習還是很重要的&#xff0c;話不多說&#xff0c;進入正題~~1、命名空間(1)namespace的價值與作用在C/C中&#xff0c;變量、函數和后面要學到的類都是大量存在的&#xff0c;這些變…

vue2 面試題及詳細答案150道(141 - 150)

《前后端面試題》專欄集合了前后端各個知識模塊的面試題&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

第十三章 Go包管理

文章目錄使用logurs處理程序日志logrus 常用配置使用viper處理程序配置使用logurs處理程序日志 下載包&#xff0c;在終端執行命令 go get github.com/sirupsen/logrus官方示例 package mainimport (log "github.com/sirupsen/logrus" )func main() {log.WithFiel…

EP01:【Python 第一彈】基礎入門知識

一、基礎入門知識 1.1 代碼規范 1.1.1 語句分隔符 ; 換行 1.1.2 格式化 對 Windows 和 Linux 操作系統&#xff0c;快捷鍵是Ctrl Alt L對 macOS 操作系統&#xff0c;快捷鍵是Cmd Option L 1.1.3 注釋 單行注釋 # 這是一行注釋多行注釋 """ 這 是 …

實用的文件和文件夾批量重命名工具

在日常工作中&#xff0c;文件和文件夾的命名管理常常讓人頭疼。尤其是面對大量文件時&#xff0c;手動重命名不僅耗時&#xff0c;還容易出錯。今天&#xff0c;我要給大家推薦一款超級實用的工具——OncePower 文件批量重命名&#xff0c;它不僅能批量重命名文件和文件夾&…

【Git】報錯:git config --global http.sslBackend “openssl“

問題解決 報錯&#xff1a;git config --global http.sslBackend “openssl”解決方法&#xff1a; git config --global http.sslBackend "openssl"之后再 push 即可正常提交。 &#x1f50d; 原因分析 ??系統環境不支持 OpenSSL 后端?? Git 在某些平臺&#xf…

Redisson RLocalCachedMap 核心參詳解

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家&#xff0c;歷代文學網&#xff08;PC端可以訪問&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移動端可微信小程序搜索“歷代文學”&#xff09;總架構師&#xff0c;15年工作經驗&#xff0c;精通Java編…

AI輔助編程時代的高效規范開發指南:工具、原則與提效策略

引言&#xff1a;AI輔助編程的時代背景與核心挑戰 人工智能在編程領域的應用雖可追溯至20世紀50年代&#xff0c;但近十年實現了革命性突破&#xff0c;推動其從早期的代碼補全工具演進為能理解上下文、生成完整函數乃至項目架構的智能系統。關鍵發展里程碑包括&#xff1a;20…

百度網盤TV版1.21.0 |支持倍速播放,大屏云看片

百度網盤TV版是專為智能電視設計的應用程序&#xff0c;讓用戶可以直接在大屏幕上觀看保存在云端的視頻資源。此應用提供了與手機端幾乎相同的功能&#xff0c;包括倍速播放功能&#xff0c;使得用戶可以更方便地享受高清視頻內容。無需繁瑣的操作步驟&#xff0c;即可實現云端…

C++控制臺貪吃蛇開發(二):讓靈蛇舞動起來!

資料合集下載鏈接: ??https://pan.quark.cn/s/472bbdfcd014? 本文將深入講解蛇移動的機制,并帶你一步步實現以下功能: 理解蛇移動的核心算法:為什么蛇的移動是“倒著”更新的? 用代碼表示方向:如何使用??dx??和??dy??變量優雅地控制方向。 編寫核心??move…

Elasticsearch+Logstash+Filebeat+Kibana部署

目錄 軟件說明&#xff1a; 架構拓撲 集群模式&#xff1a; 單機模式 環境準備 部署&#xff1a; kibana es logstash filebeat es 檢查能否啟動 logstash 命令設置 es 修改es配置文件 啟用es kibana 修改kibana配置文件&#xff08;方便查看索引&#xff09…

GLM(General Language Model,通用語言模型)

&#x1f9e0; 一、GLM是什么&#xff1f;一句話概括 GLM&#xff08;General Language Model&#xff0c;通用語言模型&#xff09;是一個“大腦”&#xff0c;它通過閱讀海量書籍、網頁、對話記錄學會了人類的語言規則&#xff0c;不僅能“聽懂”你說的話&#xff0c;還能“…