在第一章中我們介紹了x64dbg
這款強大的除錯軟體,通過該軟體逆向工程師們可以手動完成對特定行程的漏洞挖掘及脫殼等操作,雖然x64dbg
支持內置Script
腳本執行模塊,但腳本引擎通常來說是不夠強大的,LyScript 插件的出現填補了這方面的不足,該插件的開發靈感來源于Immunity
除錯器中的ImmLib
庫,因Immunity
除錯器繼承自Ollydbg
導致該除錯器無法支持64位應用的除錯,同時該除錯器也長期沒有開發者進行維護,正是在這種情形之下LyScript
誕生,
- LyScript官方地址:https://github.com/lyshark/LyScript
LyScript是一款 x64dbg
自動化控制插件,通過Python
控制x64dbg
的行為,實作遠程動態除錯,解決了逆向作業者分析程式,反病毒人員脫殼,漏洞分析者尋找指令片段,原生腳本不夠強大的問題,通過與Python
相結合利用Python
語法的靈活性以及其豐富的第三方庫,加速漏洞利用程式的開發,輔助漏洞挖掘以及惡意軟體分析,
LyScript插件的安裝非常容易,讀者只需要在官方下載對應的插件并放入到plugins/
根目錄下即可,當插件加載成功,讀者可看到如下圖所示的輸出資訊,程序中可能會出現網路通信授權框,請讀者允許并放行即可;
接著讀者還需要打開命令列,并通過pip
命令安裝對應的插件包,LyScript插件一般而言分為兩個核心包LyScript
用于實作基于函式的通信機制,而LyScriptTools
則是對函式的類版封裝,兩者建議全部安裝;
- 安裝標準包:pip install LyScript32 或者 pip install LyScript64
- 安裝擴展包:pip install LyScriptTools32 或者 pip install LyScriptTools64
安裝此插件讀者應該具備了Python
開發環境,版本必須大于3.6
才可以,當環境具備后,讀者可執行上述命令,依次安裝這幾個不同的版本,
Microsoft Windows [版本 10.0.19042.1826]
(c) Microsoft Corporation,保留所有權利,
C:\Users\admin> pip install LyScript32
C:\Users\admin> pip install LyScript64
C:\Users\admin> pip install LyScriptTools32
C:\Users\admin> pip install LyScriptTools64
4.1.1 如何使用插件
LyScript 插件提供了豐富的 API 封裝函式,包括暫存器、除錯、模塊、記憶體、堆疊、行程和執行緒等不同類別的函式,這些函式可以幫助開發者更方便地訪問和修改程式的內部資訊,便于除錯和破解,但需要開發者具備一定的編程和除錯經驗,并遵守相應的規范和準則,以確保軟體的安全和穩定性,
注意:首先讀者需要啟動帶有插件功能的
x64dbg
除錯器,并手動拖入一個任意被除錯行程到除錯器中,這是使用插件功能的必備條件,基于Python下的LyScript
模塊無法獨立運行,這一點讀者需要格外注意,
根據插件官方解釋,用戶在使用該插件時首先需要通過dbg = MyDebug()
初始化一個除錯控制類,當這個類被初始化結束后則可以通過dbg.connect()
函式連接到除錯器中,當連接被建立時則默認會創建一個持久會話直到Python腳本結束才會被強制斷開,在連接期間讀者也可通過dbg.is_connect()
檢測套接字是否存在,如下面這段代碼則是一個最基本的實作方法,
>>> from LyScript32 import MyDebug
>>>
>>> dbg=MyDebug()
>>>
>>> connect_flag = dbg.connect()
>>> print("連接狀態: {}".format(connect_flag))
連接狀態: True
>>>
>>> ref = dbg.is_connect()
>>> print("是否在連接: ", ref)
是否在連接: True
>>>
>>> dbg.close()
True
在該代碼示例中,用戶首先通過匯入 LyScript
插件中的MyDebug
類,創建了一個名為dbg
的實體,并初始化該類,接著呼叫dbg.connect()
函式,建立連接,連接成功后,使用is_connect()
函式檢查套接字是否存在,并將結果列印出來,最后,呼叫dbg.close()
函式以關閉除錯器連接,
4.1.2 讀取或設定暫存器引數
暫存器是計算機中的一種高速存盤設備,位于CPU內部,它們由一些元器件構成,通常是用于存盤和操作CPU指令和資料的硬體單元,不同的CPU架構可能會有不同的暫存器數量、位寬和功能,
暫存器是計算機架構中非常重要的一部分,因為他們能夠在CPU執行指令時快速地存盤和讀取資料,從而提高計算速度,暫存器的存盤速度比記憶體快得多,通常稱為“零快取器延遲”(zero cache delay),所以它們是程式優化的主要目標之一,
暫存器的功能多種多樣,包括存盤資料、指令地址、指令結果,以及用于計算、判斷等各種用途,常見的暫存器包括累加器、計數器、指標暫存器、標志暫存器等,在程式中,暫存器經常用來存盤中間計算結果和臨時變數,通常比記憶體訪問更快,從而提高程式運行效率,
在x64dbg中暫存器通常會展現在螢屏的右上角,以32位為例,默認情況下暫存器可被分為,通用暫存器,標志暫存器,DR系列特殊暫存器組,以及段選擇子等,
通用暫存器以及該暫存器的功能如下表格所示;
暫存器名 | 描述 |
---|---|
EAX | 累加器,用于存放一些計算結果或指標, |
ECX | 計數器,主要用于回圈計數等功能, |
EDX | 資料暫存器,被用于存放一些指標或標志資訊, |
EBX | 基地址暫存器,主要用于訪問記憶體中的資料, |
ESP | 堆疊指標,用于指向當前的堆疊頂, |
EBP | 基址指標,通常被用來指向當前的堆疊幀, |
ESI | 源索引暫存器,通常用于字串操作, |
EDI | 目標索引暫存器,也常常用于字串操作, |
標志暫存器以及該暫存器的功能如下表格所示;
標志暫存器 | 含義 |
---|---|
CF | 進位標志 (Carry Flag),該標志表示在執行無符號算術指令時是否發生了進位, |
PF | 奇偶標志 (Parity Flag),該標志表示指令執行后結果的低八位中1的個數是否為偶數,如果是偶數,標志位被設定為1,否則為0, |
AF | 奧半字進位標志 (Auxiliary Carry Flag),該標志表示執行指令后低四位的進位情況, |
ZF | 零標志 (Zero Flag),該標志表示上一條指令執行后結果是否為零,如果結果為零,標志位被設定為1,否則為0, |
SF | 符號標志 (Sign Flag),該標志表示結果是否為負數,如果結果為負數,標志位被設定為1,否則為0, |
TF | 除錯標志 (Trap Flag),該標志用于單步除錯,當該標志被設定為1時,CPU將在執行完每一條指令后暫停,這使得除錯器可以檢查這一指令對暫存器和存盤器的影響, |
IF | 中斷允許標志 (Interrupt Flag),如果該標志為1,表示CPU允許回應來自外部設備的可屏蔽中斷請求, |
DF | 方向標志 (Direction Flag),該標志用于指示字串操作指令是否應該向前 (DF=0) 或向后 (DF=1) 方向進行操作, |
OF | 溢位標志 (Overflow Flag),該標志表示在執行有符號算術指令時是否發生了溢位, |
在LyScript
插件中,通常會使用get_register()
函式獲取特定通用暫存器的引數,與之對應的可以使用set_register()
函式實作設定,如下片段則是分別獲取與設定特定暫存器組的函式呼叫規范;
>>> eax = dbg.get_register("eax")
>>> hex(eax)
'0xa'
>>>
>>> eip = dbg.get_register("eip")
>>> hex(eip)
'0x76fdc3b8'
>>>
>>> flag = dbg.set_register("eax",100)
>>> flag
True
>>> hex(dbg.get_register("eax"))
'0x64'
同理,對于獲取與設定標志暫存器,也有一對標準的通用函式get_flag_register()
函式用于獲取一個標志,而與之對應的set_flag_register()
函式則用于設定一個標志,需要注意的是在設定標志時,第二個引數需傳入一個狀態[設定為真 True] / [設定為假 False]
而不是接受一個字符或整數;
>>> tf = dbg.get_flag_register("tf")
>>> tf
False
>>>
>>> zf = dbg.get_flag_register("zf")
>>> zf
True
>>>
>>> flag = dbg.set_flag_register("cf",True)
>>> flag
True
>>>
4.1.3 使用除錯控制系列函式
除錯器的核心功是對程式進行除錯,而除錯器內部實作往往會呼叫作業系統提供的除錯API,除錯系列函式是這些API之一,用于幫助開發者在程式執行時得到更多的資訊,包括記憶體值、指令執行狀態、變數狀態等,以便更加全面和深入地了解代碼的運行情況和錯誤,除錯系列函式的主要作用如下:
- 用于設定和管理斷點,包括硬體斷點、軟體斷點等,
- 提供各種除錯命令,包括單步執行、運行到某個指定位置、查看記憶體暫存器的狀態資訊等,為程式的除錯程序提供必要的資訊,
總之,除錯系列函式為除錯器提供了豐富的操作介面和除錯工具,使得開發人員能夠更加深入和全面地了解程式的運行狀態,并借助這些資訊更好地除錯和定位程式的錯誤和漏洞,
首先介紹的是set_debug()
函式,該函式是除錯器中一個非常重要的函式,它被用于影響除錯器的狀態,常見的操作包括前進一次、后退一次、暫停除錯、終止除錯等,在除錯程序中,開發人員會根據需要進行不同的除錯操作,以理解程式執行的程序、獲得代碼執行的狀態資訊以及找到代碼中的錯誤,
該函式的可用的動作范圍包括:暫停(Pause)、運行(Run)、步入(StepIn)、步過(StepOut)、到結束(StepOver)、停止(Stop)以及等待(Wait),通過呼叫set_debug()函式,并傳遞相應的引數,讀者可以方便地進行除錯操作,并隨時獲取程式的運行狀態資訊,例如,將引數設定為“暫停”,則可以暫停程式的執行、查看程式記憶體中的值以及檢查程式呼叫堆疊等資訊;將引數設定為“運行”則可以繼續程式的執行,直到遇到下一個斷點或者程式結束,
我們以步入(StepIn)、步過(StepOut)為例,讀者可使用如下命令執行一次動作;
>>> dbg.set_debug("StepIn")
True
>>> dbg.set_debug("StepOut")
True
>>>
此外判斷除錯器動作也是一種非常普遍的功能,插件內提供了is_debugger() /is_running()/is_run_locked()
三個除錯函式,函式is_debugger
可用于驗證當前除錯器是否處于除錯狀態,函式is_running
則用于驗證是否在運行,函式is_run_locked
用于檢查除錯器是否被鎖定(暫停),這三個函式的呼叫規范與上方基本一致;
>>> dbg.is_debugger()
True
>>> dbg.is_running()
False
>>> dbg.is_run_locked()
True
4.1.4 使用斷點設定系列函式
斷點是除錯器中常用的工具之一,可以幫助開發人員暫停程式的運行并檢查程式中的錯誤,x64dbg中的斷點分為以下幾類:
-
軟體斷點(BP):軟體斷點是一種在程式執行期間暫停程式并引起中斷的代碼指令,可用于修復軟體中的一些缺陷或除錯程式,在x64dbg中,使用“F2”鍵可以在程式的代碼段中設定軟體斷點,碰到指定斷點時會暫停程式并進入除錯模式,以便對程式進行除錯,
-
硬體斷點:硬體斷點是一種針對某個具體的地址,由CPU硬體支持的斷點,當程式執行到該地址時,CPU會中斷程式并通知除錯器進行除錯,硬體斷點在除錯器中設定方式和軟體斷點相同,也是通過“F2”鍵來設定,在使用硬體斷點時,需要特殊注意硬體斷點的數量,因為硬體斷點數量通常非常有限,
-
記憶體斷點:記憶體斷點是一種根據條件變化暫停程式執行的斷點,它可以對記憶體地址進行監視,當記憶體中的指定值在程式運行時發生變化時觸發中斷,在x64dbg中,可以通過“右鍵選單”中的“記憶體瀏覽器”或“記憶體”視窗設定記憶體斷點,
LyScript插件可以使用set_breakpoint()
函式設定軟體斷點,使用delete_breakpoint()
函式洗掉一個軟體斷點,使用check_breakpoint()
函式可用于檢測斷點是否被命中,使用get_all_breakpoint()
可用于輸出當前所有斷點
>>> eip = dbg.get_register("eip")
>>> dbg.set_breakpoint(eip)
True
>>> dbg.check_breakpoint(eip)
True
>>> ref = dbg.get_all_breakpoint()
>>> ref
[{'addr': 4584081, 'enabled': 1, 'hitcount': 0, 'type': 1}, {'addr': 1996337564, 'enabled': 1, 'hitcount': 0, 'type': 1}, {'addr': 1996337612, 'enabled': 1, 'hitcount': 0, 'type': 1}, {'addr': 1996337643, 'enabled': 1, 'hitcount': 0, 'type': 1}]
同理,當讀者需要設定硬體斷點是可使用set_hardware_breakpoint()
設定,但需要注意硬體斷點在32位系統中最多設定4個,如果需要取消斷點則可使用delete_hardware_breakpoint()
函式將斷點進行移除;
斷點型別可用范圍:[型別 0 = HardwareAccess / 1 = HardwareWrite / 2 = HardwareExecute]
>>> ref = dbg.set_hardware_breakpoint(eip,2)
>>> print(ref)
True
>>> ref = dbg.delete_hardware_breakpoint(eip)
>>> print(ref)
True
4.1.5 使用堆疊系列函式
堆疊視窗是除錯器非常重要的一個功能視窗,可以幫助開發人員監視程式運行時的堆疊資訊,該視窗能夠顯示當前執行緒的呼叫堆疊、區域變數(Local Variables)以及函式引數(Function Parameters)等重要資訊,并以圖形化的方式呈現出來,方便用戶進行查看和除錯,
在x64dbg的堆疊視窗中,對于每一個程式運行時的執行緒,都會顯示當前執行緒的呼叫堆疊資訊,最上面的堆疊幀表示當前正在執行的函式,下面堆疊幀則為呼叫該函式的函式,用戶可以通過向上和向下翻轉堆疊堆疊幀查看程式函式呼叫的層級,便于查找程式執行程序中的錯誤和問題,
此外,在當前呼叫堆疊幀中,用戶還可以查看當前函式的引數和區域變數等資訊,這些資訊通常是有助于除錯程式問題的關鍵性資訊,用戶可以通過右鍵單擊堆疊視窗中的任何一幀來切換該幀的狀態,包括指標、引數、影像、字串、十六進制等,以便更加準確地查看當前堆疊的資訊,
綜上所述,堆疊視窗是x64dbg除錯器中非常重要的一個功能視窗,可以幫助用戶在程式執行程序中理解、除錯和跟蹤程式執行的層次結構和變數資訊,解決代碼的問題,提高開發效率,
堆疊系列函式包括了push_stack()
用于向目標堆疊中壓入一個數值,與之對應的pop_stack()
則用于在堆疊中彈出一個元素,peek_stack()
函式用于檢查堆疊內的引數,可設定偏移值,不設定則默認檢查第一個也就是堆疊頂,
>>> check = dbg.peek_stack()
>>> check
1996055601
>>>
>>> check = dbg.peek_stack(1)
>>> hex(check)
'-0x757bb72f'
>>>
>>> dbg.push_stack(10)
True
>>> dbg.push_stack(10)
True
>>> dbg.pop_stack()
True
>>> check = dbg.peek_stack(1)
>>> hex(check)
'0x76f96431'
>>>
4.1.6 使用反匯編系列函式
反匯編是除錯器中非常重要的核心功能之一,它可以將已編譯的二進制代碼轉換為對應的匯編代碼,幫助開發人員了解程式的執行流程和代碼邏輯,并定位代碼問題,在x64dbg除錯器中,反匯編功能是其核心功能之一,具有以下特點:
- 顯示匯編代碼:x64dbg反匯編視窗可以將二進制代碼反匯編為對應的匯編代碼,包括指令、暫存器、記憶體地址等資訊,方便開發人員進行代碼分析和除錯,
- 支持多種格式:除了常見的AT&T格式和Intel格式匯編代碼之外,x64dbg還支持多種反匯編碼格式,比如Hopper、GDB和IDA等,滿足不同開發人員的需求,
- 集成除錯功能:x64dbg反匯編視窗還集成了除錯功能,支持在反匯編視圖中設定斷點、單步執行、條件斷點等操作,可以幫助開發人員更加有效地除錯程式,
- 支持多種反匯編引擎:x64dbg支持多種反匯編引擎,包括TitanEngine、Capstone、BeaEngine等,可以進行更加準確和全面的反匯編分析,
反匯編是x64dbg除錯器的核心功能之一,可以幫助開發人員進行代碼分析和除錯,定位代碼問題,提高開發效率,通過x64dbg的反匯編功能,開發人員可以有效地了解程式的代碼邏輯、執行流程和指令序列,為除錯和分析程式提供有力的支持,
當讀者需要使用插件控制除錯器反匯編時可以使用get_disasm_code()
該函式主要用于對特定記憶體地址進行反匯編,需傳入兩個引數,并輸出一個字典型別的資料集合,如下案例我們反匯編EIP位置處向下的30個行;
>>> eip = dbg.get_register("eip")
>>> disasm_dict = dbg.get_disasm_code(eip,30)
>>>
>>> for ds in disasm_dict:
... print("地址: {} 反匯編: {}".format(hex(ds.get("addr")),ds.get("opcode")))
...
地址: 0x76fdb19c 反匯編: ret
地址: 0x76fdb19d 反匯編: mov ecx, dword ptr ds:[0x770537C0]
地址: 0x76fdb1a3 反匯編: test cl, 0x3
地址: 0x76fdb1a6 反匯編: je 0x76FDC66E
地址: 0x76fdb1ac 反匯編: push eax
地址: 0x76fdb1ad 反匯編: push 0x76F36CF0
4.1.7 使用記憶體讀寫系列函式
記憶體讀寫功能,可以讓讀者在除錯階段直接讀取和修改程式的記憶體內容,方便程式除錯和分析,下面是對LyScript插件記憶體讀寫功能的簡要概述:
-
記憶體讀取:通過LyScript插件,開發人員可以通過代碼讀取已經加載的程式行程的記憶體中特定地址的值,該插件提供了幾個不同的記憶體讀取函式,包括ReadByte()、ReadWord()、ReadDword()、ReadQword()等,通過這些函式,開發人員可以直接讀取目標視窗中的指定記憶體地址,以獲取其值,
-
記憶體寫入:除了讀取程式記憶體的值,LyScript插件還支持修改程式的記憶體值,記憶體寫入函式為WriteByte()、WriteWord()、WriteDword()、WriteQword()等幾個相關的函式,通過這些函式,開發人員可以直接修改目標視窗中的指定記憶體地址,以達到除錯和分析程式的目的,
通過LyScript插件的記憶體讀寫功能,讀者可以直接讀取和修改目標程式的記憶體資訊,方便除錯和分析程式,同時,該插件也提供了一些記憶體操作API,一些常用的記憶體操作功能,幫助安全從業者更加方便地操作記憶體資料,
當讀者需要讀取記憶體資料時可以使用read_memory_byte()
來實作,如下案例中通過get_register()
函式獲取到當前EIP的記憶體地址,并使用記憶體讀函式獲取該記憶體中的前十條資料集,輸出效果如下所示;
>>> eip = dbg.get_register("eip")
>>>
>>> for index in range(0,10):
... ref = dbg.read_memory_byte(eip+index)
... print(hex(ref))
...
0xc3
0x8b
0xd
0xc0
0x37
0x5
0x77
0xf6
0xc1
0x3
至此本章基本介紹就到此為止,本章介紹了在Windows
平臺中使用LyScript
插件進行反匯編和除錯的相關內容,首先介紹了LyScript
插件的基本功能和使用方法,如通過不同的命令進行反匯編、查看匯編代碼、設定斷點等,并結合具體案例,演示了如何在LyScript
中使用不同的命令進行程式反匯編和除錯,同時,還介紹了除錯器中常用的斷點型別及其功能,并以x64dbg
為例對堆疊視窗的功能進行詳細介紹,讀者如果需要了解更多關于LyScript
插件的使用手冊可自行去官方查閱,
原文地址
https://www.lyshark.com/post/20c98ded.html
文章作者:lyshark (王瑞)文章出處:https://www.cnblogs.com/LyShark/p/17533219.html
本博客所有文章除特別宣告外,均采用 BY-NC-SA 許可協議,轉載請注明出處!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/556729.html
標籤:訊息安全
上一篇:前端Vue自定義頂部導航欄navBar 導航欄搜索框searchBar 導航欄右側選單按鈕button
下一篇:返回列表