發現漏洞的第一步則是需要尋找到可利用的反匯編指令片段,在某些時候遠程緩沖區溢位需要通過類似于jmp esp
等特定的反匯編指令實作跳轉功能,并以此來執行布置好的ShellCode
惡意代碼片段,LyScript
插件則可以很好的完成對當前行程記憶體中特定函式的檢索作業,
一般而言遠程緩沖區溢位攻擊通常利用的是一些具有緩沖區溢位漏洞的函式或是特定的匯編指令片段,如:
- strcpy:該函式將一個字串復制到另一個字串緩沖區中,但不會檢查緩沖區的大小,因此很容易導致緩沖區溢位,
- gets:該函式將用戶輸入的資料讀入字串緩沖區中,但不會檢查緩沖區的大小,因此很容易導致緩沖區溢位,
- sprintf:該函式將一個字串格式化到字串緩沖區中,但不會檢查緩沖區的大小,因此很容易導致緩沖區溢位,
在遠程緩沖區溢位攻擊中,攻擊者也可以利用匯編指令jmp esp
來實作對攻擊代碼的執行,該指令允許攻擊者跳轉到堆疊中的任意位置,并從那里執行惡意代碼,
4.3.1 搜索可利用匯編指令集
在默認情況下,LyScript插件并不具備搜索連續指令的能力,雖然提供了get_disasm_code()
系列的反匯編函式,但此類函式通常僅僅只能實作簡單的反匯編功能,讀者如果需要實作其他附加功能,含需要自行動手去實作,首先我們自行實作一個簡單的匯編指令檢索功能,用于尋找可利用的指令片段"pop esp","jmp esp","jmp eax","pop ecx"
等指令集,
這段代碼實作的機制可總結為如下步驟;
- 1.呼叫
connect
函式來連接到要除錯的程式,并使用get_local_base
和get_local_size
函式獲取程式的記憶體范圍, - 2.定義一個名為
search_asm
的串列,該串列包含要搜索的匯編指令, - 3.使用一個
while
回圈來遍歷記憶體范圍中的每一個地址,并呼叫get_disasm_one_code
函式獲取該地址處的反匯編代碼, - 4.使用另一個for回圈來遍歷
search_asm
串列中的每一個指令,并檢查當前反匯編代碼是否與串列中的指令匹配,如果匹配,則輸出該地址和反匯編代碼,
代碼很容易被理解和實作,本質上僅僅只是提取所記憶體中所有的匯編指令集,并依次列舉對比是否符合串列中的條件,其最終實作代碼如下所示;
from LyScript32 import MyDebug
if __name__ == "__main__":
dbg = MyDebug()
dbg.connect()
local_base_start = dbg.get_local_base()
local_base_end = local_base_start + dbg.get_local_size()
print("開始地址: {} --> 結束地址: {}".format(hex(local_base_start),hex(local_base_end)))
search_asm = ["pop esp","jmp esp","jmp eax","pop ecx"]
while local_base_start <= local_base_end:
disasm = dbg.get_disasm_one_code(local_base_start)
# print("地址: 0x{:08x} --> 反匯編: {}".format(local_base_start,disasm))
# 尋找指令
for index in range(0, len(search_asm)):
if disasm == search_asm[index]:
print("地址: {} --> 反匯編: {}".format(hex(local_base_start), disasm))
# 遞增計數器
local_base_start = local_base_start + dbg.get_disasm_operand_size(local_base_start)
dbg.close()
如上代碼被運行后,則會輸出當前行程內所有可被利用的指令片段,其輸出效果圖如下圖所示;
4.3.2 搜索可利用機器碼
機器碼的搜索與匯編指令集的搜索方式基本保持一致,但慶幸的是搜索指令集可使用scan_memory_all()
這個官方函式,該函式可用于掃描當前EIP所處位置,也就是當前EIP所在模塊的所有符合條件的機器碼,需要注意的是,在搜索具有漏洞函式時,通常我們會搜索行程內的完整模塊,則此時應該先得到該模塊的入口地址,并通過set_register()
設定到該模塊所在記憶體,然后再次對該記憶體區域進行搜索,代碼中opcode
用于指定一段機器碼序列,此處讀者可指定搜索多種機器碼,并將搜索結果放入到該串列內進行存盤,
這段代碼的實作原理可總結為如下所示的步驟;
- 定義一個名為
opcode
的串列,該串列包含要搜索的機器碼, - 然后使用一個for回圈來遍歷每個模塊,并呼叫
get_all_module
函式獲取程式中的模塊串列,對于每個模塊,它將eip暫存器設定為該模塊的入口點,然后呼叫scan_memory_all
函式搜索該模塊中是否存在要搜索的機器碼, - 如果找到了指定的機器碼,則輸出模塊名稱、匹配個數以及機器碼,并輸出該機器碼所在的地址,
根據上述流程可總結為如下所示的代碼片段;
from LyScript32 import MyDebug
import time
if __name__ == "__main__":
dbg = MyDebug()
dbg.connect()
# 需要搜索的指令集片段
opcode = ['ff 25','ff 55 fc','8b fe']
# 回圈搜索指令集記憶體地址
for index,entry in zip(range(0,len(opcode)), dbg.get_all_module()):
eip = entry.get("entry")
base_name = entry.get("name")
if eip != 0:
dbg.set_register("eip",eip)
search_address = dbg.scan_memory_all(opcode[index])
if search_address != False:
print("搜索模塊: {} --> 匹配個數: {} --> 機器碼: {}"
.format(base_name,len(search_address),opcode[index]))
# 輸出地址
for search_index in search_address:
print("[*] {}".format(hex(search_index)))
time.sleep(0.3)
dbg.close()
以strcpy
函式為例,讀者只需要搜索特征['57 8b 7c 24 08 eb 6e','ff 55 fc','8b fe']
即可定位到當前模塊內所有呼叫該函式機器其他函式的記憶體地址,
運行后即可輸出當前模塊內所有被呼叫機器碼的詳細地址,輸出效果如下圖所示;
原文地址
https://www.lyshark.com/post/af00a46a.html
文章作者:lyshark (王瑞)文章出處:https://www.cnblogs.com/LyShark/p/17535906.html
本博客所有文章除特別宣告外,均采用 BY-NC-SA 許可協議,轉載請注明出處!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/556804.html
標籤:其他
上一篇:萬字好文:大報文問題實戰
下一篇:返回列表