Edilkamin pellet stoves remote control reverse engineering. This is documenting my journey to reverse engineering The Mind Edilkamin app. The goal was to be able to control the stove wirelessly without having to use the proprietary app.
The steps to decompile an APK are mainly described in this article: Reverse Engineering Sodexo's API
Here we summarize some of them.
- APK used: https://play.google.com/store/apps/details?id=com.edilkamin.stufe
- version: 1.2.3 (19 November 2021)
Assuming the APK is already loaded on the Android device, proceed as below to download on the computer. Get the APK on device path:
adb shell pm list packages -f | grep edilkamin
Output:
package:/data/app/com.edilkamin.stufe-Di57pxUTs3wzjQF0dIxeEQ==/base.apk=com.edilkamin.stufe
Copy to the computer:
adb shell cp /data/app/com.edilkamin.stufe-Di57pxUTs3wzjQF0dIxeEQ==/base.apk /sdcard/
adb pull /sdcard/base.apk .
Decompile (jadx v1.3.3):
jadx --output-dir base base.apk
Often an interesting starting point is the base/resources/res/values/strings.xml
file.
We find the usual google_api_key
and google_app_id
, but no endpoint prefix or anything that
will be used in the short terms.
The APK source contains a lot of thirdparty code, but the actual application code is located in:
base/sources/com/edilkamin/stufe/
Let's grep
into it looking for some endpoints:
cd base/sources/com/edilkamin/stufe/ && grep -irE 'http(s)://' .
Output extract:
./network/EdilkaminApiServiceKt.java: public static final String BASE_URL = "https://s5zsjtooy4.execute-api.eu-central-1.amazonaws.com/test/";
./network/EdilkaminApiServiceKt.java: public static final String PROD_URL = "https://fxtj7xkgc6.execute-api.eu-central-1.amazonaws.com/prod/";
Other interesting files found and their extract:
base/sources/com/edilkamin/stufe/network/ApiService.java
:
@PUT("device/{mac_address}")
Object editAssociation(@Header("Authorization") String str, @Path("mac_address") String str2, @Body EditDeviceAssociationBody editDeviceAssociationBody, Continuation<Object> continuation);
@GET("device/{macAddress}/info")
Object getFireplaceInfo(@Path("macAddress") String str, Continuation<? super GeneralResponse> continuation);
base/resources/res/raw/amplifyconfiguration.json
:
"Default": {
"PoolId": "eu-central-1_BYmQ2VBlo",
"AppClientId": "7sc1qltkqobo3ddqsk4542dg2h",
"Region": "eu-central-1"
}
curl https://fxtj7xkgc6.execute-api.eu-central-1.amazonaws.com/prod/
Output (status code 403):
{ "message": "Missing Authentication Token" }
Let's try an unauthenticated endpoint then, remember that file network/ApiService.java
.
curl --verbose https://fxtj7xkgc6.execute-api.eu-central-1.amazonaws.com/prod/device/AA:BB:CC:DD:EE:FF/info
Output (status code 404):
{}
That looks already promising. After poking that endpoint around and using the real device MAC address we get a valid response. Note how the MAC address is all lower case and no column:
curl --verbose https://fxtj7xkgc6.execute-api.eu-central-1.amazonaws.com/prod/device/aabbccddeeff/info
Output (status code 200):
{"mac_address":"aabbccddeeff","pk":1,"component_info":{"temp_umidity_voc_probe_3":...}}
Bingo!
curl --verbose --request PUT --header "Content-Type: application/json" \
--data '{"mac_address":"aabbccddeeff", "name": "power", "value": 1}' \
https://fxtj7xkgc6.execute-api.eu-central-1.amazonaws.com/prod/mqtt/command
It seems like most endpoints let you read info or control the stove without any authentication. All we need is a valid device MAC address. Don't leak your MAC address or people can potentially control your stove.
October 2022 update: the endpoints got updated to require a JWT token and the stoves are linked to the account.