Skip to content

Firmware upgrade sequence documentation #111

@kasparsd

Description

@kasparsd

I've been able to capture the network traffic when the app attempts to update the Wi-Fi module firmware. See this blog post for the full details.

gree-wifi-firmware-upgrade

Update Sequence

The app fetches the hid value from the unit to extract the firmwareCode which it then checks against the regional update servers like eu.grih.gree.com/wifiModule/Lastversion?firmwareCode=362001065736 that respond with:

{"CreateDate":"2023-07-14 02:29:37","commProtVer":"V1.2.1","desc":"In this version, we have fixed some known issues.","forcedUpgrade":0,"r":200,"url":"http://eu.grih.gree.com/wifiModule/image/10141/145680","ver":"3.77"}

Note that the same firmwareCode from the global server returns a different response while the URL binaries are identical (as verified by the md5 hashes).

The app then sends the extracted firmware URL to the unit with the following payload:

{"cid":"0b484895e0dd","i":0,"pack":"OoTBKh2jsVL1ub3k6oQkT6mzvcMpFaG+XU+9N4WVBjdT8ikJJd8lsO7ID231MggE7ZHERYByIQyOEMRdRZXQ1BlngXm9zF15S891hChiDP8VU4iur2KcklAVo+SrB+yvbq7opZ+mtUBG6cyX1DH9Hw==","t":"pack","tcid":"UNIT_MACID","uid":0}

where pack is encrypted with the dynamic key (instead of the hardcoded) and contains the following:

{"t":"upgrade","url":"http://eu.grih.gree.com/wifiModule/image/10141/145680","mac":"UNIT_MACID"}

to which the unit responds with:

{"t":"pack","i":1,"uid":0,"cid":"UNIT_MACID","tcid":"0b484895e0dd","pack":"PACK_PAYLOAD_WITH_STATIC_KEY"}

where the payload is encrypted with the shared (hardcoded) key:

{"t":"ret","r":200,"mac":"UNIT_MACID"}

Firmware verification

Based on the strings I extracted from the firmware files, it appears to be checking the validity of the downloaded firmware binary by comparing its md5 hash to the FileMd5 HTTP header included in the firmware response from the update server:

$ curl -I http://eu.grih.gree.com/wifiModule/image/10141/145680
HTTP/1.1 200 OK
Date: Sun, 03 Nov 2024 12:09:19 GMT
Content-Type: application/octet-stream
Content-Length: 145680
Connection: keep-alive
Server: nginx
Content-Disposition: attachment; filename="U-QCOM4004CV3.77.bin-9979849298584095054.bin"
Content-Range: bytes 0-145679/145680
FileMd5: f5ac9d07b5499dac210d550710f7ef2a
supcc: 3324d648008ce504a8a519571dc2aa8e4816e5ae92c53100a3dd9052e9b9165c
Strict-Transport-Security: max-age=31536000
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache
Set-Cookie: HttpOnly
Set-Cookie: Secure

so any custom firmware URLs would need to support this too!


While my unit is currently failing to update to the latest 3.77 due to unknown reasons, it would be interesting to see if anyone else is able to get this working successfully. I was able to send an upgrade sequence with a custom URL and the unit responded with a 200 success like above (while it didn't actually upgrade).

I'm not sure if this can be added to this library in any meaningful way but I wanted to document it for anyone looking for the solution. Exposing this to users could lead to bricked devices as they upload incorrect firmware files.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions