天天看點

LyScriptTools 調試控制類API接口手冊

LyScriptTools子產品中的DebugControl類主要負責控制x64dbg調試器的行為,例如擷取或設定寄存器組,執行單步指令等,此類内的方法也是最常用的。

DebugControl 說明文檔被:Softnessi 整理

調試類指令總結如下表所示:

DebugControl 類内函數名 函數作用
GetEAX() 擷取通用寄存器系列
SetEAX(decimal_value) 設定特定寄存器中的值(十進制)
GetZF() 擷取标志寄存器系列
SetZF(decimal_bool) 設定标志寄存器的值(布爾型)
Script_InitDebug(path) 傳入檔案路徑,載入被調試程式
Script_CloseDebug() 終止目前被調試程序
Script_DetachDebug() 讓程序脫離目前調試器
Script_RunDebug() 讓程序運作起來
Script_ERun() 釋放鎖并允許程式運作,忽略異常
Script_SeRun() 釋放鎖并允許程式運作,跳過異常中斷
Script_Pause() 暫停調試器運作
Script_StepInto() 步進
Script_EStepInfo() 步進,跳過異常
Script_SeStepInto() 步進,跳過中斷
Script_StepOver() 步過到結束
Script_StepOut() 普通步過F8
Script_Skip() 跳過執行
Script_Inc(register) 遞增寄存器
Script_Dec(register) 遞減寄存器
Script_Add(register,decimal_int) 對寄存器進行add運算
Script_Sub(register,decimal_int) 對寄存器進行sub運算
Script_Mul(register,decimal_int) 對寄存器進行mul乘法
Script_Div(register,decimal_int) 對寄存器進行div除法
Script_And(register,decimal_int) 對寄存器進行and與運算
Script_Or(register,decimal_int) 對寄存器進行or或運算
Script_Xor(register,decimal_int) 對寄存器進行xor或運算
Script_Neg(register,decimal_int) 對寄存器參數進行neg反轉
Script_Rol(register,decimal_int) 對寄存器進行rol循環左移
Script_Ror(register,decimal_int) 對寄存器進行ror循環右移
Script_Shl(register,decimal_int) 對寄存器進行shl邏輯左移
Script_Shr(register,decimal_int) 對寄存器進行shr邏輯右移
Script_Sal(register,decimal_int) 對寄存器進行sal算數左移
Script_Sar(register,decimal_int) 對寄存器進行sar算數右移
Script_Not(register,decimal_int) 對寄存器進行not按位取反
Script_Bswap(register,decimal_int) 進行位元組交換也就是反轉
Script_Push(register_or_value) 對寄存器入棧
Script_Pop(register_or_value) 對寄存器彈出元素
Pause() 内置API暫停
Run() 内置API運作
StepIn() 内置API步入
StepOut() 内置API步過
StepOut() 内置API到結束
Stop() 内置API停止
Wait() 内置API等待
IsDebug() 判斷調試器是否在調試
IsRunning() 判斷調試器是否在運作

自動控制類主要功能如上表示,其中Script開頭的API是調用的腳本指令實作,其他的是API實作,我們以批量自動載入程式為例,示範該類内函數是如何使用的。

import os
import pefile
import time
from LyScript32 import MyDebug
from LyScriptTools32 import Module
from LyScriptTools32 import Disassemble
from LyScriptTools32 import DebugControl

# 得到特定目錄下的所有檔案,并傳回清單
def GetFullFilePaht(path):
    ref = []
    for root,dirs,files in os.walk(str(path)):
        for index in range(0,len(files)):
            ref.append(str(root + "/" + files[index]))
    return ref

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

    # 初始化調試控制器
    debug = DebugControl(dbg)

    # 得到特定目錄下的所有檔案
    full_path = GetFullFilePaht("d://test/")

    for i in range(0,len(full_path)):
        debug.Script_InitDebug(str(full_path[i]))
        time.sleep(0.3)
        debug.Script_RunDebug()

        time.sleep(0.3)
        local_base = dbg.get_local_base()
        print("目前調試程序: {} 基位址: {}".format(full_path[i],local_base))

        time.sleep(0.3)
        # 關閉調試
        debug.Script_CloseDebug()

    dbg.close()
           

如果你不使用

Script_InitDebug

來加載被調試程序,你也可以使用如下方式打開一個檔案。

import win32api
import win32gui, win32con
import win32clipboard
import re
import time
from LyScript32 import MyDebug

class cWindow:
    def __init__(self):
        self._hwnd = None

    def SetAsForegroundWindow(self):
        win32gui.SetForegroundWindow(self._hwnd)

    def Maximize(self):
        # 最大化
        win32gui.ShowWindow(self._hwnd, win32con.SW_MAXIMIZE)

    def _window_enum_callback(self, hwnd, regex):
        if self._hwnd is None and re.match(regex, str(win32gui.GetWindowText(hwnd))) is not None:
            self._hwnd = hwnd

    def find_window_regex(self, regex):
        self._hwnd = None
        win32gui.EnumWindows(self._window_enum_callback, regex)

    def hide_always_on_top_windows(self):
        win32gui.EnumWindows(self._window_enum_callback_hide, None)

    def _window_enum_callback_hide(self, hwnd, unused):
        if hwnd != self._hwnd:
            if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) & win32con.WS_EX_TOPMOST:
                className = win32gui.GetClassName(hwnd)
                if not (className == 'Button' or className == 'Shell_TrayWnd'):
                    win32gui.ShowWindow(hwnd, win32con.SW_FORCEMINIMIZE)

    def OpenFile(self,path):
        # 按下F3
        win32api.keybd_event(0x72, 0, 0, 0)
        win32api.keybd_event(0x72, 0, win32con.KEYEVENTF_KEYUP, 0)

        # 打開剪貼闆
        win32clipboard.OpenClipboard()
        # 清空剪貼闆
        win32clipboard.EmptyClipboard()
        # 設定剪貼闆内容
        win32clipboard.SetClipboardData(win32con.CF_UNICODETEXT, path)
        # 擷取剪貼闆内容
        date = win32clipboard.GetClipboardData()
        print("[*] OpenFile = {}".format(date))
        # 關閉剪貼闆
        win32clipboard.CloseClipboard()
        time.sleep(0.2)

        # 按下ctrl+v
        win32api.keybd_event(0x11, 0, 0, 0)
        win32api.keybd_event(0x56, 0, 0, 0)
        win32api.keybd_event(0x56, 0, win32con.KEYEVENTF_KEYUP, 0)
        win32api.keybd_event(0x11, 0, win32con.KEYEVENTF_KEYUP, 0)

        # 按下回車
        win32api.keybd_event(0x0D, 0, 0, 0)
        win32api.keybd_event(0x0D, 0, win32con.KEYEVENTF_KEYUP, 0)

    def deatch(self):
        # 按下Ctrl+Alt+F2
        win32api.keybd_event(0x11, 0, 0, 0)
        win32api.keybd_event(0x12, 0, 0, 0)
        win32api.keybd_event(0x71, 0, 0, 0)
        win32api.keybd_event(0x11, 0, win32con.KEYEVENTF_KEYUP, 0)
        win32api.keybd_event(0x12, 0, win32con.KEYEVENTF_KEYUP, 0)
        win32api.keybd_event(0x71, 0, win32con.KEYEVENTF_KEYUP, 0)

# 打開調試程式
def OpenFile(path):
    regex = ".*x32dbg.*"
    cWindows = cWindow()
    cWindows.find_window_regex(regex)
    cWindows.SetAsForegroundWindow()
    cWindows.SetAsForegroundWindow()
    cWindows.OpenFile(path)

# 關閉調試程式
def DeatchFile():
    regex = ".*x32dbg.*"
    cWindows = cWindow()
    cWindows.find_window_regex(regex)
    cWindows.SetAsForegroundWindow()
    cWindows.SetAsForegroundWindow()
    cWindows.deatch()

# 得到腳本傳回值
def GetScriptValue(dbg,script):
    try:
        ref = dbg.run_command_exec("push eax")
        if ref != True:
            return None
        ref = dbg.run_command_exec(f"eax={script}")
        if ref != True:
            return None
        reg = dbg.get_register("eax")
        ref = dbg.run_command_exec("pop eax")
        if ref != True:
            return None
        return reg
    except Exception:
        return None
    return None

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

    # 批量打開一個清單
    for item in ["D:\Win32Project.exe","D:\Windows Tools\C32ASM\c32asm.exe"]:
        OpenFile(item)
        time.sleep(3)

        for i in range(1,100):
            dbg.set_debug("StepIn")
            time.sleep(0.2)

        eip = dbg.get_register("eip")
        print("eip = > {}".format(hex(eip)))

        time.sleep(3)
        DeatchFile()
           
文章作者:

lyshark (王瑞)

文章出處:

https://www.cnblogs.com/LyShark/p/16554842.html

版權聲明:

本部落格文章與代碼均為學習時整理的筆記,文章

[均為原創]

作品,轉載請

[添加出處]

,您添加出處是我創作的動力!

轉載文章,請遵守

《中華人民共和國著作權法》

相關規定或遵守

《署名CC BY-ND 4.0國際》

禁止演繹規範,合理合規,攜帶原創出處轉載。