User Tools

Site Tools


doc:appunti:hardware:insta360_one_rs_wifi_reverse_engineering

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
doc:appunti:hardware:insta360_one_rs_wifi_reverse_engineering [2023/07/04 14:43] – [Running tcpdump on the Insta360] niccolodoc:appunti:hardware:insta360_one_rs_wifi_reverse_engineering [2023/09/08 10:46] (current) – [Insta360: WiFi protocol reverse engineering] niccolo
Line 1: Line 1:
 ====== Insta360: WiFi protocol reverse engineering ====== ====== Insta360: WiFi protocol reverse engineering ======
  
-I purchased an **Insta360 ONE RS** action camera in June 2023, I'm rather satisfied by its performances, but I'm really disappointed by the accompanying Android app. The app (version 1.40.1) is a monster download of **676 Mb**, once installed it requires more than 1 Gb of storage. It is rather invasive about permissions request because it wants access to the camera (the phone's camera!), contacts, microphone and phone. Once started it is totally **social oriented**, presenting me **blatantly useless info** about what other people does with their cameras.+Get the open source software from the **[[https://github.com/RigacciOrg/insta360-wifi-api/|RigacciOrg/insta360-wifi-api]]** GitHub repository. 
 + 
 +I purchased an **[[insta360_one_rs|Insta360 ONE RS]]** action camera in June 2023, I'm rather satisfied by its performances, but I'm really disappointed by the accompanying Android app. The app (version 1.40.1) is a monster download of **676 Mb**, once installed it requires more than 1 Gb of storage. It is rather invasive about permissions request because it wants access to the camera (the phone's camera!), contacts, microphone and phone. Once started it is totally **social oriented**, presenting me **blatantly useless info** about what other people does with their cameras.
  
 **What I need is a simple remote control** for my action camera, not another invasive and useless social network. Beside that, the app doesn't work on my phone; maybe because the hardware specs are not at the cutting edge of techonolgy (but neverthless my phone has 4 Gb of RAM and a 4 cores MediaTek Helio A22 SoC), whenever I tap the icon to start the live view the app crashes. So the basic function of remote controlo does not work. **What I need is a simple remote control** for my action camera, not another invasive and useless social network. Beside that, the app doesn't work on my phone; maybe because the hardware specs are not at the cutting edge of techonolgy (but neverthless my phone has 4 Gb of RAM and a 4 cores MediaTek Helio A22 SoC), whenever I tap the icon to start the live view the app crashes. So the basic function of remote controlo does not work.
Line 19: Line 21:
 So I installed the Insta360 app into a **rooted** Android smartphone. On the same phone I'm running the **Termux** app where I installed the **tcpdump** package. So I discovered that the app talks to the Insta360 camera through the port **6666/TCP**, where a server is expecting and returning messages. The messages are not in clear text: it turned out that they are serialized using the **[[https://protobuf.dev/|Protocol Buffers]]** mechanism (thanks to this **[[https://hackaday.io/project/188975-insta360-x3-ble-remote-control-with-esp32|Hackaday.io post]]** which gave me the enlightening hint). So I installed the Insta360 app into a **rooted** Android smartphone. On the same phone I'm running the **Termux** app where I installed the **tcpdump** package. So I discovered that the app talks to the Insta360 camera through the port **6666/TCP**, where a server is expecting and returning messages. The messages are not in clear text: it turned out that they are serialized using the **[[https://protobuf.dev/|Protocol Buffers]]** mechanism (thanks to this **[[https://hackaday.io/project/188975-insta360-x3-ble-remote-control-with-esp32|Hackaday.io post]]** which gave me the enlightening hint).
  
-===== Running tcpdump on the Insta360 =====+===== Running tcpdump into the Insta360 ===== 
 + 
 +If your Android device is not rooted, you can still capture the WiFi traffic between the Android app and the Insta360 camera by just executing **tpcudmp** directly on the GNU/Linux operating system of the camera. You have to download and install the required binaries, which are fortunately provided by the **[[http://entware.net/|Entware Projec]]**.
  
 Download from **[[http://bin.entware.net/|entware.net]]** the following packages (choose **aarch64** architecture, kernel **3.10**): Download from **[[http://bin.entware.net/|entware.net]]** the following packages (choose **aarch64** architecture, kernel **3.10**):
  
   * libc_2.27-11_aarch64-3.10.ipk   * libc_2.27-11_aarch64-3.10.ipk
 +  * libgcc_8.4.0-11_aarch64-3.10.ipk
   * libpcap_1.10.4-1_aarch64-3.10.ipk   * libpcap_1.10.4-1_aarch64-3.10.ipk
   * librt_2.27-11_aarch64-3.10.ipk   * librt_2.27-11_aarch64-3.10.ipk
Line 31: Line 36:
  
 Create a directory into the SD card **/tmp/SD0/opt/** and unpack the above archives, keeping the directory structure and dereferencing links into plain files (the SD filesystem does not support symbolic links). Create a directory into the SD card **/tmp/SD0/opt/** and unpack the above archives, keeping the directory structure and dereferencing links into plain files (the SD filesystem does not support symbolic links).
 +
 +Suppose that the Android device running the Insta360 app has IP address 192.168.42.2, run the following script at the command line of the camera:
  
 <code bash> <code bash>
 #!/bin/sh #!/bin/sh
 test -f /opt/bin/tcpdump || mount -o bind /tmp/SD0/opt /opt test -f /opt/bin/tcpdump || mount -o bind /tmp/SD0/opt /opt
-/opt/bin/tcpdump -w /tmp/SD0/tcpdump.log -s0 -n 'host 192.168.42.2'+/opt/bin/tcpdump -w /tmp/SD0/tcpdump-$(date +%m%d%H%M%S).log -s0 -n 'host 192.168.42.2'
 </code> </code>
 +
 +
 +===== Packets anatomy =====
 +
 +==== Sent Packets ====
 +
 +=== Sync Packet ===
 +
 +^ Offset  ^ Content  ^ Bytes  ^ Note  ^
 +|   0 | Packet Length     | 4   | Overall length of the packet, including this 4 bytes.  |
 +|   4 | 0x06 0x00 0x00    | 3   | Message Type: Sync Packet.  |
 +|   7 | syNceNdinS        | 10  | Magic String.  |
 +
 +=== Keep Alive Packet ===
 +
 +^ Offset  ^ Content  ^ Bytes  ^ Note  ^
 +|   0 | Packet Length     | 4   | Overall length of the packet, including this 4 bytes.  |
 +|   4 | 0x05 0x00 0x00    | 3   | Message Type: Keep Alive.  |
 +
 +=== Phone Commands ===
 +
 +^ Offset  ^ Content  ^ Bytes  ^ Note  ^
 +|   0 | Packet Length     | 4  | Overall length of the packet, including this 4 bytes.  |
 +|   4 | 0x04 0x00 0x00    | 3  | Message Type: Phone Command.  |
 +|   7 | Message Code      | 2  | Examples: PHONE_COMMAND_GET_OPTIONS, PHONE_COMMAND_SET_OPTIONS, PHONE_COMMAND_TAKE_PICTURE, PHONE_COMMAND_START_CAPTURE, etc.  |
 +|   9 | 0x02              | 1  |
 +|  10 | Sequence Number   | 3  | Each command sent to the camera have its increasing sequence number, the relative response contains the same sequence number.  |
 +|  13 | 0x80 0x00 0x00    | 3  |
 +|  16 | Protobuf Message  | Variable  | The message serialized using Protocol Buffers.  |
 +
 +
 +==== Received Packets ====
 +
 +=== Notifications or Response to Phone Commands ===
 +
 +^ Offset  ^ Content  ^ Bytes  ^ Note  ^
 +|   0 | Packet Length     | 4  | Overall length of the packet, including this 4 bytes.  |
 +|   4 | 0x04 0x00 0x00    | 3  | Response Type: Phone Command.  |
 +|   7 | Response Code     | 2  | Examples: 200: OK, 500: ERROR, CAMERA_NOTIFICATION_CURRENT_CAPTURE_STATUS, etc.  |
 +|   9 | 0x02              | 1  |
 +|  10 | Sequence Number   | 3  | Matches to the requesting message.  |
 +|  13 | 0x80              | 1  |
 +|  14 | Unknown           | 2  |  |
 +|  16 | Protobuf Message  | Variable  | The response message serialized using Protocol Buffers.  |
  
  
Line 51: Line 102:
 </code> </code>
  
-Then **extract some protobuf binary messages from the tcpdump output**; in the following example we try to decode a binary message received from the camera by the Android app. It seems that each message is prefixed by a 12 bytes header (more on that later), so in the Python code strip that header away and keep only the message body before calling the ''protobuf_to_json()'' function:+Then **extract some protobuf binary messages from the tcpdump output**; in the following example we try to decode a binary message received from the camera by the Android app. Each message is prefixed by a 12 bytes header (see packets anatomy, above), so in the Python code strip that header away and keep only the message body before calling the ''protobuf_to_json()'' function:
  
 <code python> <code python>
Line 114: Line 165:
 ===== Getting the .proto definitions ===== ===== Getting the .proto definitions =====
  
-:!: **WARNING**: In this paragraph you can read about my first attempt in getting the *.proto files from a demo executable. It turned out that **the files were not complete and not fully up-to-date**. It is advised to use the current Android app to get a more recent version of the *.proto files. See the next paragraph for the recipe.+:!: **WARNING**: In this paragraph you can read about my first attempt in getting the *.proto files from a demo executable. It turned out that **the files were not complete and not fully up-to-date**. It is advised to use the current Android app to get a more recent version of the *.proto files. See the **[[#getting_the_proto_files_from_the_android_apk|next paragraph for the full recipe]]**.
  
 To understand the messages structure of the messages exchanged betwwen the software and the camera **it is necessary to have the .proto files** that define the syntax, but how can you do it without having access to the non-free source codes of Insta360? To understand the messages structure of the messages exchanged betwwen the software and the camera **it is necessary to have the .proto files** that define the syntax, but how can you do it without having access to the non-free source codes of Insta360?
Line 183: Line 234:
  
 ===== Getting the .proto files from the Android APK ===== ===== Getting the .proto files from the Android APK =====
 +
 +Download the .proto file extractor tool from **[[https://github.com/RigacciOrg/insta360-wifi-api/tree/main/utils|this repository]]**. Download the Android app and extract the **libOne.so** file from it. Then run the following recipe:
  
 <code bash> <code bash>
Line 219: Line 272:
 echo "Python files were compiled into the pb2 directory." echo "Python files were compiled into the pb2 directory."
 </code> </code>
 +
 +===== The Insta360 Python remote program =====
 +
 +On the **[[https://github.com/RigacciOrg/insta360-wifi-api/|insta360-wifi-api GitHub repository]]** you can find a Python library which implements basic communication with the Insta360 camera over WiFi connection. There is also an example Python program with the basic functionality of **remote control**. You can easily run it from a PC with GNU/Linux, but you can also install the required Python language and libraries in MS-Windows and even on Android. I run that program on my smartphone, it just required to install the **[[https://f-droid.org/en/packages/com.termux/|Termux]]** app.
 +
 +
 +===== Unsolved Problems =====
 +
 +It seems **impossibile to change some settings via the WiFi API**; e.g. I was not able to change:
 +
 +  * Sharpness
 +  * Prompt Sound
 +  * Indicator Light (LEDs)
 +
 +When some settings are changed via the WiFi API, **the preview on the camera screen does not reflect that change**; nor in the live stream, nor into the on-screen-display labels. E.g. white balance, capture resolution, fielf of view. Fortunately if you start the video capture, the settings are effective.
 +
 +
 +===== White Balance Settings =====
 +
 +It is possible to change the white balance setting by changing the value of **white_balance** choosing from some enumerated presets or directly by changing the temperature value of **white_balance_value**. There seems to be some inconsistency between the labels assigned to the presets in the .proto files and the actual temperature values. I think that the best choice is to assign the white_balance_value, ignoring the enumerated presets.
 +
 +^ white_balance_value  ^ white_balance  ^ Protobuf Enum Label  ^
 +|   AUTO |   0 | WB_AUTO  |
 +|   2000 |   6 |  |
 +|   2200 |   7 |  |
 +|   2400 |   8 |  |
 +|   2600 |   9 |  |
 +|   2800 |   1 | WB_2700K  |
 +|   3000 |  10 |  |
 +|   3200 |  11 |  |
 +|   3400 |  12 |  |
 +|   3600 |  13 |  |
 +|   3800 |  14 |  |
 +|   4000 |   2 | WB_4000K  |
 +|   4500 |  15 |  |
 +|   5000 |   5 | WB_7500K  |
 +|   5500 |  16 |  |
 +|   6000 |  17 |  |
 +|   6500 |   3 | WB_5000K  |
 +|   7000 |  18 |  |
 +|   7500 |   4 | WB_6500K  |
 +|   8000 |  19 |  |
 +|   8500 |  20 |  |
 +|   9000 |  21 |  |
 +|   9500 |  22 |  |
 +|  10000 |  23 |  |
 +
  
 ===== Web References ===== ===== Web References =====
doc/appunti/hardware/insta360_one_rs_wifi_reverse_engineering.1688474619.txt.gz · Last modified: 2023/07/04 14:43 by niccolo