Top Banner
Deep Inside Android Hacks Keishin Yokomaku (KeithYokoma) @ Drivemode, Inc. Android All Stars #dotsandroid
53
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Deep Inside Android Hacks

Deep Inside Android HacksKeishin Yokomaku (KeithYokoma) @ Drivemode, Inc.

Android All Stars #dotsandroid

Page 2: Deep Inside Android Hacks

Profile

• Keishin Yokomaku at Drivemode, Inc.

• Social: @KeithYokoma

• Publication: Android Training

• Product:

• Like: Bicycle, Photography, Tumblr

• Nickname: Qiita Meister

Page 3: Deep Inside Android Hacks

Drivemode

• Now available on Play Store!

• http://bit.ly/1LYdxAg

Page 4: Deep Inside Android Hacks

E-book

• AndroidTraining / iOS Training

• http://amzn.to/1mZNydv

Page 5: Deep Inside Android Hacks

How to Hack Android

Page 6: Deep Inside Android Hacks

How to Hack Android

• Using public APIs

• Reflection to access hidden APIs

• AIDL to communicate with System services

Page 7: Deep Inside Android Hacks

Using public APIs

Page 8: Deep Inside Android Hacks

Using public APIs

• It’s official!

• Less likely to crash coming from customizations

Page 9: Deep Inside Android Hacks

android.media.session

• Lollipop API

• Components

• MediaSession and MediaSession.Token

• MediaController

• Notification.MediaStyle

Page 10: Deep Inside Android Hacks

MediaSession and MediaController

• Permit transport control by session token

Media Application

MediaSession

Other Application

MediaController

Token

Transport Control

Page 11: Deep Inside Android Hacks

NotificationListenerService

• Background service listening to status bar notification events

NotificationManager

Notificationnotify

NotificationListenerService

onNotificationPosted

Page 12: Deep Inside Android Hacks

Notification.MediaStyle

• Pass MediaSession.Token to system notification

• When you listen to notification event…

• MediaSession.Token is in `extras`

• Key for `extras` is defined on Notification

• MediaSession.Token is valid even if the receiver is not intended to

Page 13: Deep Inside Android Hacks

–Someone

“This is more like session hijacking”

Page 14: Deep Inside Android Hacks

Take control of music playback

public class MusicNotificationWatcher extends NotificationListenerService { private Bus eventBus; @Override public void onNotificationPosted(StatusBarNotification sbn) { MediaSession.Token token = sbn.getNotification().extras.getParcelable(Notification.EXTRA_MEDIA_SESSION); eventBus.post(new NewMusicNotification(token)); }}

public class MyActivity extends Activity { private MediaController controller; @Subscribe public void onNewMusicNotificationAdded(NewMusicNotification event) { controller = new MediaController(this, event.getToken()) }}

Page 15: Deep Inside Android Hacks

Take control of music playback

public class MusicNotificationWatcher extends NotificationListenerService { private Bus eventBus; @Override public void onNotificationPosted(StatusBarNotification sbn) { MediaSession.Token token = sbn.getNotification().extras.getParcelable(Notification.EXTRA_MEDIA_SESSION); eventBus.post(new NewMusicNotification(token)); }}

public class MyActivity extends Activity { private MediaController controller; @Subscribe public void onNewMusicNotificationAdded(NewMusicNotification event) { controller = new MediaController(this, event.getToken()) }}

Page 16: Deep Inside Android Hacks

Take control of music playback

public class MusicNotificationWatcher extends NotificationListenerService { private Bus eventBus; @Override public void onNotificationPosted(StatusBarNotification sbn) { MediaSession.Token token = sbn.getNotification().extras.getParcelable(Notification.EXTRA_MEDIA_SESSION); eventBus.post(new NewMusicNotification(token)); }}

public class MyActivity extends Activity { private MediaController controller; @Subscribe public void onNewMusicNotificationAdded(NewMusicNotification event) { controller = new MediaController(this, event.getToken()) }}

Page 17: Deep Inside Android Hacks

“Is it practical?”

Page 18: Deep Inside Android Hacks

Is it practical?

• It depends

• You cannot fully cover overall music experience

• For keyguard apps, this is good enough

Page 19: Deep Inside Android Hacks

“Is it affordable?”

Page 20: Deep Inside Android Hacks

Is it affordable?

• No

• Because it works only on Lollipop and with Google Play Music

Page 21: Deep Inside Android Hacks

Reflection to access hidden APIs

Page 22: Deep Inside Android Hacks

Reflection to access hidden APIs

• It’s unofficial, dirty, unpaved…

• No IDE support for you

• Be careful about ProGuard settings

• Breaking changes might be happening under the hood

• Performance issue

Page 23: Deep Inside Android Hacks

ProGuard

• Do not obfuscate statements called via reflection

Page 24: Deep Inside Android Hacks

Reflection basics

• Class

• Object#getClass(), Class.forName(), Class literal

• Method

• Class#getDeclaredMethods(), Class#getDeclaredMethod()

• Field

• Class#getDeclaredFields(), Class#getDeclaredField()

Page 25: Deep Inside Android Hacks

Example

package com.sample;

public class Something { private void foo(String str) {}}

public class ReflectionSample { public void reflect(Something something) throws Exception { Method foo = something.getDeclaredMethod(“foo”, String.class); foo.setAccessible(true); foo.invoke(something, “bar”); }}

Page 26: Deep Inside Android Hacks

Example

package com.sample;

public class Something { private void foo(String str) {}}

public class ReflectionSample { public void reflect(Something something) throws Exception { Method foo = something.getDeclaredMethod(“foo”, String.class); foo.setAccessible(true); foo.invoke(something, “bar”); }}

Page 27: Deep Inside Android Hacks

Example

package com.sample;

public class Something { private void foo(String str) {}}

public class ReflectionSample { public void reflect(Something something) throws Exception { Method foo = something.getDeclaredMethod(“foo”, String.class); foo.setAccessible(true); foo.invoke(something, “bar”); }}

Page 28: Deep Inside Android Hacks

Example

package com.sample;

public class Something { private void foo(String str) {}}

public class ReflectionSample { public void reflect(Something something) throws Exception { Method foo = something.getDeclaredMethod(“foo”, String.class); foo.setAccessible(true); foo.invoke(something, “bar”); }}

Page 29: Deep Inside Android Hacks

Accessing hidden APIs

• Methods / Fields

• getDeclared** to get private (or hidden) one

• setAccessible(true) to make it visible to us

Page 30: Deep Inside Android Hacks

“Why are you using wrecking reflection?” “Because it is practical”

Page 31: Deep Inside Android Hacks

Practicality of reflection

• Aggressive usage

• to get informations that is generally prohibited for normal apps

• to use system functions

• Reluctant usage

• to avoid/patch bugs in framework

Page 32: Deep Inside Android Hacks

Aggressive reflection

• You can do almost everything

• Read `RemoteViews` operations

• Read actual `Intent` on `PendingIntent`

• Call hidden method to register object onto system service

Page 33: Deep Inside Android Hacks

Karma of aggressive reflection

• Spoil encapsulation

• Need to pay attention to the object state

• It may not work

• No guarantee that every phone has the same method or field

• Google is watching you

Page 34: Deep Inside Android Hacks

Reluctant reflection

• Avoid bugs in framework

• Ex. http://bit.ly/1HkJvR4

• Fix wrong path for preferences files on G***** S

• Ex. http://bit.ly/1E5kB7L

• Backward compatibility

Page 35: Deep Inside Android Hacks

Benefits of reluctant reflection

• Reduce a lot of pains on users who are using broken phone

• Keep new API available on old phones

Page 36: Deep Inside Android Hacks

AIDL to communicate with System services

Page 37: Deep Inside Android Hacks

AIDL to communicate with System services

• Yet another dirty work

• Be careful about ProGuard settings

Page 38: Deep Inside Android Hacks

ProGuard

• Do not obfuscate auto generated codes and implementation

Page 39: Deep Inside Android Hacks

AIDL basics

• Implementing AIDL stub

• Put .aidl in `src/main/aidl`

• Compile it

• Implement stub methods in Java code

Page 40: Deep Inside Android Hacks

A lot of AIDLs in framework

• Intent, Bundle, Uri, Bitmap, Rect, Account…

• Data container objects passed to each processes

• MediaSession, ICameraService, ITelephonyService…

• Abstraction of some operations

Page 41: Deep Inside Android Hacks

Media Controller on the Lock Screen

• Android 4.0 and above (up to Android 4.2)

• RemoteControlClient and IRemoteControlDisplay

Media Application

RemoteControl Client

Lock Screen

IRemoteControlDisplay

Publish media state

Transport Control

AudioManager

Page 42: Deep Inside Android Hacks

Media Controller on the Lock Screen

• Android 4.0 and above (up to Android 4.2)

• RemoteControlClient and IRemoteControlDisplay

Media Application

RemoteControl Client

Lock Screen

IRemoteControlDisplay

Publish media state

Transport Control

AudioManager

Page 43: Deep Inside Android Hacks

IRemoteControlDisplay

// in IRemoteControlDisplay.aidlpackage android.media;

oneway interface IRemoteControlDisplay { // various methods declared…}

// in Java codepublic class RemoteControlDisplay extends IRemoteControlDisplay.Stub { // various implementations here…}

Page 44: Deep Inside Android Hacks

AudioManager

private final AudioManager mAudioManager;private final IRemoteControlDisplay mDisplay;

public void setUp() throws Exception { Method register = mAudioManager.getClass().getDeclaredMethod( “registerRemoteControlDisplay”, IRemoteControlDisplay.class); register.invoke(mAudioManager, mDisplay);}

public void tearDown() throws Exception { Method unregister = mAudioManager.getClass().getDeclaredMethod( “unregisterRemoteControlDisplay”, IRemoteControlDisplay.class); unregister(mAudioManager, mDisplay);}

Page 45: Deep Inside Android Hacks

AIDL Versioning

• IRemoteControlDisplay

• IRemoteControlDisplay is available from ICS

• New method is added on JB

• But…

• The method name is the same (overloaded)

• AIDL does not support overloading

Page 46: Deep Inside Android Hacks

Workaround for method overload

• AIDL definition

• Keep the latest

• Java implementation

• Declare every version of overloaded methods

Page 47: Deep Inside Android Hacks

IRemoteControlDisplay

// ICS versiononeway interface IRemoteControlDisplay {setPlaybackState(int id, int state, long stateChangeTimeMs);

}

// JB versiononeway interface IRemoteControlDisplay {setPlaybackState(int id, int state, long stateChangeTimeMs, long currentPosMs, float speed);

}

Page 48: Deep Inside Android Hacks

IRemoteControlDisplay

public class RemoteControlDisplay extends IRemoteControlDisplay.Stub { public void setPlaybackState(int id, int state, long stateChangeTimeMs) {

}

@Override public void setPlaybackState(int id, int state, long stateChangeTimeMs, long currentPosMs, float speed) {

}}

Page 49: Deep Inside Android Hacks
Page 50: Deep Inside Android Hacks

Internal AIDL usage

• Be aware of method declaration

• If no method found, the app will crash

• Keep compatible

• Define the same signature method on implementation

Page 51: Deep Inside Android Hacks
Page 52: Deep Inside Android Hacks

“Don’t be afraid. Keep calm and happy hacking!”

Page 53: Deep Inside Android Hacks

Deep Inside Android HacksKeishin Yokomaku (KeithYokoma) @ Drivemode, Inc.

Android All Stars