Learn to Block Lucky Patcher in Android apps, in mobile CI/CD with a Data-Driven DevSecOps™ build system.
What is Lucky Patcher?
Lucky Patcher is a free ‘app modifier’ app used for cheating in Android mobile games. Although there are both root and no-root versions of Lucky Patcher, the more powerful hacking/modding functions require root access or Rooting Android. On rooted devices, Lucky Patcher enables more powerful functions, such as the ability to bypass in-app purchases, obtain special game powers, disable ads in mobile games, or turn off licensing verification to play premium games for free.
Why Block Lucky Patcher in Android Apps?
Lucky Patcher is harmful to mobile games and game developers for several reasons. For one, gamers/hackers can use Lucky Patcher to bypass license validation and/or disable mobile advertising – the two primary revenue sources for most mobile games. In addition, blocking Lucky Patcher preserves the integrity of the game and prevents attrition from non-cheaters who are frustrated by the growing number of players who use tools like Lucky Patcher to gain advantages at the expense of honest players. Appdome’s Root Detection feature allows app developers to quickly and easily protect apps against Rooting, by blocking apps such as Lucky Patcher that rely on Android rooting and root cloaking in order to enable the more powerful cheating features.
Prerequisites for Using Root Detection:
To use Appdome’s mobile app security build system to Block Lucky Patcher , you’ll need:
- Appdome account (create a free Appdome account here)
- A license for Root Detection
- Mobile App (.apk or .aab for Android)
- Signing Credentials (see Signing Secure Android apps and Signing Secure iOS apps)
Block Lucky Patcher on Android apps using Appdome
On Appdome, follow these 3 simple steps to create self-defending Android Apps that Block Lucky Patcher without an SDK or gateway:
-
Upload the Mobile App to Appdome.
-
Upload an app to Appdome’s Mobile App Security Build System
-
Upload Method: Appdome Console or DEV-API
-
Android Formats: .apk or .aab
-
Root Detection Compatible With: Java, JS, C++, C#, Kotlin, Flutter, React Native, Unity, Xamarin, Cordova and other Android apps
-
-
Build the feature: Root Detection.
-
Building Root Detection by using Appdome’s DEV-API:
-
Create and name the Fusion Set (security template) that will contain the Root Detection feature as shown below:
-
Follow the steps in Sections 2.2.1-2.2.2 of this article, Building the Root Detection feature via Appdome Console, to add the Root Detection feature to this Fusion Set.
-
Open the Fusion Set Detail Summary by clicking the “...” symbol on the far-right corner of the Fusion Set, as shown in Figure 1 above, and get the Fusion Set ID from the Fusion Set Detail Summary (as shown below):
Figure 2: Fusion Set Detail Summary
Note: Annotating the Fusion Set to identify the protection(s) selected is optional only (not mandatory). -
Follow the instructions below to use the Fusion Set ID inside any standard mobile DevOps or CI/CD toolkit like Bitrise, App Center, Jenkins, Travis, Team City, Circle CI or other system:
-
Build an API for the app – for instructions, see the tasks under Appdome API Reference Guide
-
Look for sample APIs in Appdome’s GitHub Repository
-
Figure 1: Fusion Set that will contain the Root Detection feature
Note: Naming the Fusion Set to correspond to the protection(s) selected is for illustration purposes only (not required). -
-
Building the Root Detection feature via Appdome Console
To build the Root Detection protection by using Appdome Console, follow the instructions below.
-
Where: Inside the Appdome Console, go to Build > Security Tab > OS Integrity section.
-
When you select the Root Detection you'll notice that your Fusion Set you created in step 2.1.1 now bears the icon of the protection category that contains Root Detection
Figure 4: Fusion Set that displays the newly added Root Detection protection
-
Click Build My App at the bottom of the Build Workflow (shown in Figure 3).
-
Congratulations! The Root Detection protection is now added to the mobile app
-
Using Threat-Events™ for Lucky Patcher Intelligence and Control in Android Apps
Appdome Threat-Events™ provides consumable in-app mobile app attack intelligence and defense control when Lucky Patcher is detected. To consume and use Threat-Events™ for Lucky Patcher in Android Apps, use registerReceiver in the Application OnCreate, and the code samples for Threat-Events™ for Lucky Patcher shown below.
The specifications and options for Threat-Events™ for Lucky Patcher are:
Threat-Event™ Elements | Block Lucky Patcher Method Detail |
---|---|
Appdome Feature Name | Root Detection |
Threat-Event Mode | |
OFF, IN-APP DEFENSE | Appdome detects, defends and notifies user (standard OS dialog) using customizable messaging. |
ON, IN-APP DETECTION | Appdome detects the attack or threat and passes the event in a standard format to the app for processing (app chooses how and when to enforce). |
ON, IN-APP DEFENSE | Uses Appdome Enforce mode for any attack or threat and passes the event in a standard format to the app for processing (gather intel on attacks and threats without losing any protection). |
Certified Secure™ Threat Event Check | |
Visible in ThreatScope™ | |
Developer Parameters for Blocking Lucky Patcher Threat-Event™ | |
Threat-Event NAME | RootedDevice |
Threat-Event DATA | reasonData |
Threat-Event CODE | reasonCode |
Threat-Event REF | 6109 |
Threat-Event SCORE | |
currentThreatEventScore | Current Threat-Event score |
threatEventsScore | Total Threat-events score |
Threat-Event Context Keys | |
---|---|
message | Message displayed for the user on event |
externalID | The external ID of the event which can be listened via Threat Events |
osVersion | OS version of the current device |
deviceModel | Current device model |
deviceManufacturer | The manufacturer of the current device |
fusedAppToken | The task ID of the Appdome fusion of the currently running app |
kernelInfo | Info about the kernel: system name, node name, release, version and machine. |
carrierPlmn | PLMN of the device |
deviceID | Current device ID |
reasonCode | Reason code of the occured event |
buildDate | Appdome fusion date of the current application |
devicePlatform | OS name of the current device |
carrierName | Carrier name of the current device |
updatedOSVersion | Is the OS version up to date |
deviceBrand | Brand of the device |
deviceBoard | Board of the device |
buildUser | Build user |
buildHost | Build host |
sdkVersion | Sdk version |
timeZone | Time zone |
deviceFaceDown | Is the device face down |
locationLong | Location longitude conditioned by location permission |
locationLat | Location latitude conditioned by location permission |
locationState | Location state conditioned by location permission |
wifiSsid | Wifi SSID |
wifiSsidPermissionStatus | Wifi SSID permission status |
internalError | Internal error code as hex |
extendedMessageText | Internal error code |
rInternalErrorCode | Internal error code |
reason | Reason for the root detection |
With Threat-Events™ enabled (turned ON), Android developers can get detailed attack intelligence and granular defense control in Android applications and create amazing user experiences for all mobile end users when Lucky Patcher is detected.
The following is a code sample for native Android apps, which uses all values in the specification above for Root Detection:
Java
x
1
22
1
21
1
IntentFilter intentFilter = new IntentFilter();
2
intentFilter.addAction("RootedDevice");
3
BroadcastReceiver threatEventReceiver = new BroadcastReceiver() {
4
@Override
5
public void onReceive(Context context, Intent intent) {
6
String message = intent.getStringExtra("message"); // Message shown to the user
7
String reasonData = intent.getStringExtra("reasonData"); // Threat detection cause
8
String reasonCode = intent.getStringExtra("reasonCode"); // Event reason code
9
String currentThreatEventScore = intent.getStringExtra("currentThreatEventScore"); // Current threat event score
10
String threatEventsScore = intent.getStringExtra("threatEventsScore"); // Total threat events score
11
String variable = intent.getStringExtra("<Context Key>"); // Any other event specific context key
12
​
13
// Your logic goes here (Send data to Splunk/Dynatrace/Show Popup...)
14
}
15
};
16
​
17
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
18
registerReceiver(threatEventReceiver, intentFilter, Context.RECEIVER_NOT_EXPORTED);
19
} else {
20
registerReceiver(threatEventReceiver, intentFilter);
21
}
Kotlin
x
1
20
1
val intentFilter = IntentFilter()
2
intentFilter.addAction("RootedDevice")
3
val threatEventReceiver = object : BroadcastReceiver() {
4
override fun onReceive(context: Context?, intent: Intent?) {
5
var message = intent?.getStringExtra("message") // Message shown to the user
6
var reasonData = intent?.getStringExtra("reasonData") // Threat detection cause
7
var reasonCode = intent?.getStringExtra("reasonCode") // Event reason code
8
var currentThreatEventScore = intent?.getStringExtra("currentThreatEventScore") // Current threat event score
9
var threatEventsScore = intent?.getStringExtra("threatEventsScore") // Total threat events score
10
var variable = intent?.getStringExtra("<Context Key>") // Any other event specific context key
11
​
12
// Your logic goes here (Send data to Splunk/Dynatrace/Show Popup...)
13
}
14
}
15
​
16
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
17
registerReceiver(threatEventReceiver, intentFilter, Context.RECEIVER_NOT_EXPORTED)
18
} else {
19
registerReceiver(threatEventReceiver, intentFilter)
20
}
React Native
x
24
24
1
const { ADDevEvents } = NativeModules;
2
const aDDevEvents = new NativeEventEmitter(ADDevEvents);
3
4
function registerToDevEvent(action, callback) {
5
NativeModules.ADDevEvents.registerForDevEvent(action);
6
aDDevEvents.addListener(action, callback);
7
}
8
9
export function registerToAllEvents() {
10
registerToDevEvent(
11
"RootedDevice",
12
(userinfo) => Alert.alert(JSON.stringify(userinfo))
13
14
var message = userinfo["message"] // Message shown to the user
15
var reasonData = userinfo["reasonData"] // Threat detection cause
16
var reasonCode = userinfo["reasonCode"] // Event reason code
17
var currentThreatEventScore = userinfo["currentThreatEventScore"] // Current threat event score
18
var threatEventsScore = userinfo["threatEventsScore"] // Total threat events score
19
var variable = userinfo["<Context Key>"] // Any other event specific context key
20
21
// Your logic goes here (Send data to Splunk/Dynatrace/Show Popup...)
22
);
23
}
24
Xamarin/MAUI Android
x
16
16
1
RegisterReceiver(new ThreatEventReceiver(), new IntentFilter("RootedDevice"));
2
3
class ThreatEventReceiver : BroadcastReceiver
4
{
5
public override void OnReceive(Context context, Intent intent)
6
{
7
String message = intent.GetStringExtra("message"); // Message shown to the user
8
String reasonData = intent.GetStringExtra("reasonData"); // Threat detection cause
9
String reasonCode = intent.GetStringExtra("reasonCode"); // Event reason code
10
String currentThreatEventScore = intent.GetStringExtra("currentThreatEventScore"); // Current threat event score
11
String threatEventsScore = intent.GetStringExtra("threatEventsScore"); // Total threat events score
12
String variable = intent.GetStringExtra("<Context Key>"); // Any other event specific context key
13
14
// Your logic goes here (Send data to Splunk/Dynatrace/Show Popup...)
15
}
16
}
Xamarin/MAUI iOS
12
1
NSNotificationCenter.DefaultCenter.AddObserver(
2
(NSString)"RootedDevice", // Threat-Event Identifier
3
delegate (NSNotification notification)
4
{
5
var message = notification.UserInfo.ObjectForKey("message"); // Message shown to the user
6
var reasonData = notification.UserInfo.ObjectForKey("reasonData"); // Threat detection cause
7
var reasonCode = notification.UserInfo.ObjectForKey("reasonCode"); // Event reason code
8
var currentThreatEventScore = notification.UserInfo.ObjectForKey("currentThreatEventScore"); // Current threat event score
9
var threatEventsScore = notification.UserInfo.ObjectForKey("threatEventsScore"); // Total threat events score
10
var variable = notification.UserInfo.ObjectForKey("<Context Keys>"); // Any other event specific context key
11
// Your logic goes here (Send data to Splunk/Dynatrace/Show Popup...)
12
});
Cordova
x
10
10
1
window.broadcaster.addEventListener("RootedDevice", function(userInfo) {
2
var message = userInfo.message // Message shown to the user
3
var reasonData = userInfo.reasonData // Threat detection cause
4
var reasonCode = userInfo.reasonCode // Event reason code
5
var currentThreatEventScore = userInfo.currentThreatEventScore // Current threat event score
6
var threatEventsScore = userInfo.threatEventsScore // Total threat events score
7
var variable = userInfo.<Context Key> // Any other event specific context key
8
9
// Your logic goes here (Send data to Splunk/Dynatrace/Show Popup...)
10
});
Flutter
xxxxxxxxxx
44
1
import 'dart:async';
2
​
3
import 'package:flutter/material.dart';
4
import 'package:flutter/services.dart';
5
​
6
class PlatformChannel extends StatefulWidget {
7
const PlatformChannel({super.key});
8
​
9
@override
10
State<PlatformChannel> createState() => _PlatformChannelState();
11
}
12
​
13
class _PlatformChannelState extends State<PlatformChannel> {
14
static const String _eventChannelName = 'RootedDevice'; // Replace with your EventChannel name
15
static const EventChannel _eventChannel = EventChannel(_eventChannelName);
16
​
17
@override
18
void initState() {
19
super.initState();
20
_eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);
21
}
22
​
23
void _onEvent(Object? event) {
24
setState(() {
25
// Adapt this section based on your specific event data structure
26
var eventData = event as Map;
27
​
28
// Example: Accessing 'externalID' field from the event
29
var externalID = eventData['externalID'];
30
​
31
// Customize the rest of the fields based on your event structure
32
String message = eventData['message']; // Message shown to the user
33
String reasonData = eventData['reasonData']; // Threat detection cause
34
String reasonCode = eventData['reasonCode']; // Event reason code
35
String currentThreatEventScore = eventData['currentThreatEventScore']; // Current threat event score
36
String threatEventsScore = eventData['threatEventsScore']; // Total threat events score
37
​
38
// Any other event specific context key
39
String variable = eventData['<Context Key>'];
40
});
41
}
42
​
43
// Your logic goes here (Send data to Splunk/Dynatrace/Show Popup...)
44
}
Using Appdome, there are no development or coding prerequisites to build secured Android Apps by using Root Detection. There is no SDK and no library to code or implement in the app and no gateway to deploy in your network. All protections are built into each app and the resulting app is self-defending and self-protecting.
Releasing and Publishing Mobile Apps with Root Detection
After successfully securing your app by using Appdome, there are several available options to complete your project, depending on your app lifecycle or workflow. These include:
- Deploying/Publishing Secure mobile apps to Public or Private app stores
- built on Appdome.
Related Articles:
- How to Build Jailbreak Detection, Protect iOS Apps
- How to Build Root Detection, Protect Android Apps
- How to Protect iOS Apps from Jailbreak Detection Bypass Tools
If you have any questions, please send them our way at support.appdome.com or via the chat window on the Appdome platform.
Thank you!
Thanks for visiting Appdome! Our mission is to secure every app on the planet by making mobile app security easy. We hope we’re living up to the mission with your project.