LyScriptTools模塊中的DebugControl類主要負責控制x64dbg調試器的行爲,例如獲取或設置寄存器組,執行單步命令等,此類內的方法也是最常用的。
LyScript項目地址: https://github.com/lyshark/LyScript
調試類命令總結如下表所示:
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()