Tuesday 27 October 2020

Magnet Weekly CTF writeup - Week 3

 And we're on to week 3 of the Magnet Weekly CTF Challenge! This week's question still references the Android image from week 1:

Which exit did the device user pass by that could have been taken for Cargo?

This week's question had me stumped initially and added to the difficulty was the three answer attempt limit. Thankfully Magnet Forensics was generous enough to give a hint on Cache Up, which pointed players to one of their webinar on mobile artifact comparison.

From the webinar hint, my instinct tells me that this had to do with the Pixel equivalent of 'live photos' - a.k.a. motion photos - where the phone records and trims up to 3 seconds of video when taking a photo with motion enabled.

So I started looking at the MVIMG*.jpg files in the DCIM folder:

$ ls data/media/0/DCIM/Camera/ | grep MVIMG
MVIMG_20200305_145544.jpg
MVIMG_20200306_151636.jpg
MVIMG_20200307_130221.jpg
MVIMG_20200307_130237.jpg
MVIMG_20200307_130326.jpg
MVIMG_20200307_185225.jpg
MVIMG_20200307_201453.jpg
MVIMG_20200310_133405.jpg

There were 8 motion photos and I needed a way to extract the embedded video within. A quick Google search did not disappoint and I found a ready script by Jerry Peek on StackOverflow that does exactly what we needed.

#!/bin/bash
# extract-mvimg: Extract .mp4 video and .jpg still image from a Pixel phone
# camera "motion video" file with a name like MVIMG_20191216_153039.jpg
# to make files like IMG_20191216_153039.jpg and IMG_20191216_153039.mp4
#
# Usage: extract-mvimg MVIMG*.jpg [MVIMG*.jpg...]

for srcfile
do
  case "$srcfile" in
  MVIMG_*_*.jpg) ;;
  *)
    echo "extract-mvimg: skipping '$srcfile': not an MVIMG*.jpg file?" 2>&1
    continue
    ;;
  esac

  # Get base filename: strip leading MV and trailing .jpg
  # Example: MVIMG_20191216_153039.jpg becomes IMG_20191216_153039
  basefile=${srcfile#MV}
  basefile=${basefile%.jpg}

  # Get byte offset. Example output: 2983617:ftypmp4
  offset=$(grep -F --byte-offset --only-matching --text ftypmp4 "$srcfile")
  # Strip trailing text. Example output: 2983617
  offset=${offset%:*}

  # If $offset isn't an empty string, create .mp4 file and
  # truncate a copy of input file to make .jpg file.
  if [[ $offset ]]
  then
    dd status=none "if=$srcfile" "of=${basefile}.mp4" bs=$((offset-4)) skip=1
    cp -ip "$srcfile" "${basefile}.jpg" || exit 1
    truncate -s $((offset-4)) "${basefile}.jpg"
  else
    echo "extract-mvimg: can't find ftypmp4 in $srcfile; skipping..." 2>&1
  fi
done

Running the script against the MVIMG*.jpg files earlier and looking through the extracted videos, I noted an interesting frame extracted from MVIMG_20200307_130326.jpg:


The video appears to have captured a signboard on a highway, with the keyword 'Cargo' on it. Unfortunately the video quality isn't the best (or maybe it's just my screen) and I could not make out clearly what was on the signboard.

Checking the EXIF metadata of the image gives us the following information:

$ exiftool data/media/0/DCIM/Camera/MVIMG_20200307_130326.jpg 
ExifTool Version Number         : 12.00
File Name                       : MVIMG_20200307_130326.jpg
Directory                       : data/media/0/DCIM/Camera
File Modification Date/Time     : 2020:03:07 07:03:28-05:00
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
Make                            : Google
Camera Model Name               : Pixel 3
Modify Date                     : 2020:03:07 13:03:26
Date/Time Original              : 2020:03:07 13:03:26
Create Date                     : 2020:03:07 13:03:26
GPS Version ID                  : 2.2.0.0
GPS Altitude                    : 246.8 m Above Sea Level
GPS Date/Time                   : 2020:03:07 12:03:26Z
GPS Latitude                    : 60 deg 11' 38.70" N
GPS Longitude                   : 11 deg 5' 46.65" E

Looking up the GPS coordinates on Google Maps places us within Gardermoen Airport in Norway, next to Starbucks - not quite what I expected since the motion photo clearly showed the device user on the move outdoors.

Refusing to be daunted, I checked the EXIF of the images that were sequentially before and after the motion photo of interest and noted that MVIMG_20200307_185225.jpg places the user in Gamle Oslo, Norway. Since the motion photos suggests that the device user was on a bus, I used Google Maps for directions from Gardermoen Airport to Gamle Oslo and followed the route on street view. My persistence finally paid off when I found the signboard at 60°10'14.3"N 11°06'13.8"E.


Answer: E16

Fun fact: E16 is actually the route and not exit, unlike what the question suggests. From Wikipedia: European route E16 is the designation of a main west-east road through Northern Ireland, Scotland, Norway and Sweden.

Tuesday 20 October 2020

Magnet Weekly CTF writeup - Week 2

Magnet is hosting a weekly DFIR challenge until the end of 2020. Head on over to https://magnetweeklyctf.ctfd.io to sign up if you haven't already done so!


This week's question:

What domain was most recently viewed via an app that has picture-in-picture capability?

This question is based off the Android image we were given in week 1. To start, we have to determine which apps supports picture-in-picture (PIP). Per the Android Developers' guide, apps have to declare support for PIP by registering video activity in their manifest by setting android:supportsPictureInPicture to true.

I unpacked the MUS_Android.tar image given and used apkanalyzer from the Android SDK to print out the manifest files from all the Android packages (apks) in data/app.

$ find data/app -name "base.apk" -print0 | xargs -0 -i apkanalyzer manifest print {} > manifest-all

Stringing a bunch of grep commands together to search for packages with android:supportsPictureInPicture="true" from the printed manifests in the previous step gives us the following 7 out of 79 packages with PIP capability:

$ grep -E "package=|PictureInPicture=\"true\"" manifest-all | grep -B 1 "PictureInPicture" | grep package
    package="com.google.android.apps.maps"
    package="com.facebook.orca"
    package="com.google.android.apps.tachyon"
    package="com.google.android.youtube"
    package="com.android.chrome"
    package="com.google.android.videos"
    package="com.google.android.gms"

Of the above, the most likely candidate to start with is Chrome, as the other apps are not known for being used to view other domains. The Chrome app history is located in the database at data/data/com.android.chrome/app_chrome/Default/History. Opening up the History SQLite database with DB Browser for SQLite, a quick join and sort of the visits and urls table by visit_time gives us:


Answer: malliesae.com

Friday 16 October 2020

Installing Android SDK command-line tools on Linux

 Recently I had to use some tools from the Android SDK on Linux and it was surprisingly not as straightforward as I thought it'll be. Perhaps Google was trying to convince folks to use Android Studio...

Anyways, the first step is to download the command-line tools from Android Developers. (Click on "Download Options" for more options.) Grab the zip file for command-line tools and unzip it to a folder of choice. You should see a tools folder, with the necessary binaries in the bin subfolder.

If you get a Warning: Could not create settings error when trying to run tools/bin/sdkmanager, that's because the tools directory hierarchy has been changed starting from Android SDK Command-line Tools 1.0.0 (6200805). (Refer to the excellent answer by Jing Li on Stack Overflow here.) The solution therefore, is to move the unzipped tools folder into the cmdline-tools subfolder, and add cmdline-tools/tools/bin to your path.

Assuming the sdkmanager is located at /home/<username>/cmdline-tools/tools/bin/sdkmanager, one would add the following to their bash profile (~/.bashrc):

export PATH=$PATH:/home/<username>/cmdline-tools/tools/bin

Exit and restart the terminal, and the Android SDK command-line tools should work now. Some useful commands:

$ sdkmanager --help
$ sdkmanager --list
$ sdkmanager --install <package>

Note: to use certain tools such as apkanalyzer, one would also need to install the necessary packages with sdkmanager.

Tuesday 13 October 2020

Magnet Weekly CTF writeup - Week 1

Magnet Forensics has recently launched a weekly capture-the-flag (CTF) challenge that will run through the last quarter of 2020! Head on over to their blog for more details on the challenge and how to sign up.

For challenge one, we are provided with an Android image which is a tar file containing what appears to be a filesystem extraction of an Android phone.The challenge question was:

What time was the file that maps names to IP's recently accessed?
(Please answer in this format in UTC: mm/dd/yyyy HH:MM:SS)

I had to first figure out which is the file that maps names to IP addresses on Android. According to this answer on StackOverflow, it is no different than on a standard Linux system - i.e. the /etc/hosts file. However I could not find an /etc/hosts file in the given Android tar image.

Running a search for an "etc/hosts" file in the tarball points me to data/adb/modules/hosts/system/etc/hosts.

$ tar -tvf MUS_Android.tar | grep "etc/hosts"
-rw-r--r-- 0/0                85 2020-03-05 05:50 data/adb/modules/hosts/system/etc/hosts

A quick check of the contents of the file after extracting confirms it to be the one we are after.

$ cat data/adb/modules/hosts/system/etc/hosts
127.0.0.1       localhost
::1             ip6-localhost
184.171.152.175 malliesae.com

Based on the above output, the file was last modified on 5th March 2020 at 05:50 UTC but we also need the seconds for the answer. A quick search on the internet indicates that the --full-time option is available for both the ls and tar commands, giving us timestamp information in ISO format.

So listing the specific file in our tarball with the --full-time option gives us:

$ tar --full-time -tvf MUS_Android.tar 'data/adb/modules/hosts/system/etc/hosts'
-rw-r--r-- 0/0              85 2020-03-05 05:50:18 data/adb/modules/hosts/system/etc/hosts

While the challenge technically asked for recently accessed (i.e. last accessed) instead of last modified, I could not find any other timestamp. Checking with 7zip also revealed only a single modified timestamp.


Answer: 03/05/2020 05:50:18

Magnet Summit 2022 Virtual CTF - Windows

Magnet Forensics recently concluded their Virtual CTF for the Magnet Summit 2022.  Participants were provided with the following three image...