Tuesday, July 26, 2011

BlackBerry Messenger / Google Talk for BlackBerry Save-files

My last post, "BlackBerry Text Message Parsing, AKA, Why I use Linux for Forensics," had unintended but pleasant consequences: it introduced me to BlackBerry forensics expert Shafik Punja.  I really wrote the post to comment on the versatility of the Linux operating system, and fortunately I erred in calling the file that was the subject of my discussion a "BlackBerry Text Message" save file, rather than the BlackBerry Messenger (BBM) save file that it was.

Shafik corrected me and taught me a bit more about the file type that I'll share here in the event that you missed his comments.  BBM messenger does not save message content by default.  It is a user selected option, and only available in BBM v5 and higher.  The files can be saved to the device's internal memory or an installed memory card.  Google Talk has the same save options and defaults as BBM, and also saves in the same basic format.

Shafik asked if I could write a program to parse the files.  I agreed and quickly converted the basic Bash script in my last post to a more complete program.  However, when Shafik tried to run the program in OS X, it failed because OS X and Linux do not utilize the same 'date' command.  I was faced with writing a new program for use in OS X, which I wished to support, or make my current script intelligently determine the OS in which it was running and apply the correct date command syntax.

Nothing seems like a bigger waste to me than to write essentially the same thing twice.  Isn't there a way to write a program that doesn't have to be altered based on the operating system in which it is run, I asked?  Then a little Australian-accented voice of reason reached my conscious thought: why don't you learn python?  For the millionth time: Thank you Michael, good idea.

Michael Cohen, a software engineer at Google and author/maintainer of pyFLAG, AFF4,  and other tools soon to be released, has suggest many times over that I learn python, but I only recently started to do so.  Python is an excellent solution for cross platform programs, and I decided it was time to start.

The BBM / GTalk file format

BBM and GTalk save files are CSV text files with the following basic structure:
Application Name, version[newline]
DateCode, "Sender_ID", "Receiver_ID", Message[newline]
...

The first line of the file is the source application and the application version, separated by a comma. The version is followed by a newline control code.

The remaining lines are formatted thus: the line starts with a DateCode consisting of a 21 digit number. The first 8 digits are the date of the sent message rendered as YYYYMMDD. The remaining 13 digits are Unix epoch time, rendered in milliseconds. In the case of BBM, the sender Hex_ID follows the DateCode, separated by a comma and encapsulated in parenthesis. Similarly, the receiver's Hex_ID follows. For GTalk, the sender and receiver are identified by Google Account ID. Finally, the message, in text, is stored followed by a newline control code.

One minor issue in rendering the file in a spreadsheet centers on the message field. Messages are not encapsulated in commas; therefore, messages with commas will not format well in spreadsheets without additional spreadsheet configuration. This might not be a problem for one file, but would be a major annoyance for many files (one of my colleagues found 23 BBM save files on an SD card). I determined to encapsulate the message field in quotes to overcome this issue.

The python3 code I settled on follows:
import sys
from time import strftime, localtime

def main(csv):
    line_no = 0
    with open(csv) as db_file:
        for line in db_file:
            if line_no == 0:
                print(line)
                print('Date,DateCode,Sender,Receiver,Message')
                line_no += 1
            else:
                datecode, sender, receiver, message = line.split(',', 3)
                date = int(datecode[8:18])
                date = strftime('%Y-%m-%d %H:%M:%S (%Z)', localtime(date))
                print('"{}",{},"{}","{}","{}"'.format(date, datecode, sender, receiver, message.strip()))

if __name__ == '__main__':
    for file in sys.argv[1:]:
        main(file)

I won't try to explain all the code here, because with my rudimentary knowledge of python, I'm likely to misspeak. I will highlight a couple parts of the script and a couple of nice python features, however. First, the "if" condition in line 8 is present to skip over date decoding in the first line of the file. Instead, it prints the line, and adds a line of column headers to help with interpreting the remaining message data.

Line 13 demonstrates a very nice python feature: multiple value assignment. Here, I assign data from line 2 and higher, one line at a time (note the 'for' loop) to the datecode, sender, receiver, and message objects. To work correctly, however, there needs to be four values to assign to the four objects. The split method divides a string object into a list of strings based on a delimiter. Here, I configure split to divide on commas a maximum of three times. This creates a list of four strings. Remaining commas are ignored and included in the last string, which here is assigned to 'message'.

Line 14 converts the 'datecode' string to an integer, and line 15 uses the 'strftime' and 'localtime' functions from the 'time' module to convert the Unix epoch time embedded in the datecode to a human-readable format. I use string slicing, that is, selecting a portion of the datecode string by its position in the string (also called indexing where the starting position is 0), to extract the 10 digits that represent the Unix epoch value. The last three digits of the datecode are ignored since they represent milliseconds.

The final line of which to take note is Line 16, where a few things of import are occurring. First, the interpreted datecode is printed. The original datecode follows for reference and validation purposes, and then the remainder of the line. A format method is applied that replaces the brackets place holders in the print string with the objects that are arguments of the format method. Here, the message object is encapsulated in quotes. Also, the message object has the strip method applied to remove the newline control code at the end of each message to improve formatting.

Though I won't comment on it, I'll include the bash script I wrote first for comparison:
line_no=0 #set counter

cat $1 | while read line
do
    if [ $line_no -eq 0 ]
    then
        echo ${i}  #print first line unaltered
        echo "Date,DateCode,Sender,Receiver,Message"
        line_no=1
    else
        for var in date sent rcvd message
        do
            eval $var="\${line%%,*}"
            [[ "$var" = "message" ]] && message=$line #ignore commas in message
            line="${line#*,}"
        done
        date=$(date +"%Y-%m-%d %H:%M:%S (%Z)" -d @${date:8:10}) #convert date code and store
        len=$((${#message}-1)) #subtract 1 from remainder length for stripping newline control code
        echo "\"$date\",\"$sent\",\"$rcvd\",\"${message:0:$len}\""
    fi
done

Thursday, July 21, 2011

BlackBerry Text Message Parsing, AKA, Why I use Linux for Forensics

A little detour from my usual posts to explain why I use Linux for forensics, though my upbringing was in Windows-based tools like EnCase.  A colleague contacted me today with a little issue: He had found a BlackBerry text messaging backup file in CSV format (EDIT: This was actually a BlackBerry Messenger save file) on an external memory card, but the date code for each message was perplexing.  He asked me if I could help in interpret the code.  It looked like the following:
201010181287467321760
The full format of the CSV was "date, from(hexID), to(hexID), message."  It was obvious to my colleague and me that the first 8 digits of the date code was the date of the message in plain text, i.e., "20101018" or "2010-10-18."  My Unix roots made the remaining digits of the numeric string easy to identify: unixepoch in milliseconds, i.e., 1287467321760 milliseconds since 1-1-1970 00:00:00.

A quick verification with the date command, but truncating the date at seconds (i.e., dividing by 1000):
$ date -d @1287467321
Mon Oct 18 22:48:41 PDT 2010

The converted unixepoch date matches the plain text date. We seem to have interpreted the code correctly, and now we know the local time of the message as well.

But of course, using the date command is not why I find Linux so valuable.  It because of the ease with which I was able to convert the whole file, having discovered the meaning of the date code.  Remember the format of the file?  It was "date, from(hexID), to(hexID), message."

Consider three lines from the file as an example:
201010181287467321760,"6C31FB2C","0F315216",Hey
201010191287534544913, Oct 19 17:29:04 PDT 2010,"6C31FB2C","0F315216",Hey, you there?
201010191287534602157,"0F315216","6C31FB2C",Yeah, let's meet.

A quick, simple while loop to read each line of the Messenger save file,
$ cat backup.csv | while read line; do date=${line%%,*}; remainder=${line#*,}; echo "$(date -d @${date:8:10}),$remainder"; done
Mon Oct 18 22:48:41 PDT 2010,"6C31FB2C","0F315216",Hey
Tue Oct 19 17:29:04 PDT 2010,"6C31FB2C","0F315216",Hey, you there?
Tue Oct 19 17:30:02 PDT 2010,"0F315216","6C31FB2C",Yeah, let's meet.
...

Let me break that down:
cat backup.csv | while read line  #read a line of the file, assign to variable 'line'
do
  date=${line%%,*}  #read everything up to the first comma, assign to variable 'date'
  remainder=${line#*,}  #read everything beyond the first comma, assign to variable 'remainder'
  echo "$(date -d @${date:8:10}),$remainder" #convert digits 9-18 to local time, print localtime and the remainder of the line to stdout
done

The key to this solution is something I didn't learn in my initial studies of Bash, but I make extensive use of it now: variable expansion. I use the various expansions available in Bash 4 to assign portions each line to variables that I could then operate on and print the result. I won't discuss all available expansions here, but I will explain those I used:

Removing the longest match from the end:

Consider: Each line contained comma separated values. I really only needed to operated on the first value -- the date code. I prefer, as much as possible, to not call external tools, such as cut or awk, so as to not unnecessarily start external processes. Bash variable expansion makes this possible. The syntax ${var%%PATTERN} will remove the longest match to PATTERN from the variable 'var'.

So, in line 3, date=${line%%,*} assigns to the 'date' variable all of the contents of the 'line' variable up to the first comma. Thus, in the case of the first line, date="201010181287467321760".

Removing the shortest match from the beginning:

With the date code isolated in the 'date' variable, we still need to print the rest of the line once we convert the date. The syntax ${var#PATTERN} will remove the shortest match to PATTERN from the variable 'var'.

So, in line 4, remainder=${line#*,} assigns to the 'remainder' variable all of the contents of the 'line' variable after the first comma. Thus, in the case of the first line, remainder=""6C31FB2C","0F315216",Hey"

Returning a substring of a variable:

Finally, we need to isolate the unix epoch time from the plain text date in the date code now stored in the variable 'date'. We do this by indexing. The syntax ${var:OFFSET:LENGTH} will return a substring of the variable 'var' starting at OFFSET for the specified LENGTH. The first character in a variable is indexed at offset 0.

So, in line 5, ${date:8:10} returns 10 characters of the variable 'date' starting at the 9th character (remember, indexing starts at 0). Thus, we have now fed the unix epoch date string incorporated in the Messenger date code to the unix date command to be converted to local time in a human readable format.

Line five is a complex command, that indexes the 'date' variable, converts it in a sub-process with the date command, and then echo the result with the contents of the 'remainder' variable appended.

Where to go from here:

If you have some Bash skills, but want to advance them, I recommend the book "Pro Bash Programming: Scripting the GNU/Linux Shell" by Chris F.A. Johnson from Apress.

Tuesday, July 19, 2011

Mounting Split Raw Images

A raw image, made with dd or a variant, is still a common image format, and will not go away soon even as many argue the benefits of forensic images such as the Expert Witness Format (supplied through libewf) and the Advanced Forensic Format (supplied through afflib).  But raw images can be difficult to tote around because they are bit for bit copies which makes the copy as large as the original.  As such, the images are often split to fit on external media such as DVD.

But splitting, while solving storage problems, creates a new problem.  What if you want to mount the image for examination?  True, Sleuthkit can handle the examination of split raw images, but sometimes there is no equal to simply mounting an image during an examination.

Let me illustrate using a situation I encountered yesterday.  A colleague had a split raw image of over 200 segments that he wished to mount and then boot in a virtual machine.  He tried to follow my tutorial  but was unsuccessful, uncertain as to why.  When I looked into the situation with him, the issue became clear: xmount, the tool used to create a virtual disk from a disk image, was only mounting the first segment of the split raw image, despite being given all the segments as arguments as is required with Expert Witness Format images.  More simply put, xmount does not handle split raw images.  It will handle a single raw image file just fine, however.

What to do?  One could simply cat the files together, but that means doubling storage requirements, at least until the concatenation operation is concluded.  That might not be feasible or desirable, and it can be very time consuming.  In this case, we were talking 300 GB of data.  It would be great to be able to treat the segments as one file, and pass that file to xmount to accomplish the purpose.

Affuse to the rescue!  Affuse is part of the afflib tool suite.  It creates a virtual file system using fuse and mounts it to a location you specify.  You only pass the first segment of the split image as an argument.  The command takes the form:

# affuse image mount_point

Affuse creates an image.raw file (that is, the name of the segment with '.raw' appended)  in the mount point along with a log file.  Yes, its that easy.

To finish the scenario, xmount can then take the image.raw file as an argument to create the virtual disk, thusly:

# xmount --in dd --out vdi --cache image.cache mount_point/image.raw new_mount_point/

This command tells xmount that the input file, image.raw, is raw data, the output desired is a VirtualBox vdi format, that a cache file called "image.cache" is desired to store system changes when the virtual machine is running.  The .vdi file will be mounted in the "new_mount_point" directory.  If xmount is unfamiliar to you, I recommend you read my previous post.

Like affuse, xmount utilizes the fuse file system.  Both utilities accept fuse file system arguments as well as tool specific arguments, so read only mounting and permissions options exist (type "man fuse" at the command line for more details).  As always, practice on non-case data to become familiar with the tools.

Wednesday, June 29, 2011

Google Chrome Download History

Google Chrome keeps a wealth of data that is of interest to the forensic examiner.  There are tools that look at the browser history and cache, but tools that examine the download history are less frequent.  Part of the reason it is overlooked by examiner's, I suspect, is that the download history is a table in the 'History' SQLite database, and not a separate file itself.

The History database, found in '/home//.config/chromium/Default' for the open version of chrome, i.e., Chromium, contains the following tables:
$ sqlite3 History .tables
downloads             presentation          urls
keyword_search_terms  segment_usage         visit_source
meta                  segments              visits


The downloads table is the focus of this post.  It is structured as follows:

$ sqlite3 History .schema | grep downloads
CREATE TABLE downloads (id INTEGER PRIMARY KEY,full_path LONGVARCHAR NOT NULL,url LONGVARCHAR NOT NULL,start_time INTEGER NOT NULL,received_bytes INTEGER NOT NULL,total_bytes INTEGER NOT NULL,state INTEGER NOT NULL);

For the uninitiated, the table schema tells us that each record contains 'id', 'full_path', 'url', 'start_time', 'received_bytes', 'total_bytes', and 'state' fields.  We can extract the data in csv format, as follows:
sqlite -header -csv History "SELECT * FROM downloads"

That's nice, but the dates are unixepoch and we don't know what the 'state' integer means, though it can be deduced from the 'received_bytes' and 'total_bytes' fields and studying a known source of data.  I determined that state 1 and 2 mean "complete" and "incomplete" download respectively.

To convert unixepoch to local time, we use the SQLite datetime function.   We tell datetime to take the start_time integer, interpret it as unixepoch time, and translate to localtime.  Exerpted from the rest of the query, it looks like this:
datetime(start_time,'unixepoch','localtime')

For clarity in the output, it would be nice to convert the state integer to its text equivalent.  We can do this with the case command.  The case command is the if/then statement of SQLite.  In its simplest application it takes the form 'CASE  WHEN x=w1 THEN r1 WHEN x=w2 THEN r2 ELSE r3 END' where x is the field data, w is a comparison value, and r is the result that is returned.  It is easiest to understand when we apply it to our current circumstance:
CASE WHEN state=1 THEN 'complete' WHEN state=2 THEN 'incomplete' ELSE 'unknown' END

Putting it all together, we can obtain nicely formatted output from the downloads table of the Chrome History database with the following command:
sqlite3 -header -csv History "SELECT id,full_path, url, datetime(start_time,'unixepoch','localtime') AS date, received_bytes, total_bytes, CASE WHEN state=1 THEN 'complete' WHEN state=2 THEN 'incomplete' ELSE 'unknown' END AS state FROM downloads"

The caps in the commands are not required, but are designed to make reading the SQLite operators easier.  You may have noted the "AS" operators after the datetime function and case expressions.  It serves to replace the expressions as the header for that column in your csv output.

Your output should look like:
id,full_path,url,date,received_bytes,total_bytes,state
1,/home/slosleuth/Downloads/keepnote_0.7.3-1_all.deb,http://keepnote.org/keepnote/download/keepnote_0.7.3-1_all.deb,"2011-06-23 12:04:46",500022,500022,complete
2,/home/slosleuth/Downloads/iso/nbcaine2.0.dd.gz,http://www.caine-live.net/Downloads/nbcaine2.0.dd.gz,"2011-06-24 13:25:42",85962197,0,incomplete
3,/home/slosleuth/Downloads/iso/nbcaine2.0gz.md5.txt,http://www.caine-live.net/Downloads/nbcaine2.0gz.md5.txt,"2011-06-24 13:27:23",51,51,complete

I hope this helps you with SQLite queries in general and specifically to parse the data in the Google Chrome downloads table of the History SQLite database. 

Monday, June 13, 2011

Extending gThumb for forensics

I've searched high and low, and many times, for a good image viewer to be used in Linux-based forensics.  In the end, and despite some shortcomings, I always end up using gThumb, a GUI image viewer and browser.  The advantages of gThumb are that it integrates well with the Gnome desktop environment, has a robust search facility, finds files recursively, and can be extended by the user.

The focus of this post is extending gThumb.  Today, many images are rich in EXIF data, much of which gThumb displays in a property window.  However, it misses data like GPS coordinates that can be found in some images like those taken by the iPhone.  My favorite tool for reading EXIF data is exiftool by Phil Harvey, but it's a command line tool.  So, how does one integrate command line data with a GUI tool like gThumb?  Yad!

No, I didn't just utter an explicative.  Yad stands for "yet another dialog" and is a fork of the zenity project.  Zenity is a simple to use GUI front end for command line scripts.  However, yad has many more features and is under active development.  Yad had many stock dialog boxes, and I will illustrate its use here as I extend gThumb with exiftool by displaying the exiftool output in a yad dialog box.

gThumb has the option to run user scripts, accessed through the toolbar: Tools | Personalize.


This opens the "Command" dialog box.  Clicking the "New" button opens the "New Command" dialog where the user command is inputted.


Assuming both yad and exiftool are installed in you operating system, you can create an exiftool extention as follows:

Name: exiftool
Command: exiftool %F | yad --text-info --title="exiftool: %B" --fontname="Monospace 10" --width=600 --height=800
Shortcut: <select from drop down if a shortcut key is desired>
Terminal command (shell script): leave checked
Save the command and close the main Command box.  You can select your new command from the tools menu or by the number pad shortcut you created.


The results appear in a yad "text-info" dialog box:



If you made a mistake, or need to edit your command use the Command window through "Tool | Personalize."


With this basic format, gThumb extensions are only limited by your creativity!

SD Card Construction, (or Burning Ants with a Magnifying Glass)

A coworker brought me an SD card today because she could not delete any files from it.  I noticed the lock switch was missing from the card, and after inserting the card into a portable reader, I confirmed the card was write protected.  This got me curious: just how does the switch on an SD card work?  I've relied on it for write protecting evidence, but I didn't really know how reliable the switch was.

With great gusto, I snapped the card in half to examine its contents.  I did it with as much joy of discovery as a young boy has when first focusing the suns rays on ants with a magnifying glass.  What I found inside surprised me: a very simple chip occupying about 1/3 of the card housing.  I determined--by examining similar cards--that the switch did not bridge any electrical contacts on the chip, so write protection was not a function on the card itself.

I turned my attention to several card readers I have lying about.  One has a very shallow card well, which makes visualizing the electrical contacts quite easy.  I noted that on the side of the reader, in a location corresponding to the switch on an SD card, there was a spring-loaded pin.  Through  experimentation, I determined that the pin, when depressed, allows data to be written to the card.  When the pin is extended, write-blocking occurs.  The position of the "lock" switch on the card determines the position of the pin.

Thus, (and to my surprise) write blocking is a really function of the reader, not the card.  It is possible for a reader to be constructed or damaged such that the lock switch has no effect!  Frequent inspection and testing of a card reader used for forensic analysis is warranted.

Lesson: know your equipment!

Friday, June 3, 2011

Defeating the Droid: Let the Pillaging Begin

In my last post, Defeating the Droid, I explained how to root an Android phone, at least through version 2.2.  Like other mobile devices, Android is a moving target and what works on one phone or one OS version may not work on the next.  We left off with a running adb shell with root privileges.  But how do we get the data we seek.

Bringing Up the Past

I mentioned previously that the adb shell is an ASH shell without auto-completion, inline editing, or command history.  In other words, this car is a base model without all the bells and whistles with which you might be accustomed.  Add to that a limited set of binary tools (no copy, tar, or find commands, for example) and its a bit like standing at the base of a cliff without any climbing tools.

Plan of Attack

We need tools, and we need them bad.  But we don't want to change any more data on the phone than necessary.  So, what to do?

Android phones use SD cards to store user media, like photos and music.  This card should be removed and imaged, following standard forensic imaging protocols, as part of your examination.  While the card can be imaged from within the phone, the interface is slow (took 45 minutes to image 16gb) and requires that the phone be placed in USB mass storage mode for the workstation to see it.  A locked phone may make this impossible.

Significantly, removing the card allows us to replace it with one of our own containing tools for accessing data in the phone's internal memory.  You can get by quite handily with one small tool: busybox.

You can copy busybox to the card before inserting it in the phone, but its not a necessity.  You can also use the Android Debug Bridge (adb) utility to copy busybox to an installed card using the command:
# adb push busybox /sdcard
Finally, the card you use should have enough space to capture the full internal memory of the phone.  The adb shell allows us to copy files within the device, but not to our workstations.  So, we must copy files to the SD card.

The size of our SD card can very, depending on the amount of physical memory found in the phone. This can be quite small, as in the case of the original Motorola Droid which has only 256mb of internal storage.  However newer devices, like the Droid 2, have significantly more memory with 8gb of internal storage capacity.

Sequential Processing: Starting with "dd"

I'm experienced in fingerprint development as well as computer forensics.  In fingerprint processing, there is a phenomenon known as "Sequential Processing."  Sequential processing simply means to do processing in such an order so that the first step does not inhibit the second step, and so on.  We actually do this every day in computer forensics: we image a device before before we conduct an examination, and we use the image for the examination so as to not harm the original evidence.

It is my opinion that we should do physical imaging of the device before logical.  The device we are working on has a running operating system and files are changing and being created and deleted as part of the normal process of the phone.  Further, a physical image means we can recover deleted files, so we want the physical images before we do anything that could overwrite data.  "dd" is the tool of choice here, and it can be deployed quickly (it is part of the resident operating system) and there is no set up involved, i.e., remounting of partitions.
  1. Root the device.  See my previous post if you don't know what I'm talking about.
  2. Start the adb shell if its not already running.  Look for the telltale root prompt to be sure you have "rooted" the device.

    # adb shell
    #  <-- adb shell prompt

  3. Determine the devices you want to image.  In Android, the devices are called mtdblock devices, and are listed in /proc/mtd.

    # cat /proc/mtd
    dev:    size   erasesize  name
    mtd0: 00180000 00020000 "pds"
    mtd1: 00060000 00020000 "misc"
    mtd2: 00380000 00020000 "boot"
    mtd3: 00480000 00020000 "recovery"
    mtd4: 08c60000 00020000 "system"
    mtd5: 05ca0000 00020000 "cache"
    mtd6: 105c0000 00020000 "userdata"
    mtd7: 00200000 00020000 "kpanic"

  4. Ideally, we want to image everything.  But of particular interest are the "cache" and "userdata" block devices.  The size of each device is listed in hexadecimal code.  In the above case, the "cache" device is  97124352 bytes [echo $((0x5ca0000))], and the "userdata" device is 274464768 bytes [echo $((0x105c0000))].  We need to know how the devices are addressed:

    # mount
    rootfs / rootfs ro,relatime 0 0
    ...
    /dev/block/mtdblock4 /system yaffs2 ro,relatime 0 0
    /dev/block/mtdblock6 /data yaffs2 rw,nosuid,nodev,relatime 0 0
    /dev/block/mtdblock5 /cache yaffs2 rw,nosuid,nodev,relatime 0 0
    /dev/block/mtdblock0 /config yaffs2 ro,relatime 0 0
    ...


  5. We see that the "cache" mtdblock device is addressed as /dev/block/mtdblock5 and "userdata" as /dev/block/mtdblock6.  We can make a dd image of each as follows:

    # dd if=/dev/block/mtdblock5 of=/mnt/sdcard/cache.dd
    189696+0 records in
    189696+0 records out
    97124352 bytes transferred in 24.001 secs (4046679 bytes/sec)
    # dd if=/dev/block/mtdblock6 of=/sdcard/data.dd
    /dev/block/mtdblock6: read error: I/O error
    83808+0 records in
    83808+0 records out
    42909696 bytes transferred in 8.653 secs (4958938 bytes/sec)


    Uh, oh, an error.  Normally, we overcome dd errors by adding the "conv=noerror" argument, which tells dd to continue on read error.  But the Android dd does not support that option.  So, what do we do in such a circumstance?  Give up?  Hardly!
Phase Two: Busybox

Busybox can be described as "the swiss army knife of embedded Linux."  It is a single executable file, about 1mb in size, containing many common Unix utilities, including cp, find, tar, and yes, dd!  In order to use it, we need a version compiled for Android, but I will not discuss how to compile here. It is readily available on the Web and in Android Root kits, but I'd recommend compiling a trusted version if you can.  One things certain, you cannot use the busybox binary from your workstation.  

There's a catch to using busybox.  We want to place it on our SD card so we don't change anything on the phone's internal memory, but busybox cannot be run from the SD card.  "Why?" you ask.  I'll show you:
# mount  
 ...
/dev/block/vold/179:1 /mnt/sdcard vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1000,gid=1015,fmask=0702,dmask=0702,allow_utime=0020,codepage=cp437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0

So, to make the busybox on the SD card executable, we need to remount the card with the ability to execute binary files.

  1. If busybox was not already on your card, push it to the card from a terminal on your workstation.

    # adb push busybox /mnt/sdcard
    1255 KB/s (1745016 bytes in 1.356s)


  2. Remount your card with executable permission.

    # adb shell
    # mount -o remount,rw /mnt/sdcard /mnt/sdcard
    # mount
    /dev/block/vold/179:1 /mnt/sdcard vfat rw,dirsync,relatime,uid=1000,gid=1015,fmask=0702,dmask=0702,allow_utime=0020,codepage=cp437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0


  3. Change directories to the SD card and optionally start a busybox shell.  By starting a busybox shell, we attain inline editting and a shell history.  In other words, entering commands becomes easier.

    # cd /mnt/sdcard
    # ./busybox sh


  4. Now we can dd that damaged "userdata" mdtblock again, this time passing conv=noerror because we will use the busybox dd.  Note: because busybox is not installed on the system or in the path, we have to prepend busybox utilities with ./busybox .  To see a list of available busybox tools, issue "./busybox" alone.

    # ./busybox dd if=/dev/block/mtdblock6 of=/mnt/sdcard/data.dd conv=noerror

  5. With busybox, we can also create archives of the logical files on the device.  Again, to simplify the discussion, we'll focus on the /cache and /data directories where we saw the respective mtdblock devices were mounted.  Why should we archive the logical files when we have physical images made with dd?  Because the file systems in the images are "yaffs" and present special problems I won't discuss here.  It is enough to say, for now, that your workstation likely doesn't support yaffs by default and you cannot mount and examine the images you created.  They are only useful file carving.

    Therefore, we'll use tar to make archives of the /cache and /data directories.

    # ./busybox tar czvf cache.tar.gz /cache
    tar: removing leading '/' from member names
    cache/
    cache/downloadfile-30.jpeg
    cache/downloadfile-15.jpeg
    ...
    cache/app/I-Status_Monitor.apk
    # ./busybox tar czvf data.tar.gz /data
    tar: removing leading '/' from member names
    data/
    data/tombstones/
    data/tombstones/tombstone_05
    data/tombstones/tombstone_00
    ...
    data/lost+found/
Wrapping Things Up

When you've acquired the images/files that you seek, you need to get the data from the SD card to your workstation.  The easiest way is to turn off the phone and remove the card, the read it directly.  But you can pull the files from the card with adb, too.  You might want to do this if you need the data quickly, or to free up space on a smaller card for more images/archives.  To pull the files from the card to your workstation:
  1. Use "adb pull" to move files from the SD installed in the phone to your workstation.  The command is run in a terminal on your workstation, NOT in the adb shell.  You can exit adb shell or open a new terminal window if you want to remain in the adb shell environment.

    # exit  <-- exits the busybox shell
    # exit  <-- exits the adb shell to your terminal
    # adb pull /mnt/sdcard/cache.tar.gz /some/evidence/directory/
    # adb pull /mnt/sdcard/cache.dd /some/evidence/directory/
    ...

  2. When you are done pulling all the files you plan to transfer, remove the exploit from the install directory.

    # adb shell rm /data/local/tmp/ratc.bin

    Note: I chose this method of removing the exploit to demonstrate that the adb shell command can pass arguments to the adbd daemon on the phone without dropping into the shell.  I hope to use this ability to script the process we've been discussing.
  3. Reboot the phone to kill the exploit and the phone is back in its pre-exam condition.
I'll leave the examination of the data you've recovered to you for now.  Maybe in a future post, I'll highlight some key files and how to process them (hint: mmssms.db contains text messaging, and cache.cell contains GPS data).

Time Perspective

Telling time in forensic computing can be complicated. User interfaces hide the complexity, usually displaying time stamps in a human reada...