Anti-piracy tip: Prevent debugging (Windows)

Share your advanced PureBasic knowledge/code with the community.
firace
Addict
Addict
Posts: 899
Joined: Wed Nov 09, 2011 8:58 am

Anti-piracy tip: Prevent debugging (Windows)

Post by firace »

A nice trick to keep an attacker from attaching a user-mode debugger (such as Olly or x86dbg) to your program, by having 2 instances debugging each other.

Note: This is just a quick demo, use it as a starting point. :)

Code: Select all


Global target 
ParentPID =  Val(ProgramParameter())

If ParentPID = 0
  hprocess=RunProgram(ProgramFilename(), Str(GetCurrentProcessId_()), "", #PB_Program_Open); 
  ChildPID=ProgramID(hProcess)
EndIf

If ParentPID <> 0 : target = ParentPID : Else : target = ChildPID : EndIf

Procedure debug_other(*a)
  Delay(500)
  result=DebugActiveProcess_(target)  
  
  Repeat
    WaitForDebugEvent_(@lpep.Debug_event,900)
    ContinueDebugEvent_(lpep.debug_event\dwProcessId,lpep.debug_event\dwThreadId,#DBG_CONTINUE);
  ForEver
EndProcedure

CreateThread(@debug_other(),1)

If ParentPID = 0 : parentflag$ = "I'M THE PARENT" :   Else : parentflag$ = "I'M THE CHILD" : height + 100 : EndIf

OpenWindow(0, 100, 100 + height, 340, 60, "Me: " + GetCurrentProcessId_() + " -- My target: " + target + " -- " + parentflag$)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Result (Olly screenshot):

Image
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Anti-piracy tip: Prevent debugging (Windows)

Post by Dude »

Hmm, don't get too excited; OllyDbg had no problem here:

Image
firace
Addict
Addict
Posts: 899
Joined: Wed Nov 09, 2011 8:58 am

Re: Anti-piracy tip: Prevent debugging (Windows)

Post by firace »

Dude wrote:Hmm, don't get too excited; OllyDbg had no problem here:

Strange. Windows version, PB version, Olly version?
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Anti-piracy tip: Prevent debugging (Windows)

Post by Dude »

firace wrote:Windows version, PB version, Olly version?
Windows 7 Ultimate (64-bit), PureBasic v5.62 (32-bit), OllyDbg v2.01 (32-bit).
User avatar
ar-s
Enthusiast
Enthusiast
Posts: 340
Joined: Sat Oct 06, 2007 11:20 pm
Location: France

Re: Anti-piracy tip: Prevent debugging (Windows)

Post by ar-s »

A small tip is to kill olly.exe process when it's detected. It's not a big protection, but that could stop noobs.
~Ar-S~
My Image Hoster for PB users
My webSite (french) with PB apps : LDVMULTIMEDIA
PB - 3.x / 5.7x / 6 - W11 x64 - Ryzen 7 3700x / #Rpi4

Code: Select all

r3p347 : 7ry : un71l d0n3 = 1
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Anti-piracy tip: Prevent debugging (Windows)

Post by Dude »

ar-s wrote:A small tip is to kill olly.exe process when it's detected.
Yes, but OllyDbg can launch your exes in "paused" mode (Ctrl+11), which can then be stepped through at will (F7). The cracker can then find the point in your app where the process detection exists, and remove it.
HanPBF
Enthusiast
Enthusiast
Posts: 562
Joined: Fri Feb 19, 2010 3:42 am

Re: Anti-piracy tip: Prevent debugging (Windows)

Post by HanPBF »

Tool "PELock" protects Your exe against debuggers.
User avatar
CELTIC88
Enthusiast
Enthusiast
Posts: 154
Joined: Thu Sep 17, 2015 3:39 pm

Re: Anti-piracy tip: Prevent debugging (Windows)

Post by CELTIC88 »

interested in Cybersecurity..
Opcode
Enthusiast
Enthusiast
Posts: 137
Joined: Thu Jul 18, 2013 4:58 am

Re: Anti-piracy tip: Prevent debugging (Windows)

Post by Opcode »

You can call IsDebuggerPresent but it's easy to spot the function in the code. Using the process environment block to pull the return value is less suspicious.

Code: Select all

Procedure CheckForDebugger(Parameter.i)
  
  Protected.i IsDebuggerPresent = 0
 
  Repeat
   
    !mov eax, [fs:0x30]
    !mov al, [eax+2]
    !mov [p.v_IsDebuggerPresent], al
    
    If IsDebuggerPresent <> 0
      PrintN("Debugger Detected!")
      ExitProcess_(0)
    EndIf
    
    Delay(10)
   
  ForEver
 
EndProcedure

OpenConsole("Attach To Me")
CreateThread(@CheckForDebugger(), 0)

Repeat
  PrintN("Hai!")
  Delay(1000)
ForEver
There are better ways for detecting a debugger but this is just a simple way of many.
Last edited by Opcode on Sat May 26, 2018 8:54 am, edited 1 time in total.
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Anti-piracy tip: Prevent debugging (Windows)

Post by Dude »

Opcode wrote:You can call IsDebuggerPresent but it's easy to spot the function in the code. Using the process environment block to pull the return value is less suspicious.

Code: Select all

OpenConsole()

Procedure CheckForDebugger(Parameter.i)
  
  Repeat
    
    !mov eax, [fs:0x30] 
    !mov al, [eax+2] 
    !test al, al 
    !jne ll_checkfordebugger_debuggerdetected
    !jmp ll_checkfordebugger_nodebuggerdetected
    
    DebuggerDetected:
    PrintN("Debugger Detected!")
    ExitProcess_(0)
    
    NoDebuggerDetected:
    Delay(10) ; Lets not hammer the CPU
    
  ForEver
  
EndProcedure

CreateThread(@CheckForDebugger(), 0)

Repeat
  PrintN("Hai!")
  Delay(1000)
ForEver
There are better ways for detecting a debugger but this is just a simple way of many.
Good example, Opcode -- it successfully detects OllyDbg here. I'll use that in my app. Another simple test is just to search all windows that have (say) "OllyDbg" in their title. I did that with an old app I wrote in Visual Basic many years ago, and my app simply wouldn't run if such a window was found. No error message or anything; just a silent quit. To the honest user this was never a problem because the app always ran; it was only crackers who suffered it and they should be smart enough to work out why. ;)
Opcode
Enthusiast
Enthusiast
Posts: 137
Joined: Thu Jul 18, 2013 4:58 am

Re: Anti-piracy tip: Prevent debugging (Windows)

Post by Opcode »

Dude wrote:
Opcode wrote:You can call IsDebuggerPresent but it's easy to spot the function in the code. Using the process environment block to pull the return value is less suspicious.

Code: Select all

OpenConsole()

Procedure CheckForDebugger(Parameter.i)
  
  Repeat
    
    !mov eax, [fs:0x30] 
    !mov al, [eax+2] 
    !test al, al 
    !jne ll_checkfordebugger_debuggerdetected
    !jmp ll_checkfordebugger_nodebuggerdetected
    
    DebuggerDetected:
    PrintN("Debugger Detected!")
    ExitProcess_(0)
    
    NoDebuggerDetected:
    Delay(10) ; Lets not hammer the CPU
    
  ForEver
  
EndProcedure

CreateThread(@CheckForDebugger(), 0)

Repeat
  PrintN("Hai!")
  Delay(1000)
ForEver
There are better ways for detecting a debugger but this is just a simple way of many.
Good example, Opcode -- it successfully detects OllyDbg here. I'll use that in my app. Another simple test is just to search all windows that have (say) "OllyDbg" in their title. I did that with an old app I wrote in Visual Basic many years ago, and my app simply wouldn't run if such a window was found. No error message or anything; just a silent quit. To the honest user this was never a problem because the app always ran; it was only crackers who suffered it and they should be smart enough to work out why. ;)
Updated the code in original post to make more sense with PB, if that's of any help.
User avatar
CELTIC88
Enthusiast
Enthusiast
Posts: 154
Joined: Thu Sep 17, 2015 3:39 pm

Re: Anti-piracy tip: Prevent debugging (Windows)

Post by CELTIC88 »

you can use this method

Code: Select all

;IncludeFile "c:\dasm.pb"

DisableDebugger
EnableASM
Procedure anti_debugging()
  ;origin code https://github.com/invictus1306/Anti-debugging-techniques/blob/master/anti-debugging.asm
  ;NtGlobalFlag - PEB!NtGlobalFlags
  XOR eax, eax
  !MOV eax, [fs:eax+0x30]
  MOV eax, [eax+0x68]
  AND eax, 0x70
  !DB 0xeb, 0x01
  !DB 0xff, 0x85, 0xC0 ;junk byte - test eax, eax
  JNE @Detected
  
  ;obfuscation
  !DB 0xeb, 0x02
  !DB	0xcc, 0xfe, 0xeb, 0x00
  
  ;IsDebuggerPresent first - kernel32!IsDebuggerPresent
  IsDebuggerPresent_()
  CALL @eip_manipulate ; change eip (point to next instruction)
  MOV eax, 0x10
  CMP eax, 1
  JE @Detected
  
  ;IsDebuggerPresent second - PEB!IsDebugged
  XOR eax, eax
  !MOV eax,  [fs:0x18]
  !MOV eax, DWORD [ds:eax+0x30]
  !MOVZX eax, BYTE [ds:eax+0x2]
  TEST eax, eax
  JNE @Detected
  
  ;FindWindows for ollydbg
  FindWindow_("OLLYDBG",0)
  TEST eax, eax
  JNE @Detected
  
  ;software breakpoint detection into MessageBox API
  CLD
  MOV edi, @Detected
  MOV ecx, 0x13
  MOV al,0xcc
  REPNE SCASB
  JZ @Detected
  
  ;hardware breakpoint detection
  PUSH HwBpHandler
  !PUSH dword [fs:0]
  !MOV DWORD [fs:0], esp
  XOR eax, eax
  DIV eax
  !POP DWORD [fs:0]
  NOP
  NOP
  NOP
  ADD esp, 8
  TEST eax, eax
  JNE @Detected
  
  ;get write permissions for self-modifying code
  XOR esi, esi
  XOR ecx, ecx
  MOV esi,  @encrypted_code
  PUSH esp
  PUSH esp
  PUSH #PAGE_EXECUTE_READWRITE
  PUSH 0x4
  PUSH esi
  CALL _VirtualProtect@16
  POP eax
  
  ;self-modifying code
  MOV eax, 0x1234   ;key
  MOV ecx, @encrypted_code
  
  !@loop_decryption:
  XOR [ecx], al ;very simple algorithm
  INC ecx
  CMP ecx, @encrypted_code + 0x4
  JNE @loop_decryption
  
  !@encrypted_code:
  DB 0x5e, 0x4  ;push 30h
  DB 0xdf, 0x34 ;jmp at next instruction 
  POP eax
  
  JMP skiip
  !@Detected:
  MOV eax, 1
  ProcedureReturn
  !skiip:
  XOR eax, eax    
  RET
  
  !@eip_manipulate:
  ADD dword [esp], 5
  RET
  
  !HwBpHandler:
  XOR eax, eax
  MOV eax, [esp + 0xc]     ; This is a CONTEXT structure on the stack
  CMP DWORD [eax + 0x4], 0 ; Dr0
  JNE bpFound
  CMP DWORD [eax + 0x8], 0 ; Dr1
  JNE bpFound
  CMP DWORD [eax + 0xc], 0 ; Dr2
  JNE bpFound
  CMP DWORD [eax + 0x10], 0 ; Dr3
  JNE bpFound
  JMP retFromException
  
  !bpFound:
  MOV DWORD [eax + 0xb0], -1 ; HW bp found
  
  !retFromException:
  ADD DWORD [eax + 0xb8], 6
  XOR eax, eax
  RET
  
  ;force the compiler to add this function
  VirtualProtect_(0,0,0,0)
EndProcedure
EnableDebugger
DisableASM


If anti_debugging() 
  MessageRequester(":(","Debugger detectd!")
Else
  MessageRequester(":)","Perfect!")
EndIf


but do not really protect your application :(

Image

patch.1337

Code: Select all

>test22.exe
000010B1:0F->90
000010B2:85->90
000010B3:B0->90
000010B4:00->90
000010B5:00->90
000010B6:00->90
000010CF:0F->90
000010D0:84->90
000010D1:92->90
000010D2:00->90
000010D3:00->90
000010D4:00->90
000010E6:75->90
000010E7:7F->90
000010FA:75->90
000010FB:6B->90
interested in Cybersecurity..
Opcode
Enthusiast
Enthusiast
Posts: 137
Joined: Thu Jul 18, 2013 4:58 am

Re: Anti-piracy tip: Prevent debugging (Windows)

Post by Opcode »

Here's another method to add to the collection. Easy to implement, easy to bypass. Still something though.

Code: Select all

Procedure PatchDbgUiRemoteBreakin()
  
  Protected.l DbgAddr, oProtect
  
  DbgAddr = GetProcAddress_(GetModuleHandle_("ntdll.dll"), "DbgUiRemoteBreakin")
  
  VirtualProtect_(DbgAddr, 6, #PAGE_EXECUTE_READWRITE, @oProtect)
  
  PokeB(DbgAddr + 0, $68)
  PokeL(DbgAddr + 1, GetProcAddress_(GetModuleHandle_("kernel32.dll"), "ExitProcess"))
  PokeB(DbgAddr + 5, $C3)
  
  VirtualProtect_(DbgAddr, 6, oProtect, @oProtect)
  
EndProcedure
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: Anti-piracy tip: Prevent debugging (Windows)

Post by BarryG »

Opcode wrote:Here's another method to add to the collection. Easy to implement, easy to bypass. Still something though.

Code: Select all

Procedure PatchDbgUiRemoteBreakin()
  
  Protected.l DbgAddr, oProtect
  
  DbgAddr = GetProcAddress_(GetModuleHandle_("ntdll.dll"), "DbgUiRemoteBreakin")
  
  VirtualProtect_(DbgAddr, 6, #PAGE_EXECUTE_READWRITE, @oProtect)
  
  PokeB(DbgAddr + 0, $68)
  PokeL(DbgAddr + 1, GetProcAddress_(GetModuleHandle_("kernel32.dll"), "ExitProcess"))
  PokeB(DbgAddr + 5, $C3)
  
  VirtualProtect_(DbgAddr, 6, oProtect, @oProtect)
  
EndProcedure
What does this do? And do you just call that procedure alone to protect your exe?
Everything
Enthusiast
Enthusiast
Posts: 224
Joined: Sat Jul 07, 2018 6:50 pm

Re: Anti-piracy tip: Prevent debugging (Windows)

Post by Everything »

BarryG wrote:What does this do? And do you just call that procedure alone to protect your exe?
It's old useless antidebug trick which "patch" function address usually called by debuggers with 'ExitProcess' address :)
Post Reply