178 lines
4.9 KiB
Markdown
178 lines
4.9 KiB
Markdown
# MPCrypto
|
||
|
||
MPCrypto is a Python helper for generating authentication tokens and request signatures.
|
||
|
||
This project intentionally implements **legacy and non-standard behaviors** (custom hashes, double-encoding, legacy crypto) required for compatibility reasons.
|
||
|
||
---
|
||
|
||
## Features
|
||
|
||
- Device-aware behavior for `webplayer`, `android.tv`, `phone.android`, and `tablet.android`
|
||
- Basic token generation tied to device class
|
||
- Request signature generation (HMAC-SHA1)
|
||
- Support for **Basic** and **Bearer** authentication schemes
|
||
- OpenSSL-compatible salted AES-CBC decryption (`EVP_BytesToKey`) used to derive Consumer Key and Consumer Secret values
|
||
- Android app Consumer Key and Consumer Secret reconstruction via `MockDateConverter`, which implements a SHA-256–like hash with XOR masking
|
||
|
||
---
|
||
|
||
## XOR template generation (Ghidra)
|
||
|
||
The XOR templates required by `MockDateConverter` are extracted from the original Android native library using Ghidra.
|
||
|
||
This repository includes a Ghidra Python script that automates the extraction process by:
|
||
|
||
- Locating JNI-exported functions related to `MockDateConverter`
|
||
- Decompiling each function
|
||
- Recovering the XOR byte sequences used internally
|
||
- Normalizing function names into the Python-friendly `XOR_TEMPLATES` format
|
||
|
||
The script supports both DAT-backed byte arrays accessed through pointer arithmetic and hardcoded local-variable XOR sequences produced by the compiler.
|
||
|
||
The output is a ready-to-use dictionary compatible with the `MockDateConverter` constructor.
|
||
|
||
|
||
---
|
||
|
||
## Supported device classes
|
||
|
||
```
|
||
webplayer
|
||
android.tv
|
||
phone.android
|
||
tablet.android
|
||
```
|
||
|
||
---
|
||
|
||
## Initialization
|
||
|
||
`MPCrypto` can be initialized in two distinct ways depending on the device class.
|
||
|
||
### Web-based devices (`webplayer`, `android.tv`)
|
||
|
||
For web-based clients, configuration data is fetched remotely and decrypted. You must provide:
|
||
|
||
- `config_url`: URL pointing to the remote configuration source
|
||
- `config_pattern`: Regular expression used to extract the configuration payload from the response
|
||
|
||
These values are device and version specific and must be supplied by the user.
|
||
|
||
**Initialization example:**
|
||
|
||
```python
|
||
from mp_crypto import MPCrypto
|
||
|
||
mp_crypto = MPCrypto(
|
||
device_class="webplayer",
|
||
config_url="https://example.com/config.php",
|
||
config_pattern=r"some_regex_pattern_here",
|
||
)
|
||
```
|
||
|
||
### Android app devices (`phone.android`, `tablet.android`)
|
||
|
||
For Android-based clients, no remote configuration is fetched. Instead, key material is reconstructed locally using `MockDateConverter`.
|
||
|
||
In this case, you must provide:
|
||
|
||
- A fully initialized `MockDateConverter` instance
|
||
- A valid `package_name`
|
||
- A populated `xor_templates` dictionary (typically generated via the provided Ghidra script)
|
||
|
||
The library validates that all required XOR templates for the selected device class are present before proceeding.
|
||
|
||
**Initialization example:**
|
||
|
||
```python
|
||
from mp_crypto import MPCrypto
|
||
from mock_date_converter import MockDateConverter
|
||
|
||
XOR_TEMPLATES = {
|
||
'key': bytes.fromhex("0123456789abcdef"),
|
||
#...
|
||
}
|
||
|
||
mock_date_converter = MockDateConverter(
|
||
package_name="com.example.app",
|
||
xor_templates=XOR_TEMPLATES,
|
||
)
|
||
|
||
mp_crypto = MPCrypto(
|
||
device_class="phone.android",
|
||
mock_date_converter=mock_date_converter,
|
||
)
|
||
```
|
||
|
||
---
|
||
|
||
## Basic authentication example
|
||
|
||
This example shows how to sign requests using a **Basic** token for web-based devices.
|
||
|
||
```python
|
||
new_device_id = str(uuid.uuid4())
|
||
basic_token = mp_crypto.get_basic_token(new_device_id)
|
||
|
||
signature = mp_crypto.get_signature(
|
||
method="POST",
|
||
url=url,
|
||
token=basic_token,
|
||
scheme="Basic",
|
||
params=data,
|
||
)
|
||
|
||
headers = {
|
||
**default_auth_headers,
|
||
"Authorization": f"OPPlus Basic={basic_token},Signature={signature}",
|
||
}
|
||
|
||
resp = requests.post(
|
||
url,
|
||
data=data,
|
||
headers=headers,
|
||
)
|
||
```
|
||
|
||
---
|
||
|
||
## Bearer authentication example
|
||
|
||
This example shows how to sign requests using a previously obtained **Bearer** token.
|
||
|
||
```python
|
||
signature = mp_crypto.get_signature(
|
||
method="GET",
|
||
url=url,
|
||
token=login_token,
|
||
scheme="Bearer",
|
||
)
|
||
|
||
headers = {
|
||
**default_account_info_headers,
|
||
"Authorization": f"OPPlus Bearer={login_token},Signature={signature}",
|
||
}
|
||
|
||
resp = requests.get(
|
||
url,
|
||
headers=headers,
|
||
)
|
||
```
|
||
|
||
---
|
||
|
||
## Disclaimer
|
||
|
||
This project is provided for **educational and interoperability purposes only**.
|
||
|
||
1. This project does not condone piracy or violations of DRM systems.
|
||
2. All techniques are the result of reverse engineering, publicly available research, and empirical analysis.
|
||
3. Do not use this software to access, decrypt, or distribute content without proper authorization.
|
||
4. Unauthorized access or redistribution of protected content may violate applicable laws.
|
||
5. This software must not be used for illegal activities, including DRM circumvention.
|
||
6. The authors and contributors are not responsible for misuse of this project.
|
||
7. By using this software, you agree to comply with all applicable laws and regulations.
|
||
|
||
The authors assume no responsibility for misuse.
|