Skip to content

Commit

Permalink
Updated docs & added blacklisting/whitelisting feature to :antipiracy
Browse files Browse the repository at this point in the history
  • Loading branch information
cioccarellia committed Jan 20, 2024
1 parent 632b2f4 commit f1d292f
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,8 @@ public enum class DatasetEntry(public val type: DatasetType, public val software
MOB_GENIE(DatasetType.PIRATE_STORE, "Mobogenie"),
ONE_MOBILE(DatasetType.PIRATE_STORE, "1Mobile"),
SLIDE_ME(DatasetType.PIRATE_STORE, "Slide Me"),
Z_MARKET(DatasetType.PIRATE_STORE, "Z Market");
Z_MARKET(DatasetType.PIRATE_STORE, "Z Market"),

// Whitelisting / Blacklisting
BLACKLIST(DatasetType.PIRATE_APP, "Manual Blacklist")
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.kevlar.antipiracy.detection.vectors.heuristic

import android.content.pm.ApplicationInfo
import com.kevlar.antipiracy.dataset.DatasetEntry
import com.kevlar.antipiracy.detection.vectors.AntipiracyVector
import com.kevlar.antipiracy.detection.vectors.InputVector
import com.kevlar.antipiracy.detection.vectors.OutputVector
Expand All @@ -27,21 +28,35 @@ internal class HeuristicVector(private val inputVector: InputVector) : Antipirac
applicationInfo: ApplicationInfo,
targets: List<MatchableHeuristicDatasetEntry>
): OutputVector {
val whitelist = inputVector.scanConfiguration.whitelist
val blacklist = inputVector.scanConfiguration.blacklist

if (whitelist.contains(applicationInfo.packageName)) {
return OutputVector(matchingDataset = null)
}

if (blacklist.contains(applicationInfo.packageName)) {
return OutputVector(matchingDataset = DatasetEntry.BLACKLIST)
}

targets.forEach { dataSetUnit ->

// Can have multiple detection policies
dataSetUnit.detectionPolicies.forEach { detectionPolicy ->
val matchingDataset = dataSetUnit.datasetEntry

when (detectionPolicy) {
is DetectionPolicy.PackageNameDetection -> {
// We match the blacklisted package names and check if any is present in applicationInfo
if (detectionPolicy.packageNames.any { it == applicationInfo.packageName }) {
return OutputVector(dataSetUnit.datasetEntry)
return OutputVector(matchingDataset)
}
}

is DetectionPolicy.PackageNameRegex -> {
// We match (with a regex) the blacklisted package name and check if any is present in applicationInfo
if (detectionPolicy.regex.toRegex().matches(applicationInfo.packageName)) {
return OutputVector(dataSetUnit.datasetEntry)
return OutputVector(matchingDataset)
}
}

Expand All @@ -52,7 +67,7 @@ internal class HeuristicVector(private val inputVector: InputVector) : Antipirac
if (className != null && detectionPolicy.regex.toRegex()
.matches(applicationInfo.className)
) {
return OutputVector(dataSetUnit.datasetEntry)
return OutputVector(matchingDataset)
}
}

Expand All @@ -61,7 +76,7 @@ internal class HeuristicVector(private val inputVector: InputVector) : Antipirac
if (detectionPolicy.regex.toRegex()
.matches(applicationInfo.nonLocalizedLabel)
) {
return OutputVector(dataSetUnit.datasetEntry)
return OutputVector(matchingDataset)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ public abstract class Scan {


public data class PirateSoftwareScan(
override val enabled: Boolean
override val enabled: Boolean,
) : Scan()

public data class PirateStoreScan(
override val enabled: Boolean
override val enabled: Boolean,
): Scan()

public data class CollateralScan(
override val enabled: Boolean
override val enabled: Boolean,
): Scan()

public data class CustomScan(
override val enabled: Boolean
override val enabled: Boolean,
): Scan()


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,18 @@ public class ScanConfiguration(
public val stores: PirateStoreScan,
public val collateral: CollateralScan,
public val custom: CustomScan,
public val whitelist: Set<String>,
public val blacklist: Set<String>,
) {

public companion object {
public fun default(): ScanConfiguration = ScanConfiguration(
PirateSoftwareScan(enabled = false),
PirateStoreScan(enabled = false),
CollateralScan(enabled = false),
CustomScan(enabled = false)
pirate = PirateSoftwareScan(enabled = false),
stores = PirateStoreScan(enabled = false),
collateral = CollateralScan(enabled = false),
custom = CustomScan(enabled = false),
whitelist = setOf(),
blacklist = setOf()
)
}
}
Expand All @@ -47,6 +51,9 @@ public class ScanConfigurationBuilder : DslBuilder<ScanConfiguration>() {
private var collateral = CollateralScan(enabled = false)
private var custom = CustomScan(enabled = false)

private var whitelist: MutableSet<String> = mutableSetOf()
private var blacklist: MutableSet<String> = mutableSetOf()

public fun pirate(block: PirateSoftwareScanBuilder.() -> Unit = {}) {
pirate = PirateSoftwareScanBuilder().apply {
block()
Expand Down Expand Up @@ -76,8 +83,34 @@ public class ScanConfigurationBuilder : DslBuilder<ScanConfiguration>() {
}.build()
}


@Synchronized
public fun whitelist(packageName: String) {
assert(!blacklist.contains(packageName)) { "Can't add $packageName to whitelist=$whitelist: it is already contained in blacklist=$blacklist" }
whitelist.add(packageName)
}

@Synchronized
public fun whitelist(packageNameList: List<String>) {
packageNameList.forEach(::whitelist)
}



@Synchronized
public fun blacklist(packageName: String) {
assert(!whitelist.contains(packageName)) { "Can't add $packageName to blacklist=$blacklist: it is already contained in whitelist=$whitelist" }
blacklist.add(packageName)
}

@Synchronized
public fun blacklist(packageNameList: List<String>) {
packageNameList.forEach(::blacklist)
}


/**
* Builds the scan configuration
* */
override fun build(): ScanConfiguration = ScanConfiguration(pirate, store, collateral, custom)
override fun build(): ScanConfiguration = ScanConfiguration(pirate, store, collateral, custom, whitelist, blacklist)
}
2 changes: 1 addition & 1 deletion docs/pages/modules/antipiracy/antipiracy.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Scan settings are taken into account intelligently to analyze and run the batter



# Configuring `KevlarAntipiracy`
## Configuring `KevlarAntipiracy`
The antipiracy module is easy to configure, since it works automatically: you just have to choose which search criteria is used.

You may choose to configure the antipiracy module manually (using the dedicated DSL, more flexibility), or just using one of the default configurations.
Expand Down
78 changes: 69 additions & 9 deletions docs/pages/modules/antipiracy/reference.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Reference

This document contains the complete reference for every scan parameter that can be enabled in the `antipiracy` module.

## Configurations

The complete rooting configuration is as follows.

```kotlin title="Complete settings"
Expand All @@ -12,8 +16,21 @@ private val antipiracy = KevlarAntipiracy {
}
```

Once you require the attestation through `attestate(context)`, any software matching your settings
will be reported.
You can use the pre-configured scan settings if your configuration is trivial:

```kotlin title="Automatic settings"
private val antipiracy = KevlarAntipiracy.Defaults.JustPirateApps()
```

The possible configurations are:

- `KevlarAntipiracy.Defaults.Full`: Complete scan: `pirate()`, `store()` and `collateral()`;
- `KevlarAntipiracy.Defaults.JustPirateApps`: Only `pirate()`;
- `KevlarAntipiracy.Defaults.JustStores`: Only `store()`;
- `KevlarAntipiracy.Defaults.PirateAndStore`: Both `pirate()` and `store()`;
- `KevlarAntipiracy.Defaults.Empty`: No scan;

Once you require the attestation through `antipiracy.attestate(context)`, any installed application matching your settings will be reported.

```kotlin
withContext(externalDispatcher) {
Expand All @@ -24,9 +41,10 @@ withContext(externalDispatcher) {
You can find all the details about what software is regarded as pirate in the [database](database.md) page.


## Pirate Apps
The `pirate()` function tells kevlar to scan the application list, and match it against the local
dataset for pirate applications.
### Pirate Apps
The `pirate()` function tells kevlar to scan the application list, and match it against the local dataset for pirate applications.

A pirate application is software (installed on the device) that may try to maliciously interfere with the in-app purchase mechanism, or alter your application characteristics in order to induce it to perform a value-related transaction in an unsafe environment, where it can be injected/forged/cracked.

If any package is deemed to be a pirate application, it is included in the attestation

Expand All @@ -42,9 +60,10 @@ private val antipiracy = KevlarAntipiracy {



## Pirate Stores
The `store()` function tells kevlar to scan the application list, and match it against the local
dataset for pirate stores.
### Pirate Stores
The `store()` function tells kevlar to scan the application list, and match it against the local dataset for pirate stores.

A pirate store is a distribution network for android applications other that the Google Play Store.

```kotlin hl_lines="4"
private val antipiracy = KevlarAntipiracy {
Expand All @@ -57,7 +76,7 @@ private val antipiracy = KevlarAntipiracy {
```


## Collateral detection methods
### Collateral detection methods
The `collateral()` function enables kevlar to use more aggressive methods to perform the lookup of
specific pirate software.

Expand All @@ -78,3 +97,44 @@ your scan settings, we extrapolated this flag to make the switch explicit.

More details in the [detection](detection.md#collateral-tools) page.


### Manually configuring detection
If you need more advanced selection criteria / customizable scan settings with specific package names, you can use the whitelisting / blacklisting features.


!!! node
The intersection between the whitelist and the blacklist has to remain empty

#### Whitelisting
The `whitelist()` function signals to kevlar explicit package names that you want to be ignored during the scan.
Kevlar will not run the battery of tests for such packages, and discard them immediately.

```kotlin hl_lines="7"
private val antipiracy = KevlarAntipiracy {
scan {
pirate()
store()
collateral()

whitelist("com.cioccarellia.wordbucket")
}
}
```


#### Blacklisting
The `blacklist()` function signals to kevlar explicit package names that you want to be detected during the scan.
Kevlar will not run the battery of tests for such packages, and report them immediately as blacklisted.

```kotlin hl_lines="7"
private val antipiracy = KevlarAntipiracy {
scan {
pirate()
store()
collateral()

blacklist("com.kevlar.showcase")
}
}
```

Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class AntipiracyRepository @Inject constructor(
pirate()
store()
collateral()

blacklist("com.kevlar.showcase")
}
}

Expand Down

0 comments on commit f1d292f

Please sign in to comment.