Security purchases checker & validator for Android
BillingProtector is a tiny and robust library for Android, entirely written in Kotlin. Its main purpose is to check the android device state & to provide a way to execute purchases just when it is safe. Plus, it allows you to block a transition process if the application has been hacked or patched, if the device environment is corrupted or if any other suspicious conditions are detected; it can also be used to prevent your apps from being executed on an unprotected/insecure operative system, like Snapchat does with rooted devices.
Hacking android applications is way easier than how it is thought to be. Softwares like Lucky Patcher are written to bypass all your first-line defenses and to edit your app executable code, redirecting your purchases to the pirate app, and not to the Google Play Store. I've been implmenting by myself a complex and different security scheme each time, then I decided to put everything together and to realize this project, in parallel with CryptoPrefs. Remember that a skilled hacker will always find a way to crack your code. This library is a harsh barrier that will stop the 99% of the others.
BillingProtector uses jitpack as package repository. To use it you need to add that line to your project build.gradle file:
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}
And the dependency to your module build.gradle file:
dependencies {
implementation 'com.github.AndreaCioccarelli:BillingProtector:1.4.0'
}
BillingProtector has different functionalities and can be used for different purposes.
val bp = BillingProtector(context)
The code shown above creates an instance of the BillingProtector clas, passing as only argument the context of an application/activity.
You don't need to destroy any reference to that object in onDestroy()
since it doesn't hook with your context.
if (bp.isRootInstalled()) {
finish()
}
The method isRootInstalled()
is going to execute a built-in unix program to determine if the binary su
(the root permission controller) is present on the system, and it will analyze the path of that binary. From this evaluation the result is returned.
This method is safe at 100% for 3 reasons.
su
and analyzing the command stdout and stderr. This is slow, unefficient, thread-blocking, it requires your app to ask for root permissions and, in some cases of incompatibility / broken installation, it will freeze your app.su
command.if (bp.arePirateAppsInstalled()) {
for (app in bp.getPirateAppsList()) {
toast(app.packageName)
}
finish()
}
The method arePirateAppsInstalled()
is a simple iteration that goes through every installed package to check if one of them matches with the analysis metadata bundled in the library.
The method getPirateAppsList()
returns a list of PirateApp
s, that you can display to the user, launch in the system settings, retrive a specific package name or prompting to uninstall the selected software.
Warning:
arePirateAppsInstalled()
in a property. Always evaluate it at run-time, because your app can be cracked otherwise (Also if no user will probably have way know it, he'd have to open e.g. Lucky Patcher, patch your app, launch it, uninstall Lucky Patcher, wait you to get on the purchase page and then install it again to compleate the process), following a basic memory injection attack.bp.getRootBinatyPath()
This method returns the absolute path of the su
binary, if present. If not, an empty string is returned.
To operate with this file you need root permission since it will be placed in a protected file system zone.
This method works if you don't require root permissions too.