1.) - Download the APK
➜ ~ git clone https://github.com/VerSprite/BSidesSF-2015
Cloning into 'BSidesSF-2015'...
remote: Counting objects: 93, done.
remote: Compressing objects: 100% (38/38), done.
remote: Total 93 (delta 3), reused 0 (delta 0), pack-reused 37
Unpacking objects: 100% (93/93), done.
Checking connectivity... done.
➜ ~ cd BSidesSF-2015
➜ BSidesSF-2015 git:(master) cd app/
➜ app git:(master) ls -la
total 3592
drwxr-xr-x 9 rotlogix staff 306 Apr 7 10:52 .
drwxr-xr-x 7 rotlogix staff 238 Apr 7 10:52 ..
-rw-r--r-- 1 rotlogix staff 7 Apr 7 10:52 .gitignore
-rw-r--r-- 1 rotlogix staff 907915 Apr 7 10:52 app-release.apk
-rw-r--r-- 1 rotlogix staff 7223 Apr 7 10:52 app.iml
-rw-r--r-- 1 rotlogix staff 587 Apr 7 10:52 build.gradle
-rw-r--r-- 1 rotlogix staff 907915 Apr 7 10:52 crackme.apk
-rw-r--r-- 1 rotlogix staff 666 Apr 7 10:52 proguard-rules.pro
drwxr-xr-x 4 rotlogix staff 136 Apr 7 10:52 src
➜ app git:(master)
2.) - Decompile the APK with apktool - http://ibotpeaches.github.io/Apktool/
➜ app git:(master) java -jar ~/Tools/mobile/android/apktool/apktool_2.0.0rc4.jar -r d crackme.apk
I: Using Apktool 2.0.0-RC4 on crackme.apk
I: Loading resource table...
I: Copying raw resources...
I: Baksmaling classes.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...
-r
disregards decoding resources
/res
- Directory containing resources that are not compiled
➜ crackme git:(master) ✗ ls -R | grep '/res'
./res:
./res/anim:
./res/color:
./res/drawable:
./res/drawable-hdpi-v4:
./res/drawable-ldrtl-hdpi-v17:
./res/drawable-ldrtl-mdpi-v17:
./res/drawable-ldrtl-xhdpi-v17:
./res/drawable-ldrtl-xxhdpi-v17:
./res/drawable-ldrtl-xxxhdpi-v17:
./res/drawable-mdpi-v4:
./res/drawable-v21:
./res/drawable-xhdpi-v4:
./res/drawable-xxhdpi-v4:
./res/drawable-xxxhdpi-v4:
./res/layout:
./res/layout-v11:
./res/layout-v21:
./res/menu:
./res/mipmap-hdpi-v4:
./res/mipmap-mdpi-v4:
./res/mipmap-xhdpi-v4:
./res/mipmap-xxhdpi-v4:
./smali/android/support/v4/content/res:
META-INF
- Usually contains the Manifest, and Application Certifcate
➜ crackme git:(master) ✗ ls -R | grep '/META-INF'
./original/META-INF:
lib
- Directory containing compiled shared objects broken down into their specific architecture - ex: armeabi, armeabi-v7a
- armeabi - "ARM Embedded Application Binary Interface"
assets
- Directory containing assets that can be accessed by the AssetManager
AndroidManifest.xml
- Contains application, permission, and component definitions and declarations
classes.dex
- Compiled DEX executable
resources.arsc
- Precompiled resources
-- The output of apktool will breakout the APK structure a bit different --
➜ crackme git:(master) ✗ ls
AndroidManifest.xml apktool.yml original res resources.arsc smali
/smali
- Contains the disassembled format for the Dalvik bytecode
versprite
./com/versprite:
crackme
./com/versprite/crackme:
BuildConfig.smali R$anim.smali R$color.smali R$id.smali R$menu.smali R$style.smali emulator
KeyActivity$1.smali R$attr.smali R$dimen.smali R$integer.smali R$mipmap.smali R$styleable.smali generate
KeyActivity.smali R$bool.smali R$drawable.smali R$layout.smali R$string.smali R.smali
./com/versprite/crackme/emulator:
Detect.smali
./com/versprite/crackme/generate:
Generate.smali GenerateReceiver.smali
apktool leverages - https://code.google.com/p/smali/ - for this task
03.) Using Androguard for Analysis
Documentation: http://doc.androguard.re/html/index.html
Androguard is a great tool to automate APK analysis. We will be using 'Androlyze' for most of the labs, which provides interactive analysis.
➜ app git:(master) ✗ python ~/Tools/mobile/android/androguard/androlyze.py -s
Androlyze version 2.0
In [1]:
-- We can use AnalyzeAPK() to perform all of heavy lifting for us --
In [1]: a,d,dx = AnalyzeAPK("crackme.apk")
In [2]:
This returns the APK, DalvikVMFormat, and VMAnalysis objects.
APK - has access to all elements in an APK file
DalvikVMFormat - can parse a classes.dex file fo an APK
VMAnalysis - analyses a dex file
-- We can now use the class methods from the APK object to perform basic enumeration over permissions and components --
Activities
In [2]: a.get_activities()
Out[2]: ['com.versprite.crackme.KeyActivity']
-- If you type a. [tab] -> androlyze will display a list of available methods --
In [3]: a.get
a.get_AndroidManifest a.get_certificate a.get_files a.get_max_sdk_version a.get_services
a.get_activities a.get_details_permissions a.get_files_crc32 a.get_min_sdk_version a.get_signature
a.get_android_manifest_axml a.get_dex a.get_files_information a.get_package a.get_signature_name
a.get_android_manifest_xml a.get_element a.get_files_types a.get_permissions a.get_target_sdk_version
a.get_android_resources a.get_elements a.get_intent_filters a.get_providers
a.get_androidversion_code a.get_file a.get_libraries a.get_raw
a.get_androidversion_name a.get_filename a.get_main_activity a.get_receivers
We are not requesting any special permissions in this application or have any other component besides the declared activity, but here are methods you will care about with a much larger application.
a.get_services() -> Services
a.get_receivers() -> Broadcast Receivers
a.get_providers() -> Content Providers
a.get_permissions() -> Permissions
-- Let's find out what the Main Activity is for this application --
In [6]: a.get_main_activity()
Out[6]: u'com.versprite.crackme.KeyActivity'
This Activity will be the main entry point into the application.
4.) - Using Dex2Jar
Takes an APK as input, does some magic and converts the class.dex back into Java .class files, which subsequently viewed with something like JD-GUI.
➜ app git:(master) ✗ ~/Tools/mobile/android/dex2jar/d2j-dex2jar.sh crackme.apk
dex2jar crackme.apk -> crackme-dex2jar.jar
-- Output will look something like this --
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.versprite.crackme.emulator.Detect;
public class KeyActivity extends Activity
{
private EditText key;
private Button submitbtn;
public void addListenerOnButton()
{
this.key = ((EditText)findViewById(2131296320));
this.submitbtn = ((Button)findViewById(2131296321));
this.submitbtn.setOnClickListener(new View.OnClickListener()
{
public void onClick(View paramAnonymousView)
{
String str = String.valueOf(KeyActivity.this.key.getText());
Intent localIntent = new Intent();
localIntent.setAction("com.versprite.crackme.GENERATE");
localIntent.putExtra("key", str);
KeyActivity.this.sendBroadcast(localIntent);
Toast.makeText(KeyActivity.this.getApplicationContext(), "Checking Key ...", 0).show();
}
});
}
This will get you the closest to 'source'.
5.) - Putting It All Together - Analyzing Contacts.apk
-- Pull the Contacts.apk off your emulator --
➜ app git:(master) ✗ adb shell
root@vbox86p:/ # cd /system/app/
root@vbox86p:/system/app # ls -la | grep Contacts
-rw-r--r-- root root 2285951 2015-02-16 11:10 Contacts.apk
-rw-r--r-- root root 372792 2015-02-16 11:06 ContactsProvider.apk
root@vbox86p:/system/app #
➜ app git:(master) ✗ adb pull /system/app/Contacts.apk
6145 KB/s (2285951 bytes in 0.363s)
➜ app git:(master) ✗ ls
Contacts.apk app.iml crackme crackme.apk src
app-release.apk build.gradle crackme-dex2jar.jar proguard-rules.pro
-- Decompile! --
➜ app git:(master) ✗ java -jar ~/Tools/mobile/android/apktool/apktool_2.0.0rc4.jar d Contacts.apk
I: Using Apktool 2.0.0-RC4 on Contacts.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: /Users/rotlogix/Library/apktool/framework/1.apk
I: Regular manifest package...
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Baksmaling classes.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...
-- Androlyze! --
➜ app git:(master) ✗ python ~/Tools/mobile/android/androguard/androlyze.py -s
In [1]: a,d,dx = AnalyzeAPK("Contacts.apk")
-- We can leverage Androlyze's interfactive perspective to do some light scripting for even more automation! --
In [3]: for activity in a.get_activities(): print(activity)
com.android.contacts.activities.PeopleActivity
com.android.contacts.activities.ContactSelectionActivity
com.android.contacts.activities.JoinContactActivity
com.android.contacts.preference.ContactsPreferenceActivity
com.android.contacts.common.list.AccountFilterActivity
com.android.contacts.common.list.CustomContactListFilterActivity
com.android.contacts.activities.ShowOrCreateActivity
com.android.contacts.activities.GroupDetailActivity
com.android.contacts.activities.GroupEditorActivity
com.android.contacts.quickcontact.QuickContactActivity
com.android.contacts.activities.ContactDetailActivity
com.android.contacts.activities.ConfirmAddDetailActivity
com.android.contacts.activities.ContactEditorAccountsChangedActivity
com.android.contacts.activities.ContactEditorActivity
com.android.contacts.common.test.FragmentTestActivity
com.android.contacts.activities.AttachPhotoActivity
com.android.contacts.activities.PhotoSelectionActivity
com.android.contacts.common.vcard.ImportVCardActivity
com.android.contacts.common.vcard.NfcImportVCardActivity
com.android.contacts.common.vcard.CancelActivity
com.android.contacts.common.vcard.SelectAccountActivity
com.android.contacts.common.vcard.ExportVCardActivity
com.android.contacts.widget.PinnedHeaderListDemoActivity
com.android.contacts.socialwidget.SocialWidgetConfigureActivity
com.android.contacts.NonPhoneActivity
In [5]: for service in a.get_services(): print(service)
com.android.contacts.common.util.EmptyService
com.android.contacts.ContactSaveService
com.android.contacts.common.vcard.VCardService
com.android.contacts.ViewNotificationService
In [6]: for receiver in a.get_receivers(): print(receiver)
com.android.contacts.quickcontact.QuickContactBroadcastReceiver
com.android.contacts.socialwidget.SocialWidgetProvider
-- What About Permissions? --
In [9]: for permission in a.get_permissions(): print(permission)
android.permission.CALL_PRIVILEGED
android.permission.READ_CONTACTS
android.permission.WRITE_CONTACTS
android.permission.READ_CALL_LOG
android.permission.WRITE_CALL_LOG
android.permission.MANAGE_ACCOUNTS
android.permission.GET_ACCOUNTS
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_COARSE_LOCATION
android.permission.READ_PROFILE
android.permission.WRITE_PROFILE
android.permission.READ_SOCIAL_STREAM
android.permission.INTERNET
android.permission.NFC
android.permission.READ_PHONE_STATE
android.permission.MODIFY_AUDIO_SETTINGS
android.permission.MODIFY_PHONE_STATE
android.permission.WAKE_LOCK
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.WRITE_SETTINGS
android.permission.USE_CREDENTIALS
android.permission.VIBRATE
android.permission.READ_SYNC_SETTINGS
com.android.voicemail.permission.ADD_VOICEMAIL
com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL
android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK
com.android.launcher.permission.INSTALL_SHORTCUT
android.permission.REBOOT
android.permission.RECEIVE_BOOT_COMPLETED
-- What Are The Intent Filters? --
In [47]: activites = a.get_activities()
In [48]: for activity in activites:
filters = a.get_intent_filters('activity', activity)
for k,v in filters.items():
print(activity, k,v)
....:
('com.android.contacts.activities.PeopleActivity', 'action', [u'android.intent.action.MAIN', u'com.android.contacts.action.LIST_DEFAULT', u'com.android.contacts.action.LIST_CONTACTS', u'com.android.contacts.action.LIST_ALL_CONTACTS', u'com.android.contacts.action.LIST_CONTACTS_WITH_PHONES', u'com.android.contacts.action.LIST_STARRED', u'com.android.contacts.action.LIST_FREQUENT', u'com.android.contacts.action.LIST_STREQUENT', u'android.intent.action.SEARCH', u'com.android.contacts.action.FILTER_CONTACTS', u'android.intent.action.VIEW'])
('com.android.contacts.activities.PeopleActivity', 'category', [u'android.intent.category.DEFAULT', u'android.intent.category.LAUNCHER', u'android.intent.category.BROWSABLE', u'android.intent.category.APP_CONTACTS', u'android.intent.category.TAB'])
('com.android.contacts.activities.ContactSelectionActivity', 'action', [u'android.intent.action.INSERT_OR_EDIT', u'android.intent.action.PICK', u'android.intent.action.GET_CONTENT'])
('com.android.contacts.activities.ContactSelectionActivity', 'category', [u'android.intent.category.DEFAULT'])
('com.android.contacts.activities.JoinContactActivity', 'action', [u'com.android.contacts.action.JOIN_CONTACT'])
('com.android.contacts.activities.JoinContactActivity', 'category', [u'android.intent.category.DEFAULT'])
('com.android.contacts.activities.ShowOrCreateActivity', 'action', [u'com.android.contacts.action.SHOW_OR_CREATE_CONTACT'])
('com.android.contacts.activities.ShowOrCreateActivity', 'category', [u'android.intent.category.DEFAULT'])
('com.android.contacts.quickcontact.QuickContactActivity', 'action', [u'com.android.contacts.action.QUICK_CONTACT'])
('com.android.contacts.quickcontact.QuickContactActivity', 'category', [u'android.intent.category.DEFAULT'])
('com.android.contacts.activities.ContactDetailActivity', 'action', [u'android.intent.action.VIEW'])
('com.android.contacts.activities.ContactDetailActivity', 'category', [u'android.intent.category.DEFAULT'])
('com.android.contacts.activities.ContactEditorActivity', 'action', [u'android.intent.action.EDIT', u'android.intent.action.INSERT'])
('com.android.contacts.activities.ContactEditorActivity', 'category', [u'android.intent.category.DEFAULT'])
('com.android.contacts.common.test.FragmentTestActivity', 'category', [u'android.intent.category.TEST'])
('com.android.contacts.activities.AttachPhotoActivity', 'action', [u'android.intent.action.ATTACH_DATA'])
('com.android.contacts.activities.AttachPhotoActivity', 'category', [u'android.intent.category.DEFAULT'])
('com.android.contacts.common.vcard.ImportVCardActivity', 'action', [u'android.intent.action.VIEW'])
('com.android.contacts.common.vcard.ImportVCardActivity', 'category', [u'android.intent.category.DEFAULT'])
('com.android.contacts.common.vcard.NfcImportVCardActivity', 'action', [u'android.nfc.action.NDEF_DISCOVERED'])
('com.android.contacts.common.vcard.NfcImportVCardActivity', 'category', [u'android.intent.category.DEFAULT'])
('com.android.contacts.widget.PinnedHeaderListDemoActivity', 'action', [u'android.intent.action.MAIN'])
('com.android.contacts.widget.PinnedHeaderListDemoActivity', 'category', [u'android.intent.category.DEFAULT'])
('com.android.contacts.socialwidget.SocialWidgetConfigureActivity', 'action', [u'android.intent.action.APPWIDGET_PICK'])
('com.android.contacts.NonPhoneActivity', 'action', [u'android.intent.action.DIAL', u'android.intent.action.MAIN', u'android.intent.action.VIEW', u'android.intent.action.CALL_BUTTON'])
('com.android.contacts.NonPhoneActivity', 'category', [u'android.intent.category.DEFAULT', u'android.intent.category.BROWSABLE'])
-- Wrapping Up with Dex2Jar --
➜ app git:(master) ✗ ~/Tools/mobile/android/dex2jar/d2j-dex2jar.sh Contacts.apk
dex2jar Contacts.apk -> Contacts-dex2jar.jar