Lifehacks for hackers: how to monitor mobile devices’ filesystem dynamically

I suppose you want to discover how the pre-defined mobile application interacts with the filesystem and precisely understand what happens on the filesystem when this application is active. This guide describes this process for both major platforms – iOS and Android, as of February 13, 2021.

iOS

TL;DR

wget https://github.com/nowsecure/fsmon/releases/download/1.6.1/fsmon-ios -O fsmon161
chmod 755 fsmon161
ldid -e $(which bash) >entitlement.xml
ldid -Sentitlement.xml fsmon161
ps aux | grep "NAME"
./fsmon161 -c -p $(ps aux | grep NAME | tr -s " " | cut -d" " -f2 | head -1)

1 – Jailbreak the device – it’s still legal. For example, use checkra1n.

2 – Download fsmon v1.6.1 application on the device. We emphasize that the latest version might not work.

wget https://github.com/nowsecure/fsmon/releases/download/1.6.1/fsmon-ios -O fsmon161
chmod 755 fsmon161

3 –  On the device, make some adjustments:

ldid -e $(which bash) >entitlement.xml
ldid -Sentitlement.xml fsmon161

4 – Use the fsmon application.

ps aux | grep "NAME" #validate the name
./fsmon161 -c -p $(ps aux | grep NAME | tr -s " " | cut -d" " -f2 | head -1)

Android

For android, we suggest to substitute fsmon tool with inotifywait tool, because fsmon might now work correctly.

TL;DR

git clone --depth=1 https://github.com/dstmath/inotifywait-for-Android.git 
cd inotifywait-for-Android
ndk-build 
adb push /libs/armeabi-v7a/inotifywatch /data/local/tmp/
adb push /libs/armeabi-v7a/inotifywait /data/local/tmp/
adb shell
su
mount -o rw,remount /system
/data/local/tmp/inotifywait -r /data -m | grep -v base.apk

1 – Root the device,

2 – Download ndk-build,

3 – Clone inotifywait git repository and compile the application,

git clone --depth=1 https://github.com/dstmath/inotifywait-for-Android.git  

4 – You probably need to modify ./jni/Application.mk, change “armeabi” to “armeabi-v7a”,

5 – Build the application,

cd inotifywait-for-Android
ndk-build

6 – Push both binaries to an android device,

adb push /libs/armeabi-v7a/inotifywatch /data/local/tmp/
adb push /libs/armeabi-v7a/inotifywait /data/local/tmp/

7 – If needed, ask the /system partition to be writeable,

adb shell
su
mount -o rw,remount /system

8 – Use the inotifywait application.

 /data/local/tmp/inotifywait -r /data -m | grep -v base.apk

Use case

An open-source android game Pixel Dungeon has the achievment system, and I suppose that it stores the achievments locally, so we may try to modify them and get more achievments in an easy way. It could be done relatively quickly:

To repeat:

0 – Install the application,

1 – Start the filesystem monitoring,

/data/local/tmp/inotifywait -r /data/data/com.watabou.pixeldungeon/ -m | grep -v base.apk

2 – At the moment of getting any achievment, press CTRL+C on adb shell to stop the inotifywait process,

/data/local/tmp/inotifywait -r /data/data/com.watabou.pixeldungeon/ -m | grep -v base.apk
Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.
/data/data/com.watabou.pixeldungeon/ CREATE,ISDIR shared_prefs
/data/data/com.watabou.pixeldungeon/ ATTRIB,ISDIR shared_prefs
/data/data/com.watabou.pixeldungeon/ OPEN,ISDIR shared_prefs
/data/data/com.watabou.pixeldungeon/ CLOSE_NOWRITE,CLOSE,ISDIR shared_prefs
/data/data/com.watabou.pixeldungeon/ CREATE,ISDIR files
/data/data/com.watabou.pixeldungeon/ OPEN,ISDIR files
/data/data/com.watabou.pixeldungeon/ CLOSE_NOWRITE,CLOSE,ISDIR files
/data/data/com.watabou.pixeldungeon/ ATTRIB,ISDIR files
/data/data/com.watabou.pixeldungeon/files/ ATTRIB,ISDIR
/data/data/com.watabou.pixeldungeon/shared_prefs/ CREATE PixelDungeon.xml
/data/data/com.watabou.pixeldungeon/shared_prefs/ OPEN PixelDungeon.xml
/data/data/com.watabou.pixeldungeon/shared_prefs/ MODIFY PixelDungeon.xml
/data/data/com.watabou.pixeldungeon/shared_prefs/ CLOSE_WRITE,CLOSE PixelDungeon.xml
/data/data/com.watabou.pixeldungeon/shared_prefs/ ATTRIB PixelDungeon.xml
/data/data/com.watabou.pixeldungeon/shared_prefs/ MOVED_FROM PixelDungeon.xml
/data/data/com.watabou.pixeldungeon/shared_prefs/ MOVED_TO PixelDungeon.xml.bak
/data/data/com.watabou.pixeldungeon/shared_prefs/ CREATE PixelDungeon.xml
/data/data/com.watabou.pixeldungeon/shared_prefs/ OPEN PixelDungeon.xml
/data/data/com.watabou.pixeldungeon/shared_prefs/ MODIFY PixelDungeon.xml
/data/data/com.watabou.pixeldungeon/shared_prefs/ CLOSE_WRITE,CLOSE PixelDungeon.xml
/data/data/com.watabou.pixeldungeon/shared_prefs/ ATTRIB PixelDungeon.xml
/data/data/com.watabou.pixeldungeon/shared_prefs/ DELETE PixelDungeon.xml.bak
/data/data/com.watabou.pixeldungeon/files/ CREATE warrior1.dat
/data/data/com.watabou.pixeldungeon/files/ OPEN warrior1.dat
/data/data/com.watabou.pixeldungeon/files/ ATTRIB warrior1.dat
/data/data/com.watabou.pixeldungeon/files/ MODIFY warrior1.dat
/data/data/com.watabou.pixeldungeon/files/ MODIFY warrior1.dat
/data/data/com.watabou.pixeldungeon/files/ MODIFY warrior1.dat
/data/data/com.watabou.pixeldungeon/files/ CLOSE_WRITE,CLOSE warrior1.dat
/data/data/com.watabou.pixeldungeon/files/ CREATE warrior2.dat
/data/data/com.watabou.pixeldungeon/files/ OPEN warrior2.dat
/data/data/com.watabou.pixeldungeon/files/ ATTRIB warrior2.dat
/data/data/com.watabou.pixeldungeon/files/ MODIFY warrior2.dat
/data/data/com.watabou.pixeldungeon/files/ MODIFY warrior2.dat
/data/data/com.watabou.pixeldungeon/files/ MODIFY warrior2.dat
/data/data/com.watabou.pixeldungeon/files/ CLOSE_WRITE,CLOSE warrior2.dat
/data/data/com.watabou.pixeldungeon/files/ CREATE warrior3.dat
/data/data/com.watabou.pixeldungeon/files/ OPEN warrior3.dat
/data/data/com.watabou.pixeldungeon/files/ ATTRIB warrior3.dat
/data/data/com.watabou.pixeldungeon/files/ MODIFY warrior3.dat
/data/data/com.watabou.pixeldungeon/files/ MODIFY warrior3.dat
/data/data/com.watabou.pixeldungeon/files/ MODIFY warrior3.dat
/data/data/com.watabou.pixeldungeon/files/ CLOSE_WRITE,CLOSE warrior3.dat
/data/data/com.watabou.pixeldungeon/files/ CREATE warrior.dat
/data/data/com.watabou.pixeldungeon/files/ OPEN warrior.dat
/data/data/com.watabou.pixeldungeon/files/ ATTRIB warrior.dat
/data/data/com.watabou.pixeldungeon/files/ MODIFY warrior.dat
/data/data/com.watabou.pixeldungeon/files/ CLOSE_WRITE,CLOSE warrior.dat
/data/data/com.watabou.pixeldungeon/files/ CREATE warrior4.dat
/data/data/com.watabou.pixeldungeon/files/ OPEN warrior4.dat
/data/data/com.watabou.pixeldungeon/files/ ATTRIB warrior4.dat
/data/data/com.watabou.pixeldungeon/files/ MODIFY warrior4.dat
/data/data/com.watabou.pixeldungeon/files/ MODIFY warrior4.dat
/data/data/com.watabou.pixeldungeon/files/ CLOSE_WRITE,CLOSE warrior4.dat
/data/data/com.watabou.pixeldungeon/files/ CREATE badges.dat
/data/data/com.watabou.pixeldungeon/files/ OPEN badges.dat
/data/data/com.watabou.pixeldungeon/files/ ATTRIB badges.dat
/data/data/com.watabou.pixeldungeon/files/ MODIFY badges.dat
/data/data/com.watabou.pixeldungeon/files/ CLOSE_WRITE,CLOSE badges.dat

File badges.dat looks promising.

cat /data/data/com.watabou.pixeldungeon/files/badges.dat
{"badges":["NO_MONSTERS_SLAIN"]}

3 – Google the words “NO_MONSTERS_SLAIN”, find all badges in the source code, and modify the file badges.dat.