Skip to content

Latest commit

 

History

History
143 lines (98 loc) · 4.16 KB

ReverseEngineering.md

File metadata and controls

143 lines (98 loc) · 4.16 KB

Edilkamin Stove Reverse Engineering

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.

APK download & decompiling

The steps to decompile an APK are mainly described in this article: Reverse Engineering Sodexo's API

Here we summarize some of them.

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

Looking into strings.xml

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.

Let's grep through the source

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"
}

Poking the /prod/ endpoint around

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!

Turn the stove on

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

Note on Security

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.