主頁 > 企業開發 > 4.10 x64dbg 反匯編功能的封裝

4.10 x64dbg 反匯編功能的封裝

2023-07-12 08:33:39 企業開發

LyScript 插件提供的反匯編系列函式雖然能夠實作基本的反匯編功能,但在實際使用中,可能會遇到一些更為復雜的需求,此時就需要根據自身需要進行二次開發,以實作更加高級的功能,本章將繼續深入探索反匯編功能,并將介紹如何實作反匯編代碼的檢索、獲取上下一條代碼等功能,這些功能對于分析和除錯代碼都非常有用,因此是書中重要的內容之一,在本章的學習程序中,讀者不僅可以掌握反匯編的基礎知識和技巧,還能夠了解如何進行插件的開發和除錯,這對于提高讀者的技能和能力也非常有幫助,

4.10.1 搜索記憶體機器碼特征

首先我們來實作第一種需求,通過LyScript插件實作搜索記憶體中的特定機器碼,此功能當然可通過scan_memory_all()系列函式實作,但讀者希望你能通過自己的理解呼叫原生API介面實作這個需求,要實作該功能第一步則是需要封裝一個GetCode()函式,該函式的作用是讀取行程資料到記憶體中,

其中dbg.get_local_base()用于獲取當前行程內的首地址,而通過start_address + dbg.get_local_size()的方式則可獲取到該程式的結束地址,當確定了讀取范圍后再通過dbg.read_memory_byte(index)回圈即可將程式的記憶體資料讀入,而ReadHexCode()僅僅只是一個格式化函式,這段程式的核心代碼可以總結為如下樣子;

# 將可執行檔案中的單數轉換為 0x00 格式
def ReadHexCode(code):
    hex_code = []

    for index in code:
        if index >= 0 and index <= 15:
            #print("0" + str(hex(index).replace("0x","")))
            hex_code.append("0" + str(hex(index).replace("0x","")))
        else:
            hex_code.append(hex(index).replace("0x",""))
            #print(hex(index).replace("0x",""))

    return hex_code

# 獲取到記憶體中的機器碼
def GetCode():
    try:
        ref_code = []
        dbg = MyDebug()
        connect_flag = dbg.connect()
        if connect_flag != 1:
            return None

        start_address = dbg.get_local_base()
        end_address = start_address + dbg.get_local_size()

        # 回圈得到機器碼
        for index in range(start_address,end_address):
            read_bytes = dbg.read_memory_byte(index)
            ref_code.append(read_bytes)

        dbg.close()
        return ref_code
    except Exception:
        return False

接著則需要讀者封裝實作一個SearchHexCode()搜索函式,如下這段代碼實作了在給定的位元組陣列中搜索特定的十六進制特征碼的功能,

具體而言,函式接受三個引數:Code表示要搜索的位元組陣列,SearchCode表示要匹配的特征碼,ReadByte表示要搜索的位元組數,

函式首先獲取特征碼的長度,并通過一個for回圈遍歷給定位元組陣列中的所有可能匹配的位置,對于每個位置,函式獲取該位置及其后面SearchCount個位元組的十六進制表示形式,并將其與給定的特征碼進行比較,如果有一位不匹配,則計數器重置為0,否則計數器加1,如果計數器最終等于特征碼長度,則說明已找到完全匹配的特征碼,函式回傳True,如果遍歷完整個陣列都沒有找到匹配的特征碼,則函式回傳False,

# 在位元組陣列中匹配是否與特征碼一致
def SearchHexCode(Code,SearchCode,ReadByte):
    SearchCount = len(SearchCode)
    #print("特征碼總長度: {}".format(SearchCount))
    for item in range(0,ReadByte):
        count = 0
        # 對十六進制數切片,每次向后遍歷SearchCount
        OpCode = Code[ 0+item :SearchCount+item ]
        #print("切割陣列: {} --> 對比: {}".format(OpCode,SearchCode))
        try:
            for x in range(0,SearchCount):
                if OpCode[x] == SearchCode[x]:
                    count = count + 1
                    #print("尋找特征碼計數: {} {} {}".format(count,OpCode[x],SearchCode[x]))
                    if count == SearchCount:
                        # 如果找到了,就回傳True,否則回傳False
                        return True
                        exit(0)
        except Exception:
            pass
    return False

有了這兩段程式的實作流程,那么完成特征碼搜索功能將變得很容易實作,如下主函式中運行后則可搜索行程內search中所涉及到的機器碼,當搜索到后則回傳一個狀態,

if __name__ == "__main__":
    # 讀取到記憶體機器碼
    ref_code = GetCode()
    if ref_code != False:
        # 轉為十六進制
        hex_code = ReadHexCode(ref_code)
        code_size = len(hex_code)

        # 指定要搜索的特征碼序列
        search = ['c0', '74', '0d', '66', '3b', 'c6', '77', '08']

        # 搜索特征: hex_code = exe的位元組碼,search=搜索特征碼,code_size = 搜索大小
        ret = SearchHexCode(hex_code, search, code_size)
        if ret == True:
            print("特征碼 {} 存在".format(search))
        else:
            print("特征碼 {} 不存在".format(search))
    else:
        print("讀入失敗")

由于此類搜索屬于列舉類,所以搜索效率會明顯變低,搜索結束后則會回傳該特征值是否存在的一個標志;

4.10.2 搜索記憶體反匯編特征

而與之對應的,當讀者搜索反匯編代碼時則無需自行實作記憶體讀入功能,LyScript插件內提供了dbg.get_disasm_code(eip,1000)函式,可以讓我們很容易的實作讀取記憶體的功能,如下案例中,搜索特定反匯編指令集,當找到后回傳其記憶體地址;

from LyScript32 import MyDebug

# 檢索指定序列中是否存在一段特定的指令集
def SearchOpCode(OpCodeList,SearchCode,ReadByte):
    SearchCount = len(SearchCode)
    for item in range(0,ReadByte):
        count = 0
        OpCode_Dic = OpCodeList[ 0 + item : SearchCount + item ]
        # print("切割字典: {}".format(OpCode_Dic))
        try:
            for x in range(0,SearchCount):
                if OpCode_Dic[x].get("opcode") == SearchCode[x]:
                    #print(OpCode_Dic[x].get("addr"),OpCode_Dic[x].get("opcode"))
                    count = count + 1
                    if count == SearchCount:
                        #print(OpCode_Dic[0].get("addr"))
                        return OpCode_Dic[0].get("addr")
                        exit(0)
        except Exception:
            pass

if __name__ == "__main__":
    dbg = MyDebug()
    connect_flag = dbg.connect()
    print("連接狀態: {}".format(connect_flag))

    # 得到EIP位置
    eip = dbg.get_register("eip")

    # 反匯編前1000行
    disasm_dict = dbg.get_disasm_code(eip,1000)

    # 搜索一個指令序列,用于快速查找構建漏洞利用代碼
    SearchCode = [
        ["ret", "push ebp", "mov ebp,esp"],
        ["push ecx", "push ebx"]
    ]

    # 檢索記憶體指令集
    for item in range(0,len(SearchCode)):
        Search = SearchCode[item]
        # disasm_dict = 回傳匯編指令 Search = 尋找指令集 1000 = 向下檢索長度
        ret = SearchOpCode(disasm_dict,Search,1000)
        if ret != None:
            print("指令集: {} --> 首次出現地址: {}".format(SearchCode[item],hex(ret)))

    dbg.close()

如上代碼當搜尋到SearchCode內的指令序列時則自動輸出記憶體地址,輸出效果圖如下所示;

4.10.3 獲取上下一潭訓編指令

LyScript 插件默認并沒有提供上一條與下一潭訓編指令的獲取功能,筆者認為通過親自動手封裝實作功能能夠讓讀者更好的理解記憶體斷點的作業原理,則本次我們將親自動手實作這兩個功能,

在x64dbg中,軟體斷點的實作原理與通用的軟體斷點實作原理類似,具體來說,x64dbg會在程式的指令地址處插入一個中斷指令,一般是int3指令,這個指令會觸發一個軟體中斷,從而讓程式停止執行,等待除錯器處理,在插入中斷指令之前,x64dbg會先將這個地址處的原始指令保存下來,這樣,當程式被除錯器停止時,除錯器就可以將中斷指令替換成原始指令,讓程式恢復執行,

為了實作軟體斷點,x64dbg需要修改程式的可執行代碼,具體來說,它會將指令的第一個位元組替換成中斷指令的操作碼,這樣當程式執行到這個指令時就會觸發中斷,如果指令長度不足一個位元組,x64dbg會將這個指令轉換成跳轉指令,跳轉到另一個地址,然后在這個地址處插入中斷指令,

此外在除錯器中設定軟體斷點時,x64dbg會根據指令地址的特性來判斷是否可以設定斷點,如果指令地址不可執行,x64dbg就無法在這個地址處設定斷點,另外,由于軟體斷點會修改程式的可執行代碼,因此在某些情況下,設定過多的軟體斷點可能會影響程式的性能,

讀者注意:實作獲取下一潭訓編指令的獲取,需要注意如果是被命中的指令,則此處應該是CC斷點占用一個位元組,如果不是則正常獲取到當前指令即可,

  • 1.我們需要檢查當前記憶體斷點是否被命中,如果沒有命中則說明,此處需要獲取到原始的匯編指令長度,然后與當前eip地址相加獲得,
  • 2.如果命中了斷點,則此處又會兩種情況,如果是用戶下的斷點,則此處除錯器會在指令位置替換為CC斷點,也就是匯編中的init停機指令,該指令占用1個位元組,需要eip+1得到,而如果是系統斷點,EIP所停留的位置,則我們需要正常獲取當前指令地址,此處除錯器沒有改動匯編指令,僅僅只下了例外斷點,
from LyScript32 import MyDebug

# 獲取當前EIP指令的下一條指令
def get_disasm_next(dbg,eip):
    next = 0

    # 檢查當前記憶體地址是否被下了絆子
    check_breakpoint = dbg.check_breakpoint(eip)

    # 說明存在斷點,如果存在則這里就是一個位元組了
    if check_breakpoint == True:

        # 接著判斷當前是否是EIP,如果是EIP則需要使用原來的位元組
        local_eip = dbg.get_register("eip")

        # 說明是EIP并且命中了斷點
        if local_eip == eip:
            dis_size = dbg.get_disasm_operand_size(eip)
            next = eip + dis_size
            next_asm = dbg.get_disasm_one_code(next)
            return next_asm
        else:
            next = eip + 1
            next_asm = dbg.get_disasm_one_code(next)
            return next_asm
        return None

    # 不是則需要獲取到原始匯編代碼的長度
    elif check_breakpoint == False:
        # 得到當前指令長度
        dis_size = dbg.get_disasm_operand_size(eip)
        next = eip + dis_size
        next_asm = dbg.get_disasm_one_code(next)
        return next_asm
    else:
        return None

if __name__ == "__main__":
    dbg = MyDebug()
    dbg.connect()

    eip = dbg.get_register("eip")

    next = get_disasm_next(dbg,eip)
    print("下一條指令: {}".format(next))

    prev = get_disasm_next(dbg,4584103)
    print("下一條指令: {}".format(prev))

    dbg.close()

如上代碼則是顯現設定斷點的核心指令集,讀者可自行測驗是否可讀取到當前指令的下一條指令,其輸出效果如下圖所示;

讀者注意:獲取上一潭訓編指令時,由于上一條指令的獲取難點就在于,我們無法確定當前指令的上一條指令到底有多長,所以只能用笨辦法,逐行掃描對比匯編指令,如果找到則取出其上一條指令即可,

from LyScript32 import MyDebug

# 獲取當前EIP指令的上一條指令
def get_disasm_prev(dbg,eip):
    prev_dasm = None
    # 得到當前匯編指令
    local_disasm = dbg.get_disasm_one_code(eip)

    # 只能向上掃描10行
    eip = eip - 10
    disasm = dbg.get_disasm_code(eip,10)

    # 回圈掃描匯編代碼
    for index in range(0,len(disasm)):
        # 如果找到了,就取出他的上一個匯編代碼
        if disasm[index].get("opcode") == local_disasm:
            prev_dasm = disasm[index-1].get("opcode")
            break

    return prev_dasm

if __name__ == "__main__":
    dbg = MyDebug()
    dbg.connect()

    eip = dbg.get_register("eip")

    next = get_disasm_prev(dbg,eip)
    print("上一條指令: {}".format(next))

    dbg.close()

運行后即可讀入當前EIP的上一條指令位置處的反匯編指令,輸出效果如下圖所示;

原文地址

https://www.lyshark.com/post/b62cec0e.html

文章作者:lyshark (王瑞)
文章出處:https://www.cnblogs.com/LyShark/p/17542824.html
本博客所有文章除特別宣告外,均采用 BY-NC-SA 許可協議,轉載請注明出處!

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/557046.html

標籤:其他

上一篇:SQ工具|10|ArcMap資料庫合并工具

下一篇:返回列表

標籤雲
其他(162410) Python(38274) JavaScript(25530) Java(18294) C(15239) 區塊鏈(8275) C#(7972) AI(7469) 爪哇(7425) MySQL(7294) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5876) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4615) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2438) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) HtmlCss(1995) .NET技术(1986) 功能(1967) Web開發(1951) C++(1942) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1882) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 4.10 x64dbg 反匯編功能的封裝

    LyScript 插件提供的反匯編系列函式雖然能夠實作基本的反匯編功能,但在實際使用中,可能會遇到一些更為復雜的需求,此時就需要根據自身需要進行二次開發,以實作更加高級的功能。本章將繼續深入探索反匯編功能,并將介紹如何實作反匯編代碼的檢索、獲取上下一條代碼等功能。這些功能對于分析和除錯代碼都非常有用... ......

    uj5u.com 2023-07-12 08:33:39 more
  • SQ工具|10|ArcMap資料庫合并工具

    可對相同結構的資料庫進行批量合并,包括shp檔案 點擊目標資料庫選擇要'合并至'的資料庫,點擊+按鈕添加要參與合并的資料庫,選擇完所有需要合并的資料庫后,點擊確認即可完成合并。 備注: ①參與合并的資料庫結構必須相等。 ②目標資料庫建議選擇相同結構的空資料庫。 ③資料庫較多時,最好分批合并。字太少了 ......

    uj5u.com 2023-07-12 08:32:58 more
  • SQ工具|9|資料安全|ArcMap自動保存|ArcMap自動備份插件

    可解決在作業程序中停電、軟體閃退等一系列問題導致的ArcMap自動退出而未來得及保存資料造成的資料丟失的問題 一、自動保存 在開啟編輯的狀態下,設定保存周期,狀態選擇開啟點擊確認即可開啟自動保存任務(提示框位于右下角) 當一個保存周期內資料未變化時,將不會觸發自動保存。 狀態選擇關閉時點擊確認,即可 ......

    uj5u.com 2023-07-12 08:32:48 more
  • SQ工具|8|欄位順序編碼|同項順序編碼|自西向東,自北向南編碼

    順序編碼主要解決類似BSM等類欄位按照12345順序編碼以及同專案順序編碼。 一:順序編碼的實作 ①使用欄位計算器及OID欄位進行更新 例:如果想在index中填充從1開始依次加1的值,那么在欄位計算器中將index計算為FID+1即可,在源檔案為shp檔案時,OID一直保持從0開始遞增的值。但是在 ......

    uj5u.com 2023-07-12 08:27:25 more
  • SQ工具|7|域值型欄位的更新

    應用場景:如不動產登記系統中的ZDJBXX表,存在欄位YT和GHYTMC,兩欄位按照土地用途型別字典表一一對應,比如0702對應農村宅基地。根據YT更新GHYTMC。 已內置了四組字典,分別是土地用途,房屋用途,房屋性質,房屋型別 分別選擇對應的鍵欄位,值欄位;值欄位為要更新的欄位,若勾選下方選擇框 ......

    uj5u.com 2023-07-12 08:22:10 more
  • 4.10 x64dbg 反匯編功能的封裝

    LyScript 插件提供的反匯編系列函式雖然能夠實作基本的反匯編功能,但在實際使用中,可能會遇到一些更為復雜的需求,此時就需要根據自身需要進行二次開發,以實作更加高級的功能。本章將繼續深入探索反匯編功能,并將介紹如何實作反匯編代碼的檢索、獲取上下一條代碼等功能。這些功能對于分析和除錯代碼都非常有用... ......

    uj5u.com 2023-07-11 08:24:24 more
  • 前端Vue自定義商品訂單tabs標題欄選項卡組件 可設定文字下劃線顏

    隨著技術的發展,開發的復雜度也越來越高,傳統開發方式將一個系統做成了整塊應用,經常出現的情況就是一個小小的改動或者一個小功能的增加可能會引起整體邏輯的修改,造成牽一發而動全身。 通過組件化開發,可以有效實作單獨開發,單獨維護,而且他們之間可以隨意的進行組合。大大提升開發效率低,降低維護成本。 組件化 ......

    uj5u.com 2023-07-11 08:11:19 more
  • 前端Vue自定義精美橫向步驟條組件 水平步驟條組件 可用于電商跟

    隨著技術的發展,開發的復雜度也越來越高,傳統開發方式將一個系統做成了整塊應用,經常出現的情況就是一個小小的改動或者一個小功能的增加可能會引起整體邏輯的修改,造成牽一發而動全身。 通過組件化開發,可以有效實作單獨開發,單獨維護,而且他們之間可以隨意的進行組合。大大提升開發效率低,降低維護成本。 組件化 ......

    uj5u.com 2023-07-11 08:11:15 more
  • 記錄--關于瀏覽器快取策略這件事兒

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 我們打開百度這個網站并重繪多次時時,注意到百度的logo是沒有每次都加載一遍的。我們知道圖片是img標簽中的src屬性加載出來的,這也需要瀏覽器去請求圖片資源的,那么為什么重繪多次瀏覽器只請求了一次圖片資源呢?這就涉及到了瀏覽器的緩 ......

    uj5u.com 2023-07-11 08:11:00 more
  • JS中使用Promise.all控制所有的異步請求都完成后,在執行后續邏輯

    將所有的異步耗時操作都封裝成Promise物件回傳,Promise可以將異步轉成同步,在執行完成后結果回傳到then中,然后使用Promise.all將promise物件陣列一起執行,全部執行完成后再統一回傳資訊 ......

    uj5u.com 2023-07-11 08:10:49 more