diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..64d3b37817ffc339806db2159d8a03eb109b2a97 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.pio/ +CMakeListsPrivate.txt +.idea/ diff --git a/doorbell_v7_ring/CMakeLists.txt b/doorbell_v7_ring/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..fe1d91c6f21116b04637db58c9c415f347a91bb3 --- /dev/null +++ b/doorbell_v7_ring/CMakeLists.txt @@ -0,0 +1,89 @@ +# !!! WARNING !!! AUTO-GENERATED FILE, PLEASE DO NOT MODIFY IT AND USE +# https://docs.platformio.org/page/projectconf/section_env_build.html#build-flags +# +# If you need to override existing CMake configuration or add extra, +# please create `CMakeListsUser.txt` in the root of project. +# The `CMakeListsUser.txt` will not be overwritten by PlatformIO. + +cmake_minimum_required(VERSION 3.2) +project("doorbell_v7_ring") + +include(CMakeListsPrivate.txt) + +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeListsUser.txt) +include(CMakeListsUser.txt) +endif() + +add_custom_target( + PLATFORMIO_BUILD ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion run "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_BUILD_VERBOSE ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion run --verbose "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_UPLOAD ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion run --target upload "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_CLEAN ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion run --target clean "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_MONITOR ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion device monitor "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_TEST ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion test "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_PROGRAM ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion run --target program "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_UPLOADFS ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion run --target uploadfs "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_BUILD_DEBUG ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion run --target debug "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_UPDATE_ALL ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion update + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_REBUILD_PROJECT_INDEX ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion init --ide clion + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_DEVICE_LIST ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion device list + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_executable(Z_DUMMY_TARGET ${SRC_LIST}) diff --git a/doorbell_v7_ring/README.md b/doorbell_v7_ring/README.md new file mode 100644 index 0000000000000000000000000000000000000000..4b9283b0fcde493edd8a8bb9b776dd29b4c0c7b3 --- /dev/null +++ b/doorbell_v7_ring/README.md @@ -0,0 +1,198 @@ +# Doorbell V7 Ring! + +This little arduino project triggers the indoor receiver of the Doorbell V7 +of brand Eken (ours is a "BlumWay", there are many more other fake brand +names under which it is sold). + +The project requires a 443.92 MHz transmitter/receiver pair of boards. + + +## Doorbell V7 description + +The doorbell system consists of two devices. There is an outdoor device +which is the by far more powerful system. It contains a camera and a +couple other sensors, speaker, microphone etc. It communicates its video +and audio conversations over WiFi, talking to other devices in the same +WiFi and/or with some dubious Chinese "cloud" system. + +*TODO: insert pictures* + +The other device, the indoor receiver, forwards the "ring" of the bell +into the house so it will be heard by the residents. + +It is obvious that the outdoor device communicates wirelessly with the +receiver. There is no setup of any kind involved, both devices are +paired off the self. The devices most likely use some license and +royalty free communication over a public unlicensed band. The most +likely ones here are either the ISM bands (e.g., ~ 433 MHz / 2.4 GHz) +or, less likely, SRD bands (e.g., ~ 868 MHz) (only the frequencies +which are at least available in Europe were named here). + + +## Reverse engineering the radio communication + +The first guess was right, both devices apparently communicate over +433.92 MHz. A simple RTL-SDR receiver could record some communication +at this band when the "ring" was triggered on the outdoor device and +the indoor device reacted by playing a melody. + +The cheapest and simplest option to perform some digital communication with +a low bitrate and only few data is to use amplitude modulation known as +*Amplitude Key Shifting (ASK)*. When using ASK one can transmit two or more +values at a time, each represented by a specific amplitude level. The +simplest option, i.e., the transmission of two possible values, is called +*On-Off Keying (OOK)*. In OOK the presence of a carrier wave represents a `1`, +whereas the abscence represents a `0`. With every clock cycle, one can +therefore transmit one bit. + +OOK is fairly simple to implement, there is a vast selection of ready-to-use +chips available implementing the correct behavior. For development with the +typical embedded development kits such as e.g., the Arduino, there's complete +boards available which usually come in pairs providing either a transmitter +or receiver with a data pin that either accepts or produces a digital signal, +making using 443.92 MHz for communication of e.g., sensor data or, like here, +doorbell signals very simple. + +But let's leave this aside for a second and first look at how exactly the +doorbell and its indoor relay communicate. First, we have to verify the +estimation of the frequency used for their communication. As mentioned above, +an RTL-SDR was used. It was used through gqrx. Tuning on 443.92 MHz, one +could see a short transmission whenever a "ring" was triggered. Assuming that +there is a causal relationship between the action of pressing the button and +seeing this communication in the waterfall graph, one now knows the frequency. +The next step is to see what kind of communication this is. + +Making the +assumption that this is rather a digital than an analog communication, one has +to check all possible modulations in order to find the one which is used. +Chances are good that an amplitude modulation is in use, so in gqrx for testing +one can turn on the AM demodulator and record one or more transmissions into +a WAV file. This WAV file then can be opened in any audio editor. Zooming in, +the signal will become visible. If it "looks digital", you have successfully +found both frequency and modulation. + +As mentioned above, here, an OOK is in use, which means that the demodulated +signal can be interpreted by considering every low section as `0`es and every +high section as `1`s. Now, the process of analyzing the contents is pretty +much the exactly same as when e.g., reverse engineering digital signals with +a Logic Analyzer. One has to calculate the timing etc. + +Talking about a logic analyzer, in this scenario using an SDR device and +GNU radio isn't necessary for further analysis any more. Once you know that +OOK is used at 443.92 MHz, you can use one of the receiver boards and a +simple logic analyzer with tools like sigrok (most comfortably over its UI +PulseView). The receiver demodulates and cleans up the transmitted signal and +generates a proper digital signal on a data pin. Therefore, you just have to +plug in some 5V voltage and ground to power the receiver, +then you can hook up your logic analyzer to the data and ground pins of the +receiver and record the signal directly in PulseView. This way, you can save +yourself from the hassle of handling a digital signal in a WAV file (which +also has some limitations, e.g., WAV files are typically generated with PCM +(i.e., the raw analog demodulated signal) and rather low sample rates (44.1 +or 48 kHz. Therefore you have two problems: First, you need to convert the +analog demodulated signal into a digital one that e.g., sigrok or other tools +can work with. Secondly, the low PCM sampling rate limits your bitrate +(following the Nyquvist-Shannon theorem, you can record up to a maximum of +~ 20 kb/s precisely before losing data, taking into account a safety of +4.1 kHz (value known to work for audio applications)). Therefore, the +workflow over gqrx is most useful for a first analysis, but there's more +comfortable ways to continue. + +*TODO: insert pic of signal recorded in PulseView* + +The signal was retransmitted and recorded in PulseView using a rather low +sampling rate of 250 kHz. This is a bit too low for precise timing +calculations (every pulse width is represented by < 12 data points, the +higher the more precise) but worked well enough in this case. + +PulseView supports a variety of "protocol decoders", new ones added in almost +every release. These take away the handywork of extracting the payload sent +in a digital code, once you know what kind of encoding (if any!) is in use. + +At a first glance the signal is similar to a Manchester code, however, as +PulseView's Manchester decoder confirms, the signal would contain a lot of +errors. Therefore, it was concluded that the signal must be something +different. + +The specific encoding doesn't really matter for our purposes, though. Therefore, +the signal was interpreted as *Non-Return to Zero (NRZ)* (most basic encoding +you could think of, most other encodings like e.g., the Manchester code, can +be interpreted as NRZ as well (for Manchester, you have double the actual +bitrate, with `01` and `10` pairs representing the two states of a bit that is +transmitted)). + +Using the information discovered so far, one can calculate the pulse width of +the signal. PulseView provides a *timing* decoder for this purpose. We've +observed that the shortest pulses in the signal are 300 µs long and every other +state is a multiple of this value. Therefore this signal is NRZ with a bit +every 300 µs. There are around 40 repetations of the exact same code with gaps +of around 4.7 ms. Those retransmissions are most likely a sort of safety to +make sure that temporary interferences (e.g., when another device is +transmitting at the same time; there is no globally unified system for +transmitting digital codes in these bands and therefore there's no unfied MAC +system, instead most countries regulate that one may e.g., transmit only at most +1% in a given time interval with a strongly limited EIRP to group local devices +instead of trying to detect and/or avoid collisions, which would be possible +only with a unified protocol which every device implements) don't affect a +ring action too much, at least one code should make it through to the receiver. + +An interesting observation is that the code is static, i.e., has never changed +in any recording we made over a couple of weeks. This means that "replay attacks" +are well possible. This really makes things easier for us, as our target was to +simulate the signal with cheap commodity hacking hardware. + + +## Test run + +Having temporary access to a USRP B200 (a combiend receiver-transmitter software +defined radio device), we could test our assumption that replaying the signal +could trigger the doorbell before proceeding. We recorded the signal with +Universal Radio Hacker and replayed it. As expected, the doorbell receiver +played its annoying jingle. + + +## Reproducing the signal + +In this scenario, the easiest way to procede was to simply write down the single +bits observed in PulseView. Knowing the pulse width, one can now reproduce this +radio signal. + +As mentioned above, there are simple OOK transmitter boards which accept a digital +signal of any kind and turn on and off a 433.92 MHz carrier wave based on that. +Therefore, all we have to do is generate this digital signal and hook up one +of these OOK transmitters and should hear a "ring" from the receiver device. + +A Chinese Arduino Nano clone is very suitable to generate this signal. Its +microprocessor is way fast enough for this application. Even smaller ones, like +for example an ATTiny (e.g., an ATTiny85) would suffice. Anything more powerful +than a Nano is actually a waste of hardware. The ATmega328p on the Nano runs at +16 MHz, i.e., a single CPU cycle is 0.125 µs long. We have to change the state of +the data pin every 300 µs, i.e., around every 2400th cycle. A huge advantage of these +microprocessors is that one can block any kind of interrupt, i.e., use them as +realtime signal generators. But at a safety factor of 2400 or more, this isn't an +absolute necessity. A Raspberry Pi could probably also simulate this signal just +fine. + +For this project, we used an Arduino Nano clone. Please see the code in this +repository, primarily `main.cpp`. +The signal is represented by an array of `0`es and `1`s and generated in a `for` +loop which reads values from said array, changes the state of the pin and then +waits for 300 µs before the next iteration. Taking into account the CPU cycles +needed for the loop doesn't make a lot of sense, as mentioned above the time +between state changes is 2400 CPU cycles, and the signal is quite short +(< 100 samples). The generated signal does derive from original signal, +however that won't have any real effect on the transmission. By replicating the +original sender's behavior and repeating the signal 40 times, chances are good +at least one (but much likely more) can be decoded properly by the receiver. + + +## Further possible attacks + +By shorting the data pin to the main voltage of the transmitter, you can +effectively distort the doorbell ring signal (and any other sensor, e.g., +weather stations, etc.) and prevent receivers from decoding the signal. +You can also generate some random signal at a random bitrate. + +**Please note that this kind of attack does most likely provide a violation +of the fair-use regulations made for the unlicensed radio bands and should +only ever be done for evaluation or demonstration purposes!** diff --git a/doorbell_v7_ring/main.cpp b/doorbell_v7_ring/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..df55054c46b570dbf0b957dc4428f8c399908bfb --- /dev/null +++ b/doorbell_v7_ring/main.cpp @@ -0,0 +1,58 @@ +#include <Arduino.h> + +#define SEND_PIN 10 + +#define LONG 9 +#define SHORT 3 + +static int code[] = { +1,1,1,0, +1,1,1,0, +1,0,0,0, +1,1,1,0, +1,1,1,0, + +1,0,0,0, +1,1,1,0, +1,0,0,0, +1,0,0,0, +1,0,0,0, + +1,1,1,0, +1,1,1,0, +1,0,0,0, +1,1,1,0, +1,0,0,0, + +1,0,0,0, +1,1,1,0, +1,1,1,0, +1,1,1,1, +}; +int code_len = sizeof(code) / sizeof(int); + +void ring() { + digitalWrite(SEND_PIN, LOW); + delayMicroseconds(4700); + + for (int i = 0; i < code_len; ++i) { + digitalWrite(SEND_PIN, code[i] == 0 ? LOW : HIGH); + delayMicroseconds(300); + } + + digitalWrite(SEND_PIN, LOW); +} + +#define REPETATIONS 40 + +void setup() { + Serial.begin(9600); +// pinMode(SEND_PIN, OUTPUT); + Serial.println("RING!"); + for (int i = 0; i < REPETATIONS; ++i) { + ring(); + } + Serial.println("RANG!"); +} + +void loop() {} diff --git a/doorbell_v7_ring/platformio.ini b/doorbell_v7_ring/platformio.ini new file mode 100644 index 0000000000000000000000000000000000000000..729d0e9d847b6f31998a12260f1c8499e7b04887 --- /dev/null +++ b/doorbell_v7_ring/platformio.ini @@ -0,0 +1,27 @@ +;PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +src_dir = . + +[common] +lib_deps = + +[env:nanoatmega328] +platform = atmelavr +board = nanoatmega328 +framework = arduino +lib_deps = ${common.lib_deps} + +[env:nodemcuv2] +platform = esp8622 +board = nodemcuv2 +framework = arduino +lib_deps = ${common.lib_deps}