Debugging interface
Software debugging is a technical process aimed at diagnosing and resolving errors, defects, and abnormal behaviors in computer software. It is a crucial step in the software development process, helping developers understand the execution process of the program, identify problems, and ultimately fix errors.
Software debugging plays a crucial role in computer security, binary security, and vulnerability mining, helping to discover and fix security vulnerabilities, defects, and potential attack surfaces in software.
The LyScript plugin offers a variety of debugging interfaces, which are crucial for automated testing. It's essential to master the use of these interfaces. This guide will cover aspects such as debugging initialization, executing actions, and setting breakpoints.
Debugging actions
OpenDebug/DetachDebug/CloseDebug
OpenDebug
Initialize the debugger by passing in the executable file path and attach it to the target program to start a debugging session. Return a dictionary containing debugger status, prompt information, and executed commands upon success, and return false upon failure.
DetachDebug
Disconnect the debugger from the target program, but keep the debugger instance. Return a dictionary containing separation status and prompt information upon success, and return false upon failure.
CloseDebug
Close the debugger instance and release related resources. Return a dictionary containing a closed status and prompt information upon success, and return false upon failure.
call interface function:
>>> debugger.OpenDebug("d://test.exe")
Return value of interface function (JSON):
{
'state': 'debugger_opened_success',
'message': 'Debuggerinitializedsuccessfully',
'executed_command': 'InitDebugd: //test.exe'
}
>>>
call interface function:
>>> debugger.DetachDebug()
Return value of interface function (JSON):
{
'state': 'debugger_detached_success',
'message': 'Debuggerhasbeendetached'
}
>>>
call interface function:
>>> debugger.CloseDebug()
Return value of interface function (JSON):
{
'state': 'debugger_closed_success',
'message': 'Debuggerhasbeenclosed'
}
IsDebugger/IsRunningLocked/IsRunning
IsDebugger
Check if the debugger is active. Return a dictionary containing debugger activity status and prompt information upon success, and return false upon failure.
IsRunningLocked
Check if the debugger is running in a locked state. Return a dictionary containing locked running status and prompt information upon success, and return false upon failure.
IsRunning
Check if the debugger is currently running. Return a dictionary containing running status and prompt information upon success, and return false upon failure.
call interface function:
>>> debugger.IsDebugger()
Return value of interface function (JSON):
{
'is_debugger': True,
'message': 'Debuggerisactive'
}
>>>
call interface function:
>>> debugger.IsRunningLocked()
Return value of interface function (JSON):
{
'is_running_locked': True,
'message': 'Debuggerisrunninginlockedstate'
}
>>>
call interface function:
>>> debugger.IsRunning()
Return value of interface function (JSON):
{
'is_running': False,
'message': 'Debuggerisnotrunning'
}
Wait/Run/Pause/Stop/StepIn/StepOut/StepOver
Wait
Put the debugger into a waiting state. Return a dictionary containing waiting status and prompt information upon success, and return false upon failure.
Run
Start the debugger to run. Return a dictionary containing running status and prompt information upon success, and return false upon failure.
Pause
Pause the debugger from running. Return a dictionary containing pause status and prompt information upon success, and return false upon failure.
Stop
Stop the debugger from running. Return a dictionary containing stop status and prompt information upon success, and return false upon failure.
StepIn
Perform a single step entry operation (enter the function called by the current instruction). Return a dictionary containing the single step entry status and prompt information upon success, and return false upon failure.
StepOut
Perform a step out operation (from the current function to the return position). When successful, return a dictionary containing the step out status and prompt information; when failed, return false.
StepOver
Perform a single step skip operation (execute the current instruction, or directly execute the entire function if it is a function). When successful, return a dictionary containing the single step skip status and prompt information; when failed, return false.
call interface function:
>>> debugger.Wait()
Return value of interface function (JSON):
{
'state': 'debugger_wait_success',
'message': 'Debuggerisnowinwaitstate'
}
call interface function:
>>> debugger.Run()
Return value of interface function (JSON):
{
'state': 'debugger_run_success',
'message': 'Debuggerisnowrunning'
}
call interface function:
>>> debugger.Pause()
Return value of interface function (JSON):
{
'state': 'debugger_pause_success',
'message': 'Debuggerhasbeenpaused'
}
call interface function:
>>> debugger.Stop()
Return value of interface function (JSON):
{
'state': 'debugger_stop_success',
'message': 'Debuggerhasbeenstopped'
}
call interface function:
>>> debugger.StepIn()
Return value of interface function (JSON):
{
'state': 'debugger_stepin_success',
'message': 'Debuggerperformedstepin'
}
call interface function:
>>> debugger.StepOut()
Return value of interface function (JSON):
{
'state': 'debugger_stepout_success',
'message': 'Debuggerperformedstepout'
}
call interface function:
>>> debugger.StepOver()
Return value of interface function (JSON):
{
'state': 'debugger_stepover_success',
'message': 'Debuggerperformedstepover'
}
Breakpoint setting
Software breakpoints and hardware breakpoints are commonly used tools in debugging. Software breakpoints are achieved by inserting special instructions into program code, pausing execution when the program reaches the breakpoint position, making it easier to observe program status and variable values. In contrast, hardware breakpoints utilize the internal debugging function of the processor to trigger interrupt operations when the processor monitors program addresses, without the need to modify program code. They are suitable for scenarios such as embedded systems and are usually faster.
ShowBreakPoint
Get the details of all the breakpoints set in the current debugger, including breakpoint type, address, status, module, etc. When successful, return a dictionary containing a list of breakpoints, the total number of breakpoints, and operation result information. When failed, return false.
call interface function:
>>> debugger.ShowBreakPoint()
Return value of interface function (JSON):
{
'breakpoints': [
{
'type': 1,
'address': 16715891,
'enabled': True,
'singleshoot': True,
'active': True,
'name': 'entry breakpoint',
'module': 'test.exe',
'slot': 0,
'hit_count': 0,
'fast_resume': False,
'silent': False,
'break_condition': '',
'log_text': '',
'log_condition': '',
'command_text': '',
'command_condition': ''
},
{
'type': 2,
'address': 2008777048,
'enabled': True,
'singleshoot': False,
'active': True,
'name': '',
'module': 'ntdll.dll',
'slot': 0,
'hit_count': 0,
'fast_resume': False,
'silent': False,
'break_condition': '',
'log_text': '',
'log_condition': '',
'command_text': '',
'command_condition': ''
}
],
'count': 2,
'message': 'Breakpointsretrievedsuccessfully'
}
SetBreakPoint
Set a breakpoint by passing in a memory address (supporting hexadecimal string format, such as "0x77BB80C9") to pause program execution at a specified location during debugging. Return a dictionary containing the operation result, breakpoint address (hexadecimal), and corresponding decimal value upon success, and false upon failure.
call interface function:
>>> eip = debugger.get_register("eip")
>>> eip
Return value of interface function (JSON):
{
'message': 'Registervalueretrievedsuccessfully',
'register_name': 'EIP',
'register_index': 30,
'value_decimal': 2008776905,
'value_hex': '0x77BB80C9',
'platform': 'x86'
}
>>>
call interface function:
>>> debugger.SetBreakPoint(eip.get("value_hex"))
Return value of interface function (JSON):
{
'message': 'Breakpointsetsuccessfully',
'address': '0x77BB80C9',
'address_value': 2008776905
}
DeleteBreakPoint
By passing in the memory address of the target breakpoint (supporting hexadecimal string format, such as "0x77BB80C9"), delete the breakpoint at that address. When successful, return a dictionary containing the deletion result, target address, and corresponding decimal value. If failed, return false (if there is no breakpoint at the target address).
call interface function:
>>> debugger.DeleteBreakPoint("0x77BB80C9")
Return value of interface function (JSON):
{
'message': 'Breakpointdeletedsuccessfully',
'address': '0x77BB80C9',
'address_value': 2008776905
}
SetHardwareBreakPoint
Set a specific type of hardware breakpoint (based on CPU debug registers) by passing in the target memory address (supporting hexadecimal string format, such as "0x77BB80C9") and hardware breakpoint type value. When successful, return a dictionary containing the setting result, breakpoint type description, type value, target address, and corresponding decimal value. If failed, return false.
call interface function:
>>> debugger.SetHardwareBreakPoint("0x77BB80C9",1)
Return value of interface function (JSON):
{
'message': 'Hardwarebreakpointsetsuccessfully',
'breakpoint_type': 'HardwareWrite',
'breakpoint_type_value': 1,
'address': '0x77BB80C9',
'address_value': 2008776905
}
>>>
call interface function:
>>> debugger.SetHardwareBreakPoint("0x77BB80C9",2)
Return value of interface function (JSON):
{
'message': 'Hardwarebreakpointsetsuccessfully',
'breakpoint_type': 'HardwareExecute',
'breakpoint_type_value': 2,
'address': '0x77BB80C9',
'address_value': 2008776905
}
DeleteHardwareBreakPoint
By passing in the memory address of the target hardware breakpoint (supporting hexadecimal string format, such as "0x77BB80C9"), delete the hardware breakpoint already set at that address (implemented based on CPU debug registers). When successful, return a dictionary containing the deletion result, target address, and corresponding decimal value. If failed, return false (if there is no hardware breakpoint at the target address).
call interface function:
>>> debugger.DeleteHardwareBreakPoint("0x77BB80C9")
Return value of interface function (JSON):
{
'message': 'Hardwarebreakpointdeletedsuccessfully',
'address': '0x77BB80C9',
'address_value': 2008776905
}
CheckBreakPoint
By passing in the memory address of the target breakpoint (supporting hexadecimal string format, such as "0x77BB80C9"), check if the breakpoint at that address has been hit, and return the comparison information between the current instruction pointer (EIP) and the target address. Return a dictionary containing breakpoint hit status, target address, current EIP value, and other information upon success, and return false upon failure.
call interface function:
>>> debugger.CheckBreakPoint("0x77BB80C9")
Return value of interface function (JSON):
{
'is_hit': True,
'message': 'Breakpointishit',
'target_address': '0x77BB80C9',
'target_address_value': 2008776905,
'current_eip': '0x77BB80C9',
'current_eip_value': 2008776905
}
>>>
call interface function:
>>> debugger.CheckBreakPoint("0x77BB80E5")
Return value of interface function (JSON):
{
'is_hit': False,
'message': 'Breakpointnothit',
'target_address': '0x77BB80E5',
'target_address_value': 2008776933,
'current_eip': '0x77BB80C9',
'current_eip_value': 2008776905
}
CheckBreakPointDisable
By passing in the target address (supporting hexadecimal string format, such as "0x77BB80C9"), check if the breakpoint at that address is disabled. If the address has no breakpoints or breakpoints are enabled, return the "not disabled" status; Only when there is a breakpoint in the address and it has been disabled, return the 'disabled' status. Return a dictionary containing disabled status, target address, prompt information, and result description upon success, and return false upon failure.
call interface function:
>>> debugger.CheckBreakPointDisable("0x77BB80C9")
Return value of interface function (JSON):
{
'is_disabled': False,
'address': '0x77BB80C9',
'address_value': 2008776905,
'hint': 'False=breakpointisenabledORnobreakpointexistsatthisaddress',
'message': 'Breakpointisenabledornotexists'
}
>>>
call interface function:
>>> debugger.CheckBreakPointDisable("0x77BB80E5")
Return value of interface function (JSON):
{
'is_disabled': False,
'address': '0x77BB80E5',
'address_value': 2008776933,
'hint': 'False=breakpointisenabledORnobreakpointexistsatthisaddress',
'message': 'Breakpointisenabledornotexists'
}
CheckBreakPointType
By passing in the memory address of the target breakpoint (supporting hexadecimal string format, such as "0x77BB80C9"), query the specific type of breakpoint at that address (such as software breakpoint, hardware breakpoint). If successful, return a dictionary containing the breakpoint type value, type description, target address, and operation result. If failed, return false (if there is no breakpoint at the target address).
call interface function:
>>> debugger.CheckBreakPointType("0x77BB80C9")
Return value of interface function (JSON):
{
'breakpoint_type_value': 1,
'breakpoint_type_desc': 'SoftwareBreakpoint(INT3)',
'address': '0x77BB80C9',
'address_value': 2008776905,
'message': 'Breakpointtyperetrievedsuccessfully'
}
>>>
call interface function:
>>> debugger.CheckBreakPointType("0x77BB80E5")
Return value of interface function (JSON):
{
'breakpoint_type_value': 2,
'breakpoint_type_desc': 'HardwareBreakpoint',
'address': '0x77BB80E5',
'address_value': 2008776933,
'message': 'Breakpointtyperetrievedsuccessfully'
}