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