You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Kevlar does not automatically detect a "standard" unsafe environment and gives a 0/1 answer.
56
+
Kevlar does not automatically detect a "standard" unsafe environment and give a 0/1 answer.
57
57
The kind of environment that is acceptable for your app to run in can be configured in each package individually.
58
58
59
59
You may be indifferent to some things (e.g. root detection) and very sensitive about others (e.g. app tampering & piracy detection).
@@ -66,14 +66,14 @@ If you don't explicitly instruct kevlar to check for a feature, then that featur
66
66
## Design
67
67
Each kevlar package contains custom implementations for what it has to scan for, but they all share the same overall structure, to make it easy to work with. Once you learn how to use a package, then you can transfer that knowledge to the other ones.
68
68
69
+
69
70
```mermaid
70
71
graph LR
71
72
I[Inizialization] -.Settings..-> K{Kevlar};
72
73
AREQ[Attestation Requests] --> K
73
-
K --> |Clear| P[Passed];
74
-
K --> |Failed| NP[Not Passed];
75
-
P --> ARES[Attestation Result]
76
-
NP --> ARES
74
+
K --> ARES[Attestation Result]
75
+
ARES --> |Clear| P[Passed];
76
+
ARES --> |Failed| NP[Not Passed];
77
77
```
78
78
79
79
The founding idea is a flow of attestations. You initialize the package passing to it your settings (what you want to check for). Then you can go ahead and start requesting attestations. An attestation can either be Clear (passed) or Failed (non passed), according to your detection settings.
Kevlar does not automatically detect a "standard" unsafe environment and gives a 0/1 answer.
32
+
Kevlar does not automatically detect a "standard" unsafe environment and give a 0/1 answer.
33
33
The kind of environment that is acceptable for your app to run in can be configured in each package individually.
34
34
35
35
You may be indifferent to some things (e.g. root detection) and very sensitive about others (e.g. app tampering & piracy detection).
@@ -46,10 +46,9 @@ Each kevlar package contains custom implementations for what it has to scan for,
46
46
graph LR
47
47
I[Inizialization] -.Settings..-> K{Kevlar};
48
48
AREQ[Attestation Requests] --> K
49
-
K --> |Clear| P[Passed];
50
-
K --> |Failed| NP[Not Passed];
51
-
P --> ARES[Attestation Result]
52
-
NP --> ARES
49
+
K --> ARES[Attestation Result]
50
+
ARES --> |Clear| P[Passed];
51
+
ARES --> |Failed| NP[Not Passed];
53
52
```
54
53
55
54
The founding idea is a flow of attestations. You initialize the package passing to it your settings (what you want to check for). Then you can go ahead and start requesting attestations. An attestation can either be Clear (passed) or Failed (non passed), according to your detection settings.
The antipiracy package contains tools for the detection of different categories of pirate software that may be installed and running on target devices.
Copy file name to clipboardexpand all lines: docs/pages/modules/integrity/implementation.md
+16-13
Original file line number
Diff line number
Diff line change
@@ -69,9 +69,9 @@ debug check.
69
69
70
70
The hardcoded metadata you need to find is the following:
71
71
72
-
- Your application **package name**: Will check that the running binary's package name matches the
72
+
- Your application **package name**: Will be used to check that the running binary's package name matches the
73
73
hardcoded package name;
74
-
- Your application **signature**: Will check that the running binary's signature is the same as the
74
+
- Your application **signature**: Will be used to check that the running binary's signature is the same as the
75
75
hardcoded signature.
76
76
77
77
Additionally, you should consider enabling the other two kinds of checks:
@@ -115,7 +115,7 @@ integrity.attestate(context)
115
115
```
116
116
117
117
118
-
!!! fail "Do not"
118
+
!!! danger "Do not"
119
119
Maybe, just maybe, you may be tempted to so something like this:
120
120
121
121
```kotlin title="VERY_BAD_hardcoded_metadata.kt"
@@ -136,15 +136,18 @@ For the signature, it's not so straightforward to extract because it depends on
136
136
You have two different ways to get your keystore signature. In the examples we will find the debug signature, but you need to find the signature of the keystore you use to sign your application when publishing on google play.
137
137
138
138
#### Direct application extraction
139
-
The most practical way to read your keystore it is to put the following line of code in your app, to then sign the application with the key you are interested in acquiring the signature string of, and run it.
139
+
The most practical way to read your keystore it is to put the following line of code in your app (it is a courtesy method provided by kevlar to do just that), to then sign the application with the key you are interested in acquiring the signature string of, and run it.
140
140
141
141
```kotlin
142
142
// This returns the signature of the current running application.
143
143
val signature:String=KevlarIntegrity.obtainCurrentAppSignature(context)
144
+
145
+
// Log it to the console for extracting the signature
146
+
Log.d("SIGNATURE", signature)
144
147
```
145
148
146
149
This will output the current app signature.
147
-
That's the reference string you need to give to kevlar (whichwill extract the runtime signature of your app and match it against that string).
150
+
That's the reference string you need to give to kevlar through `hardcodedSignatures()` (which, once an attestation is requested, will extract the runtime signature of your app _(which may be tampered with, if someone recompiled your application)_and match it against that string you just extracted).
148
151
149
152
!!! example "Android debug signature"
150
153
Every android application is signed with some key.
@@ -154,7 +157,7 @@ That's the reference string you need to give to kevlar (which will extract the r
154
157
!!! warning "Signature extraction & Google Play App Signing API"
155
158
If you are using Google Play App Signing, the key you sign your application with is not the one your app is distributed with (See the [official docs](https://developer.android.com/studio/publish/app-signing) regarding the matter, and a relevant [issue](https://github.com/kevlar-kt/kevlar/issues/1) in kevlar).
156
159
157
-
In this case the easiest way to get your actual signature would be to upload a dummy version of your app (which logs the runtime signature) through google play store, let the backend process and sign it, download it (through the archive manager on the play console), install & run it locally on an emulator/device, and save the runtime signature. Once you have done this (quite tedious) procedure, you have your signature and can pass it to kevlar.
160
+
In this case the easiest way to get your actual signature would be to upload a dummy version of your app (which logs the runtime signature) through google play store, let the backend process and sign it, download it (through the archive manager on the play console), install & run it locally on an emulator/device, and save the runtime signature. Once you have done this (quite tedious, but once-in-a-lifetime) procedure, you have your signature and can pass it to kevlar.
158
161
159
162
#### Android studio extraction
160
163
Running `./gradlew signingReport` will spit out all the details for all the different keystores in your project.
@@ -180,22 +183,22 @@ Alias: null
180
183
```
181
184
182
185
We then have to convert it in a string form (like that we have the raw hex bytes, we want a base64 encoding of the binary signature).
183
-
In this case the conversion (you can use online tools to do this) yields `J+nqXLfuIO8B2AmhkMYHGE4jDyw=`.
186
+
In my case the conversion (you can use[sha1_to_base64](https://emn178.github.io/online-tools/base64_encode.html) online tools to do this) yields `J+nqXLfuIO8B2AmhkMYHGE4jDyw=`.
184
187
185
-
!!! fail "Play Signing"
186
-
Since we don't have access to the keystore file if we use Play Signing, this method is not viable in that case, and you have to resort to uploading a dummy version of the app, download its play-signed version through the releases page, and extract the signature from that APK file.
188
+
!!! danger "Incompatible With Play Signing"
189
+
Since we don't have access to the "real" keystore file if we're using use Play Signing, this method is not viable in that case, and you have to resort to uploading a dummy version of the app, download its play-signed version through the releases page, and extract the signature from that APK file.
187
190
188
191
189
192
## Obfuscating metadata
190
193
The second step (optional but recommended) is obfuscating the metadata you just gathered, so that it
191
-
is **saved** in an obfuscated form (in your bytecode, so that automatic tools / unskilled attackers can't easily find it), but passed to kevlar deobfuscated (so that we have the original truth valuesat run time).
194
+
is **stored** in an obfuscated form (in your bytecode, so that automatic tools / unskilled attackers can't easily find it), but passed to kevlar deobfuscated (obviously kevlar has to receive the real, intended value, so that we have the original truth values. The idea is to perform the deobfuscation/decryption just at run time, not leaving a trace of the actual plaintext signature in the application code).
192
195
193
-
This means that we ship with out app the obfuscated data and the way to convert that obfuscated data back to plaintext to feed kevlar.
196
+
This means that we'll ship with our app the obfuscated data, and then at runtime (when kevlar is invoked) we will convert that obfuscated data back to plaintext to feed kevlar.
194
197
195
-
There are a few different ways to do it, all of them are fully implemented in the `:showcase` module:
198
+
There are a few different ways to do it, all of them are fully implemented in the `:showcase` module for you check out:
196
199
197
200
### No obfuscation (not recommended)
198
-
In this case you just save the values as they are, and pass them in `HardcodedMetadata`
201
+
In this case you just save the values as they are, and pass them in `HardcodedMetadata`:
The integrity package contains tools for the detection of tampering attempts against your app.
@@ -30,7 +29,7 @@ It is capable of detecting:
30
29
31
30
!!! warning Automatic vs Specific attack
32
31
This package is the best defense against automatic and/or unskilled attacks.
33
-
If implemented well, it will kill off most of them
32
+
If implemented well, it will kill off most of them.
34
33
35
34
36
35
To [implement](implementation.md) this, you initialize `KevlarIntegrity` and provide your desired settings (which influence what is to be checked and what not). Then you can submit attestation requests (which will be executed according to your settings).
@@ -73,11 +72,11 @@ Thus there are no default configuration: you have to manually specify each item
@@ -53,24 +53,25 @@ private val integrity = KevlarIntegrity {
53
53
}
54
54
```
55
55
56
-
You can find instruction on where to find the right parameters in [implementation](implementation.md).
56
+
You can find instruction on how to derive the right parameters for your app in [implementation](implementation.md).
57
57
In this case you simply have to pass in the package name of your app, so kevlar knows what is the right package.
58
58
59
59
60
60
## Signature check
61
61
The `signature()` function tells kevlar to enable the integrity checks for the application signature.
62
62
63
63
This is a parametric setting, since kevlar needs to know what is the "right" application signature is.
64
-
Once kevlar has all the required data it is able to differentiate between genuine and tampered binaries.
64
+
65
+
Once kevlar has all the required data, it is able to differentiate between genuine and tampered binaries (by checking the hardcoded data against the runtime-provided information).
@@ -106,33 +107,32 @@ private val integrity = KevlarIntegrity {
106
107
}
107
108
```
108
109
109
-
If debug flags are found on your application it will be reported.
110
+
If any debug flag is found on your application, it will be reported.
110
111
111
112
112
113
## Installer check
113
114
The `installer()` function tells kevlar to enable installer checks.
114
115
115
-
Since android R, google introduced APIs to check the original installer of a certain package.
116
-
With this check, you can instruct kevlar to analyze that installer (if available) and detect
117
-
whether it is allowed or not by your security policy.
116
+
Since android R, google introduced new APIs to check for the original installer of a certain package.
117
+
118
+
With this check, you can instruct kevlar to analyze (if available) which software installed your application, and detect whether it is allowed or not by your security policy.
118
119
119
-
In this case, the only allowed installer package is the Google Play Store, but you can always
120
-
add more through the `allowInstaller` function.
120
+
In this case, the only allowed installer package is the Google Play Store, but you can always add more (whitelist) through the `allowInstaller` function.
Copy file name to clipboardexpand all lines: docs/pages/modules/rooting/implementation.md
+5-27
Original file line number
Diff line number
Diff line change
@@ -59,37 +59,15 @@ We go ahead and create a working single-attestation example (for system modifica
59
59
60
60
## Configuration
61
61
As we said, the kinds of checks you can run are divided in two different categories, `targets` and `status`.
62
-
The first is to check for eventual system modification, the former to check for eventual in-system status.
62
+
The first is to check for system modification, the former to check for eventual in-system status.
63
63
64
-
The following complete configuration runs every check that kevlar disposes.
64
+
The following is the default (most commonly chosen) configuration.
65
65
66
-
In details:
67
-
68
-
-`flagPermissive()`, if enabled, will report `DetectableSystemStatus.SELINUX` also if selinux status is set to permissive status (which is a stricter criteria), while by default it will only trip if selinux is disabled;
69
-
-`allowExplicitRootCheck()`, if enabled, will use more aggressive checks to determine if any of the required targets is installed, including explicitly trying to acquire root access.
0 commit comments