How to scan firmwares to spot debuggable apps in them and achieve a system shell on your phone/tablet
Posted: Mon Nov 11, 2024 12:24 pm
This is a guide to find debuggable apps inside android firmwares and update.zip files. Debuggable apps with system shared uid can allow privilege escalation from uid 2000 (adb shell) to uid 1000 (system). Any android app in existence has a package name, then if them have the property android:debuggable=”true” after application tag them will be debuggable. You can modify any app to have this tag if it is not a system app and if it doesn’t have signature checks like init.d scripts support app which would prevent apk modifications but this is pointless. We will see now why it is pointless, let’s explain some stuff first. Android is based on Linux, but his kernel is hybrid. It hereditated the Linux permissions scheme but them work a bit differently than a normal Linux system. On a normal Linux system users have id 1000 as user identifier and it’s almost unprivileged, and to do actions that require real privileges (they still can do actions on files they own but it’s pointless) they require to invoke sudo or directly enter the superuser account as “sudo su”, you can as well login to another user with “login $USER” where $USER is the other user username, insert his password and you will then obtain a shell as him. This is limited as on /etc/passwd you won’t be able to access users that do not have /bin/sh or /bin/bash and these users include Linux services. Why I’m teaching you all this? Better understanding and free stuff i guess but let’s go ahead. How this reflects
on android? On android users except root are hold by apps, system apps hold uid 1000, but not all apps that come preinstalled with the device have it, only ones with android:sharedUserId=”android.uid.system” in the <manifest> tag are real system apps, other ones are fake ones actually, if you check their uid using https://github.com/MuntashirAkon/AppMan ... ses/latest you will find out that their uid is
far superior to 1000. But don’t get tricked, on Linux lower is the uid more powerful is the user, root is 0, system is 1000 which represents the system and on the desktop a normal user, then there are
other users. Here is a good page but not all seems to be correct probably because was taken from a device and ids after 1000 can change (user apps ones only and maybe others) so cross check it:https://sonyxperiadev.github.io/ChkBugR ... 00008.html. As you can see there are other ids, like android.media that can be hold by apps, and if you manage to find an app with that you could get a shell as android.media which is the id that manages files in android. Anyway, let’s explain how to run a shell as a debuggable app first: install the app, then:
adb shell
run-as com.example
Replace com.example with the app package name, you can get it from manifest looking manually, or by looking at the apk by MiXplorer, or by AppManager. If there aren’t issues you will be granted a shell in a new line in the data directory of the app, then with “id” you can check if you have uid 1000, if you do congrats, else maybe you used an app with another shared uid so check it’s the correct one, if the id is 1000x and up and doesn’t match any of the shared uids (note that the link i provided previously could not be always correct so check elsewhere), you can also check the app signature comparing to one of the system ones or more, it has to match, this is another requirement for this kind of privilege escalation, if signature doesn’t match the app won’t be allowed to be part of the system or any other shared uid it has, this is why I was telling at the start that modding apps is pointless, everyone is good enough to add a bunch of strings to apps, but why is so difficult to get
system shells? Obviously there are checks to prevent tampering. The only way to get this kind of privilege escalation is to find these apps on original firmwares and update.zips from the OEM. This is the purpose of this guide. This guide requires wsl or a Linux system. To do the scan you need this first:https://github.com/Skorpion96/scan_apk_for_debuggable (I suggest you to use the aapt only as it’s much more faster than the other one), get any firmware from the manufacturer, if it is zip open
it, if it has a system directory you can extract it, same for vendor, then go on your file manager search bar and enter the system folder, search “.apk” on Linux or “*.apk” on windows, copy all the files or cut them, create a new folder in the one where you downloaded the script and name it for example apk, then paste inside this new folder the apk files you copied or cutted previously. Then install aapt: sudo apt-get install python3 -y && pip install pip3 && pip3 install aapt [enter] after everything completes you can run the script:
cd Downloads (or the folder where you have the script)
chmod +x scan_apk_for_debuggable-aapt-only.sh
./scan_apk_for_debuggable-aapt-only.sh apk (or the name of the folder you used for the apks)
Wait for the scan to complete, it will tell you at the end if will find any debuggable app and if there are with shared uid. If you happen to find some try to install them on the device and run-as package.name. Obviously not always firmwares are this way, sometimes they have a system.img, vendor.img and cache.img (not all of them always), you may need to open them with 7zip or mount as disk image on Linux, but if doesn’t work before that you may want to: simg2img system.img system.ext4.img, if the cmd generates the other image mount that instead. You can try to fix the filesystem with "fsck system.img" or "fsck system.ext4.img" if linux still fails to mount the image. If it tells it’s not a sparse image and you can’t mount the original as well you can install binwalk: sudo apt-get install binwalk (or use the guide for your distribution), then: "binwalk -e system.img" it may extract the image or give you informations, for example if it tells you yaffs system image you must use this method to extract the image (after getting info if you see it’s not extracting or it’s going crazy just ctrl+c):
sudo unyaffs system.img out
Then copy the apks from out directory using search functionality like i explained previously. If the image is squashfs:
sudo unsquashfs system.img out
If you have super.img use lpunpack to extract it first:lpunpack super.img (use this:https://xdaforums.com/attachments/otato ... z.6165221/)
Can happen the image is encrypted, for example rabbit r1 one is, in that case binwalk may be able to extract the content: binwalk -e -M system.img
Another case may be if the system image is split in more parts, in that case, extract the ones which are heavy, there may be ones that are few kb, just ignore those and extract the others, then you can:
mv system_1.img system.img
binwalk -e system.img
select all the apk files or zips or them may be other formats, then cut them and paste in a new folder called apk
cd apk && rename "s/.zip$/.apk/" **.zip && cd ..
./scan_apk_for_debuggable-aapt-only.sh apk
repeat the process for every part of the system
Another way could be for example to rename system_1.raw.img to system.img.0000, system_2.raw.img to system.img.0001 and so on, then use programs like peazip to open the first part of the system, in this case system.img.0001, if you are lucky you will see all system.img contents, then you can use peazip search function and search *.apk and extract all apks on apk folder to then analyze them using the scan_apk_for_debuggable-aapt-only.sh. During the opening of system.img.0000 at the question "Disambiguation: open file as new archive" select yes. after the search first press CTRL+A to select all apks, then during the extraction select "Extract (without path)", this will ensure apks will be on the root of apk folder.
The guide is complete with this, I hope it will help you achieving system privileges on your devices.
on android? On android users except root are hold by apps, system apps hold uid 1000, but not all apps that come preinstalled with the device have it, only ones with android:sharedUserId=”android.uid.system” in the <manifest> tag are real system apps, other ones are fake ones actually, if you check their uid using https://github.com/MuntashirAkon/AppMan ... ses/latest you will find out that their uid is
far superior to 1000. But don’t get tricked, on Linux lower is the uid more powerful is the user, root is 0, system is 1000 which represents the system and on the desktop a normal user, then there are
other users. Here is a good page but not all seems to be correct probably because was taken from a device and ids after 1000 can change (user apps ones only and maybe others) so cross check it:https://sonyxperiadev.github.io/ChkBugR ... 00008.html. As you can see there are other ids, like android.media that can be hold by apps, and if you manage to find an app with that you could get a shell as android.media which is the id that manages files in android. Anyway, let’s explain how to run a shell as a debuggable app first: install the app, then:
adb shell
run-as com.example
Replace com.example with the app package name, you can get it from manifest looking manually, or by looking at the apk by MiXplorer, or by AppManager. If there aren’t issues you will be granted a shell in a new line in the data directory of the app, then with “id” you can check if you have uid 1000, if you do congrats, else maybe you used an app with another shared uid so check it’s the correct one, if the id is 1000x and up and doesn’t match any of the shared uids (note that the link i provided previously could not be always correct so check elsewhere), you can also check the app signature comparing to one of the system ones or more, it has to match, this is another requirement for this kind of privilege escalation, if signature doesn’t match the app won’t be allowed to be part of the system or any other shared uid it has, this is why I was telling at the start that modding apps is pointless, everyone is good enough to add a bunch of strings to apps, but why is so difficult to get
system shells? Obviously there are checks to prevent tampering. The only way to get this kind of privilege escalation is to find these apps on original firmwares and update.zips from the OEM. This is the purpose of this guide. This guide requires wsl or a Linux system. To do the scan you need this first:https://github.com/Skorpion96/scan_apk_for_debuggable (I suggest you to use the aapt only as it’s much more faster than the other one), get any firmware from the manufacturer, if it is zip open
it, if it has a system directory you can extract it, same for vendor, then go on your file manager search bar and enter the system folder, search “.apk” on Linux or “*.apk” on windows, copy all the files or cut them, create a new folder in the one where you downloaded the script and name it for example apk, then paste inside this new folder the apk files you copied or cutted previously. Then install aapt: sudo apt-get install python3 -y && pip install pip3 && pip3 install aapt [enter] after everything completes you can run the script:
cd Downloads (or the folder where you have the script)
chmod +x scan_apk_for_debuggable-aapt-only.sh
./scan_apk_for_debuggable-aapt-only.sh apk (or the name of the folder you used for the apks)
Wait for the scan to complete, it will tell you at the end if will find any debuggable app and if there are with shared uid. If you happen to find some try to install them on the device and run-as package.name. Obviously not always firmwares are this way, sometimes they have a system.img, vendor.img and cache.img (not all of them always), you may need to open them with 7zip or mount as disk image on Linux, but if doesn’t work before that you may want to: simg2img system.img system.ext4.img, if the cmd generates the other image mount that instead. You can try to fix the filesystem with "fsck system.img" or "fsck system.ext4.img" if linux still fails to mount the image. If it tells it’s not a sparse image and you can’t mount the original as well you can install binwalk: sudo apt-get install binwalk (or use the guide for your distribution), then: "binwalk -e system.img" it may extract the image or give you informations, for example if it tells you yaffs system image you must use this method to extract the image (after getting info if you see it’s not extracting or it’s going crazy just ctrl+c):
sudo unyaffs system.img out
Then copy the apks from out directory using search functionality like i explained previously. If the image is squashfs:
sudo unsquashfs system.img out
If you have super.img use lpunpack to extract it first:lpunpack super.img (use this:https://xdaforums.com/attachments/otato ... z.6165221/)
Can happen the image is encrypted, for example rabbit r1 one is, in that case binwalk may be able to extract the content: binwalk -e -M system.img
Another case may be if the system image is split in more parts, in that case, extract the ones which are heavy, there may be ones that are few kb, just ignore those and extract the others, then you can:
mv system_1.img system.img
binwalk -e system.img
select all the apk files or zips or them may be other formats, then cut them and paste in a new folder called apk
cd apk && rename "s/.zip$/.apk/" **.zip && cd ..
./scan_apk_for_debuggable-aapt-only.sh apk
repeat the process for every part of the system
Another way could be for example to rename system_1.raw.img to system.img.0000, system_2.raw.img to system.img.0001 and so on, then use programs like peazip to open the first part of the system, in this case system.img.0001, if you are lucky you will see all system.img contents, then you can use peazip search function and search *.apk and extract all apks on apk folder to then analyze them using the scan_apk_for_debuggable-aapt-only.sh. During the opening of system.img.0000 at the question "Disambiguation: open file as new archive" select yes. after the search first press CTRL+A to select all apks, then during the extraction select "Extract (without path)", this will ensure apks will be on the root of apk folder.
The guide is complete with this, I hope it will help you achieving system privileges on your devices.