4

Long time ago I noticed that using

set follow-fork-mode child

in GDB on FreeBSD doesn't really work. This problem occurs very often with some challenges on various Capture The Flag contests. For example, a server will spawn a child which would handle the connection. The child code has a vulnerability which I would like to debug, but gdb just never follows the childs execution and I can't really observe the vulnerability being triggered.

So far, I've solved this problem in two ways:

  1. Making a connection, waiting for a child to spawn and than attaching GDB to it.

    This works since the spawned child has it's own PID to which I can attach, but is rather painful since first I have to make a connection from one session, attach with GDB in another, and then send the payload/continue the connection in the first.

  2. Patching the binary after the fork call to continue the execution in the parent process instead of the child.

    This is also painful since then I have to restart the whole parent process to create another debugging session.

There are some other tricks that can be employed, but these are enough to illustrate my point.

Now I know there have been some limitations on FreeBSD in the past regarding this but has anything improved?

Is there any way to patch GDB to add this functionality? Any suggestions for an easier way of overcoming this?

2
  • On my Linux box I have to set follow-fork-mode child but also catch fork inorder to make GDB stop on the fork call and follow the child.
    – dna
    Jun 12, 2013 at 19:54
  • on linux it's fine, bsd has the problem with follow-fork-mode... and it seems it's still there...
    – 0xea
    Jun 17, 2013 at 10:40

2 Answers 2

5

Try to set a catchpoint on fork if you are want to both the parent and the child.

set-follow-fork-mode ask 
catch fork 

Concerning your second point, I have this macro in my .gdbinit (I believe ultimately originating from Tavis Ormandy). It is imminently useful in many cases, your own included.

define assemble
 # dont enter routine again if user hits enter
 dont-repeat
 if ($argc)
  if (*$arg0 = *$arg0)
    # check if we have a valid address by dereferencing it,
    # if we havnt, this will cause the routine to exit.
  end
  printf "Instructions will be written to %#x.\n", $arg0
 else
  printf "Instructions will be written to stdout.\n"
 end
 printf "Type instructions, one per line.\n"
 printf "End with a line saying just \"end\".\n"
 if ($argc)
  # argument specified, assemble instructions into memory
  # at address specified.
  shell nasm -f bin -o /dev/stdout /dev/stdin \
    <<< "$( echo "BITS 32"; while read -ep '>' r && test "$r" != end; \
                do echo -E "$r"; done )" | hexdump -ve \
        '1/1 "set *((unsigned char *) $arg0 + %#2_ax) = %#02x\n"' \
            > ~/.gdbassemble
  # load the file containing set instructions
  source ~/.gdbassemble
  # all done.
  shell rm -f ~/.gdbassemble
 else
  # no argument, assemble instructions to stdout
  shell nasm -f bin -o /dev/stdout /dev/stdin \
    <<< "$( echo "BITS 32"; while read -ep '>' r && test "$r" != end; \
                do echo -E "$r"; done )" | ndisasm -i -b32 /dev/stdin
 end
end
document assemble
Assemble instructions using nasm.
Type a line containing "end" to indicate the end.
If an address is specified, insert instructions at that address.
If no address is specified, assembled instructions are printed to stdout.
Use the pseudo instruction "org ADDR" to set the base address.
end
3
  • Nice macro, I definitely gonna use it! Huh it's zsh unfriendly :p
    – dna
    Jun 15, 2013 at 9:38
  • For zsh read -ep '>' r should be replaced by read r
    – dna
    Jun 15, 2013 at 10:43
  • accepted the answer because of that nice macro and it helps a lot:) especially since there is no real solution (at least i haven't found one yet, see my answer), the problem is that follow-fork-mode doesn't work on bsd, and that hasn't been fixed yet...
    – 0xea
    Jun 17, 2013 at 10:59
0

I was digging a bit into this, and found this question on SO by mrduclaw (link in the original article is dead, but web archive has it). He has the exact same problem like I do, and exactly the same motivation for finding a solution.

So I was digging around some more and it turns out freebsd until recently didn't have support for forks in it's ptrace. There was a patch submitted but I can't really figure out if it's applied. Will try to apply it myself and see if it will start working then.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.