Tag Archives: gdb

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 opensource.apple.com. 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 http://svn.macosforge.org/repository/darwinbuild/trunk/plists/. 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://github.com/gdbinit/gdb-ng.git
# cd gdb-ng
# bash pack.sh
# 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.

fG!

How to compile GDB for iOS!

One obstacle that I faced long time ago and came again into spotlight is how to recompile gdb for iOS. It is not useful to fix the arm disassembler and then not be able to compile. As far as I know there isn’t any documentation available or an easy method to accomplish this – Saurik’s build environment is not public (?) and Apple sources do not compile directly. Darwinbuild project works great for OS X but it’s a question mark for iOS.

Darwinbuild it is! After some failed hacking last Friday (progress was great and it was near completation), I decided to try to fix the loose end today. Success was finally achieved.
This post contains almost all the information that you need to recompile gdb yourself. There is something that you will need to complete by trial & error. Let’s start the fun!

The reference post on darwinbuild usage is this one, written by yours truly. You should follow it and modify accordingly with the information provided here. My OS X version is still Snow Leopard but you should have no problems with Lion.
The image size should be 2GB, and you should use the build # 10K540. When you execute the “darwinxref edit”, use the following information:

environment = {
INSTALLED_PRODUCT_ASIDES = YES;
MACOSX_DEPLOYMENT_TARGET = 10.6;
NEXT_ROOT = "";
RC_ARCHS = "armv7 armv6";
RC_JASPER = YES;
RC_NONARCH_CFLAGS = "-pipe";
RC_OS = macos;
RC_PRIVATE = /private;
RC_RELEASE = SnowLeopard;
RC_TARGET_CONFIG = iphoneos;
RC_XBS = YES;
SEPARATE_STRIP = YES;
UNAME_RELEASE = 10.0;
UNAME_SYSNAME = Darwin;
};

Word of caution: be careful with copy & pasting this because of the “” (if you get an error while saving from darwinxref edit).

The next step is to edit the darwinbuild database. It’s located at “.build/xref.db”, inside the Build10K540 folder you should be located at. You need to change the gdb version to the latest one, 1708 instead of 1344. Execute the following sql statement to verify it:

SELECT * FROM properties WHERE project="gdb" AND property="version";

and then update the field:

UPDATE properties SET VALUE="1708" WHERE project="gdb" AND property="version";

Start compilation with “darwinbuild -nochroot gdb”. Version 1708 will be downloaded. When configuration/compilation starts, abort it with ctrl-c.
You will need to create a link (there is probably a more elegant solution to this!). Go to the usr/lib folder inside the iOS SDK. There you need to make a link from “crt1.10.6.o” to “crt1.o”.  Small example from my system:

lrwxr-xr-x  1 root  wheel     6 Apr 14 04:12 /Developer4/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/usr/lib/crt1.10.6.o -> crt1.o
-rw-r–r–  1 root  wheel  2720 Aug 30  2011 /Developer4/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/usr/lib/crt1.3.1.o
-rw-r–r–  1 root  wheel  4584 Aug 30  2011 /Developer4/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/usr/lib/crt1.o

Next step is to modify the file “BuildRoot/SourceCache/gdb/gdb-1708/src/gdb/macosx/macosx.defs”. Here you need to replace the import for exc.defs. Change:

#import

to:

#import "/Developer4/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/usr/include/mach/exc.defs"

(modify your path accordingly)

Last step for now is to modify the Makefile. We need to modify it so the ARM cross-compiling tools are used. It’s located at BuildRoot/SourceCache/gdb/gdb-1708/Makefile. To make it easier, you have my Makefile as a reference (all files at the end). I left the places that you need to modify tagged with FIXME. Your task is to change the paths.

Now you are ready to compile and start the trial and error process. This time, compile with “darwinbuild -nochroot -nosource gdb”. This will not unpack again the source package and will keep our previous changes.
The compilation process will start and hopefully you will observe lots of output, which is a good sign! Near completation, errors regarding missing includes will start to appear. Your task is to manually copy them from OS X “/usr/include” to the iOS SDK “usr/include” folder (in my case /Developer4/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/usr/include/). The only modifications that you will need to do are to edit some files and change the import location to relative paths (or absolute if you prefer). Not elegant, but it works! When you reach the missing architecture includes, you can use the ones from i386. Sorry for not having a complete file list – I was hacking this without great hope that it would work heheheh.

And that’s it! After you fix the missing includes and defs, the compile should successfully finish and you have your shiny recompile gdb. You can also apply my gdb patches (recommended!). Before starting to compile everything, just go to the SourceCache folder, apply the patch and compile.
Follow the steps from the reference post to copy the compiled binary, apply the necessary entitlements (reference), upload to your device and enjoy 🙂

If you don’t feel adventurous enough then I include a fat binary (armv6 and armv7) with my patches. You just need to add the entitlements.
Pancake (from Radare) created a package for this version. Add http://cydia.radare.org to your repo list and install it from there. Thanks to pancake for his work 🙂

Any question or problem you run into leave a comment so everyone else can benefit from the (potential) solution.

Have fun,
fG!

Makefile.gz

gdb-arm-apple-darwin.gz

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
 
SHA256(Makefile.gz)= 9aa69bc9b5a77a682c5bc74435440f26e839c0b216861f64a1af4f5a6432dfaf
SHA256(gdb-arm-apple-darwin.gz)= 7c3744c1be024a28c594c0ad90d75f0d187c5e53d9cb09d0183bba19b7415e6d
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
Comment: GPGTools - http://gpgtools.org
 
iQEcBAEBAgAGBQJPkTVwAAoJEAADGo6F9Uj36RUIAJF5E3Ak7d/q6MR0tNPMIoKy
/v9lEkt9bBr0QBo/GHj0bEkcVKp58Ft3y2yE14qkk7BpxHYGalvzTLNGy9uk3TRL
xprJpwKxttpms14+N+tNKBEKu3g5iItMbyWiip60UWbhYMlmXpKQFOMxJeHQIYLy
88KlbqEfiztil4UY04q/CUjxFfV38lvQCosgjDJ2XHHMrsJNvxfLslEkMTxOrbS5
C64TNQ3lj7SWvVBgAQ9OkjrWqNcPJyULth9ScKEixhWNHzcjZmIxP9+9PmrfviAn
rckSlEVhNDtOf9tsDfBaMM2STmPG5unuhaMR2vda+VVAtNOHZ+KO1MY6k6y+Zfk=
=jUdm
-----END PGP SIGNATURE-----

Update: List of added/modified include files (I forgot about the power of find :X)
./_locale.h
./libproc.h
./mach/arm/machine_types.defs
./mach/exc.defs
./mach/mach_types.defs
./mach/mach_vm.h
./mach/machine/machine_types.defs
./mach/machine/thread_state.h
./mach/std_types.defs
./ncurses_dll.h
./net/route.h
./sgtty.h
./sys/dir.h
./sys/ioctl_compat.h
./sys/kern_control.h
./sys/proc_info.h
./sys/ptrace.h
./sys/ttychars.h
./sys/ttydev.h
./termcap.h

Gdbinit v8.0: simultaneous support for x86/x86_64 and ARM architectures!

Here it is, a merge between the x86 and ARM versions of gdbinit. The only inconvenience is that you need to manually change the target, using the “32bits” and “64bits” commands for x86/x86_64 architectures, and “arm” for ARM. That’s a small price to pay for 🙂

This version features a lot of cosmetic fixes (indentation mostly) but also some fixes to the ARM related code, and a new command – dumpmacho. This command will dump the Mach-O header to a file. You need to supply the start address and the output filename. Only the header information is dumped – sometimes I need to dump the header and load it into otool or machoview to verify some things. Just a command to automate things!

The next step is to try to compile a new iOS gdb version that features my fixes. I think I will do another attempt to add the armv7 instructions to gdb so it’s not a major pain to debug these binaries. Let’s see if I can succeed this time.

There’s no test suite for gdbinit (<xxxxxxxx> testing is for chumps) ! From my tests everything is working, if not leave a msg here or at github.

Enjoy,
fG!

gdbinit8.gz
SHA256(gdbinit)= fb510d812dabbad968e68ad1e4916aa85400d6375e0e404f5893946151420238

Anti-debug trick #1: Abusing Mach-O to crash GDB

I developed this funny trick while trying to find a solution for a problem in a freelance project. It is pretty easy to implement and fun 🙂

The trick consists in abusing the offset field in the dylib_command and pointing it to somewhere else. From the Mach-O File Format Reference, the command structures are:

struct dylib_command              struct dylib                            union lc_str
{                                 {                                       {
 uint_32 cmd;                      union lc_str name;                      uint32_t offset;
 uint_32 cmdsize;                  uint_32 timestamp;                      #ifndef __LP64__
 struct dylib dylib;               uint_32 current_version;                char *ptr;
}                                  uint_32 compatibility_version;          #endif
                                  }                                       }

The definition of the offset field is:
“A long integer. A byte offset from the start of the load command that contains this string to the start of the string data.”

Usually this field is always 0x18 (24 bytes). This means that the library name string is located after the dylib_command command, whose size is 24 bytes. Right now your evil brain should be interpreting that definition as “an offset (anywhere) that contains the start of the string data“. If not, don’t worry, evilness takes practice 🙂

What happens if you put the string somewhere else and change the offset to point there? GDB crashes, otool can’t recognize the offset and so on.

Otool:

Load command 20
          cmd LC_LOAD_DYLIB
      cmdsize 88
         name ?(bad offset 28548)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 30.0.0
compatibility version 1.0.0

GDB:

GNU gdb 6.3.50-20050815 (Apple version gdb-1344 + reverse.put.as patches v0.3) (Mon Aug 22 00:31:56 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin"...gdb-i386-apple-darwin(68831) malloc: *** mmap(size=18446744073709506560) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug

Fun stuff, right ? 🙂
The problem with the debugger attach is that I assumed gdb would also crash if attached and forgot to try if it was true. It is a minor problem – the crackme is designed to resist a debugger attach.

The next trick is even more fun but requires some time to write the post. I didn’t took all the notes and I need to “rediscover” it to show you where the problem is.

Enjoy,
fG!

Gdbinit v7.4.4 – the skip command

Here is a small update to gdbinit with a new command, “skip”.
This command will skip over the current instruction, without executing it. Usually I do it manually by set $pc=newvalue but this involves copy&paste and mouse movements and gets boring after a while. It’s great to skip over calls while you are trying some stuff and analysing some program behavior.
By default it will not execute the command at the new address. You can change this by modifying the configuration variable on top of gdbinit.

This command uses a little hack that Hopper’s author told me – the $_ variable will hold the last address, so we can disassemble 2 lines and compute the difference to retrieve the instruction size. Gdb has no command to retrieve the instruction size at a given address.
I did some (incomplete) work to add a new command for this. Being an economist, I can’t avoid this dilemma – to invest or not (more) time into gdb. Gdb source is a boring mess and LLDB is improving. I am thinking to try to create an initial LLDB port of gdbinit. This should allow me to understand its true potential as reversing debugger and take a decision where to invest time & resources.

Have fun,
fG!

gdbinit744.gz
SHA256(gdbinit744.gz)= 2b223998571069f00edebd606d055c5b370ede5a8cb2b2fe69093c310e32c547

How gdb disables ASLR in Mac OS X Lion

This isn’t a rocket science post but more like some notes for future reference 🙂
Lion finally introduces full ASLR and gdb has the possibility to disable that feature when analyzing target binaries. A new gdb setting was added, “disable-aslr”, which allows to enable or disable this feature.

By default this feature appears to be enabled (I am just looking at gdb source code) and it’s set by the variable “disable_aslr_flag” configured at gdb/macosx/macosx-tdep.c source file. But this isn’t the place where the magic happens. That is located in gdb/fork-child.c file (well there’s a second version at macosx/macosx-nat-inferior.c).
A very rough draft of gdb workflow is something like this:

  1. Fork
  2. If we are the child process, drop privileges
  3. If we are the child process, use ptrace to “stop” the new process
  4. Exec the target
  5. Use again ptrace to resume the child
  6. Wait for breakpoint events

Step 4 in Apple’s gdb version tries to use posix_spawn instead of exec (or any of its variants) to launch the target. This allows to set some special attributes in the new process. One of the new attributes in Lion is “_POSIX_SPAWN_DISABLE_ASLR”. The name should be explicit about its purpose 🙂

The piece of code that sets it in gdb/fork-child.c is:

(...)
            if (disable_aslr_flag)
              ps_flags |= _POSIX_SPAWN_DISABLE_ASLR;
            retval = posix_spawnattr_setflags(&attr, ps_flags);
(...)

If posix_spawn fails gdb will then try to execvp the target. At the kernel side, this is dealt with in “posix_spawn()” at “bsd/kern/kern_exec.c”:

(...)
                /*
                 * Disable ASLR for the spawned process.
                 */
                if (px_sa.psa_flags & _POSIX_SPAWN_DISABLE_ASLR)
                        OSBitOrAtomic(P_DISABLE_ASLR, &p->p_flag);
                /*
                 * Forcibly disallow execution from data pages for the spawned process
                 * even if it would otherwise be permitted by the architecture default.
                 */
                if (px_sa.psa_flags & _POSIX_SPAWN_ALLOW_DATA_EXEC)
                        imgp->ip_flags |= IMGPF_ALLOW_DATA_EXEC;
        }
 
        /*
         * Disable ASLR during image activation.  This occurs either if the
         * _POSIX_SPAWN_DISABLE_ASLR attribute was found above or if
         * P_DISABLE_ASLR was inherited from the parent process.
         */
        if (p->p_flag & P_DISABLE_ASLR)
                imgp->ip_flags |= IMGPF_DISABLE_ASLR;

And that’s it! A new flag added, processes spawned with that flag active and bye bye ASLR 😉
Enjoy,
fG!