天天看點

LyScript 擷取上一條與下一條指令

LyScript 插件預設并沒有提供上一條與下一條彙編指令的擷取功能,當然你可以使用​

​LyScriptTools​

​工具包直接調用内置指令得到,不過這種方式顯然在效率上并不理想,我們需要在LyScript插件API基礎上自己封裝實作這個功能。

LyScript項目位址:​​https://github.com/lyshark/LyScript​​

擷取下一條彙編指令: 下一條彙編指令的擷取需要注意如果是被命中的指令則此處應該是CC斷點占用一個位元組,如果不是則正常擷取到目前指令即可。

  • 1.我們需要檢查目前記憶體斷點是否被命中,如果沒有命中則說明此處我們需要擷取到原始的彙編指令長度,然後與目前eip位址相加獲得。
  • 2.如果命中了斷點,則此處有兩種情況
  • 1.1 如果是使用者下的斷點,則此處調試器會在指令位置替換為CC,也就是彙編中的init停機指令,該指令占用1個位元組,需要eip+1得到。
  • 1.2 如果是系統斷點,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,12391436)
    print("下一條指令: {}".format(prev))

    dbg.close()      

擷取結果如下:

LyScript 擷取上一條與下一條指令

擷取上一條彙編指令: 上一條指令的擷取難點就在于,我們無法确定目前指令的上一條指令到底有多長,是以隻能用笨辦法,逐行掃描對比彙編指令,如果找到則取出其上一條指令即可。

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()      

輸出效果如下: