Live data from Hacker News

The Ptrace Anti-RE Trick

hkopp.github.io

31–36 of 36 posts

Re: The Ptrace Anti-RE Trick

#32
post #29

We used to place an INT3 vectored exception handler on function entry points and do everything interesting inside the exception handler. This made the execution stack basically invisible to every debugger since it doesn't debug exception handlers. You can enable/disable interrupts and tracing and whatever you need to do inside the exception handler to guarantee that nobody can see what you are doing and/or verify tha…

A debugger sees exceptions before the application does, and it knows which exceptions it should handle by itself (e.g. breakpoints set by the user) vs passing them to the application. I don't have a windows machine rn to verify but I'd expect your assumption that it's impossible to debug an INT3 VEH to be incorrect.

Yes, however you can easily detect when a debugger is attached and avoid placing the VEH. There are only two mechanisms for a debugger to operate: by placing its own VEH (or UHE), or by populating one of the four hardware breakpoint registers, and both are very easy to detect.

Re: The Ptrace Anti-RE Trick

#33
post #7

I've seen this used preemptively - have the process ptrace itself on startup (and then do nothing with it) to make it impossible (or at least far-from-trivial) for other interested parties to ptrace it.

You can just patch the call then, right? I.e. turn it into NOPs

Yes. Or if it's using dynamic libraries and not compiled static, you can use LD_PRELOAD and overwrite ptrace() to do nothing. You don't have to patch anything then, which might be easier.

   int ptrace(int request, int pid, void *addr, void *data) {
       return 0;
   }
And compile it:

  gcc -shared myptrace.c -o myptrace.so
Afterwards you can eiher

  LD_PRELOAD=./mytrace.so ./thebinary     # shell
  ltrace -S -l ./mytrace.so ./thebinary   # strace in shell
or for gdb

  set environment LD_PRELOAD=./mytrace.so

Re: The Ptrace Anti-RE Trick

#34
post #29

Earlier quoted context omitted.

A debugger sees exceptions before the application does, and it knows which exceptions it should handle by itself (e.g. breakpoints set by the user) vs passing them to the application. I don't have a windows machine rn to verify but I'd expect your assumption that it's impossible to debug an INT3 VEH to be incorrect.

Yes, however you can easily detect when a debugger is attached and avoid placing the VEH. There are only two mechanisms for a debugger to operate: by placing its own VEH (or UHE), or by populating one of the four hardware breakpoint registers, and both are very easy to detect.

Sure there's a gazillion ways of detecting a debugger (specifically on windows), but then we are back to detecting debuggers. My point was that VEH (alone) doesn't prevent any sort of debugging, specifically not the VEH handler itself.

Btw, debuggers (on windows) won't usually install VEH to support BPs, they'll use the win32 debugger infrastructure where the OS manages exceptions and delivers them to the attached debugger object (which again can be detected in several ways). They also do not technically need HW bp registers, although often they will. A simple way to implement BPs is to write 0xCC (INT3) to the text section, then restore original bytes when the INT3 fires.

Re: The Ptrace Anti-RE Trick

#35
post #33

Earlier quoted context omitted.

You can just patch the call then, right? I.e. turn it into NOPs

Yes. Or if it's using dynamic libraries and not compiled static, you can use LD_PRELOAD and overwrite ptrace() to do nothing. You don't have to patch anything then, which might be easier. int ptrace(int request, int pid, void *addr, void *data) { return 0; } And compile it: gcc -shared myptrace.c -o myptrace.so Afterwards you can eiher LD_PRELOAD=./mytrace.so ./thebinary # shell ltrace -S -l ./mytrace.so ./thebinary…

Thanks, both! This was used in a static build that decrypted and checksummed its binary before execution, which ruled out naive implementations of the attacks above. I agree there are ways round these too, but I believe it was just intended to discourage amateurs rather than protect against serious hacking.

Re: The Ptrace Anti-RE Trick

#36
post #34

Earlier quoted context omitted.

Yes, however you can easily detect when a debugger is attached and avoid placing the VEH. There are only two mechanisms for a debugger to operate: by placing its own VEH (or UHE), or by populating one of the four hardware breakpoint registers, and both are very easy to detect.

Sure there's a gazillion ways of detecting a debugger (specifically on windows), but then we are back to detecting debuggers. My point was that VEH (alone) doesn't prevent any sort of debugging, specifically not the VEH handler itself. Btw, debuggers (on windows) won't usually install VEH to support BPs, they'll use the win32 debugger infrastructure where the OS manages exceptions and delivers them to the attached de…

I don't disagree that it's possible, just in my experience the debugger VEH was fired after my application's own VEH and not before it, so the debugger did not step into the VEH. And if you want to hide something from static analysis it's not a bad way, even if it is meta to "security through obscurity". The barrier to entry for implementation is pretty low, like ~50 LOCs so it's not going to be on the level of like state sponsored malware or something like that.
Post reply on HN