This is an example for submitting a CrackMe in the Downloads section of the site.
You can download the file and run Debug Blocker x64. Nothing too exciting will happen!
The challenge here would be to patch the debug-blocker function so that it does not spawn a second process.
; ------------------------------------------------------------------
;
; PureBasic DebugBlocker() function, creates a copy of the currently running
; process as a child and attaches to it for self-debugging. This method is
; commonly referred to as "self-debugging" or "Debug Blocker" and is used
; to protect the parent (now child) process from being debugged. Only one
; Ring-3 debugger can be attached to a process in Windows OS.
;
; Return Values:
;
; This function does not return a value.
;
; Remarks:
;
; Debugging events and actions are handled within the function.
;
; By Teddy Rogers / PureBasic 5.24 LTS
;
; ------------------------------------------------------------------
Declare DebugBlocker()
If OpenWindow(1, #Null, #Null, 300, 60, "Self-debugging Example", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
ButtonGadget(1, 5, 5, 290, 50, "CLICK ME!", #PB_Button_MultiLine)
Repeat
MyEvent = WaitWindowEvent()
Select MyEvent
Case #PB_Event_Gadget
Select EventGadget()
Case 1
DebugBlocker()
EndSelect
EndSelect
Until MyEvent = #PB_Event_CloseWindow
EndIf
; A very simple example of self-debugging (Debug-Blocker)...
Procedure DebugBlocker()
Protected ghMutex, EXIT_PROCESS_DEBUG_EVENT
; Create a mutex object, we can use it as an identity to limit the number of spawned processes to be self-debugged...
ghMutex = CreateMutex_(#Null, #True, "Blocker_Mutex")
If ghMutex = #Null Or GetLastError_() = #ERROR_ALREADY_EXISTS ; If return handle is the existing object GetLastError returns ERROR_ALREADY_EXISTS.
CloseHandle_(ghMutex)
MessageBox_(WindowID(1), "Self-debugging already in progress...", "Error", #MB_ICONERROR | #MB_TOPMOST | #MB_SETFOREGROUND)
ProcedureReturn
EndIf
; Find out who we are and create a duplicate process of ourselves...
GetStartupInfo_(lpStartupInfo.STARTUPINFO)
If CreateProcess_(#Null, GetCommandLine_(), #Null, #Null, #False, #DEBUG_PROCESS, #Null, #Null, @lpStartupInfo, @lpProcessInformation.PROCESS_INFORMATION)
; Infinitely wait for the debugging event EXIT_PROCESS_DEBUG_EVENT in our new process...
Repeat
If WaitForDebugEvent_(@myDebug.DEBUG_EVENT, -1)
If PeekB(@myDebug\dwDebugEventCode) = #EXIT_PROCESS_DEBUG_EVENT
EXIT_PROCESS_DEBUG_EVENT = #True
EndIf
EndIf
; Continue debugging the process...
If Not ContinueDebugEvent_(myDebug\dwProcessId, myDebug\dwThreadId, #DBG_CONTINUE)
MessageBox_(WindowID(1), "Debugging error!", "Error", #MB_ICONERROR | #MB_TOPMOST | #MB_SETFOREGROUND)
EndIf
Until EXIT_PROCESS_DEBUG_EVENT
; Tidy up process handles identified in the PROCESS_INFORMATION structure...
CloseHandle_(lpProcessInformation\hProcess)
CloseHandle_(lpProcessInformation\hThread)
EndIf
ReleaseMutex_(ghMutex)
CloseHandle_(ghMutex) ; Destroy the created Blocker_Mutex
EndProcedure
This is where I as the author would post my own solution if I wanted to add one.
This field is optional.
Recommended Comments