From Paul's Security Weekly
Jump to: navigation, search
Palo Alto Networks
Tenable Network Security
The SANS Institute
Pwnie Express
Black Hills Information Security


PaulDotCom Security Weekly - Episode 226 - for Thursday January 13th, 2011.

Episode Media

MP3 pt 1

MP3 pt 2

Guest Interview with Scott Ullrich & Warren Baker of the pfsense firewall project

Scott is the co-founder/developer/hackathon organizer for pfSense. He is also a FreeBSD Fan, BSD License lover, RC Plane hobbyist, and most importantly, a fan of Stargate.

Warren Baker is avid user of FreeBSD and runs his own 2 man company. He is also author of the pfSense unbound package.

Project Background

pfSense is a free, open source customized distribution of FreeBSD tailored for use as a firewall and router. The project includes a package system allowing further expandability without adding bloat and potential security vulnerabilities to the base distribution. pfSense is a popular project with more than 1 million downloads since its inception, and proven in countless installations ranging from small home networks protecting a PC and an Xbox to large corporations, universities and other organizations protecting thousands of network devices.

The project started in 2004 as a fork of the m0n0wall project, but focused towards full PC installations rather than the embedded hardware focus of m0n0wall.


  1. How did you get your start in computers/information security?
  2. I've experienced that FreeBSD has a very solid IP stack, in terms of security and performance, why do you think this is the case?
  3. How did the idea for pfSense come about?
  4. We talk a lot on the show about firewalls, what is it about firewalls that have kept them as a mainstay for security? Do they create a false sense of security?
  5. What are some things about pfSense that make it a better choice for firewalls than other open-source or commercial products?
  6. What are some of the coolest features of pfSense?
  7. Tell us about the add-ons, how are they created and what are some examples?
  8. What's new/different in 2.0?
  9. Compared with other opensource projects, how well is pfSense documented?
  10. Any advice or gotchas on using pfSense 2.0 as a VPN endpoint for "road warriors"

Guest Tech Segment: Eric Monti on iPhone Application Reversing and Rootkits

Eric Monti is a Senior Security Researcher at Trustwave's SpiderLabs. He has over 12 years experience in the security industry team focused on security tools development, vulnerability research and detection, malware analysis, and reverse engineering.

What if jailbreak techniques were instead used for malicious purposes?

In this technical segment he'll explain how he reverse engineered jailbreaks to develop exploits, deliver malicious payloads, and create a propagating (wormlike) process for installing malicious rootkits on every iOS device that Apple makes. He'll also demonstrate a proof of concept attack in which he roots one or more iOS devices stealthily without letting the user know.

You can catch some information on

Eric's Write-up

At the Toorcon and Ekoparty conferences late last year I gave a presentation on iPhone rootkit techniques. At a high level, both presentations focused specifically on the jailbreakme.com exploit released at the end of August 2010, but also discussed several approaches to mobile rootkits, specifically focusing on the iOS operating system. Some of the techniques I discussed or at least made reference to included:

  1. Kernel layer rootkits: Usually entails identifying the location of the kernel syscall "sysent" table and modifying function pointers in memory to add subversive hooks in the kernel to control various aspects of the system behavior.
  2. Userland layer rootkits: Typically involves replacing and/or adding system binaries to add backdoors, hide processes, etc. In some cases can often also incorporate library injection techniques to avoid having to change any files in an obvious manner.
  3. Application layer rootkits: Basically userland rootkits but for a specifically targetted application (often 3rd party, not part of the operating system).

I covered specific information in my presentation on implementing application-centric rootkits. This included techniques for reversing iTunes App Store applications. The techniques can then be used to find suitable locations for hooking application logic and use this information to develop drop-in libraries which can be injected into applications. In my presentation at toorcon, I demonstrated an application rootkit targetting an iPhone credit-card payment application called Square. This specific application is really cool, and I picked it only because it presented a "juicy" target to play with (plus it was a free download). The Square application itself is no more or less secure than many other iOS applications.

The same techniques I used for this research can be applied to other apps in the Apple App Store. But, forty minutes on stage is not an ideal venue to cover detailed technical information, so I'd like to take the opportunity of writing this article for PaulDotCom to provide additional details on how all of this worked in my research.

Reversing App Store Binaries

Some reversing of iOS apps is often a required first step if the intent is to identify opportunities for runtime hooking or researching iOS application security. The primary obstacle to overcome in reversing iOS binaries from the App Store is that all published applications are encrypted using Apple's binary encryption scheme. Decrypting this format is not a new technique, but it's good to understand how it works. Aside from researching and experimenting with rootkits, this is also an invaluable technique to understand when auditing the security of 3rd party iPhone applications.

A few important things to note before going any further:

  1. This guide is probably more useful to security researchers reversing apps for security auditing purposes than malware authors.
  2. If you are looking for an actual rootkit or evil injectable library code in this article, look elsewhere. The demonstration example here is completely benign by design.
  3. I am _not_ advocating cracking 3rd party applications to bypass DRM or avoid paying for software in any way. The purpose of my research has never been to steal hard work from others, but to validate and verify the security of my iPhone. Software and DRM cracking and is an interesting and valuable computer security science, but when applied in practice it's a just crappy thing to do to authors and other developers. Don't be a jerk!
  4. Similarly, I am _not_ advocating the development of iPhone rootkits, but I hope that in researching, discussing, and publishing information about this topic, it will help protect against them.

That said, onto the actual important things to note:

  1. To follow along, you will need access to an iOS device and either the Apple iOS SDK or 3rd the party OpenSource iPhone development toolchain. For research purposes, you'll want to jailbreak the iDevice and install an ssh server as well.
  2. Regardless which SDK you use, it's priobably easier to have a OS X box (or Linux box in the case of the opensource toolchain).
  3. Finally, this comes up a lot so: the iPhone emulator is of little use when reversing 3rd party apps. It actually runs intel code compiled specifically to target the emulator in your xcode projects. It won't work with binaries downloaded from the Apple App Store since those are for an arm architecture. It's certainly a neat peice of software, but save yourself the time and trouble and skip this for reversing apps. Others have tried and failed already so you don't have to.

A pretty well established process exists for decrypting encrypted iOS app store binaries, and involves dumping the code and data sections of the binary out of memory on the device after they've been decrypted. This is done at runtime using a debugger, usually gdb. Not surprisingly, this process requires a jailbroken iDevice. Several pre-packaged utilities have been published for iOS to automate this process, but it helps to understand what is going on under their hood when reseaching app security issues. An excellent article by Pedram Amini was written circa 2009 for the DVlabs security blog describing how this process works. Although Mr Amini's article is extremely clear and well written, I will revisit the binary decryption process here and hopefully provide a bit more context as well as focus on additional details specific to reversing Objective-C code.

First, we need to download an application and find it on our phone. For this example we're just going to use Just Light Flashlight, a very simple app. All it does is turn an iPhone or iPod Touch screen all white at full brightness so that you can use it like a flashlight. We really can't do anything actually sneaky with Just Light. The most we can probably shoot for is mildly annoying. That said, is perfect for experimenting with since it is free and it is a really basic Objective-C program to start reversing on.

Getting Around the Device and First Looks

Once we have the application on our device, we should find the directory where the binary was installed. Each downloaded application gets stored in the /var/mobile/Applications directory on the device in a subdirectory named with a UUID. Lets SSH to the device and cd into that directory. Note the UUID below will be different on your device:

myMac:/var/mobile root# cd /var/mobile/Applications/*/Just\ Light*.app
myMac:/var/mobile root# pwd
/var/mobile/Applications/0276A138-F954-5E1B-A982-24CDA2A9153D/Just Light.app

Once in the app directory, we are basically inside the application bundle containing all the files downloaded in the application package.

iPhone root# ls -l
total 80
lrwxr-xr-x 1 mobile mobile    28 Oct 13 16:49 CodeResources -> _CodeSignature/CodeResources
-rw-r--r-- 1 mobile mobile   625 Oct 13 16:49 Info.plist
-rwxr-xr-x 1 mobile mobile 20064 Oct 13 16:49 Just\ Light*
-rw-r--r-- 1 mobile mobile  1310 Oct 13 16:49 MainWindow.nib
-rw-r--r-- 1 mobile mobile     8 Oct 13 16:49 PkgInfo
-rw-r--r-- 1 mobile mobile   218 Oct 13 16:49 ResourceRules.plist
drwxr-xr-x 2 mobile mobile   136 Oct 13 16:49 SC_Info/
drwxr-xr-x 2 mobile mobile   102 Oct 13 16:49 _CodeSignature/
-rw-r--r-- 1 mobile mobile  3771 Oct 13 16:49 icon.png

You'll probably want to go ahead and copy this directory structure recursively onto the workstation or other system you'll be doing your reversing from right away. We still have some more work to do on the iDevice too, though so stay logged in. You'll notice I'm bouncing a lot between my mac and my iPhone in the examples that follow but I'll try to include pointers for how to do each bit on either whenever possible.

One directory up from the *.app dir is the sandbox in which the application runs and may include additional data we might care about at runtime. We won't really be concerned with data for this example, but you probably want to be aware of this for real-world cases. It is very common to find sqlite db's and other interesting files laying around in these sandbox directories, so definitely look around when you're doing this in the real world.

Lets just glance up at it to get our bearings:

root# ls ..
Documents/  Just\ Light.app/  Library/  iTunesArtwork  iTunesMetadata.plist  tmp/

The file we primarily care about is the executable "Just Light". However, in some cases, it may useful to view the NIB files for the application. The NIBs are where xcode compiles UI information for Cocoa applications. In this case there is only MainWindow.nib (which most apps will also likely have). A NIB file is actually a binary encoded plist file. We can get a human readable version of it with a tool called 'plutil' (provided with OS X, conveniently re-implemented on iOS in the Erica Sadun utilities from Cydia) Convert it to XML plist format like so:

iPhone root# cp MainWindow.nib MainWindow.plist
iPhone root# plutil -convert xml1 MainWindow.plist
Converted 1 files to XML format
iPhone root# head MainWindow.plist 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

There's not much to the UI in this application, but you can sometimes make use of this extra info in real-world reversing sessions. Lets move onto the binary.

If we load "Just Light" into IDA or any other static reversing tool right now, it won't be much use to us. All the interesting stuff is encrypted. To illustrate this, lets run this through a tool called class-dump which we'll revisit later. Suffice to say that class-dump should give us extensive info on Objective-C classes stored in the executable, but right now it doesn't work on the encrypted data:

myMac:Just Light.app emonti$ class-dump Just\ Light 
 *     Generated by class-dump 3.3.2 (64 bit).
 *     class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2010 by Steve Nygard.

#pragma mark -

 * File: Just Light
 * Arch: arm v6 (armv6)
 *       Objective-C Garbage Collection: Unsupported
 *       This file is encrypted:
 *           cryptid: 0x00000001, cryptoff: 0x00001000, cryptsize: 0x00001000

There are a few things that we can do with the file right now, though. Particularly, we can inspect the Mach-O headers with the otool and view a symbol table with nm. As with many things, Apple doesn't provide an otool and nm for iOS, but they are available the Cydia package odcctools. Note that many of the OS X command-line tools provided with xcode will work on iOS binaries as well. You may also want to compile a gnu binutils package to support mach-o and arm architectures on your workstation.

You may have used otool before to do ldd-style library listings, but that's just part of what it can do for us.

myMac:Just Light.app emonti$ otool -L Just\ Light 
Just Light:
        /System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 678.29.0)
        /System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 752.0.0)
        /System/Library/Frameworks/CoreGraphics.framework/CoreGraphics (compatibility version 64.0.0, current version 359.13.2)
        /usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.0.10)
        /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0)
        /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 478.29.0)

The symbol table isn't always very verbose, but in this case it contains some rather interesting info as well. We can dump it with 'nm':

myMac:Just Light.app emonti$ nm Just\ Light 
000020b8 t -[Just_LightAppDelegate applicationDidFinishLaunching:]
000020f8 t -[Just_LightAppDelegate dealloc]
00002140 t -[Just_LightAppDelegate setWindow:]
00002134 t -[Just_LightAppDelegate window]
00003014 D _NXArgc
00003010 D _NXArgv
000031f0 d _OBJC_CLASS_$_Just_LightAppDelegate
         U _OBJC_CLASS_$_NSAutoreleasePool
         U _OBJC_CLASS_$_NSObject
         U _OBJC_CLASS_$_UIApplication
000031ec d _OBJC_IVAR_$_Just_LightAppDelegate.window
0000322c d _OBJC_METACLASS_$_Just_LightAppDelegate
         U _OBJC_METACLASS_$_NSObject
         U _UIApplicationMain
00003008 D ___progname
00001000 A __mh_execute_header
         U __objc_empty_cache
         U __objc_empty_vtable
0000300c D _environ
         U _exit
0000206c t _main
         U _objc_msgSend
         U _objc_msgSendSuper2
         U _objc_setProperty
00003018 d dyld__mach_header
0000204c t dyld_stub_binding_helper
00002000 T start

From 'otool -L' we see that the application hooks several Objective-C frameworks. And 'nm' gave us some tell-tale objective-C information. While this doesn't guarantee that the core is written in Objective-C, it is still encouraging. It's worth pointing out that otool can even dump Objective-C information similar to what class-dump does with 'otool -o'. But if you try it now you'll see that it gives us what might be class metadata, except that the info is not very useful because it refers to strings and other info "from a protected section".

#       -o     Display the contents of the __OBJC segment used by the Objective-C run-time system.

myMac:Just Light.app emonti$ otool -o Just\ Light 
Just Light:
Contents of (__DATA,__objc_classlist) section
00003324 0x31f0
           isa 0x322c
    superclass 0x0
         cache 0x0
        vtable 0x0
          data 0x3204 (struct class_ro_t *)
                    flags 0x10
            instanceStart 4
             instanceSize 8
               ivarLayout 0x0
                     name 0x25c4 some string from a protected section
              baseMethods 0x3280 (struct method_list_t *)
                   entsize 12
                     count 4
                      name 0x22d0 some string from a protected section

So, we already see there are some structures and symbol information exposed in our encrypted binary, but it is far from a complete picture. After decryption we'll see the __OBJC section provides much more useful info.

Before we go into further reversing, we need to understand a little about some distinctions between Mach-O and FAT files on darwin. "Just Light" happens to be a Mach-O binary without a FAT header. The FAT file format is how Apple is able to bundle what they call "universal binaries" as a single file and contains more than one mach section. Each Mach-O section (generally speaking) contains a seperate copy of the executable code for the architecture it has been compiled for. You'd think that since iOS is arm, there would only ever be one architecture, but this is not true with newer binaries. You will likely run into newer programs that are FAT files containing armv6 and armv7 code together. I don't happen to have any, but older binaries may even include armv4 or armv5

My preferred quick/dirty way to inspect files is using the file(1) command. Using otool gives us a bit more information.

myMac:Just Light.app emonti$ file Just\ Light 
Just Light: Mach-O executable arm

myMac:Just Light.app emonti$ otool -h Just\ Light 
Just Light:
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedface      12          6  0x00          2    18       1880 0x00000085

myMac:Just Light.app emonti$ otool -f Just\ Light
# ... nada

We can see Just Light is a Mach-O arm executable and otool identified Mach-O header fields as "cputype 12 / subtype 6" which is armv6. There is no FAT header (as illustrated with otool -f)

By contrast, lets look at a newer, FAT executable from iOS. I'll use iBooks for this example since I happen to have it laying around. If you want to follow along, you can grab a copy from the app store for free. This one is published by Apple, and since it's on the App store, it's also encrypted.

myMac:Just Light.app emonti$ file ../iBooks.app/iBooks 
../iBooks.app/iBooks: Mach-O universal binary with 2 architectures
../iBooks.app/iBooks (for architecture armv6):        Mach-O executable arm
../iBooks.app/iBooks (for architecture armv7):        Mach-O executable arm

myMac:Just Light.app emonti$ otool -h ../iBooks.app/iBooks 
../iBooks.app/iBooks (architecture armv6):
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedface      12          6  0x00          2    41       4640 0x00000085
../iBooks.app/iBooks (architecture armv7):
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedface      12          9  0x00          2    41       4640 0x00000085

myMac:Just Light.app emonti$ otool -f ../iBooks.app/iBooks 
Fat headers
fat_magic 0xcafebabe
nfat_arch 2
architecture 0
    cputype 12
    cpusubtype 6
    capabilities 0x0
    offset 4096
    size 2424704
    align 2^12 (4096)
architecture 1
    cputype 12
    cpusubtype 9
    capabilities 0x0
    offset 2428928
    size 1996640
    align 2^12 (4096)

We see that iBooks contains Mach-O sections for multiple architectures, and the file type is a "universal binary" (aka FAT). The architectures contained are armv6(cputype 12/subtype 6) and armv7(cputype 12/subtype 9). The otool -f command now shows us information on the FAT header as well. For more info on darwin's architecture system see arch(3).

Thinning Mach-O Binaries for Reversing

The reason we care about the architecture and binary format is to focus on one in further steps to decrypt a FAT binary. We will want to identify exactly what our preferred iDevice cputype is to know what code in the file is actually being run. Here's a short program to help do that.

/* archinfo by eric monti 
 * a utility for displaying the effective preferred mach-o architecture 

#include <mach-o/arch.h>
#include <stdio.h>

int main(int argc, char ** argv) {
  char * byteorders[3] = {"unknown", "little-endian", "big-endian"};
  const NXArchInfo *ai = NXGetLocalArchInfo();

  printf("name=%s, desc='%s', cputype=%i, subtype=%i, byteorder=%s(%i)\n",
      ai->name, ai->description, ai->cputype, ai->cpusubtype, 
      byteorders[(ai->byteorder > 2 || ai->byteorder < 0 ) ? 0 : ai->byteorder], 

Once we compile this for iOS and upload it to our device, we can use it to identify the default architecture. Here's what I see on an iPhone 4.

iPhone:/var/mobile root# ./archinfo 
name=armv7, desc='arm v7', cputype=12, subtype=9, byteorder=little-endian(1)

So, this means that when my iPhone is presented with a FAT binary that includes an armv7 architecture, it will default to using that architecture. The device may still work with earlier arm architectures (at least armv6). So if a armv6 Mach-O binary or a FAT binary containing only armv6 is run, it should still work too.

This complicates reversing for us somewhat. If we were to reverse engineer iBooks, it'd be nice just to focus on one architecture at a time. Using lipo(1) we can create a "thin" binary from a "fat" one. Lets "thin" iBooks down to our default architecture:

myMac:~_exes emonti$ lipo -thin armv7 iBooks -output iBooks_armv7
myMac:~_exes emonti$ file iBooks_armv7 
iBooks_armv7: Mach-O executable arm
myMac:~ emonti$ otool -h iBooks_armv7 
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedface      12          9  0x00          2    41       4640 0x00000085

Thankfully, we don't need to worry about any of this for "Just Light" (at least the version I have). It is already a thin armv6 binary. So if all that seemed like an unnecessary digression, sorry. But trust me when I say this usually gets glossed over and it can really frustrate you if/when you run into an encrypted FAT iOS binary you want to reverse.

Decrypting the Binary

Alright, so we have a thinned single-architecture Mach-O binary ready to start reversing on. We're ready to decrypt. You may have noticed earlier that class-dump spat out some header information in the Just Light binary when it informed us it wouldn't work on an encrypted file:

 * File: Just Light
 * Arch: arm v6 (armv6)
 *       Objective-C Garbage Collection: Unsupported
 *       This file is encrypted:
 *           cryptid: 0x00000001, cryptoff: 0x00001000, cryptsize: 0x00001000

These are Mach-O header values which are part of the LC_ENCRYPTION_INFO load command. We can list all load commands in a binary with "otool -l" as follows:

myMac:Just Light.app emonti$ otool -l Just\ Light
# theres a ton of info displayed, some is more useful than others
# skip to the LC_ENCRYPTION_INFO structure...
Load command 9
          cmd LC_ENCRYPTION_INFO
      cmdsize 20
 cryptoff  4096
 cryptsize 4096
 cryptid   1

What the LC_ENCRYPTION_INFO structure above tells us is:

  1. Encryption is enabled: cryptid = 1
  2. The encryption data starts at offset 4096 (or 0x1000): cryptoff = 4096
  3. The encrypted data is 4096 (or 0x1000) bytes long: cryptoff = 4096

Note the offset is relative from the beginning of the Mach-O header when it is loaded into memory. We can determine this what the true offset in memory is from 'nm'. When we ran nm earlier we saw:

00001000 A __mh_execute_header
00002000 T start

This indicates where the Just Light encrypted section will be located in memory before and after decryption.

In this case we got lucky and have a 'start' symbol pointing at the address 0x2000. However, 'start' is not always present in the symbol table, so a more reliable method is to take the offset for __mh_execute_header and add the 'cryptoff' value to that. This gives us 0x2000 too!

The 'start' symbol also implies we should set a breakpoint at 0x2000 to get at decrypted code before it is run. However, it is not always there and technically, does strictly have to be the entrypoint of the program. A more reliable way of identifying the entrypoint is to again use 'otool -l' and find the LC_UNIXTHREAD load command.

Load command 8
        cmd LC_UNIXTHREAD
    cmdsize 84
     flavor ARM_THREAD_STATE
	    r0  0x00000000 r1     0x00000000 r2  0x00000000 r3  0x00000000
	    r4  0x00000000 r5     0x00000000 r6  0x00000000 r7  0x00000000
	    r8  0x00000000 r9     0x00000000 r10 0x00000000 r11 0x00000000
	    r12 0x00000000 r13    0x00000000 r14 0x00000000 r15 0x00002000
	    r16 0x00000000

The LC_UNIXTHREAD load command is initializes thread state when the main thread is created on launch. Initializing thread state is really just a matter of setting all the registers in the state you want them before executing the thread. Notice how r15 is set to 0x2000? In this case, r15 represents the program counter on ARM and the pc is the equivalient of eip on x86. This is a much more definitive indication for the entrypoint in our target. Note however, it does not necessarily have to point to the beginning of the encrypted section, but will almost always be somewhere inside it.

We are ready to load our target in a gdb and have a breakpoint address that should fire before any real code is executed. We know where to look for the encrypted data, which is also where it will be located when it is decrypted. This early breakpoint is important, since our target may implement any manner of anti-debugging tricks which are becoming all the more common on iOS as Apple and developers raise the bar against software crackers and, to a lesser extent... us.

Now, lets open our target in gdb. Again, gdb is available as a Cydia package.

iPhone # gdb --quiet Just\ Light 
(gdb) break *0x2000
Breakpoint 1 at 0x2000

Before we execute, lets just take a quick look at the encrypted code at 0x2000. We notice that these are not yet valid instructions:

(gdb) x/5i 0x2000
0x2000:        addge        r4, r7, r4, asr r11
0x2004:        bl        0xfe147a48
0x2008:        ldrbcc        r5, [r4, #3476]
0x200c:        andmi        lr, r12, r12, lsl #7
0x2010:        svcpl        0x003dcbc2

What happens next is when we run the code it will be decrypted by the kernel's mach loader. Our breakpoint at 'start' should fire immediately after.

(gdb) run
Starting program: Just Light 
Removing symbols for unused shared libraries . done
Reading symbols for shared libraries ..................................................... done

Breakpoint 1, 0x00002000 in ?? ()

What does our decrypted section look like now?

(gdb) x/5i 0x2000
0x2000:        ldr        r0, [sp]
0x2004:        add        r1, sp, #4        ; 0x4
0x2008:        add        r4, r0, #1        ; 0x1
0x200c:        add        r2, r1, r4, lsl #2
0x2010:        bic        sp, sp, #7        ; 0x7

Success! Lets now dump this entire section out to a file. We'll use the 'cryptsize' value from earlier to determine the size of data to dump. The cryptsize was 0x1000. Added that to our cryptoff in memory at 0x2000. The end of the crypt section in memory is at 0x3000.

In a pinch, we can also use gdb to tell us the address ranges of the regions we're looking at.

(gdb) info mach-regions
Region from 0x0 to 0x1000 (---, max ---; copy, private, not-reserved)
   ... from 0x1000 to 0x2000 (r-x, max r-x; copy, private, not-reserved)
   ... from 0x2000 to 0x3000 (r-x, max rwx; copy, private, not-reserved)
   ... from 0x3000 to 0x4000 (rw-, max rw-; copy, private, not-reserved)
   ... from 0x4000 to 0x6000 (r--, max r--; copy, private, not-reserved)

Lets dump the decrypted data out to a file and quit gdb. We're done with gdb for decryption purposes. The rest of this process will involve static analysis.

(gdb) dump memory decrypted.bin 0x2000 (0x2000 + 0x1000)
(gdb) quit
The program is running.  Exit anyway? (y or n) y

Creating a File Suitable for Reversing

We now have the decrypted data from the executable, but it doesn't have a header or any of the rest of the Mach-O file around it. While we could technically disassemble and/or decode this file, it'll be harder without the header. Lets copy the file we created down onto our workstation and create a decrypted Mach-O file to work with.

myMac:Just Light.app emonti$ cp "Just Light" "Just Light_decrypted"

Open it up the *_decrypted file in your favorite hex editor. If your favorite hex editor doesn't let you do basic things like jump to offsets, paste binary data, and search hex strings, you need to find a new favorite hex editor. I like 0xED or hex fiend on macs.

We'll search for the cryptinfo section first and fix it up. This file isn't going to be "encrypted" when were done, and some tools we may want to use will need the headers to reflect that. So lets search for the LC_ENCRYPTION_INFO in the binary. There's more elegant ways to do this, like actually parsing the mach-O headers, but this works just fine 99% of the time. First take the info we got from otool and convert it back to binary. The values are little endian and the structure for the load command looks like so:

cmd LC_ENCRYPTION_INFO (21000000h)
  cmdsize 20           (14000000h)
  cryptoff 4096        (00100000h)
  cryptsize 4096       (00100000h)
  cryptid 1            (01000000h)

The binary sequence to search for should look like:

When I search for the load command in my working copy of Just Light, I find it at offset 0x0560. The cryptid value is located 16 bytes further in at offset 0x0570. Change it from "01 00 00 00" to "00 00 00 00". Save the file and we can confirm our modification with 'otool -l' like so:

myMac:Just Light.app emonti$ otool -l Just\ Light_decrypted |less
Load command 9
          cmd LC_ENCRYPTION_INFO
      cmdsize 20
 cryptoff  4096
 cryptsize 4096
 cryptid   0    <--

Now all that's left to do is take the decrypted data from decrypted.bin and save it to the file over the encrypted blob. In another window of our hex editor, just copy all the contents of decrypted.bin. In the hex editor window with "Just Light_decrypted" open, jump to file offset 0x1000 and overwrite everything from here to 0x2000 with the contents of decrypted.bin.

If you don't want to use a hex editor for this and/or want to automate it, I've included some code to help. Firstly, grab a copy of the ruby blackbag. There's a command-line tool called 'bgrep' included. we'll use to find the offset of the LC_ENCRYPTION_INFO structure.

myMac:Just Light.app emonti$ bgrep -x "2100000014000000001000000010000001000000" Just\ Light_decrypted 
myMac:Just Light.app emonti$ ruby -e 'puts 0x00000560'

Here's a ruby script that automates the rest of this. It requires you know the offset of the LC_ENCRYPTION_INFO structure in the file, which we just got from 'bgrep'. I didn't include that step in the script because it might be advantageous to be able to use this on FAT binaries as well.

#!/usr/bin/env ruby
# uncrypt.rb by eric monti
# A utility for patching encrypted mach-o binaries with decrypted data.
# usage: uncrypt.rb exe_file dec_file lc_offset


if( ARGV.include?("-h") or not 
    (exe = ARGV.shift and decrypt = ARGV.shift and lc_offset = ARGV.shift))
  STDERR.puts "usage: #{File.basename $0} exe_file dec_file lc_offset"
  exit 1

lc_offset = lc_offset.to_i
decrypt_dat = File.read(decrypt)

File.open(exe, "r+") do |f|
  f.pos = lc_offset
  cmd, cmdsize, cryptoff, cryptsize, cryptid = lc.unpack("I5")

    STDERR.puts "Error: Invalid LC_ENCRYPTION_INFO structure at 0x%0.8x" % lc_offset
    exit 1
  elsif cryptsize != decrypt_dat.size
    STDERR.puts "Error: Your decrypted data from #{decrypt} does not have the correct size"
    STDERR.puts "Expected #{cryptsize} got #{decrypt_dat.size} from file"
    exit 1
    STDERR.puts( "** Found LC_ENCRYPTION_INFO Structure at bytes offset #{lc_offset}",
                 "** lc_cmd=0x%0.8x, cmdsize=0x%0.8x, cryptoff=0x%0.8x, cryptsize=0x%0.8x, cryptid=0x%0.8x" %[
                   cmd, cmdsize, cryptoff, cryptsize, cryptid] )

    if cryptid != 0
      STDERR.puts "!! Patching cryptid"
      f.pos -= 4

    STDERR.puts "!! Writing #{cryptsize} bytes of decrypted data from #{decrypt.inspect} to #{exe.inspect}"
    # write our decrypted data at cryptoff, we assume it is equal to cryptsize
    f.pos = cryptoff

Save that to a file called 'uncrypt.rb' and run the following. Note that our lc_offset of 1376 was determined by bgrep previously, and may not necessarily be the same on your copy of the binary:

myMac:Just Light.app emonti$ ruby uncrypt.rb "Just Light_decrypted" decrypted.bin 1376
** Found LC_ENCRYPTION_INFO Structure at bytes offset 1376
** lc_cmd=0x00000021, cmdsize=0x00000014, cryptoff=0x00001000, cryptsize=0x00001000, cryptid=0x00000001
!! Patching cryptid
!! Writing 4096 bytes of decrypted data from "decrypted.bin" to "Just Light_decrypted"

Decrypted, at Last

So we finally have a decrypted binary in hand. Lets take it for a spin with class-dump to see what all that fuss was for.

myMac:Just Light.app emonti$ class-dump Just\ Light_decrypted 
 *     Generated by class-dump 3.3.2 (64 bit).
 *     class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2010 by Steve Nygard.

#pragma mark Named Structures

struct CGPoint {
    float _field1;
    float _field2;

struct CGRect {
    struct CGPoint _field1;
    struct CGSize _field2;

struct CGSize {
    float _field1;
    float _field2;

#pragma mark -

 * File: Just Light_decrypted
 * Arch: arm v6 (armv6)
 *       Objective-C Garbage Collection: Unsupported

@protocol NSObject
- (BOOL)isEqual:(id)arg1;
- (unsigned int)hash;
- (Class)superclass;
- (Class)class;
- (id)self;
- (struct _NSZone *)zone;
- (id)performSelector:(SEL)arg1;
- (id)performSelector:(SEL)arg1 withObject:(id)arg2;
- (id)performSelector:(SEL)arg1 withObject:(id)arg2 withObject:(id)arg3;
- (BOOL)isProxy;
- (BOOL)isKindOfClass:(Class)arg1;
- (BOOL)isMemberOfClass:(Class)arg1;
- (BOOL)conformsToProtocol:(id)arg1;
- (BOOL)respondsToSelector:(SEL)arg1;
- (id)retain;
- (oneway void)release;
- (id)autorelease;
- (unsigned int)retainCount;
- (id)description;

@protocol UIApplicationDelegate <NSObject>

- (void)applicationDidFinishLaunching:(id)arg1;
- (void)applicationDidBecomeActive:(id)arg1;
- (void)applicationWillResignActive:(id)arg1;
- (BOOL)application:(id)arg1 handleOpenURL:(id)arg2;
- (void)applicationDidReceiveMemoryWarning:(id)arg1;
- (void)applicationWillTerminate:(id)arg1;
- (void)applicationSignificantTimeChange:(id)arg1;
- (void)application:(id)arg1 willChangeStatusBarOrientation:(int)arg2 duration:(double)arg3;
- (void)application:(id)arg1 didChangeStatusBarOrientation:(int)arg2;
- (void)application:(id)arg1 willChangeStatusBarFrame:(struct CGRect)arg2;
- (void)application:(id)arg1 didChangeStatusBarFrame:(struct CGRect)arg2;

@interface Just_LightAppDelegate <UIApplicationDelegate>
    UIWindow *window;

- (void)applicationDidFinishLaunching:(id)arg1;
- (void)dealloc;
@property(retain) UIWindow *window; // @synthesize window;


Curious readers may also want to try 'otool -o' to see what kind of info it provides. It can be useful for other reversing tasks since it gives some low level details, but it's output is harder to read. We'll stick to class-dump's output for this exercise. It actually gives us a properly formatted objective-C header file that spells out all the class interfaces in our executable.

We can see now the prototypes which describe the interface for the symbols we saw earlier using 'nm'.

myMac:Just Light.app emonti$ nm Just\ Light_decrypted 
000020b8 t -[Just_LightAppDelegate applicationDidFinishLaunching:]
000020f8 t -[Just_LightAppDelegate dealloc]
00002140 t -[Just_LightAppDelegate setWindow:]
00002134 t -[Just_LightAppDelegate window]

The class interface from class-dump looks like:

@interface Just_LightAppDelegate <UIApplicationDelegate>
    UIWindow *window;

- (void)applicationDidFinishLaunching:(id)arg1;
- (void)dealloc;
@property(retain) UIWindow *window; // @synthesize window;

Now, this is a really basic application, so it's not surprising that the Objective-C class interface has just about nothing interesting going on. If you want to see a much more interesting class interface, try running class-dump against /Applications/MobileSafari.app/MobileSafari. I'll leave it as an excercise to the reader, but note that you won't need any of this fuss with decrypting MobileSafari. It is not an app store binary!

I picked Just Light specifically because it is a simple app (and free!). So lets run with that. To see just how simple this app is, disassemble the contents and see for yourself. Bear with me, but we won't actually be using a disassembler much in this exercise.

myMac:Just Light.app emonti$ otool -Vt Just\ Light_decrypted 
(__TEXT,__text) section
00002000	e59d0000	ldr	r0, [sp]
00002004	e28d1004	add	r1, sp, #4	; 0x4
00002008	e2804001	add	r4, r0, #1	; 0x1

# or... if you have a suitable objdump from binutils...
myMac:Just Light.app emonti$ objdump -d Just\ Light_decrypted 
Disassembly of section .text:

00002000 <start>:
    2000:	e59d0000 	ldr	r0, [sp]
    2004:	e28d1004 	add	r1, sp, #4
    2008:	e2804001 	add	r4, r0, #1
    200c:	e0812104 	add	r2, r1, r4, lsl #2
    2010:	e3cdd007 	bic	sp, sp, #7

"Did he just say we won't be disassembling?" you're asking, right? This is supposed to be an article on reversing, library injection, and function hooking! Well, we're going to do it the "easy way" using some educated guessing combined with some convenient features of the the Objective-C runtime. Pretty much everything you will get from the app store is heavily Objective-C driven, so it makes sense to take advantage of it.

Hooking the Objective-C Runtime

Since Objective-C is a dynamic runtime, it presents some interesting opportunities for runtime hooking for security purposes or otherwise. Objective-C is the primary application coding language employed in iOS apps. Objective-C enables developers to access the Cocoa API as well as various library frameworks on the iOS platform. As with other aspects of the underlying operating system, iOS shares a great deal in common with Mac OS X in its Objective-C runtime and libraries. Not surprisingly, Apple strongly encourages using Objective-C to allow 3rd party developers to take advantage of various features on iOS. Thus, most user applications we find from Apple and the iPhone App Store will be written with at least some Objective-C code and many implement most if not all of their functionality using it.

The process for hooking methods in Objective-C is called Swizzling and the runtime provides some features that let do it very easily. Consider the following code:

  1 /* phoshizzle.m by eric monti
  2  *
  3  * Hook [NSObject init] and watch children get created at runtime in the logs.
  4  *
  5  * compile with -dynamiclib -init _hook_setup
  6  * 
  7  */
  9 #import <Foundation/Foundation.h>
 10 #import <objc/runtime.h>
 12 // This macro sets up a hook into the objective-C runtime
 13 #define HookObjC(cl, sel, new, bak) \
 14  (*(bak) = method_setImplementation(class_getInstanceMethod((cl), (sel)), (new)))
 16 // Holds a pointer to the original [NSObject init]
 17 static IMP orig_init;
 19 // our overridden [NSObject init] hook
 20 id hook_init(id _self, SEL _cmd) {
 21   NSLog(@"Class Initialized: %@", [_self class]);
 22   return orig_init(_self, _cmd);
 23 }
 25 void hook_setup(void)
 26 {
 27   // hook [NSObject init]
 28   HookObjC(objc_getClass("NSObject"),
 29            @selector(init),
 30            (IMP) hook_init,
 31            (IMP *) &orig_init);
 32 }  

At lines 13 and 14 we define a macro called HookObjC. This is what we use to let the objective-C runtime do our work for us. The key to this macro is two very handy functions defined in the include file objc/runtime.h.

OBJC_EXPORT id objc_getClass(const char *name);
OBJC_EXPORT Method class_getInstanceMethod(Class cls, SEL name);
OBJC_EXPORT IMP method_setImplementation(Method m, IMP imp) 

On line 20 we define a function we call 'hook_init' which will become the hook for and take the place of NSObject.init whenever it is called. This code just logs a message and then calls the original init implementation. The important thing to remember about this hook is that the hook must match the return type and arguments from the objective C method it will replace. But in the case of NSObject.init, it is a well documented function. The first arguments always passed to obj-C instance methods are a reference to 'self' followed by a selector which indicates the method. In the case of 'init' there are no other arguments.

On line 25, we define a function that will be called when the library initializes. All this library init routine does is initialize the the "swizzle" at lines 28 through 31 using the HookObjC macro.

The macro calls class_getInstanceMethod() to get a reference to the "init" method of the "NSObject" class. That reference is passed to method_setImplementation() to point it at our own implementation, hook_init(). The original implementation of 'init' is saved as 'orig_init'.

When this code is run inside of any objective-C program, it should produce log information like the following (bear with me I'll cover injection soon):

Thu Jan  3 16:20:55 iPhone Just Light[11729] <Notice>: MS:Notice: Loading: /Library/MobileSubstrate/DynamicLibraries/phoshizzle.dylib
Thu Jan  3 16:20:55 iPhone Just Light[11729] <Warning>: Class Initialized: WTFMainThreadCaller
Thu Jan  3 16:20:55 iPhone Just Light[11729] <Warning>: Class Initialized: _NSThreadData
Thu Jan  3 16:20:55 iPhone Just Light[11729] <Warning>: Class Initialized: WebDatabasePauser
Thu Jan  3 16:20:55 iPhone Just Light[11729] <Warning>: Class Initialized: UIDevice
Thu Jan  3 16:20:56 iPhone Just Light[11729] <Warning>: Class Initialized: Just_LightAppDelegate
Thu Jan  3 16:20:56 iPhone Just Light[11729] <Warning>: Class Initialized: UIRuntimeOutletConnection
Thu Jan  3 16:20:56 iPhone Just Light[11729] <Warning>: Class Initialized: UIWindow
... and so on

We can already see how this ability to hook into the runtime could be valuable to us. We have effectively inserted new code into initialization of every NSObject. NSObject is the base class for all objects in the objective-C, so this translates into access to everything in the runtime! And we did it in very few lines of code.

Here's a more "specific" hook designed specifically to target Just Light.

/* phoshizzle2.m by eric monti
 * A basic hook PoC designed to make Just Light turn the screen red instead 
 * of white.

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <objc/runtime.h>

// This macro sets up a hook into the objective-C runtime
#define HookObjC(cl, sel, new, bak) \
 (*(bak) = method_setImplementation(class_getInstanceMethod((cl), (sel)), (new)))

static IMP hook_orig;

void hook(id _self, SEL _cmd, id arg) {
  [_self setBackgroundColor:[UIColor redColor]];
  hook_orig(_self, _cmd, arg);

void hook_setup(void)
  HookObjC(objc_getClass("UIWindow"), @selector(makeKeyAndVisible), 
           (IMP) hook, (IMP *) &hook_orig);

This is where we begin to see and think about how a targetted application hook might work. Though as promised from the get-go, this is hardly sneaky and only mildly annoying.

What we've done here is similar to the original phoshizzle.m code, but instead of hooking NSObject.init, we've targetted a specific class used by the UI and modified data in our hook. What we do is the flashlight color from white to red. This is done by hooking the UIWindow when it is made visible with the 'makeKeyAndVisible' method and changing the color before calling the original implementation.

In more robust applications, we can often find interesting class methods specific to the application to hook this way. These may yield sensitive information, offer opportunities for backdoors, or help us to instrument and dynamically analyze a program for security research, etc.

Consider for example how you might capitalize on a hook in this objective-C method prototype (found in a real application's class interface obtained using class-dump):

 (BOOL)loginAsUser:(id)arg1 withPassword:(id)arg2

Conventional C function pointer hooks are still possible even without the objective-C runtime, ofcourse. But the objective-C runtime offers interesting new opportunities in this area with a minimum amount of effort, particularly as it relates to reverse engineering.

Library Injection

With a dynamic library or bundle to inject in hand, we were able to to get it loaded into a target program in the previous section. There are numerous approaches to library injection on various operating systems. Several well established techniques exist on OS X/darwin. As it turns out, they are also shared by iOS. Additionally a jailbreak specific option may exist and is nice for testing code against, if not for use as part of your security research toolkit directly:

  1. DYLD_INSERT_LIBRARIES and several other environment variables are significant to the dyld(1) subsystem and allow dynamically adding code to processes as they are launched. Those familiar with "LD_PRELOAD" on linux will find this familiar territory as well. Often, these variables can be set and made persistent by adding them to a targetted application's launchd configuration. In 2009, Charlie Miller described a plist configuration he used to load custom code persistently into CommCenter via launchd for fuzzing iOS SMS messages.
  2. The Mach-O binary format stores "rpaths" which indicate the dynamic shared library install names loaded by an executable when it is launched. We can examine these "rpaths" using 'otool -L'. These linking relationships are usually created at compile time, however a tool called install_name_tool(1) on OS X can be used to add, change, or delete the rpaths in an executable file or library. Although a copy of otool and install_name_tool are not provided by Apple for iOS, iOS versions of otool and install_name_tool can also be obtained via the Cydia odcctools package. In a pinch, we can write our own lightweight tools to examine and modify the Mach-O headers in much the same way as otool and install_name_tool.
  3. At BlackHat USA 2009, Dino Dai Zovi presented rootkit injection toolkit for OS X that he called Machavelli. The techniques presented by Mr. Dai Zovi are primarily based on Mach IPC, which is a facility of the XNU kernel architecture shared by both iOS and OS X. Usermode runtime bundle injection is facilitated by a tool called inject-bundle. The inject-bundle tool was based on an earlier tool called 'mach_inject' from the mach_star suite. These techniques can be used on iOS as well, although injecting bundles at runtime requires minor custom patches to the toolchains to work on ARM architectures as well as additional steps to ensure entitlements for access to the necessary mach ports.
  4. The Cydia-driven jailbreak environment (the one pretty much everybody ends up with via 3rd party jailbreaks) includes the Mobilesubstrate subsystem. This facility is specifically designed for injecting arbitrary code into other processes on jailbroken iPhones and is what allows 3rd party Cydia developers to develop run-time patches to existing apps via code injection into iPhone apps like MobileSafari, etc. MobileSubstrate can be used to inject code any 3rd party app store application as well as Apple's own applications shipped with iOS.

In my presentation demo at toorcon, I was using MobileSubstrate out of convenience, however I avoided the use of the convenience functions it provides for creating Objective-C hooks or conventional C function pointer hooks. I did this specifically so that my hooks would easier to use with a wider range of library injection techniques.

Other injection techniques may offer stealthier ways to inject code, but MobileSubstrate is a great way to get started and test whether your hooks are working. MobileSubstrate is effectively already hooked into every process on the system through launchd, so it basically just provides us a convenient abstraction to do what it's already doing itself. All thats needed with MobileSubstrate is to compile the our injectable library and create a plist file which specifies a filter for which applications the library should be loaded into at runtime.

myMac:/var/mobile root# cd /Library/MobileSubstrate/DynamicLibraries
myMac:/Library/MobileSubstrate/DynamicLibraries root# ls -l phoshizzle2.*
-rwxr-xr-x 1 root wheel 25040 Jan  6 17:45 phoshizzle2.dylib*
-rw-r--r-- 1 root wheel    54 Jan  6 17:45 phoshizzle2.plist
myMac:/Library/MobileSubstrate/DynamicLibraries root# cat phoshizzle2.plist
Filter = {Bundles = ("com.justlightapp.justlight");};
myMac:/Library/MobileSubstrate/DynamicLibraries root# 


As mentioned previously, some code injection techniques require certain special iOS entitlements to work. Saurik wrote a very informative article on entitlements on his blog some time ago, which highlights the use of a tool he wrote for Cydia apps called 'ldid'. While iOS's security architecture restricts this ability, jailbreaking an iOS device enables you to bypass these restrictions. Indeed, this is one of the very things that jailbreaking is designed to do. It is for this reason that any successful rootkit attempt must generally be preceeded by some level of jailbreak of the underlying iOS system regardless whether it targets kernel, userland, or application layers.

Some of the significant entitlements we are interested in might include:

  • task_for_pid-allow, to allow controlling other processes (via the task_for_pid() function)
  • get-task-allow, to enable ptrace() access to other processes.
  • run-unsigned-code, to allow running code without a signature.


One of the most significant ideas to take away about iOS rootkits is that a large body of knowledge and information exists and is published on the XNU kernel and the darwin operating system much of which translates almost directly to iOS. In other words, although the iOS landscape may feel somewhat foreign at first, we are not starting completely from scratch with a new and different operating system. (similarly, a common base exists between Linux and Android in many ways).

Finally, much of the custom code I used in this article is available online. The package includes a makefile and some information on how to set up your environment with an iOS SDK.

Go out and have fun reversing some apps!

Stories For Discussion

  1. Crack[ing in the Cloud] - [pauldotcom] - Is this a big deal? Some, like Hoff, are like "meh". Its something we've covered in the past a lot. I'm kind of thinking along the lines that this is hacking the human, not the technology. We set weak WPA-PSK because the user needs to know them. How do we remove the human element from this equation? I can set a random 16 character passphrase, but thats too "hard" for the user.
  2. Attacking High-Frequency Trading Networks - [pauldotcom] - Ever since I read "Daemon" I've been sensitive to this threat. I often wonder if this could really happen.
  3. New workaround included in Security Advisory 2488013 - [pauldotcom] - Dear Microsoft, we want patches, not workarounds.
  4. IRIX - Local Kernel Memory Disclosure/Denial of Service - [pauldotcom] - People still use SGI IRIX? So cool, brings back fond memories of my purple pizza box system.
  5. HP Network Node Manager Command Injection Vulnerability - [pauldotcom] - This is beautiful, an HP application that is used to manage the network. Its got the network topology information, and likely has access to the entire network. Now, without authentication, it has a command injection vulnerability! Awesome! Such a deadly combination, so much fun stuff. If I find this on the network, or search your browser history for it, I have a juicy target. Command injection is a great vulnerability, and its a perfect jumping off point.
  6. Derbycon! - [pauldotcom] - I'm so proud that we are involved with this conference. It is going to be a lot of fun, great fellow speakers. I hope you can make it!
  7. Fax TDoS Attacks As a Result of WikiLeaks - [pauldotcom] - This is a really neat side effect of the wikileaks thing. Some of the leaks had fax numbers in it. The fax numbers of commpanies that do not support wikileaks have been published, and are receiveing LOTS of calls. Some of these fax machines could be essential for some companies. Looks like telcos will be receiving some orders for number changes.
  8. Friends? You bet. - [Larry] - Dan brings up good points about some players in the pentest tool industry - lets all get along. Each one has strengths and weaknesses, so lets all use them together.
  9. Kidzui, the browser for kids - [Larry] Billed as a safe internet browser for kids that lets them go only to sites approve by a third party for kid friendly stuff, IE youtube, etc. So, great ANOTHER browser. Here's my call: PLEASE PLEASE PLEASE someone fuzz this and break the heck out of it. I think the concept has some merit, but I suspect that it was incredibly poor in the security execution.
  10. Magic? - [Larry] - No, MagicTree! What is this you ask? A closed source penetration test information management application. Disclaimer, I haven't used it yet but you can bet I'm going tot try it… Take your nmap, Nessus, etc scan data (or run scans form the interface), import and it can compile into easily searchable data across multiple tools. At the end, you can even output a report…which are customizable. That last part can be the part that is full of win.
  11. Internet Photo Eraser? - [Larry] - Post your photos online with an expiration. Hmm, but doesn't save me from folks who download and save, or to those who forget to run it through this specialized tool first. Sometimes the only way to be secure isn't through the use of yet another layer or too, it is to stop being fscking stupid.
  12. Bet you didn't think of that… - [Larry] - Cell enabled traffic lights to synchronize data. They also have modem and GPS. Wait, what? Ok, first, what data are they sending back, unless they have a camera, or are worried about incredibly accurate synchronization. But GPS? Really? How often do they move? Ok, here's the kicker: The cell enabled lights all have sim cards. Of which someone stole 400 of them and used them for free phonecalls. The fix? More expensive than the cost of the materials.

Other Stories of Interest