SlideShare a Scribd company logo
How to recognise that the user
has just uninstalled your Android
app
fb.me/pjakubczyk
+AleksanderPiotrowski
@pelotasplus
Opera Max
The Java way
Read the broadcast
<receiver android:name=".PackageWatcher">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action
android:name="android.intent.action.PACKAGE_REMOVED"/>
<action
android:name="android.intent.action.PACKAGE_REPLACED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>
Read the broadcast
void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
Iterator<String> it =
bundle.keySet().iterator;
while (it.hasNext()) {
String key = it.next();
Log.e("DDD", key +"="+bundle.get(key)); }
Usually we see (install)
E/DDD (29199): Dumping Intent start
[android.intent.extra.UID=10089]
[android.intent.extra.user_handle=0]
E/DDD (29199): Dumping Intent end
Usually we see (reinstall)
E/DDD (29199): Dumping Intent start
[android.intent.extra.REMOVED_FOR_ALL_USERS=false]
[android.intent.extra.UID=10089]
[android.intent.extra.DATA_REMOVED=false]
[android.intent.extra.REPLACING=true]
[android.intent.extra.user_handle=0]
E/DDD (29199): Dumping Intent end
Usually we see (uninstall)
E/DDD (29199): Dumping Intent start
[android.intent.extra.REMOVED_FOR_ALL_USERS=true]
[android.intent.extra.UID=10089]
[android.intent.extra.DATA_REMOVED=true]
[android.intent.extra.user_handle=0]
E/DDD (29199): Dumping Intent end
Let’s uninstall our app
and there’s nothing ….
Why ?
OS unregisters listener during removal
What Opera does?
It does not listen for package removal
it does some magic ;-)
… not in Java code
Getting the APK
Getting the APK
● genymotion with
gapps installed
● get app from play store
● be careful with the right ABI
Getting the APK
1.adb shell
2.pm list packages
Getting the APK
3. pm path com.opera.max
4. adb pull
/data/app/com.opera.max.apk
Hacking APK
Apktool
A tool for reverse engineering
Android apk files
Made with <3 in Poland ;-)
Apktool
Easy to use
$ apktool d
com.opera.max.apk
Apktool
● decoded XML files
● smali assembly code
● PNGs, layouts, resources
● id-s mapping
with Opera Max APK
live apktool demo
Opera Findings
Found a clue!
There are *.so files
We can inspect them to see more
Tools: strings, objdump, nm, readelf
rudy$ strings opera/lib/armeabi/libuo.so (II)
...
inotify_init
inotify_add_watch
inotify_rm_watch
/data/data/%s/
%s%s
inotify framework
http://linux.die.net/man/7/inotify
The inotify API provides a mechanism
for monitoring file system events.
Inotify can be used to monitor individual
files, or to monitor directories.
rudy$ strings opera/lib/armeabi/libuo.so (I)
...
Android
start
android.intent.action.VIEW
--user
...
am command
part of Android system
/system/bin/am
A way to start apps, intents and
whatnot
more details
$ ps
USER PID PPID
u0_a91 24318 20265 246900 27716 ffffffff b6edf5cc S
com.opera.max
u0_a91 24337 24318 856 336 c00e4944 b6f72158 S
/data/app-lib/com.opera.max-2/libuo.so
The scenario
1. Fork the native process
2. Inside the child process use inotify to watch
a file
3. Watcher is woken up on file deletion. Start
another native process
4. The last process run the ‘am’
(ActivityManager) command to run intent.
Setup
JNI
local.properties
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System,
please read the
sdk.dir=/Users/alek/android-sdk
ndk.dir=/Users/alek/android-ndk-r10e
build.gradle
android.defaultConfig {
applicationId "pl.pelotasplus.actionafteruninstall"
ndk {
moduleName "hello-jni"
ldLibs "log", "android"
stl "stlport_static"
}
}
MainActivity.java declaring
public class MainActivity extends AppCompatActivity {
public native String stringFromJNI();
public native void observer();
static {
System.loadLibrary("hello-jni");
// System.loadLibrary("/data/data/com.foo.test/lib/liba.so");
}
}
MainActivity.java calling
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
textView.setText(stringFromJNI());
observer();
}
project structure
Native code
JNI
Sample by Google
jstring
Java_pl_pelotasplus_actionafteruninstall_MainActivity_stringFro
mJNI
(JNIEnv* env, jobject thiz)
{
return (*env)->NewStringUTF(
env,
"Hello from JNI ! Compiled with ABI foo."
);
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_LDFLAGS += -llog -lpthread
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_ABI := armeabi-v7a
# all
APP_STL := stlport_static
inotify on Linux
int main( int argc, char **argv) {
int length, i = 0;
int fd;
int wd;
char buffer[BUF_LEN];
fd = inotify_init();
printf("fd=%dn", fd);
}
inotify on Linux
int main( int argc, char **argv)
{
[...]
wd = inotify_add_watch(fd, "/var/tmp",
IN_MODIFY | IN_CREATE | IN_DELETE);
length = read( fd, buffer, BUF_LEN );
printf("length=%dn", length);
if (length < 0) {
perror("read");
}
inotify on Linux
while (i < length) {
struct inotify_event *event = (struct inotify_event*)&buffer[ i];
printf("Event len %dn", event->len);
if (event->len) {
if (event->mask & IN_DELETE) {
if (event->mask & IN_ISDIR) {
printf( "The directory %s was deleted.n", event->name );
} else {
printf( "The file %s was deleted.n", event->name );
inotify on Android (pseudo code)
void observer(void) {
inotify_init();
inotify_add_watch(fd, DIRECTORY, IN_DELETE);
if (event->mask & IN_DELETE) {
startIntent();
}
}
first attempt
void
Java_pl_pelotasplus_actionafteruninstall_MainActivity_observer(JNIEnv* env, jobject
thiz)
{
observer();
}
App blocked as native code blocked app
second attempt, with thread
void
Java_pl_pelotasplus_actionafteruninstall_MainActivity_observer
(JNIEnv* env, jobject thiz)
{
pthread_attr_init(&attr);
pthread_create(&thread, &attr, &observer_thread, NULL);
}
App not blocked but native code stopped when stopping app for
uninstalling
third attempt, with fork
void
Java_pl_pelotasplus_actionafteruninstall_MainActivity_observer(JNIEnv* env, jobject thiz)
{
pid_t pid;
pid = fork();
if (pid == 0) {
__android_log_print(ANDROID_LOG_INFO, TAG, "Fork childn");
observer();
}
}
start intent, another fork
void startIntent(void) {
pid_t p = fork();
if (p == 0) {
__android_log_print(ANDROID_LOG_INFO, TAG, "startIntent %d", getpid());
system("/system/bin/am start --user 0 -a
android.intent.action.VIEW -d http://droidcon.de");
}
}
Live demo of our app
https://github.com/
pelotasplus/Action
AfterUninstall
Check the dirty source code
Moral
> What happens when I call fork() in JNI code? Will this totally break the
> Activity lifecycle model in Android?
Don't do this. Just don't.
--
Dianne Hackborn
Android framework engineer
hack...@android.com
http://markmail.org/message/ruqp2t6gvhnhv654

More Related Content

What's hot

Unix Programming with Perl 2
Unix Programming with Perl 2Unix Programming with Perl 2
Unix Programming with Perl 2
Kazuho Oku
 
Стажировка 2016-07-27 02 Денис Нелюбин. PostgreSQL и jsonb
Стажировка 2016-07-27 02 Денис Нелюбин. PostgreSQL и jsonbСтажировка 2016-07-27 02 Денис Нелюбин. PostgreSQL и jsonb
Стажировка 2016-07-27 02 Денис Нелюбин. PostgreSQL и jsonb
SmartTools
 
Unix Programming with Perl
Unix Programming with PerlUnix Programming with Perl
Unix Programming with Perl
Kazuho Oku
 
Continuous testing In PHP
Continuous testing In PHPContinuous testing In PHP
Continuous testing In PHP
Eric Hogue
 
Introduction to puppet - Hands on Session at HPI Potsdam
Introduction to puppet - Hands on Session at HPI PotsdamIntroduction to puppet - Hands on Session at HPI Potsdam
Introduction to puppet - Hands on Session at HPI Potsdam
Christoph Oelmüller
 
Perl web app 테스트전략
Perl web app 테스트전략Perl web app 테스트전략
Perl web app 테스트전략
Jeen Lee
 
Intro django
Intro djangoIntro django
Intro django
Alexander Lyabah
 
Using the Power to Prove
Using the Power to ProveUsing the Power to Prove
Using the Power to Prove
Kazuho Oku
 
Firefox OS learnings & visions, WebAPIs - budapest.mobile
Firefox OS learnings & visions, WebAPIs - budapest.mobileFirefox OS learnings & visions, WebAPIs - budapest.mobile
Firefox OS learnings & visions, WebAPIs - budapest.mobile
Robert Nyman
 
Guarding Your Code Against Bugs with Continuous Testing
Guarding Your Code Against Bugs with Continuous TestingGuarding Your Code Against Bugs with Continuous Testing
Guarding Your Code Against Bugs with Continuous Testing
Eric Hogue
 
EC2
EC2EC2
Commencer avec le TDD
Commencer avec le TDDCommencer avec le TDD
Commencer avec le TDD
Eric Hogue
 
Reactive Web - Servlet & Async, Non-blocking I/O
Reactive Web - Servlet & Async, Non-blocking I/OReactive Web - Servlet & Async, Non-blocking I/O
Reactive Web - Servlet & Async, Non-blocking I/O
Arawn Park
 
NodeJs
NodeJsNodeJs
NodeJs
dizabl
 
The Art Of Application Logging PHPNW12
The Art Of Application Logging PHPNW12The Art Of Application Logging PHPNW12
The Art Of Application Logging PHPNW12
benwaine
 
Debian 5 Hardening Tips
Debian 5 Hardening TipsDebian 5 Hardening Tips
Debian 5 Hardening Tips
s3m1llon
 
Docker for data science
Docker for data scienceDocker for data science
Docker for data science
Calvin Giles
 
Puppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the ForgePuppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the Forge
Puppet
 
Introduction to JavaFX 2
Introduction to JavaFX 2Introduction to JavaFX 2
Introduction to JavaFX 2
Thierry Wasylczenko
 
General fraction
General fractionGeneral fraction
General fraction
Zain ul islam Adil
 

What's hot (20)

Unix Programming with Perl 2
Unix Programming with Perl 2Unix Programming with Perl 2
Unix Programming with Perl 2
 
Стажировка 2016-07-27 02 Денис Нелюбин. PostgreSQL и jsonb
Стажировка 2016-07-27 02 Денис Нелюбин. PostgreSQL и jsonbСтажировка 2016-07-27 02 Денис Нелюбин. PostgreSQL и jsonb
Стажировка 2016-07-27 02 Денис Нелюбин. PostgreSQL и jsonb
 
Unix Programming with Perl
Unix Programming with PerlUnix Programming with Perl
Unix Programming with Perl
 
Continuous testing In PHP
Continuous testing In PHPContinuous testing In PHP
Continuous testing In PHP
 
Introduction to puppet - Hands on Session at HPI Potsdam
Introduction to puppet - Hands on Session at HPI PotsdamIntroduction to puppet - Hands on Session at HPI Potsdam
Introduction to puppet - Hands on Session at HPI Potsdam
 
Perl web app 테스트전략
Perl web app 테스트전략Perl web app 테스트전략
Perl web app 테스트전략
 
Intro django
Intro djangoIntro django
Intro django
 
Using the Power to Prove
Using the Power to ProveUsing the Power to Prove
Using the Power to Prove
 
Firefox OS learnings & visions, WebAPIs - budapest.mobile
Firefox OS learnings & visions, WebAPIs - budapest.mobileFirefox OS learnings & visions, WebAPIs - budapest.mobile
Firefox OS learnings & visions, WebAPIs - budapest.mobile
 
Guarding Your Code Against Bugs with Continuous Testing
Guarding Your Code Against Bugs with Continuous TestingGuarding Your Code Against Bugs with Continuous Testing
Guarding Your Code Against Bugs with Continuous Testing
 
EC2
EC2EC2
EC2
 
Commencer avec le TDD
Commencer avec le TDDCommencer avec le TDD
Commencer avec le TDD
 
Reactive Web - Servlet & Async, Non-blocking I/O
Reactive Web - Servlet & Async, Non-blocking I/OReactive Web - Servlet & Async, Non-blocking I/O
Reactive Web - Servlet & Async, Non-blocking I/O
 
NodeJs
NodeJsNodeJs
NodeJs
 
The Art Of Application Logging PHPNW12
The Art Of Application Logging PHPNW12The Art Of Application Logging PHPNW12
The Art Of Application Logging PHPNW12
 
Debian 5 Hardening Tips
Debian 5 Hardening TipsDebian 5 Hardening Tips
Debian 5 Hardening Tips
 
Docker for data science
Docker for data scienceDocker for data science
Docker for data science
 
Puppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the ForgePuppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the Forge
 
Introduction to JavaFX 2
Introduction to JavaFX 2Introduction to JavaFX 2
Introduction to JavaFX 2
 
General fraction
General fractionGeneral fraction
General fraction
 

Viewers also liked

Uo Inspiration
Uo InspirationUo Inspiration
Uo Inspiration
Cara Cubbage
 
RoboSpock
RoboSpockRoboSpock
lake victoria brotherhood photo alubm presentation 2
lake victoria brotherhood photo alubm presentation 2lake victoria brotherhood photo alubm presentation 2
lake victoria brotherhood photo alubm presentation 2lake victoria brotherhood
 
Robospock droidcon '14
Robospock   droidcon '14Robospock   droidcon '14
Robospock droidcon '14
Przemek Jakubczyk
 
Android accounts & sync
Android accounts & syncAndroid accounts & sync
Android accounts & sync
Przemek Jakubczyk
 
It's always your fault. Poznań ADG 2016
It's always your fault. Poznań ADG 2016It's always your fault. Poznań ADG 2016
It's always your fault. Poznań ADG 2016
Przemek Jakubczyk
 
Récapitulatif de tous les résultats fin 2012des sociétés cotées au 16 Mars 20...
Récapitulatif de tous les résultats fin 2012des sociétés cotées au 16 Mars 20...Récapitulatif de tous les résultats fin 2012des sociétés cotées au 16 Mars 20...
Récapitulatif de tous les résultats fin 2012des sociétés cotées au 16 Mars 20...www.bourse-maroc.org
 
Récapitulatif des résultats au 27 mars 2012
Récapitulatif des résultats au 27 mars 2012Récapitulatif des résultats au 27 mars 2012
Récapitulatif des résultats au 27 mars 2012www.bourse-maroc.org
 

Viewers also liked (9)

Uo Inspiration
Uo InspirationUo Inspiration
Uo Inspiration
 
RoboSpock
RoboSpockRoboSpock
RoboSpock
 
lake victoria brotherhood photo alubm presentation 2
lake victoria brotherhood photo alubm presentation 2lake victoria brotherhood photo alubm presentation 2
lake victoria brotherhood photo alubm presentation 2
 
Robospock droidcon '14
Robospock   droidcon '14Robospock   droidcon '14
Robospock droidcon '14
 
Android accounts & sync
Android accounts & syncAndroid accounts & sync
Android accounts & sync
 
It's always your fault. Poznań ADG 2016
It's always your fault. Poznań ADG 2016It's always your fault. Poznań ADG 2016
It's always your fault. Poznań ADG 2016
 
Récapitulatif de tous les résultats fin 2012des sociétés cotées au 16 Mars 20...
Récapitulatif de tous les résultats fin 2012des sociétés cotées au 16 Mars 20...Récapitulatif de tous les résultats fin 2012des sociétés cotées au 16 Mars 20...
Récapitulatif de tous les résultats fin 2012des sociétés cotées au 16 Mars 20...
 
Upline daily du 29 02 2012
Upline daily du 29 02 2012Upline daily du 29 02 2012
Upline daily du 29 02 2012
 
Récapitulatif des résultats au 27 mars 2012
Récapitulatif des résultats au 27 mars 2012Récapitulatif des résultats au 27 mars 2012
Récapitulatif des résultats au 27 mars 2012
 

Similar to How to recognise that the user has just uninstalled your android app

How to recognise that the user has just uninstalled your app
How to recognise that the user has just uninstalled your appHow to recognise that the user has just uninstalled your app
How to recognise that the user has just uninstalled your app
Aleksander Piotrowski
 
Iwatch tech 1
Iwatch tech 1Iwatch tech 1
Iwatch tech 1
ShailajaMca
 
An inconvenient truth: Evading the Ransomware Protection in windows 10 @ LeHack
An inconvenient truth: Evading the Ransomware Protection in windows 10 @ LeHackAn inconvenient truth: Evading the Ransomware Protection in windows 10 @ LeHack
An inconvenient truth: Evading the Ransomware Protection in windows 10 @ LeHack
Soya Aoyama
 
Jakob Holderbaum - Managing Shared secrets using basic Unix tools
Jakob Holderbaum - Managing Shared secrets using basic Unix toolsJakob Holderbaum - Managing Shared secrets using basic Unix tools
Jakob Holderbaum - Managing Shared secrets using basic Unix tools
DevSecCon
 
Uninstall opera
Uninstall operaUninstall opera
Uninstall opera
Przemek Jakubczyk
 
Gdg san diego android 11 meetups what's new in android - ui and dev tools
Gdg san diego android 11 meetups  what's new in android  - ui and dev toolsGdg san diego android 11 meetups  what's new in android  - ui and dev tools
Gdg san diego android 11 meetups what's new in android - ui and dev tools
Svetlin Stanchev
 
Android
AndroidAndroid
Android
Pranav Ashok
 
Node.js basics
Node.js basicsNode.js basics
Node.js basics
Ben Lin
 
test
testtest
test
jianzong
 
Information track presentation_final
Information track presentation_finalInformation track presentation_final
Information track presentation_final
Kazuki Omo
 
Linux Security APIs and the Chromium Sandbox
Linux Security APIs and the Chromium SandboxLinux Security APIs and the Chromium Sandbox
Linux Security APIs and the Chromium Sandbox
Patricia Aas
 
Gimli: Server Process Monitoring and Fault Analysis
Gimli: Server Process Monitoring and Fault AnalysisGimli: Server Process Monitoring and Fault Analysis
Gimli: Server Process Monitoring and Fault Analysis
Wez Furlong
 
Virus Bulletin 2015: Exposing Gatekeeper
Virus Bulletin 2015: Exposing GatekeeperVirus Bulletin 2015: Exposing Gatekeeper
Virus Bulletin 2015: Exposing Gatekeeper
Synack
 
MacOS forensics and anti-forensics (DC Lviv 2019) presentation
MacOS forensics and anti-forensics (DC Lviv 2019) presentationMacOS forensics and anti-forensics (DC Lviv 2019) presentation
MacOS forensics and anti-forensics (DC Lviv 2019) presentation
OlehLevytskyi1
 
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiGrâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Jérémy Derussé
 
PHP Backdoor: The rise of the vuln
PHP Backdoor: The rise of the vulnPHP Backdoor: The rise of the vuln
PHP Backdoor: The rise of the vuln
Sandro Zaccarini
 
Android dev
Android devAndroid dev
Android dev
yincan sheng
 
FRIDA 101 Android
FRIDA 101 AndroidFRIDA 101 Android
FRIDA 101 Android
Tony Thomas
 
My name is Trinidad
My name is TrinidadMy name is Trinidad
My name is Trinidad
David Calavera
 
Permission enforcement s in android new (1)
Permission   enforcement s  in android new (1)Permission   enforcement s  in android new (1)
Permission enforcement s in android new (1)
Siddhartha Kakarla
 

Similar to How to recognise that the user has just uninstalled your android app (20)

How to recognise that the user has just uninstalled your app
How to recognise that the user has just uninstalled your appHow to recognise that the user has just uninstalled your app
How to recognise that the user has just uninstalled your app
 
Iwatch tech 1
Iwatch tech 1Iwatch tech 1
Iwatch tech 1
 
An inconvenient truth: Evading the Ransomware Protection in windows 10 @ LeHack
An inconvenient truth: Evading the Ransomware Protection in windows 10 @ LeHackAn inconvenient truth: Evading the Ransomware Protection in windows 10 @ LeHack
An inconvenient truth: Evading the Ransomware Protection in windows 10 @ LeHack
 
Jakob Holderbaum - Managing Shared secrets using basic Unix tools
Jakob Holderbaum - Managing Shared secrets using basic Unix toolsJakob Holderbaum - Managing Shared secrets using basic Unix tools
Jakob Holderbaum - Managing Shared secrets using basic Unix tools
 
Uninstall opera
Uninstall operaUninstall opera
Uninstall opera
 
Gdg san diego android 11 meetups what's new in android - ui and dev tools
Gdg san diego android 11 meetups  what's new in android  - ui and dev toolsGdg san diego android 11 meetups  what's new in android  - ui and dev tools
Gdg san diego android 11 meetups what's new in android - ui and dev tools
 
Android
AndroidAndroid
Android
 
Node.js basics
Node.js basicsNode.js basics
Node.js basics
 
test
testtest
test
 
Information track presentation_final
Information track presentation_finalInformation track presentation_final
Information track presentation_final
 
Linux Security APIs and the Chromium Sandbox
Linux Security APIs and the Chromium SandboxLinux Security APIs and the Chromium Sandbox
Linux Security APIs and the Chromium Sandbox
 
Gimli: Server Process Monitoring and Fault Analysis
Gimli: Server Process Monitoring and Fault AnalysisGimli: Server Process Monitoring and Fault Analysis
Gimli: Server Process Monitoring and Fault Analysis
 
Virus Bulletin 2015: Exposing Gatekeeper
Virus Bulletin 2015: Exposing GatekeeperVirus Bulletin 2015: Exposing Gatekeeper
Virus Bulletin 2015: Exposing Gatekeeper
 
MacOS forensics and anti-forensics (DC Lviv 2019) presentation
MacOS forensics and anti-forensics (DC Lviv 2019) presentationMacOS forensics and anti-forensics (DC Lviv 2019) presentation
MacOS forensics and anti-forensics (DC Lviv 2019) presentation
 
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiGrâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
 
PHP Backdoor: The rise of the vuln
PHP Backdoor: The rise of the vulnPHP Backdoor: The rise of the vuln
PHP Backdoor: The rise of the vuln
 
Android dev
Android devAndroid dev
Android dev
 
FRIDA 101 Android
FRIDA 101 AndroidFRIDA 101 Android
FRIDA 101 Android
 
My name is Trinidad
My name is TrinidadMy name is Trinidad
My name is Trinidad
 
Permission enforcement s in android new (1)
Permission   enforcement s  in android new (1)Permission   enforcement s  in android new (1)
Permission enforcement s in android new (1)
 

How to recognise that the user has just uninstalled your android app

  • 1. How to recognise that the user has just uninstalled your Android app fb.me/pjakubczyk +AleksanderPiotrowski @pelotasplus
  • 3.
  • 5. Read the broadcast <receiver android:name=".PackageWatcher"> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED"/> <action android:name="android.intent.action.PACKAGE_REMOVED"/> <action android:name="android.intent.action.PACKAGE_REPLACED"/> <data android:scheme="package"/> </intent-filter> </receiver>
  • 6. Read the broadcast void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); Iterator<String> it = bundle.keySet().iterator; while (it.hasNext()) { String key = it.next(); Log.e("DDD", key +"="+bundle.get(key)); }
  • 7. Usually we see (install) E/DDD (29199): Dumping Intent start [android.intent.extra.UID=10089] [android.intent.extra.user_handle=0] E/DDD (29199): Dumping Intent end
  • 8. Usually we see (reinstall) E/DDD (29199): Dumping Intent start [android.intent.extra.REMOVED_FOR_ALL_USERS=false] [android.intent.extra.UID=10089] [android.intent.extra.DATA_REMOVED=false] [android.intent.extra.REPLACING=true] [android.intent.extra.user_handle=0] E/DDD (29199): Dumping Intent end
  • 9. Usually we see (uninstall) E/DDD (29199): Dumping Intent start [android.intent.extra.REMOVED_FOR_ALL_USERS=true] [android.intent.extra.UID=10089] [android.intent.extra.DATA_REMOVED=true] [android.intent.extra.user_handle=0] E/DDD (29199): Dumping Intent end
  • 10. Let’s uninstall our app and there’s nothing …. Why ? OS unregisters listener during removal
  • 11. What Opera does? It does not listen for package removal it does some magic ;-) … not in Java code
  • 13. Getting the APK ● genymotion with gapps installed ● get app from play store ● be careful with the right ABI
  • 14. Getting the APK 1.adb shell 2.pm list packages
  • 15. Getting the APK 3. pm path com.opera.max 4. adb pull /data/app/com.opera.max.apk
  • 17. Apktool A tool for reverse engineering Android apk files Made with <3 in Poland ;-)
  • 18. Apktool Easy to use $ apktool d com.opera.max.apk
  • 19. Apktool ● decoded XML files ● smali assembly code ● PNGs, layouts, resources ● id-s mapping
  • 20. with Opera Max APK live apktool demo
  • 22. Found a clue! There are *.so files We can inspect them to see more Tools: strings, objdump, nm, readelf
  • 23. rudy$ strings opera/lib/armeabi/libuo.so (II) ... inotify_init inotify_add_watch inotify_rm_watch /data/data/%s/ %s%s
  • 24. inotify framework http://linux.die.net/man/7/inotify The inotify API provides a mechanism for monitoring file system events. Inotify can be used to monitor individual files, or to monitor directories.
  • 25. rudy$ strings opera/lib/armeabi/libuo.so (I) ... Android start android.intent.action.VIEW --user ...
  • 26. am command part of Android system /system/bin/am A way to start apps, intents and whatnot
  • 27. more details $ ps USER PID PPID u0_a91 24318 20265 246900 27716 ffffffff b6edf5cc S com.opera.max u0_a91 24337 24318 856 336 c00e4944 b6f72158 S /data/app-lib/com.opera.max-2/libuo.so
  • 28. The scenario 1. Fork the native process 2. Inside the child process use inotify to watch a file 3. Watcher is woken up on file deletion. Start another native process 4. The last process run the ‘am’ (ActivityManager) command to run intent.
  • 30. local.properties # Location of the SDK. This is only used by Gradle. # For customization when using a Version Control System, please read the sdk.dir=/Users/alek/android-sdk ndk.dir=/Users/alek/android-ndk-r10e
  • 31. build.gradle android.defaultConfig { applicationId "pl.pelotasplus.actionafteruninstall" ndk { moduleName "hello-jni" ldLibs "log", "android" stl "stlport_static" } }
  • 32. MainActivity.java declaring public class MainActivity extends AppCompatActivity { public native String stringFromJNI(); public native void observer(); static { System.loadLibrary("hello-jni"); // System.loadLibrary("/data/data/com.foo.test/lib/liba.so"); } }
  • 33. MainActivity.java calling protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.textView); textView.setText(stringFromJNI()); observer(); }
  • 36. Sample by Google jstring Java_pl_pelotasplus_actionafteruninstall_MainActivity_stringFro mJNI (JNIEnv* env, jobject thiz) { return (*env)->NewStringUTF( env, "Hello from JNI ! Compiled with ABI foo." ); }
  • 37. Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c LOCAL_LDFLAGS += -llog -lpthread include $(BUILD_SHARED_LIBRARY)
  • 38. Application.mk APP_ABI := armeabi-v7a # all APP_STL := stlport_static
  • 39. inotify on Linux int main( int argc, char **argv) { int length, i = 0; int fd; int wd; char buffer[BUF_LEN]; fd = inotify_init(); printf("fd=%dn", fd); }
  • 40. inotify on Linux int main( int argc, char **argv) { [...] wd = inotify_add_watch(fd, "/var/tmp", IN_MODIFY | IN_CREATE | IN_DELETE); length = read( fd, buffer, BUF_LEN ); printf("length=%dn", length); if (length < 0) { perror("read"); }
  • 41. inotify on Linux while (i < length) { struct inotify_event *event = (struct inotify_event*)&buffer[ i]; printf("Event len %dn", event->len); if (event->len) { if (event->mask & IN_DELETE) { if (event->mask & IN_ISDIR) { printf( "The directory %s was deleted.n", event->name ); } else { printf( "The file %s was deleted.n", event->name );
  • 42. inotify on Android (pseudo code) void observer(void) { inotify_init(); inotify_add_watch(fd, DIRECTORY, IN_DELETE); if (event->mask & IN_DELETE) { startIntent(); } }
  • 43. first attempt void Java_pl_pelotasplus_actionafteruninstall_MainActivity_observer(JNIEnv* env, jobject thiz) { observer(); } App blocked as native code blocked app
  • 44. second attempt, with thread void Java_pl_pelotasplus_actionafteruninstall_MainActivity_observer (JNIEnv* env, jobject thiz) { pthread_attr_init(&attr); pthread_create(&thread, &attr, &observer_thread, NULL); } App not blocked but native code stopped when stopping app for uninstalling
  • 45. third attempt, with fork void Java_pl_pelotasplus_actionafteruninstall_MainActivity_observer(JNIEnv* env, jobject thiz) { pid_t pid; pid = fork(); if (pid == 0) { __android_log_print(ANDROID_LOG_INFO, TAG, "Fork childn"); observer(); } }
  • 46. start intent, another fork void startIntent(void) { pid_t p = fork(); if (p == 0) { __android_log_print(ANDROID_LOG_INFO, TAG, "startIntent %d", getpid()); system("/system/bin/am start --user 0 -a android.intent.action.VIEW -d http://droidcon.de"); } }
  • 47. Live demo of our app
  • 49. Moral > What happens when I call fork() in JNI code? Will this totally break the > Activity lifecycle model in Android? Don't do this. Just don't. -- Dianne Hackborn Android framework engineer hack...@android.com http://markmail.org/message/ruqp2t6gvhnhv654