Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tab10CPro Strings #66

Closed
junrenshi opened this issue Nov 4, 2023 · 18 comments
Closed

Tab10CPro Strings #66

junrenshi opened this issue Nov 4, 2023 · 18 comments

Comments

@junrenshi
Copy link

I install GetBooxUpxKeys in a Boox Tab 10C Pro, and get outputs:

"MODEL" = "Tab10CPro",
"STRING_SETTINGS" = "D999393AEAA81119AC0F8C8C1EA11089",
"STRING_UPGRADE" = "CD7894A509490BAF2BAA129686A083E4"

fingerprint: Onyx/Tab10CPro/Tab10CPro:11/2023-10-30_17-05_3.5_edb1c449c/4119:user/release-keys

Using the strings to decrypt update.upx results in error:

python3 DeBooxUpx.py Tab10CPro
Traceback (most recent call last):
File "/Users/shi/Downloads/decryptBooxUpdateUpx/DeBooxUpx.py", line 337, in
decrypter = DeBooxUpx(**boox_strings[device_name])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/shi/Downloads/decryptBooxUpdateUpx/DeBooxUpx.py", line 289, in init
self.decryptStr(tmpKey, STRING_SETTINGS))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/shi/Downloads/decryptBooxUpdateUpx/DeBooxUpx.py", line 296, in decryptStr
return cipher.decrypt(b64decode(string)).decode().strip()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 0-1: invalid continuation byte

It seems GetBooxUpxKeys cannot get correct strings for this new device.

@RenateUSB
Copy link
Collaborator

RenateUSB commented Nov 7, 2023

You have (presumably) the Base64 decoded string.
The current setup uses Base64 strings

Post libota_jni.so and I'll check without Java.

@junrenshi
Copy link
Author

Yes, they do look like hexadecimal numbers.

libota_ini.so is here:
libota_jni.tgz

@RenateUSB
Copy link
Collaborator

I get the same results as you.
(The libjni_ota.so does not have those values as either binary or string directly in it. It's generated.)
But that is 32 hex digits, which is 16 bytes or 128 bits.

The strings we've been using have been 44 characters which can be evenly base64 converted to 33 bytes or 264 bits.
(Note that none of the strings end in '=', which means it's an even 4 char to 3 byte conversion.)

This new libota_jni.so has a third JNI function, Java_com_onyx_android_onyxotaservice_RsaUtil_nativeDecryptFile
So maybe things have changed radically. @Hagb

@Hagb
Copy link
Owner

Hagb commented Nov 9, 2023

@junrenshi Could you please upload your /system/app/OnyxOtaService/OnyxOtaService.apk? It might be needed to decompile this apk to try to find how it works.

@junrenshi
Copy link
Author

The file is now moved to /sys/priv-app/OnyxOtaService/.

Here is the file:
OnyxOtaService.apk.tgz

@RenateUSB
Copy link
Collaborator

Would you have a link for that update.upx?
I can't seem to find it.

@junrenshi
Copy link
Author

@RenateUSB
Copy link
Collaborator

Works nicely for me. :)

Poke3:/data/local/assets # unzip -l update.zip
Archive:  update.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
      155  2009-01-01 00:00   payload_properties.txt
        0  2009-01-01 00:00   apex_info.pb
      678  2009-01-01 00:00   care_map.pb
      615  2009-01-01 00:00   META-INF/com/android/metadata
     1030  2009-01-01 00:00   META-INF/com/android/metadata.pb
     1513  2009-01-01 00:00   META-INF/com/android/otacert
1556748068  2009-01-01 00:00   payload.bin
---------                     -------
1556752059                     7 files

@junrenshi
Copy link
Author

Great! You did that. Can I do that as well?

@RenateUSB
Copy link
Collaborator

That was my proof of concept, extracting without Python or Java.
I don't pretend to understand any of this encryption junk.

You can mod the stock DeBooxUpd to only work for the Tab10CPro.
@Hagb will have to figure out what to do going forward.

Just insert these two lines in DeBooxUpd, line 287, right after self.path: str =

        self.key = b'\xd9\x99\x39\x3a\xea\xa8\x11\x19\xac\x0f\x8c\x8c\x1e\xa1\x10\x89'
        self.iv = b'\xcd\x78\x94\xa5\x09\x49\x0b\xaf\x2b\xaa\x12\x96\x86\xa0\x83\xe4'

@junrenshi
Copy link
Author

Great! It also works for me. Thanks a lot!

@hexomethyl
Copy link

Hey guys,

Recently got my Note air 3C, after looking at both libota_jni.so and OnyxOtaService.apk, Boox seems to have changed how the decryption of the Upx files work.

Previously there was a function which returns the AES secret key (Java_com_onyx_android_onyxotaservice_RsaUtil_nativeGetSecretKey) and AES IV (Java_com_onyx_android_onyxotaservice_RsaUtil_nativeGetIvParameter), these were encrypted using DES (With the model name as the key, lol) and encoded using Base64.

Now for my new device with fingerprint: "Onyx/NoteAir3C/NoteAir3C:11/2023-10-17_09-55_3.5_a37b266eb/2482:user/test-keys", this is no longer the case.

Now there are two functions exported from the libota_jni.so dynamic library that return the direct AES secret key and AES IV.
These functions have mangled C++ names but are getKeyString and getInitVectorString

This means that the fancy DES decryption is no longer needed but rather the parameters can be feed straight into AES to perform the decryption.

Here is a modified version of the script to extract the new private key/IV
@Hagb Feel free to use this code


from ExAndroidNativeEmu.androidemu.const import emu_const
from ExAndroidNativeEmu.androidemu.emulator import Emulator
from ExAndroidNativeEmu.androidemu.internal import elf_reader
from ExAndroidNativeEmu.androidemu.java.classes.types import *
from ExAndroidNativeEmu.androidemu.utils.memory_helpers import read_utf8


AES_SECRET_KEY_FUNCTION = 'getKeyString'
AES_IV_FUNCTION = 'getInitVectorString'


def call_function(so_path, function_name, *args):
    # Initialize emulator
    reader = elf_reader.ELFReader(so_path)
    if reader.is_elf32():
        emulator = Emulator(
            vfs_root="ExAndroidNativeEmu/vfs",
            arch=emu_const.ARCH_ARM32,
            config_path="ExAndroidNativeEmu/emu_cfg/default.json"
        )
    else:
        emulator = Emulator(
            vfs_root="ExAndroidNativeEmu/vfs",
            arch=emu_const.ARCH_ARM64,
            config_path="ExAndroidNativeEmu/emu_cfg/default.json"
        )

    module = emulator.load_library(so_path)
    function_symbol = [module.find_symbol(export) for export in module.symbols if function_name in export]
    result = emulator.call_native(function_symbol[-1], *args)
    return read_utf8(emulator.mu, result)


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("python %s /path/to/libota_jni.so" % __file__)
        exit(0)

    secret_key = call_function(sys.argv[1], AES_SECRET_KEY_FUNCTION)
    iv = call_function(sys.argv[1], AES_IV_FUNCTION)

    print(f"AES Secret key: {secret_key}")
    print(f"AES Initialization vector: {iv}")

Below I have attached the corresponding binaries and screenshots of the new apk and library functions.

image
image
image

Binaries.zip

@RenateUSB
Copy link
Collaborator

For now we can just backtrack to the strings:

    'Tab10CPro': {
        'MODEL': 'Tab10CPro',
        'STRING_SETTINGS': 'on8l4AwDwIgVNi6AgrAqLzkc94XMx9O37CCELz23Fm+J',
        'STRING_UPGRADE': 'pQIr4QYOsvxLqxXik9cIIzca+QzC2pa9U/hY8p/EAkur'
    }

@Iey4iej3

This comment was marked as off-topic.

@Iey4iej3 Iey4iej3 mentioned this issue Nov 22, 2023
@Hagb
Copy link
Owner

Hagb commented Nov 22, 2023

Thank @RenateUSB and @hexomethyl ! I'm thinking that we could store these strings in boox_strings dict of DeBooxUpx like the older ones, and determine whether it is the AES keys or the DES-encrypted AES keys based on the length of the string?

@RenateUSB
Copy link
Collaborator

RenateUSB commented Nov 22, 2023

@Hagb I think that there are a number of ways to do this:

  1. Use 32 character hex strings for everything. The old strings can be decrypted into new source
  2. Use 44 character base64 string for everything. The new strings can be encrypted into new source
  3. Use a mixture using the same slot names
  4. Use a mixture using new slot names (key, iv) for new style strings

I think that (1) is the best solution. It's less text. It's the way forward.
In the short term I think that (2) is fine for now.
See #62 for four new model strings of which two are "back encrypted".

@Hagb
Copy link
Owner

Hagb commented Nov 22, 2023

@RenateUSB Thank you! The solution (1) and the code looks good to me.
Could you please submit a PR? Btw, Steam in deUpxSteam is a typo I made, which should be Stream. You could fix it together.

@Iey4iej3
Copy link

Close this issue by d48b8cb

@Hagb Hagb closed this as completed Nov 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants
@Iey4iej3 @Hagb @junrenshi @RenateUSB @hexomethyl and others