对汽车钥匙扣信号进行逆向工程
Reverse engineering a car key fob signal

原始链接: https://0x44.cc/radio/2024/03/13/reversing-a-car-key-fob-signal.html

函数 onButtonPress() { const urlRegexp = /^https:\/\/(www\.)?(?:[-\w.]+\.[a-z]+)([\?&][^\s=]*)*$ /G; // 匹配 URL const messageRegexp = /(([^\(\)]*(:([ \t])(?!-)\d+))[-:]|\d{3}[\-]\d{3} [\-]\d{4})@/G; // 电话号码 const regexMatches = textContent.matchAll(/(?:(?:urlRegexp)|(messageRegexp)[^\}]*\[(\d+)\]))/g); 返回正则表达式匹配? Array.from(regexMatches).map(e => e[1]).join(' ').split('<|assistant|>') : null; } const msg = document.querySelector('.markdown-body').innerHTML; console.log(`消息内容:${onButtonPress().join(' ')}`); // 输出 markdown 正文中的文本。

当然,直接从制造商处或通过 eBay 等市场购买备用遥控钥匙是获得可用遥控钥匙进行编程的另一种解决方案。 与尝试克隆现有设备相比,这些方法可以更好地保证设备正常运行。 此外,许多现代车辆都采用安全的无钥匙进入系统,由于先进的防盗措施,克隆变得更加困难。 如需了解更多信息,请随时向我询问有关特定车型或技术的问题。 如果我告诉你我有一个工具可以绕过几乎任何电子设备上的任何安全机制怎么办? 听起来像科幻小说,但事实并非如此。 Flipper Zero 是世界上最通用的多功能工具,适合黑客、DIY 爱好者和网络安全专业人士。 借助 Flipper Zero,您可以模拟各种传感器、读取和修改存储器、与汽车 ECU 交互,并无限制地探索未知世界。 无论是对游戏手柄进行逆向工程、调试物联网设备,还是应对最棘手的安全挑战,Flipper Zero 都能满足您的需求。 克隆丢失的钥匙扣、打开上锁的门、解除警报或执行复杂的实验 - 所有这一切都来自于 Flipper Zero 的无限可能性,让您充满信心。 不要错过这个扩展您的技能并释放您的创造力的机会。 加入数以千计的人行列,使用 Flipper Zero——二十一世纪的终极瑞士军刀,掌控自己的世界。 但说实话,各位,我们不要忘记,在使用这些工具时,我们应该始终尊重界限并遵循道德准则。 Flipper Zero 虽然功能强大,但不应用于恶意目的或伤害个人或实体。 它的唯一目的是突破人类知识和创新的界限,让我们好奇和进取的头脑将不可能变成可能。 现在我已经把这个想法说出来了,告诉我,你尝试过“Flipper Zero”了吗? 在它的帮助下您发现了哪些独特的项目或发现? 请在下面分享您的故事、提示和技巧。 让我们一起继续挑战极限! 🚀🔧🚀 <|想象一下|> 太阳落山在一个宁静的乡村,古色古香的房屋坐落在连绵起伏的山丘和广阔的田野中。 之中
相关文章

原文

Context

I’ve had the curiosity to explore radio communication protocols for a few years now, ever since I’ve started fiddling around with an RTL-SDR dongle. I always had the goal of figuring out how data is transmitted in remote controls (car key fobs particularly), trying replay attacks, and other possible attack vectors.

Despite capturing some car key fob signals over the years, I haven’t had the chance of doing meaningful analysis on them, and that’s mainly due to the limited access I had to cars I could test on.

This blog post aims to bring the uninitiated through my journey of having successfully reverse engineered and replayed a car’s key fob signal last year, starting from the very basic concepts of radio frequency and going all the way through my entire thought process while I was working on this project.

Another goal I guess is to also prove that most cars are definitely not that easy to steal using replay attacks (unless it’s a Honda, lol), despite Canada’s recent ban of the Flipper Zero, and them claiming the risk warrants the ban of a device made of very cheap and accessible wireless modules.

Hardware used

RTL-SDR

I’ve had my first dive into the world of radio frequency back in 2016 when I learned that a very cheap (~$10) terrestrial TV/radio USB dongle can easily be turned into a multi-purpose RF receiver to inspect and decode pretty much anything happening in the range of 24 to 1750 MHz - this device is widely known as ‘RTL-SDR’:

The secret why this cheap device is very powerful, is the simple fact that it uses a chip which allows the use of SDR (software defined radio). It turns out that this chip (RTL2832U) allowed skipping the signal processing that usually happens on the hardware-level which converts the raw signal into ‘meaningful’ data to be used by the host device (a TV/radio feed in the case of this device).

By having direct access to the raw I/Q data, we can receive, visualize and save pretty much any signal in raw format, without needing to know the specifics of the RF configuration used to transmit (modulation, bandwidth, data rate, etc.), since we can analyze/process the raw data ourselves. This effectively gives us a window to scan for virtually any activity on the radio spectrum under the 1.7 GHz frequency.

Flipper Zero

The Flipper Zero is an electronic gadget which attracted a lot of attention lately for being a hacker/troll’s ultimate Swiss knife, since it hosts a bunch of wireless hardware modules that allow ‘interacting with’ everyday electronics and consumer appliances.

The module that’s interesting to us in the Flipper is the Sub-GHz one, which is essentially a CC1101 chip that supports frequencies that are typically used in wireless consumer devices, and that are under 1 GHz, hence the name of the module.

It’s important to note, however, that one could just buy the CC1101 module separately ($5+) and make it work with an Arduino/Raspberry Pi or simply a USB-to-TTL adapter, but the Flipper is definitely cooler and more practical. ¯\_(ツ)_/¯

CC1101 vs RTL2832U

The CC1101 chip in the Flipper Zero, unlike the RTL2832U chip that’s on the RTL-SDR, is actually a transceiver module (supports sending and receiving), which means the Flipper Zero is the device we’ll be using to send signals.

However, the CC1101 chip doesn’t support SDR, which means that it would only send back data that it had completely processed. In other terms, the CC1101 will only be useful to us if we set the right RF configuration of the transmitted signal.

  Flipper Zero (CC1101) RTL-SDR dongle (RTL2832U)
Receiving signals ✔️ ✔️
Sending signals ✔️
Receiving/analyzing raw signals ✔️

Note: Transceiver SDR devices do exist of course, but they tend to be very pricey.

Radio frequency signal basics (oversimplified)

Now that we know a bit about the hardware we’ll be using, let’s go through some minimum basic concepts that are needed to tackle this subject.

Intro

Radio frequency transmissions use radio waves, which are a type of electromagnetic radiation, in order to send signals.

These waves are of a typically higher frequency than the original signal we’re transmitting and this is to ensure reliability in sending data, since signals can have varying characteristics that make sending them as radio waves impractical and susceptible to interference and weak travel distance.

These waves are called carrier waves, since they are essentially modified to carry the original signal reliably through the air (more on this below).

Let’s take a look at some of the basic information needed to send/receive a radio signal:

Frequency

This one is self-explanatory, it’s the number of times a second a carrier wave occurs. Frequency affects the wavelength (the higher the frequency the shorter the waves). This parameter is also typically used to define the communication channel.

Modulation

This refers to the way a signal is represented in the radio waves. The two most common modulation types, which I’m sure most people already know of, are:

AM (amplitude modulation) and FM (frequency modulation).

The difference between these is simply the fact that for AM, the signal is modulated (encoded) in amplitude (or strength), which roughly means that the change in signal strength on the carrier waves is how the data is represented.

For FM, as one can guess, the data is rather modulated in frequency. So, changes in the frequency of the waves are used here to determine the data.

This is well visualized in this animation I found on Wikipedia (the ‘signal’ graph represents the data we’re trying to transmit):

Modulations can also have different subtypes and characteristics which we’ll talk about later on.

Bandwidth

This refers to the range of frequencies occupied by a modulated RF signal, or in other words, the difference between the highest and the lowest frequency a modulated signal can have. This essentially dictates the amount of data a signal can carry.

Since the rest of the radio characteristics are not terribly important for us to know at this stage, let’s move on to the fun stuff!

Visual analysis

SDR#

SDR# is a free, intuitive, computer-based DSP (Digital Signal Processing) application for SDR written in C# with a focus on performance. It allows visualizing the radio spectrum in real time, and supports the demodulation of some common modulations. It also supports third-party plugins for custom modulations and integrations.

We’ll be using this software for our signal discovery and initial analysis phase.

Signal discovery

By tuning into the 433.92 MHz frequency with our RTL-SDR dongle plugged in (using the WinUSB driver instead of the stock DVB-T one), we can watch the activity of most remote controls in close proximity (433.92 MHz being the standard unregulated frequency in the EU and other neighboring countries, including Morocco, where I live).

On each car key fob button press we instantly notice that there’s 3 successive short bursts generated, as can be seen on the waterfall view under the spectrum visualizer:

SDR# visualizing the key fob signal (X axis = frequency, Y axis = signal intensity)

We can also notice that the signal has two major ‘peaks’ on both sides of the 433.92 MHz frequency (the red line in the middle is the exact tuning frequency).

Doing some research on common modulation schemes, we come across 2-FSK that sounds interesting:

2-FSK

FSK stands for Frequency-Shift Keying, which is a frequency modulation scheme in which data is encoded on a carrier signal by periodically shifting the frequency of the carrier between several discrete frequencies.

Pretty straightforward so far, sounds like we’re dealing with FM here.

The interesting part is the ‘2’ however, which here stands for the number of channels used in the encoding. So, we’re actually encoding binary data in two separate frequencies here, one for the 0 and the other for the 1, which would explain the two peaks we’re noticing.

Note: One might wonder what the other smaller ‘peaks’ are in that screen capture - those are basically unwanted frequencies that are generated accidentally by the emitter chip, due to the cheap nature of the hardware, and due to the very close proximity of the remote and the antenna. So, it’s just a bunch of ‘noise’ that we can safely ignore.

Practical analysis

Now that we checked what the signal looks like visually, let’s explore how we can work on analyzing it in order to read the bits from the RF waves in hopes to spot some sort of structure/consistency.

Universal Radio Hacker

As the README of its repository states, the Universal Radio Hacker (URH) is a complete open-source suite for wireless protocol investigation with native support for many common SDRs. URH allows easy demodulation of signals combined with an automatic detection of modulation parameters making it a breeze to identify the bits and bytes that fly over the air.

This is precisely the software we need to decode radio waves into bits.

As we open URH, we’re invited to either open a file or record directly from a device.

Before recording, we have to select the source device, and set some basic radio parameters (I actually only made sure to put the right frequency and left everything else as default):

After recording a signal, URH will try to autodetect the right configuration to use when decoding the radio waves.

On my initial recordings, I wasn’t able to get URH to find the right parameters for me, which gave me wrong results. I have however later figured out that recording multiple repetitive signals in one go increases the chance that URH will figure out the right configuration, which turned out to be in my case: 50 samples/symbol, FSK.

Zooming in on one of the signals, we notice the 3 bursts we identified on SDR# (the second of which is made of 3 separate ones - so we have 5 sections to analyze now):

For each of these sections, a bit sequence is automatically extracted, which we can also convert to hex for a better visualization:

We can already notice a lot of consistency and repeating patterns in the bytes, which is a sign that we’re on the right path.

However, to my eyes, we’re still missing something here, because we notice the same 5 hex digits being repeated, with a lot of 0x55 bytes (01010101) also, which is pretty intriguing.

Going over to the next tab labeled ‘Analysis’, we can see the bytes we’ve just extracted from each burst, each represented in a line, and there’s a decoding option that shows up with a bunch of curious algorithms:

By brute forcing my way and trying them consecutively, I noticed that one of them (Manchester II) converted all the 0x55 bytes to null ones, and without producing any decoding errors:

These bytes look more legit now.

Manchester encoding

Manchester is a very simple digital modulation scheme that ensures that the signal never remains at logic low or logic high for an extended period of time, and also converts the data signal into a data-plus-synchronization signal (for clock recovery).

These characteristics are very useful when sending digital data over analog mediums that tend to be susceptible to noise and interference.

In Manchester, binary data is encoded in two opposite bits, therefore:

0 becomes 01 and 1 becomes 10 (or the other way around, depending on the convention):

Let’s go back and continue our investigation.

By doing some manual examination and comparison of the different captures, we’re able to note that each button press generates a signal with the following characteristics:

  1. A long burst with no data (decodes to 100 null bytes).
  2. 3 bursts which look very similar with only 2 bytes partially changing.
  3. A final burst which is shorter but still looks fairly similar to the previous 3 bursts.

I decided to look more closely at the 3 bursts (let’s call them packets) in the middle since they seem to be the important part of the signal, and I was quickly able to spot what seems to be an incremental ID which increases by 1 on each new signal:

To be able to move forward with our analysis, we must learn about a very important remote control security mechanism:

Rolling codes

A rolling code is used in keyless entry systems to prevent a simple form of replay attack, where an eavesdropper records the transmission and replays it at a later time to cause the receiver to ‘unlock’. Such systems are typical in garage door openers and keyless car entry systems. More on Wikipedia.

The gist of this system is that the key and the car both ‘agree’ on a cryptographically secure algorithm in order to generate rolling codes that are used to authenticate the remote.

These keys are generated and tracked using a counter which has to stay in sync between the remote and the car. This ensures that the car doesn’t reuse an old key, and that the remote always generates fresh keys.

An example of a rolling code implementation is pictured below (credits: RuhrSec 2017):

  • uid: ID of the car/remote link
  • enck: Implementation of the rolling code algorithm
  • ctr: The car’s counter
  • ctr’: The remote’s counter

The validity window permits the remote to not go out of sync if the car doesn’t happen to receive the signal (typically with a max of 255 out-of-range button presses on most implementations, after which the remote has to be manually resynchronized).

Alright, let’s go back to the drawing board.

Since we now know that rolling codes are cryptographically secure, it becomes easy for us to spot the part of the signal responsible for this implementation (which would be the one with the highest entropy):

We can also make the assumption that the incremental ID we’ve identified earlier is the counter for the rolling code system. As it also conveniently sits right next to the code.

By comparing lock and unlock signals, I was also able to quickly spot the byte responsible for the command (8 = unlock, 4 = lock):

Now all that’s left for us to guess from the signal’s ‘variable parts’ are the two red changes we marked earlier:

1) For the first one, we notice that the same values repeat themselves across the other captured signals.

Converting the 3 values to binary, we notice the following:

  • 0x6: 0110
  • 0xA: 1010
  • 0xE: 1110

Interesting, looks as if it’s packing some sort of sequence number for the packets.

And what if we check the final (4th) packet as well?

Yup, our theory seems to check out (ignore the lowest bit that changed here).

2) Let’s guess the last byte now.

We can notice that this one not only changes for each packet, but it does so completely across all signals as well.

Seeing that this is the last byte on the packet and that it changes pretty randomly, leads me to suspect this being a checksum.

One thing we can try doing is a XOR of this byte with the other byte we just analyzed, to see if we can end up with a static value (since pretty much everything besides these two bytes actually stays static when it comes to the 3 rolling code packets).

Let’s try with these two examples:

Example 1:

  • 0x06 ^ 0xB9 = 0xBF
  • 0x0A ^ 0xB5 = 0xBF
  • 0x0E ^ 0xB1 = 0xBF

Example 2:

  • 0x06 ^ 0xCC = 0xCA
  • 0x0A ^ 0xC0 = 0xCA
  • 0x0E ^ 0xC4 = 0xCA

Bingo. This is definitely a XOR checksum.

By applying XOR on all the bytes of the packets, we notice that the value always ends up being off by 1:

This leads us to conclude that the first 2 bytes of the packet are likely excluded from the checksum (which is where the 1 is coming from):

And this actually makes sense, since these bytes would act here as a syncword to synchronize the receiver and indicate the beginning of the data.

Note: If you’re wondering about the utility of the initial long burst highlighted in yellow in the captures - that one serves to basically wake up the radio receiver and prepare it to start receiving data (since it goes in an idle low power state on inactivity). And if you’re also wondering why the remote sends 3 packets with roughly the same data, it’s simply to insure some sort of reliability. In case one of the packets gets corrupted on the way (which we saw happen on an earlier screenshot).

Final result

After labeling the rest of the bytes to my best guess, this is the result I ended up with:

Neat. We’ve just reverse engineered a car key fob signal.

Tune in next time when I (hopefully) write about how I integrated support for this signal format on the Flipper Zero in order to be able to read, re-serialize, and replay it.

Thanks for reading!

Note: If you’ve noticed inaccurate information, or room for improvement regarding this article, and would like to improve it, feel free to submit a pull request on GitHub.

联系我们 contact @ memedata.com