mirror of https://github.com/Diazole/dumper.git
Add support for Android 13
This commit is contained in:
parent
883c520432
commit
16df7440d6
|
@ -7,10 +7,10 @@ from Helpers.wv_proto2_pb2 import SignedLicenseRequest
|
||||||
|
|
||||||
|
|
||||||
class Device:
|
class Device:
|
||||||
def __init__(self, dynamic_function_name, cdm_version):
|
def __init__(self, dynamic_function_name, cdm_version, module_names):
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
self.saved_keys = {}
|
self.saved_keys = {}
|
||||||
self.widevine_libraries = ['libwvhidl.so']
|
self.widevine_libraries = module_names
|
||||||
self.usb_device = frida.get_usb_device()
|
self.usb_device = frida.get_usb_device()
|
||||||
self.name = self.usb_device.name
|
self.name = self.usb_device.name
|
||||||
|
|
||||||
|
@ -74,7 +74,13 @@ class Device:
|
||||||
loaded_modules = []
|
loaded_modules = []
|
||||||
try:
|
try:
|
||||||
for lib in self.widevine_libraries:
|
for lib in self.widevine_libraries:
|
||||||
loaded_modules.append(script.exports.getmodulebyname(lib))
|
try:
|
||||||
|
loaded_modules.append(script.exports.getmodulebyname(lib))
|
||||||
|
except frida.core.RPCException as e:
|
||||||
|
# Hide the cases where the module cannot be found
|
||||||
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
raise(e)
|
||||||
finally:
|
finally:
|
||||||
process.detach()
|
process.detach()
|
||||||
return loaded_modules
|
return loaded_modules
|
||||||
|
|
|
@ -95,6 +95,7 @@ function prepareKeyRequest(address) {
|
||||||
this.ret = args[4];
|
this.ret = args[4];
|
||||||
break;
|
break;
|
||||||
case '16.1.0':
|
case '16.1.0':
|
||||||
|
case '17.0.0':
|
||||||
this.ret = args[5];
|
this.ret = args[5];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
49
README.md
49
README.md
|
@ -3,9 +3,14 @@
|
||||||
Dumper is a Frida script to dump L3 CDMs from any Android device.
|
Dumper is a Frida script to dump L3 CDMs from any Android device.
|
||||||
|
|
||||||
## ** IMPORTANT **
|
## ** IMPORTANT **
|
||||||
The function parameters can differ between CDM versions. The default is [4] but you may have to change this for your specific version.
|
The function parameters can differ between CDM versions. The default is [4] but you may have to change this for your specific version in the [script.js](./Helpers/script.js).
|
||||||
|
|
||||||
* `CDM_VERSION` can be retrieved using a DRM Info app.
|
## Prerequisites
|
||||||
|
- Rooted Android device
|
||||||
|
- [Installed Frida server on the Android device]((https://frida.re/docs/android/))
|
||||||
|
- Installed [platform-tools ADB/Fastboot](https://developer.android.com/studio/releases/platform-tools) on the PC
|
||||||
|
- Installed [Python 3](https://www.python.org/downloads/) on the PC
|
||||||
|
- `CDM_VERSION` retrieved from the [DRM Info app](https://play.google.com/store/apps/details?id=com.androidfung.drminfo).
|
||||||
|
|
||||||
## Requirements:
|
## Requirements:
|
||||||
Use pip to install the dependencies:
|
Use pip to install the dependencies:
|
||||||
|
@ -14,34 +19,52 @@ Use pip to install the dependencies:
|
||||||
|
|
||||||
## Usage:
|
## Usage:
|
||||||
|
|
||||||
* Enable USB debugging
|
* Enable USB debugging on the Android device and connect it to the PC
|
||||||
* Start frida-server on the device
|
* [Start frida-server on the Android device](https://frida.re/docs/android/)
|
||||||
* Execute dump_keys.py
|
* Execute dump_keys.py on the PC
|
||||||
* Start streaming some DRM-protected content
|
* Start streaming some DRM-protected content on the Android device e.g. [Bitmovin](https://bitmovin.com/demos/drm)
|
||||||
|
|
||||||
The script will hook every function in your 'libwvhidl.so' module by default, effectively brute forcing the private key function name.
|
The script will hook every function in your widevine 'libwvhidl.so'/'libwvaidl.so' modules by default, effectively brute forcing the private key function name.
|
||||||
```
|
```
|
||||||
python3 .\dump_keys.py [OPTIONS]
|
python3 dump_keys.py
|
||||||
```
|
```
|
||||||
|
|
||||||
You can pass the function name to hook using the `--function-name` argument.
|
You can pass the function name to hook using the `--function-name` argument. You can use [this post](https://forum.videohelp.com/threads/404219-How-To-Dump-L3-CDM-From-Android-Device-s-(ONLY-Talk-About-Dumping-L3-CDMS)/page6#post2646150) to retrive it by yourself.
|
||||||
```
|
```
|
||||||
python3 .\dump_keys.py --function-name 'polorucp'
|
python3 dump_keys.py --function-name 'polorucp'
|
||||||
```
|
```
|
||||||
|
|
||||||
The script defaults to `args[4]` if no `--cdm-version` is provided. This will only have an effect if your version is `16.1.0`.
|
The script defaults to `args[4]` if no `--cdm-version` is provided. This will only have an effect if your version is `16.1.0` or `17.0.0`.
|
||||||
|
|
||||||
```
|
```
|
||||||
python3 .\dump_keys.py --cdm-version '16.1.0'
|
python3 dump_keys.py --cdm-version '16.1.0'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can pass the `.so` -module name using the `--module-name` argument. By default it looks in the `libwvhidl.so` and `libwvaidl.so` files. It can have multiple values. Its name can change depending on the version and SoC including but not limited to: `libwvaidl.so`, `libwvhidl.so`, `libwvdrmengine.so`, `libwvm.so`, `libdrmwvmplugin.so` [source](https://arxiv.org/abs/2204.09298). You can find your module name in the /vendor/lib64/ or /vendor/lib/ directories using an ADB shell.
|
||||||
|
|
||||||
|
```
|
||||||
|
python3 dump_keys.py --module-name 'libwvhidl.so' --module-name 'libwvaidl.so'
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Options:
|
## Options:
|
||||||
```
|
```
|
||||||
-h, --help Print this help text and exit.
|
-h, --help Print this help text and exit.
|
||||||
--cdm-version The CDM version of the device e.g. '16.1.0'.
|
--cdm-version The CDM version of the device e.g. '16.1.0'.
|
||||||
--function-name The name of the function to hook to retrieve the private key.
|
--function-name The name of the function to hook to retrieve the private key.
|
||||||
|
--module-name The name of the widevine `.so` modules.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Scenario:
|
||||||
|
1. You've got the function name
|
||||||
|
2. You've got the private key
|
||||||
|
3. Client ID extracted
|
||||||
|
4. Script closed
|
||||||
|
|
||||||
|
The following files will be created after a successful dump:
|
||||||
|
- `client_id.bin` - Device identification
|
||||||
|
- `private_key.pem` - RSA private key
|
||||||
|
|
||||||
## Known Working Versions:
|
## Known Working Versions:
|
||||||
* Android 9
|
* Android 9
|
||||||
* CDM 14.0.0
|
* CDM 14.0.0
|
||||||
|
@ -51,6 +74,8 @@ python3 .\dump_keys.py --cdm-version '16.1.0'
|
||||||
* CDM 16.0.0
|
* CDM 16.0.0
|
||||||
* Android 12
|
* Android 12
|
||||||
* CDM 16.1.0
|
* CDM 16.1.0
|
||||||
|
* Android 13
|
||||||
|
* CDM 17.0.0
|
||||||
|
|
||||||
## Temporary disabling L1 to use L3 instead
|
## Temporary disabling L1 to use L3 instead
|
||||||
A few phone brands let us use the L1 keybox even after unlocking the bootloader (like Xiaomi). In this case, installation of a Magisk module called [liboemcrypto-disabler](https://github.com/umylive/liboemcrypto-disabler) is necessary.
|
A few phone brands let us use the L1 keybox even after unlocking the bootloader (like Xiaomi). In this case, installation of a Magisk module called [liboemcrypto-disabler](https://github.com/umylive/liboemcrypto-disabler) is necessary.
|
||||||
|
|
11
dump_keys.py
11
dump_keys.py
|
@ -15,13 +15,20 @@ def main():
|
||||||
parser = argparse.ArgumentParser(description='Android Widevine L3 dumper.')
|
parser = argparse.ArgumentParser(description='Android Widevine L3 dumper.')
|
||||||
parser.add_argument('--cdm-version', help='The CDM version of the device e.g. \'14.0.0\'', default='14.0.0')
|
parser.add_argument('--cdm-version', help='The CDM version of the device e.g. \'14.0.0\'', default='14.0.0')
|
||||||
parser.add_argument('--function-name', help='The name of the function to hook to retrieve the private key.', default='')
|
parser.add_argument('--function-name', help='The name of the function to hook to retrieve the private key.', default='')
|
||||||
|
parser.add_argument('--module-name',
|
||||||
|
nargs='+',
|
||||||
|
type=str,
|
||||||
|
help='The names of the widevine `.so` modules',
|
||||||
|
default=["libwvaidl.so", "libwvhidl.so"]
|
||||||
|
)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
dynamic_function_name = args.function_name
|
dynamic_function_name = args.function_name
|
||||||
cdm_version = args.cdm_version
|
cdm_version = args.cdm_version
|
||||||
|
module_names = args.module_name
|
||||||
|
|
||||||
logger = logging.getLogger("main")
|
logger = logging.getLogger("main")
|
||||||
device = Device(dynamic_function_name, cdm_version)
|
device = Device(dynamic_function_name, cdm_version, module_names)
|
||||||
logger.info('Connected to %s', device.name)
|
logger.info('Connected to %s', device.name)
|
||||||
logger.info('Scanning all processes')
|
logger.info('Scanning all processes')
|
||||||
|
|
||||||
|
@ -29,7 +36,7 @@ def main():
|
||||||
if 'drm' in process.name:
|
if 'drm' in process.name:
|
||||||
for library in device.find_widevine_process(process.name):
|
for library in device.find_widevine_process(process.name):
|
||||||
device.hook_to_process(process.name, library)
|
device.hook_to_process(process.name, library)
|
||||||
logger.info('Functions Hooked, load the DRM stream test on Bitmovin!')
|
logger.info('Functions hooked, now open the DRM stream test on Bitmovin from your Android device! https://bitmovin.com/demos/drm')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
Loading…
Reference in New Issue