-
Notifications
You must be signed in to change notification settings - Fork 64
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
gree.py - "The length of the provided data is not a multiple of the block length" exception on initial search #52
Comments
@marius-nicolae please try the script with
|
As I wrote in the other issue ( #48 (comment) ) the
|
@marius-nicolae I've updated the script to print more details before trying to decrypt the response. Please run the verbose search command again and paste the whole output here. It should print the raw response packet now. |
Indeed, I was running an older version. Here is the new output:
|
Hello, |
Unfortunately, I've disassembled the latest version of the Android app but didn't manage to find out if there is a new encryption key for these new units. There is a libGree.so library which I've tried to dissect with Ghidra, but it only finds a huge number of randomly named functions without any instructions in them, which doesn't seem to be right. Last time I've found the generic encryption key in the same library. If you have the time, you could try to disassemble the app. |
I tried doing this, my thought process was; I should find the old key somewhere for backward compatibility, if I found it, I will find the new key somewhere around. This was the first time I used disassemblers. I had no success with the latest version. I found the already known key in an 1.7 version. As I understand this list they did some drastic changes in 1.8.0, going further they consolidated the imports (number of so-s in the lib dir) too, but the disassembled code looks kinda the same in 1.8 and 1.11 (lot of function with strange names). The TOSOT+ seems as a rebranded GREE+ after a disassembly. I also tried the invmateii app, but as I understand the code that interest us is probably in the java/kotlin land. (I found it mentioned in an other issue.) I'm almost sure that this app is a rebrand of the midea app. And after checking their site I'm not convinced that they do anything with Gree. Do we have firmwares available for decompile too? |
After a few months of pause, I took down the project from the shelf and tried to approach the problem from a different angle. Instead of trying to disassemble the Android app, I'm dissecting the iOS version. Since the GREE+ app can be installed on an M1 MacBook from the AppStore, I can access the internals of the app. I've started looking into the main executable with Ghidra and found a few different encryption and decryption methods. One of them looks like this (decompiled Swift/Objective-C code, the function and variable names are added by me by analyzing the calls and contexts, so they can be inaccurate):
I've tried to translate this to a python code and feed the data pack @marius-nicolae found:
Unfortunately I only got garbage as output, so something is not right. But the fact that these new packs can't be decrypted due to alignment issues proves that they attach some kind of extra data to the encrypted blocks and that extra info can be the decryption key for the scan response. I've also found a few new master keys in the code:
In addition I've found out that devices which have I can share the Ghidra disassembly project if someone wants to experiment. |
@tg44 The pack you've posted on the other issue seem to be decryptable with the generic key using the old method:
|
Nice! How did you do that? |
@tg44 ; the pack was decryptable with the old generic key import base64
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
def create_cipher(key):
return Cipher(algorithms.AES(key.encode('utf-8')), modes.ECB(), backend=default_backend())
if __name__ == '__main__':
#your pack from the other issue
encryptedPack = 'LP24Ek0OaYogxs3iQLjL4BZGC1L9UK8LWYY9r9h4dgWMa9lM2RqI/KytvJ32IsGSZXrOr+MakVzzXHbghPeyijnWMzaLQaaw1aFXlE9k71L0cMm8bsr/y4FkxumpRg1t0xV8+/m47OTBNaX/8aUl1ZJhYuNQNgXxv5Sro8mBB9BzMQoS41XpnORSG7+GfavhnKYbt0iIDsdp8/ftXlA9Hi9SYH2dzE8EeLZzuqwrQT280gq9HxK8Loa8WXVjgZcP4Vf5MjKxa60Xt5J1oI+lsxUuXTHkgunLg76WWGy+euo='
#the old generic key
key = "a3K8Bx%2r8Y7#xDh"
decryptor = create_cipher(key).decryptor()
pack_decoded = base64.b64decode(encryptedPack)
pack_decrypted = decryptor.update(pack_decoded) + decryptor.finalize()
print( pack_decrypted) Code above prints:
Unfortunately this does not solve anything. I have the same issue with my Vaillant Airco Units with a "tag" in their response. |
I did find the keys of my v2.0.0 Vaillant wifi-dongles by installing the gree+ app on my m1 macbook, then going to: ~/Library/Containers/GREE+/Data/Documents/room.sqlite Skip the following. I used the self encrypted string instead of the response. My fault. If i then use the following code:
i get the following output:
I'm trying to use the https://github.com/RobHofmann/HomeAssistant-GreeClimateComponent however the climate interfaces are added, but can't be updated ( EDIT: After looking around in most of the Cordova code, i have seen that most of the encrypted data is padded with pkcs7. Therefor when unpadding the data afterworths the data seems to be correct:
Output:
|
@tomikaa87 could you share the Ghidra disassembled project with me, I would like to try my luck. |
@lovery did you have any luck in disassembling the encryption protocol of packates with tag field? |
@tomikaa87 {"t":"pack","i":1,"uid":0,"cid":"502cc66cc89e","tcid":"06470c52c566","tag":"DW39Z7ZlxSgR/g1SddnjpQ==","pack":"JtoKliwtrZWlpNCVOSARFZVjvdMQgUTwNgc3BeOOhOTTdG5N10M5OI3w9aCGCJffjfuyCITofrMT4JbII6+A1+2Qyk7gfwk5dZR2EayhdZgEoOSGGofp1NG95slltfseFq+2oChWDqTDGSfh0Qvsoz/uHnpJj7cgLseHEa1Qy49usnE8T0XpY+Ox+QIjDK2y2vzlARuL1vKmpT7wkMRwPTuo1zE7mhrFvdLWdzI6Z6osCeD6tdJoLaE7k6FHvghQKe+boL4="} Találtál már esetleg valami megoldást? A GREE+ app simán működik az eszközzel, az EWPE Smart App is működik. A Wifi modul típusa: GREE GRJ532-J14 Tudsz esetleg segíteni? Köszi, üdv |
Hi everyone! I've got some firmware files, tried to find new crypto algo in the firmware itself, but with no luck. |
Well, I've been everywhere today, I hope it wasn't too invasive. I tried to link these issues such that we can keep track if them in a central place. Thanks to Maxim's suggestion, I managed to get my device's firmware. Fortunately, the version I have contains a LOT of information. Specifically, it is about the In this file, you can find the The device itself seems to run UPDATE: It seems that right before the data region there's a function which seems to take a 32-bit argument (probably an int index) and return the corresponding string data from the "ds". Therefore, the string we need might be referenced somehow by ID. It crossed my mind, that the SDK they use is now open source, as well as the FreeRTOS. Could it be possible to build a sample firmware with debugging symbols, and check to see how it's structured, to figure out if we have similar functions? |
Good news - Maxim managed to find a firmware which contains an AARCH64 version of the Gree communication thing. The best news is that it has debugging symbols! The binary is NOT stripped! The old key can be found inside. It's at maxim-smirnov/gree-wifimodule-firmware#2 (comment) EDIT: Looks like there is an update pending, version 1.53 which solves these problems. With this, it seems that my units use the key
|
I'm still having this issue.. I'm stuck on Firmware 1.08 (Vaillant) also tried to update firmware with an edited apk of gree+, still no updates. http://test.grih.gree.com/wifiModule/Lastversion?firmwareCode=362001062107 |
tag - this could be authentication tag for AES-GCM or AES-GCM-SIV. |
from Crypto.Cipher import AES
import base64
def mbedtls_gcm_auth_decrypt(key, iv, add, tag, encrypted_data):
cipher = AES.new(key, AES.MODE_GCM, nonce=iv)
cipher.update(add)
try:
decrypted_data = cipher.decrypt_and_verify(encrypted_data, tag)
return decrypted_data
except ValueError:
print("Incorrect decryption or tag verification failed")
return None
def main():
key = b'need a key' # 128bit long key
iv = b'\x54\x40\x78\x44\x49\x67\x5a\x51\x6c\x5e\x63\x13'
add = b'qualcomm-test'
tag = base64.b64decode('YOUR_BASE64_ENCODED_TAG')
encrypted_data = base64.b64decode('YOUR_BASE64_ENCODED_ENCRYPTED_DATA')
decrypted_data = mbedtls_gcm_auth_decrypt(key, iv, add, tag, encrypted_data)
if decrypted_data is not None:
print("Decrypted data:", decrypted_data.decode('utf-8'))
else:
print("Decryption failed")
if __name__ == "__main__":
main() |
New algorithm was added her RobHofmann/HomeAssistant-GreeClimateComponent#165 |
This is really cool, people confirmed it works on multiple versions. What made you believe the tag was an AES tag? How did you figure it was one of those variants specifically? I'm curious about the actual research behind the discovery, it's been a long battle. |
New devices are using AES-GCM encryotion for communication More details about the problem in tomikaa87#52
Hi,
First, thanks for your great initiative!
When using gree.py to discover my Gree devices (the search command) it first successfully decrypt my Cooper & Hunder's returned pack JSON field. Still, then it returns
The length of the provided data is not a multiple of the block length
exception while attempting to decrypt the pack field returned by the second Gree Soyal device (might be a newer model!!). I've tried to apply padding, using Python'sPKCS7(128).padder()
, it doesn't crash anymore but the decrypted data seems garbage and not a valid JSON.Are the new Gree models make use of other generic keys? Can you, please provide some guidance, on how to investigate further?
Thanks!
The text was updated successfully, but these errors were encountered: