Question

An old and well known technique for preventing executable from being debugged on OS X is to use the following call to ptrace to deny debuggers from attaching themselves to an executable.

ptrace(PT_DENY_ATTACH, 0, 0, 0);

Attempting to run an executable with this code in GDB would result in the GDB quitting with the response of [Inferior 1 (process #) exited with code 055]. Getting around this was as simple as using loading the executable into gdb, and setting a breakpoint on ptrace with b ptrace and entering y when asked Make breakpoint pending on future shared library load? (y or [n]). Unfortunately, when the executable runs, this breakpoint is never set and it exits without continuing.

Here is how to reproduce the problem.

  1. Install Xcode 5 with command line tools.
  2. Install GDB through Homebrew (brew install https://raw.github.com/Homebrew/homebrew-dupes/master/gdb.rb), code sign the executable (http://sourceware.org/gdb/wiki/BuildingOnDarwin), and reboot (restarting taskgated did not seem to work).
  3. Compile the following C program ptrace.c, compile using gcc -o ptrace ptrace.c

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/ptrace.h>
    
    int main()
    {
    ptrace(PT_DENY_ATTACH, 0, 0, 0);
    printf("Hello, World!\n");
    }
    
  4. From the directory with the compiled executable, follow along with the following.

    $ gdb ptrace
    ...
    (gdb) b ptrace
    Function "ptrace" not defined.
    Make breakpoint pending on future shared library load? (y or [n]) y
    
    Breakpoint 1 (ptrace) pending.
    (gdb) r
    Starting program: .../ptrace
    [Inferior 1 (process #) exited with code 055]
    

After further testing, the same is true for other functions that are not part of the executable, such as printf. I have scoured the internet and have not been able to find anything to suggest the above may not work. I'm open to pretty much any solution using gdb or lldb and would also appreciate any documentation as to what the issue may be.

Was it helpful?

Solution

UPDATE: GDB 7.8 is now available through Homebrew and it can resolve at least some symbols now. There are some warnings, but it seems to work now. Fat executables are not supported however.

It turns out that the GDB available through Homebrew is the official GDB which is different from the Apple GDB that was available in previous versions of Xcode. The official GDB cannot resolve the symbols to the system libraries, thus causing the issues in the question. Copying over the Apple GDB from a previous install is a possibility as it contains Apple's modifications, however it is a much older version that the official GDB, and will produce many warning when first loading an executable on OS X 10.9 Mavericks (seems to otherwise work fine for now though).

It is unlikely Apple will be continuing GDB development, so until GDB fixes this issue, using LLDB seems to be the better solution. Here is an example.

$ lldb ptrace
(lldb) b ptrace
(lldb) r

And the breakpoint will stop execution at ptrace.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top