Category Archives: Tools

Gimmedebugah: how to embedded a Info.plist into arbitrary binaries

One of the changes introduced by Mountain Lion was the removal of the old procmod convention for applications that want to access the task port of a process (aka for reversers, debuggers). Before this change, any binary that was procmod suid group set could access the task port of other processes (running as the same user). Taskgated configuration in Mountain Lion was changed and removed this possibility. Only signed binaries that contain an embedded Info.plist with a SecTaskAccess key have this feature enabled by taskgated. By embedded I mean a new section that is added to the binary at compile time, with the compiler option “–sectcreate __TEXT __info_plist Info.plist”.

  sectname __info_plist
   segname __TEXT
      addr 0x0000000100240120
      size 0x000000000000026f
    offset 0x240120
     align 2^0 (1)
    reloff 0x0
    nreloc 0
     flags 0x00000000
 reserved1 0
 reserved2 0

This is true for single-file tools; application bundles have the Info.plist in the container and so the necessary key can be added there. Refer to this Apple document for additional information.

The problem arises when we want to do the same with a tool we only have the binary version. I wanted to work on a Python debugger and use the OS X supplied version, instead of compiling a new one and maybe dive directly into some kind of hell. And of course I didn’t want to modify taskgated configuration to support the old mode. So it was another opportunity to mess around with Mach-O headers.

The stupid thing is that after testing this with Python I discovered that it does not work with Python! The reason is that Python does have a bundle with a Info.plist we can modify. In Mountain Lion it is located at /System/Library/Frameworks/Python.framework/Versions/Current/Resources/ (you can use fs_usage | grep taskgated to find out the correct location). You just need to edit it, add the following key and re-codesign the bundle with your own certificate.


Anyway, we can always learn something “new”. Assume the target is a single-file tool. What happens is that taskgated will read the Mach-O header, and search for the __info_plist section. If that section exists, SecTaskAccess key has the right configuration, and binary is signed by a trusted certificate, then task_for_pid() will be enabled for that binary.

The easy solution is to add that new section into the binary and problem solved. There is a small detail where codesign does not like if we add the plist data at the end of the current binary. It will refuse to re-codesign the modified binary. My solution is to use the header space to also store the Info.plist data. If you recall this post, the section information is not taken in account when executing the binary. But this trick works because taskgated reads again the header and uses the section offset information to lookup the data location. In theory this data can be located anywhere in the binary as long it passes codesign “integrity” checks. Adding to the end of the binary fails, although it might be possible to work around it (already lost too much time in this tool). The caveat here is that you must always codesign the target binary (if it not already) before injecting the Info.plist. It is due to codesign_allocate header free space algorithm that will detect the data inside the header and lower offset.

The code implements two modes. The first one that I did was to add a duplicate __TEXT segment with the __info_plist section (do not ask me why I went the hard way, my brain has this kind of things!) and the other is to just add a new section to the existing __TEXT segment (I thought this would not work because the kernel loader and dyld would not like it – does work without any problem).

The tool is called gimmedebugah and as always code is available here. The README has some additional details.

Since Python has a Info.plist, my original goal is defeated. Maybe it can be handy for something else in the future. Or just another example of tricks to play with Mach-O headers. At least I got some new ideas ;-).



The “all” new Onyx The Black Cat!

Suffering from post-conference boredom I decided to redo Onyx The Black Cat kernel extension to kickstart again my brain and get back to serious work. There were also some people asking for an updated version so here it is!

This reworked version uses kernel control interface to enable/disable its features. It is much better than sysctl used before. It is also compatible with Snow Leopard, Lion, and Mountain Lion, and, hopefully, it should run without any problems in future versions. It uses the disassembler to locate the locations that need to be patched. That part of the code is not pretty but it works :-). The symbols are read from the /mach_kernel at disk to maintain compatibility with Snow Leopard and below.

It contains measures to bypass the PT_DENY_ATTACH, sysctl, and kauth anti-debug tricks. Also contains an option to reenable the possiblity of task_for_pid() the kernel task (useful for testing stuff and maybe forensics), and another to patch the CPU resume flag. For some (weird?) reason Apple clears up the resume flag from EFLAGS (if I am not mistaken, similar situation happens with Windows 98), making it impossible to use that single step feature when building your custom debuggers (very useful for quick single-stepping hacks).

Tested with Snow Leopard 10.6.8 (32/64 bits), Lion 10.7.5 (64 bits), and Mountain Lion 10.8.3 (64 bits).

Code is available at github.


NoSuchCon #1 debrief and slides

NoSuchCon is over and I am finally back home. It was a really great conference with great talks and a full room all the time (let me say I am very surprised about this). The only negative thing was the projection “wall” which was really bad and “killed” almost everyone’s slides. While I understand it is an historical building, that thing must be improved, either with a temporary solution or something else. Good architecture must also be functional else it is not fulfilling its goal. Anyway, awesome conference, congrats to the organizers for all their hard work, and attendees for their enthusiastic interest.

All the conference slides are available here.

My presentation was a reworked SyScan version about OS X rootkits. The DTrace fbt was replaced by the syscall provider and an attack to Volatility, and Little Snitch was removed. Even if it was a trimmed version I still took more time than allocated. I forgot to apologize at the time for that – I just like to give too much information. Sorry for that :-).

The DTrace syscall provider slides contain an old attack – sysent shadowing – against Volatility. I sort of presented it because I have some issues with the conclusion paragraph at this blog post. It is always easy to find what you know about but what you do not know is not always true, even when simple tricks are being used. Memory forensics is a good progress but we must be very careful with its assumptions. That is my goal with those slides, always question the assumptions – your own and tools. As a side note, Volafox is (was?) also vulnerable to the same trick.

Greetings to everyone I met and special greetings to Arnaud and David for the excellent company and wine, even if Benfica lost the UEFA final :-).

Now it is time to get back to work and writing. There is at least one book to write :-).

Have fun,


Hydra, the sample util I am unable to describe!

Let me give you a small gift before moving my ass to Paris to attend and present at NoSuchCon.

Hydra is sample code of a kernel extension that will intercept process creation, suspend, and  communicate it to a userland daemon that will be in charge of patching the application.

It uses the process hijacking technique I described at SyScan presentation. Instead of injecting a library it leaves the process in a suspended state and makes its PID available for the userland daemon. This daemon will be responsible for patching and resuming the process after.

Using this technique there is no need to resign a codesign protected application because it acts after those checks are done. This is true assuming that the application does not have any additional (internal) code checksum routines. Most don’t, barely any even check codesigning result (I wanted to patch Dash, which does check the signing certificate or something and I was too lazy to find where).

As most of my code, it aims to demonstrate “technology” and different ways to do things. It is not feature complete and if I’m not mistaken all the patching could be done from the kernel (right now I’m not sure if codesigning will be verified after the interception point or not, and it is boring to verify it now).

It is available here at github. The kernel extension is fully working, the userland daemon is just a crude example of how to implement it.

See you in Paris if are attending NoSuchCon. Feel free to meet me there!

Have fun,

There is an error in my SyScan slides!

Today I discovered that my slides contain a (stupid) error!
The story begins with Alex Ionescu telling me the symbols are still available in kernel memory in Mountain Lion. I quickly verified this by doing memory dumps and it was really true. Today I finally got some time to sort it out and verify where they were. To my great surprise I fucked up bigtime on my manual calculations and was dumping the wrong memory area (DUH!). I got even more annoyed when I verified that my sample source code has the right formulas! Unfortunately I deleted the computations file I had used for slides #9 and #10, which show memory dumps of the kernel symbol strings, so I could not replicate my original error. After a while I think I found some clues why I messed up…

Snare’s original post about solving kernel symbols uses the following formula: $string_table=$linkedit_address + ($symtab->stroff – $symtab->symoff). This works in Lion because the symbols offset starts at the beginning of __LINKEDIT. This changed in Mountain Lion so that formula is not true. Rubilyn uses the same formula. One assumption that propagated into my computations and led to this mistake. Ah, assumptions, they are so dangerous :-). I should know better because those slides were created a while after the sample rootkit code. More duh!

The correct formula where symbol strings are located is  __LINKEDIT address + Kernel ASLR + (LC_SYMTAB->stroffset – __LINKEDIT->fileoffset). These are the values from the kernel image at disk, except for kernel aslr slide.

What is the real impact of this mistake? Kernel symbols can be solved from a kernel extensions in Lion and Mountain Lion without using the disk image, but keep in mind that __LINKEDIT is marked as pageable. It still holds true that it is not possible for Snow Leopard and below. The number of Snow Leopard installations is still reasonable so the solution I presented is not totally useless (besides, it can be used for other fun stuff ;-)).

Oh well, failure is part of life and the design of our brains is not perfect. You can study and read tons of books about our design flaws and still fall “victim” at unexpected times. One good reason why I love the Human brain :-).



How to compile gdb in Mountain Lion (updated)

This is an up-to-date version of the old original post about recompiling gdb and other open source packages provided by I’m doing it mostly because code signing is now mandatory for gdb and there’s a stupid old bug that Apple still didn’t fixed since Snow Leopard. I forgot about it on my latest reinstall and lost an afternoon :-). This way you and me will not make the same mistake.

You should have XCode installed. Follow these steps:

1) Download darwinbuild from their SVN repository.
1.1) Since Snow Leopard there is a svn client by default so no need to download.
1.2) Follow the instructions on how to download,compile and install darwinbuild here. Use the guide for Snow Leopard/Lion version, it’s compatible with Mountain Lion.

2) Compile and install darwinbuild:

$ make ; sudo make install

3) Create the DMG file and initialize darwinbuild environment (you should use at least 2 gigabytes):

The plists and build numbers are available at Use build number 12A269 (it’s for 10.8.0 but works ok for all others).

$ hdiutil create -size 2G -type UDIF -fs HFSX -volname Builds -uid 0 -gid 0 -attach Builds.dmg
$ sudo sh
# vsdbutil -a /Volumes/Builds
# cd /Volumes/Builds
# mkdir Build12A269
# cd Build12A269
# darwinbuild -init 12A269 (you need Internet connection)
# darwinxref edit

In darwinxref edit you need to add the gdb package to the configuration. Go to the projects section and add the following:

gdb = {
version = 1822;

Default editor is VI. Save and quit. If you have a problem with an invalid property list, use the same tab alignment as the other entries. That should fix it.

4) Clone the gdb-ng repo from github if you want my patches included (you probably do!). Else skip to step 5) (darwinbuild will download the package from Apple opensource repo).

# cd /Volumes/Builds/Build12A269/Sources
# git clone git://
# cd gdb-ng
# bash
# mv gdb-1822.tar.gz .. (check version in case it changes)
# cd /Volumes/Builds/Build12A269

5) Compile gdb.

# darwinbuild -nochroot gdb

The -nosource option has been added to recent darwinbuild versions. This option will allow you to patch directly into BuildRoot/SourceCache/.
The first time you shouldn’t use this option so darwinbuild will download gdb package. After that you can use it if you want to patch directly gdb source files (that’s what I do with my gdb patches). It’s much easier and faster than having to patch and compress the whole gdb source. After you patch, you just issue “darwinbuild -nochroot -nosource gdb” and this will not unpack the original source but instead use whatever is at SourceCache.

Wait for the compilation to finish…

Go to Roots/gdb/gdb-1822.root*/usr/libexec/gdb. You should have a gdb-i386-apple-darwin. Backup the original and copy this one over.

# cp /usr/libexec/gdb/gdb-i386-apple-darwin /usr/libexec/gdb/gdb-i386-apple-darwin.orig
# cp gdb-i386-apple-darwin /usr/libexec/gdb/

The latest step is to codesign the binary. This is because taskgated default configuration has changed and it’s not anymore sufficient to have the binary suid to procmod group. It must have entitlements and be codesigned. The process is not just creating a self-signed certificate and codesign the binary with it. There is an old bug since Snow Leopard that complicates it a little bit. Follow this guide from LLDB code signing document. You can either code sign the binary you copied above to /usr/libexec/gdb or sign it at the Roots folder and copy the signed version.

Launch gdb and see if it works. It should ask you for your password the first time (after each reboot). If everything is ok you should be able to attach to or run the target process.

Now you can enjoy your next afternoon in case you want/have to compile gdb. You might also want to download and install gdbinit to improve gdb’s output and available commands.