{"id":449,"date":"2026-11-04T06:13:00","date_gmt":"2026-11-04T14:13:00","guid":{"rendered":"https:\/\/blog.canutethegreat.com\/?p=449"},"modified":"2026-10-26T09:05:17","modified_gmt":"2026-10-26T16:05:17","slug":"flipper-zero-part-3-sub-ghz-rolling-codes","status":"publish","type":"post","link":"https:\/\/blog.canutethegreat.com\/index.php\/2026\/11\/04\/flipper-zero-part-3-sub-ghz-rolling-codes\/","title":{"rendered":"Flipper Zero, part 3: Sub-GHz remotes, rolling codes and how gates should be built"},"content":{"rendered":"<p><em>Part 3 of 5 in the Flipper Zero series. Part 1: <a href=\"https:\/\/blog.canutethegreat.com\/?p=427\">what it actually is and what it can&#8217;t do<\/a>. Part 2: <a href=\"https:\/\/blog.canutethegreat.com\/?p=433\">why so many office badges are weaker than they look<\/a>.<\/em><\/p>\n<p>Garage doors, gates, car fobs, doorbells and cheap alarm sensors all talk on a handful of license-free bands, mostly around 315, 433.92, 868 and 915 MHz depending on where you live. The Flipper Zero has a CC1101 transceiver that covers 300 to 348, 387 to 464 and 779 to 928 MHz, with regional limits on where it will transmit. That makes it a convenient way to look at your own remotes and ask whether the thing guarding your driveway was designed by someone who had met an attacker.<\/p>\n<p>Same rules as the earlier parts: my own device, my own remotes, and a defender&#8217;s goal. Transmitting captured codes at a gate or car you do not own is illegal in most places, and the receiver you are testing may belong to a landlord or an employer. Get permission first.<\/p>\n<h2>What the Flipper shows you<\/h2>\n<p>The Sub-GHz menu has Read, Read RAW, Saved and Add Manually. Read tries to decode a signal against the protocols it knows and prints the frequency, modulation and the bits. Read RAW records the pulse timing without interpreting it.<\/p>\n<p>The first photo is my own Flipper&#8217;s main menu with Sub-GHz selected, and the second is its Sub-GHz submenu.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/blog.canutethegreat.com\/wp-content\/uploads\/2026\/11\/f3-screen-8.jpg\" alt=\"Flipper Zero main menu with Sub-GHz highlighted\" \/><\/figure>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/blog.canutethegreat.com\/wp-content\/uploads\/2026\/11\/f3-screen-9.jpg\" alt=\"Flipper Zero Sub-GHz submenu: Read, Read RAW, Saved, Add Manually\" \/><\/figure>\n<p>Press a cheap fixed-code remote near it and the Flipper will show you the same bits every time. Press a rolling code remote and the bits change on every press. Seeing that difference on your own remote takes about ten seconds and is a better lesson than any slide.<\/p>\n<h2>Fixed codes: nothing to defend<\/h2>\n<p>Old remotes with DIP switches, or the cheapest 433 MHz clones, send the same code on every press. Anyone who hears it once can send it forever. There is no cryptography to attack, which is the whole problem. If your gate still uses one, the fix is to replace the receiver and remotes. Nothing you can configure makes a fixed code safe.<\/p>\n<h2>Rolling codes: what they actually are<\/h2>\n<p>A rolling code remote sends a serial number and a counter, protected so that a receiver can check the counter has moved forward. The best known design is Microchip&#8217;s KeeLoq. It uses a 32 bit block cipher with a 64 bit key and 528 rounds. The hopping part of the message carries a 16 bit synchronisation counter, and the serial number goes out in the clear next to it. In the common learning schemes the per-remote key is derived from the serial number and a manufacturer key.<\/p>\n<p>That last detail is where the trouble started. Several groups published cryptanalysis of KeeLoq in 2007 and 2008, and in 2008 Eisenbarth and colleagues presented &#8220;On the Power of Power Analysis in the Real World&#8221; at CRYPTO. They used power analysis on the receiver side to extract the manufacturer key. With that key, anyone who hears one transmission from a remote can compute its key from the serial number. That is a break of the whole product family, not of one gate.<\/p>\n<p>Receivers also have to tolerate lost presses. You pressed the button in your pocket twice, out of range, and the receiver has to accept counter 5 after seeing counter 2. So it accepts any value inside a look-ahead window. Here is a toy model of that logic. It is not KeeLoq, it uses HMAC-SHA256 truncated to 4 bytes, but the receiver behaviour is the same shape:<\/p>\n<pre tabindex=\"0\" class=\"wp-block-code\"><code>import hmac, hashlib\n\nKEY = b&quot;per-remote-secret&quot;\nWINDOW = 16\n\ndef code(counter):\n    msg = counter.to_bytes(4, &quot;big&quot;)\n    return hmac.new(KEY, msg, hashlib.sha256).digest()[:4].hex()\n\nclass CounterReceiver:\n    def __init__(self):\n        self.last = 0\n    def press(self, c):\n        for n in range(self.last + 1, self.last + 1 + WINDOW):\n            if hmac.compare_digest(code(n), c):\n                self.last = n\n                return f&quot;OPEN (counter {n})&quot;\n        return &quot;rejected&quot;<\/code><\/pre>\n<h2>Jam and capture<\/h2>\n<p>Samy Kamkar showed the practical weakness at DEF CON 23 in 2015 with a device he called RollJam. The attacker jams the receiver and records the owner&#8217;s press at the same time. The owner presses again, the attacker jams and records that too, but this time releases the earlier code to the receiver, so the door opens and nobody suspects anything. The attacker now holds a valid code the receiver has never seen.<\/p>\n<p>The diagram below compares the two receiver designs side by side.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/blog.canutethegreat.com\/wp-content\/uploads\/2026\/11\/f3-diagram.png\" alt=\"Sequence diagram comparing a counter-only receiver, where jammed and recorded codes open the gate twice, with a challenge-response receiver, where a recorded answer fails against a fresh nonce. Annotation boxes added for explanation.\" \/><\/figure>\n<p>The key point is that a counter-only receiver has no idea when a code was made. A code from yesterday is as good as one from a second ago, as long as the counter has not passed it. I ran the toy model through the scenario and rendered the real output below. The jammed presses are generated by my script, so this is a simulation of the logic, not a capture of any real remote.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/blog.canutethegreat.com\/wp-content\/uploads\/2026\/11\/f3-term.png\" alt=\"Terminal output of the toy rolling code receiver showing a replay rejected, a jam-and-capture attack succeeding twice, and a challenge-response receiver rejecting a captured answer\" \/><\/figure>\n<p>Note the third line of the middle block. The receiver accepts the stored second code long after the owner walked off. Once the stored code is used, replaying it fails, so the attack is a one-shot, but one shot is enough to open a gate.<\/p>\n<p>Counter windows have caused real vulnerabilities too. CVE-2021-46145 covers the Honda Civic 2012 key fob, where the rolling code does not expire and the counter resynchronisation can be abused to replay unlock commands. CVE-2022-27254 is a worse case on the 2018 Civic, where the remote sends the same signal for every unlock request, so it was never rolling at all.<\/p>\n<h2>How a gate should be built<\/h2>\n<p>If I were specifying a new gate or garage opener, the list would be short.<\/p>\n<p>First, the receiver should reject codes older than a few seconds, or use challenge-response. In the last block of the demo the receiver sends a random nonce and the remote answers with an HMAC of it. A captured answer fails against the next nonce, so storing it gains nothing. This needs a two way radio, which costs a little more, and that is the price of getting rid of the stored-code attack.<\/p>\n<p>Second, use a modern authenticated protocol with a per-device key that is not derived from a shared manufacturer secret. AES-based systems exist. Ask the installer what the remote actually uses, and if the answer is &#8220;rolling code&#8221; with no name attached, treat that as a fixed code until proven otherwise.<\/p>\n<p>Third, keep the radio the weaker half of the system. A gate that opens on a single radio message should not also be the only barrier to something you care about. Put cameras on it, put a lock on the inner door, and do not rely on it to separate a vehicle from the street.<\/p>\n<p>Fourth, plan to replace the remotes. Lost ones should be removed from the receiver, not just forgotten, which means choosing a receiver that actually lets you delete individual remotes.<\/p>\n<h2>Testing your own gear<\/h2>\n<p>With the Flipper you can check three things on your own remote. Does Read decode it as a known protocol or leave you with raw pulses only? Do the bits change between presses? If they do not, you have a fixed code and a replacement project. And can you find the manufacturer and model on the receiver, so you can read its actual security claims rather than guessing?<\/p>\n<p>I would not go further than that on equipment I do not control.<\/p>\n<p>Part 4 moves to USB, keystroke injection from the Bad USB menu, and how to lock endpoints down.<\/p>\n<p><em>Other parts of the Flipper Zero series: <a href=\"https:\/\/blog.canutethegreat.com\/?p=427\">part 1<\/a>, <a href=\"https:\/\/blog.canutethegreat.com\/?p=433\">part 2<\/a>, <a href=\"https:\/\/blog.canutethegreat.com\/?p=449\">part 3<\/a>, <span class=\"ctg-soon\">part 4 <small>(publishes Nov 5)<\/small><\/span>, <span class=\"ctg-soon\">part 5 <small>(publishes Nov 6)<\/small><\/span>.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Part 3 of 5 in the Flipper Zero series. Part 1: what it actually is and what it can&#8217;t do. Part 2: why so many office badges are weaker than they look. Garage doors, gates, car fobs, doorbells and cheap alarm sensors all talk on a handful of license-free bands, mostly around 315, 433.92, 868 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":454,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21,7],"tags":[218,312,317,78,315],"class_list":["post-449","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security","category-technology","tag-cryptography","tag-flipper-zero","tag-flipper-zero-series","tag-hmac","tag-sub-ghz"],"_links":{"self":[{"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/posts\/449","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/comments?post=449"}],"version-history":[{"count":2,"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/posts\/449\/revisions"}],"predecessor-version":[{"id":472,"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/posts\/449\/revisions\/472"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/media\/454"}],"wp:attachment":[{"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/media?parent=449"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/categories?post=449"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/tags?post=449"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}