Android Code Snippet Application Lock Impenetrable by crackers

For paid app only.
Two brains are better than one, three are better than two and so on.
I implement this code to protect my apps from illegal uses, crackers and hackers who try to unlock my apps functionality without paying me or my agreement.
My apps are time based, so time is very important flag in my calculation.
I decide to share it with you, to explore its weakness and increase its complexity and make it impenetrable method used by all of us in our apps.
Also to extend it to cover non-time based apps protection.
Let's start:
In manifest file editor, add this code:
B4X:
AddReceiverText(applicationlocker,
    <intent-filter>
        <action android:name="android.intent.action.TIME_SET"/>
        <action android:name="android.intent.action.TIMEZONE_CHANGED"/>
        <action android:name="android.intent.action.TIME_CHANGED"/>
    </intent-filter>
)
Create new service, I named it applicationlocker as the following:
B4X:
#Region  Service Attributes
    #StartAtBoot: True
    
#End Region

' Libraries used: ByteConverter, JavaObject, Encryption and DateUtils

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Service_Create

End Sub

Sub Service_Start (StartingIntent As Intent)
    Service.StopAutomaticForeground 'Call this when the background task completes (if there is one)

    If StartingIntent.Action="android.intent.action.TIMEZONE_CHANGED" Or StartingIntent.Action="android.intent.action.TIME_CHANGED" Or StartingIntent.Action="android.intent.action.TIME_SET" Then
        File.Delete(File.DirInternal,"system")
    End If
    
End Sub

Sub Service_Destroy

End Sub

'check app use is legal
Public Sub islegal() As Boolean
    
    '1- check if system file exist
    If (File.Exists(File.DirInternal,"system"))=False Then Return False
    
    '2- check if file content match the file creation time - not created/copied by illegal user
    Dim filecontent As String=File.ReadString(File.DirInternal,"system")
    Dim filecreationtime As Long = GetCreationTime(File.DirInternal,"system")
    If filecontent<>getMD5(filecreationtime) Then
        File.Delete(File.DirInternal,"system")
        Return False
    End If
    
    '3- check if usetime ellapsed against device datetime
    Dim p As Period=DateUtils.PeriodBetween(filecreationtime,DateTime.Now)
    If p.Months>=1 Then 'used time in months, you can change it according your needs
        File.Delete(File.DirInternal,"system")
        Return False
    End If
    
    '4- check if device datetime changed
    'it will be triggered when change happen and delete "system" file in DirInternal
    'see Service_Start
    
    '5- check last/maximum transaction date in your app database if time diff larger than legal time
    'write your code here .. return False if time consumed
    
    Return True
    
End Sub

'should be called once - example when app purchase or subscription payment done
Public Sub createlockfile
    If File.Exists(File.DirInternal,"system") Then
        File.Delete(File.DirInternal,"system")
        Sleep(200)
        File.WriteString(File.DirInternal,"system",getMD5(GetCreationTime(File.DirInternal,"system")))
    Else
        File.WriteString(File.DirInternal,"system",getMD5(GetCreationTime(File.DirInternal,"system")))
    End If
End Sub

'Android 26+ by @Erel
Sub GetCreationTime (Dir As String, FileName As String) As Long
    Dim Files As JavaObject
    Files.InitializeStatic("java.nio.file.Files")
    Dim FileSystems As JavaObject
    Dim FileSystem As JavaObject = FileSystems.InitializeStatic("java.nio.file.FileSystems").RunMethod("getDefault", Null)
    Dim Path As JavaObject = FileSystem.RunMethod("getPath", Array(File.Combine(Dir, FileName), Array As String()))
    Dim BasicFileAttributes As JavaObject
    BasicFileAttributes.InitializeStatic("java.nio.file.attribute.BasicFileAttributes")
    Dim LinkOptions As JavaObject
    LinkOptions.InitializeArray("java.nio.file.LinkOption", Array())
    Return Files.RunMethodJO("getAttribute", Array(Path, "creationTime", LinkOptions)).RunMethod("toMillis", Null)
End Sub

Sub getMD5(str As String) As String
    Dim md As MessageDigest
    Dim ByteCon As ByteConverter
    Dim md5hash() As Byte
    md5hash = md.GetMessageDigest(str.GetBytes("UTF8"),"MD5")
    Dim md5string As String
    md5string = ByteCon.HexFromBytes(md5hash)
    Return md5string
End Sub
Usage:
  • Call createlockfile function once when:
    • Your app is paid from the beginning (in first run), so the lock file should be created
    • In-app purchase or subscription success
  • Check islegal function everytime you want to check the user is legal
  • Note that islegal function step 3 can be modified according your need, in my example I'm assuming time period one month.
What crackers possible tries:
  • Delete dirinternal "system" file -> the islegal function step 1 disable app use
  • Clone "system" file from device to device -> the islegal function step 2 disable app use
  • If allowed time consumed -> the islegal function step 3 disable app use
  • Change device datetime -> Service_Start disable app use
  • Clone the entire device (including our app) to another device -> that is mean everything will resumed from stopped point in previous device -> useless cracker trick

What other possible tricks crackers think?
Discussion of this scenario and increasing its strength is useful for all of us and making this code anti-hacker-proven method.
 

Hamied Abou Hulaikah

Well-Known Member
Licensed User
Longtime User
Decompile with something like jadx.
Rebuild the apk and resign with your own key.
I think in recent android versions it is impossible to do this and making app run again,
also cracker can't find original sign key or its google play equivalent key to rebuild apk
Now in google play, you will see your app with subtitle: Protected by Google Play , it means app can't rebuilt again without original key, and can't run if rebuilt.
Am I correct?
 

peacemaker

Expert
Licensed User
Longtime User
Rebuild the apk and resign

What about if to make 2 extra checks ?

1) From Market ?
B4X:
'checks if app is installed from Play Market
Sub isFromMarket As Boolean
    Dim Obj1 As Reflector, res As String
    Obj1.Target = Obj1.GetContext
    Obj1.Target = Obj1.RunMethod("getPackageManager")
    res = Obj1.RunMethod2("getInstallerPackageName", Application.PackageName, "java.lang.String")

    If res.ToLowerCase.Contains("vending") Then
        Dim FromMarket As Boolean = True
    Else
        Dim FromMarket As Boolean = False
    End If
    Return FromMarket
End Sub

2) Check APK-signature:
B4X:
If others.GetSignatureHash <> others.mysign Then
    Activity.Finish
    ExitApplication
    Return
End If

....
'compare the app signature with your own SHA-1 like "99:9A:2E:AA:AE:CF:C8:AA:18:C4:73:DA:42" from "Private Sign key" B4A settings dialog
Sub GetSignatureHash As String
    Dim jo As JavaObject
    jo.InitializeContext
    Dim signatures() As Object = jo.RunMethodJO("getPackageManager", Null).RunMethodJO("getPackageInfo", _
     Array (Application.PackageName, 0x00000040)).GetField("signatures")
    Dim sig As JavaObject = signatures(0)
    Dim md As MessageDigest
    Dim hash() As Byte = md.GetMessageDigest(sig.RunMethod("toByteArray", Null), "SHA-1")
    Dim bc As ByteConverter
    Dim raw As String = bc.HexFromBytes(hash)
    Dim sb As StringBuilder
    sb.Initialize
    For i = 0 To raw.Length - 2 Step 2
        sb.Append(raw.CharAt(i)).Append(raw.CharAt(i + 1)).Append(":")
    Next
    sb.Remove(sb.Length - 1, sb.Length)
    Return sb.ToString
End Sub
 

agraham

Expert
Licensed User
Longtime User
Am I correct?
No, just change the package name and sign with a new key. Why should a cracked version be distributed by the Play Store anyway? Protected by Google Play is just a malware check.

I'm not going to prolong this discussion as it seems a bit pointless to me. You will not stop a determined and skillful hacker, only make it a more difficult to the extent that is necessary for it to be not worth the effort. The opcodes are there for the CPU to execute so they can always be decompiled for a hacker to inspect and alter and if necessary recompile from scratch. The more convoluted and impenetrable the code path of your protection is the more difficult it will be for a hacker to understand - particularly if the code is obfuscated. Your solution above is too trivial being a single point check that merely needs a 'return true' patched in to overcome it. Your checks should be distributed around your code and called in non-obvious fashion and checked in multiple places.
 

peacemaker

Expert
Licensed User
Longtime User
rebuilt again
So, it looks like any internal subs returning the BOOLEAN can be edited to return ONE CORRECT reply and repacked.
So, what is the correct way ?
To calculate something with help of some long generated number downloaded from a server ?
How bank apps are made safe?
 

Hamied Abou Hulaikah

Well-Known Member
Licensed User
Longtime User
So, it looks like any internal subs returning the BOOLEAN can be edited to return ONE CORRECT reply and repacked.
Yes as you said, This can be solved by returned different hashed code every call.
@agraham What I point to it, is making impenetrable method for everyone including code programmer himself, by another meaning is one way lock no unlock method for it even for app programmer.
1) From Market ?
Yes this a solution, but what about offline use!
Also hacker can use MITM tricks to modify tcp response as they want.
2) Check APK-signature:
@agraham points for important thing about this, app package name can be modified & cracker uses his own sign key and rebuild!
as it seems a bit pointless to me
never give up ;)

All should rethink again, saving our apps efforts,and at the end crackers are personals like us.
 

udg

Expert
Licensed User
Longtime User
IMHO, the weak point is, as @agraham cleaarly stated above, the "decision point" in the app.
You can set any elaborate scheme before it (server-based, local, whatever) but at one point you will have that IF ok THEN proceed weak point.
This is where the cracker will jump in and set TRUE whatever was calculated/transmitted. before.

So, again following @agraham suggestion, to better protect an app we should put a few decision points here and there, calling them at unexpected times.
Will this make our apps solid as rock? No. Just a lot harder to crack.
But, rember, that given enough skills, power and time, anything could be cracked.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
For many years there was a saying that the purpose of software protection = antipiracy, is to prevent good people from doing bad things.
In the mobile world developers have more protection built-in. It is not trivial to install apps outside of the app store.
The vast majority of users will not go to one of the dubious sites that distribute APKs and cracked APKs.
The users that do download such cracked / distributed apks are probably less likely to buy the app anyway.

My thinking is that for most developers the Google Play built-in protection should suffice.
 

Pendrush

Well-Known Member
Licensed User
Longtime User
This also carries a double risk of cracking than offline app.
This is not true.
You cannot see my server side code, so you get hard time to "crack" anything server side, specially if server side is custom app.
I can see your app code, and you cannot hide it from me easy. You can use C++ (.so) library, but you need to make one with Android NDK, and this is not bulletproof solution, but at least is harder to break.
 

udg

Expert
Licensed User
Longtime User
The users that do download such cracked / distributed apks are probably less likely to buy the app anyway.
This is exactly my way of thinking.
Neither a cracker/pirate nor someone who buys from them would ever be a customer of mine. So, in a way, there's no selling loss I've to worry about.

For a regular, paying customer I send a license key (managed on my server) and that's all. A pirate could steal the license key accessing the device (if user records it on it) or sniffing the https traffic (good luck). Anyway, they ends up with configuration data about the legitimate user (ok, a "privacy" breach but not directly caused by me) so it's almost unuseful to others.
My software is follows the SaaS paradigm, so I can easily invalidate or terminate a license key at any time.
 

Hamied Abou Hulaikah

Well-Known Member
Licensed User
Longtime User
The users that do download such cracked / distributed apks are probably less likely to buy the app anyway.
True
Neither a cracker/pirate nor someone who buys from them would ever be a customer of mine. So, in a way, there's no selling loss I've to worry about.
Good marketing point.

How will you be in case of your app is global, and google analytics tell you have +2 Millions active app use, but in real you only got paid for only 100K ? Is this painful for you? or let it pass.
Yes, SaaS is best solution for online connected users, but what about giant amount of offline users?
 
Top