courses

Schedule

How to read this page

This is the ten-week plan for CS 410/510: IoT Security. It expands the Major Topics list on the course home page into a week-by-week sequence, with the reading, the bench work, and the reasoning behind the ordering.

Dates below are for Fall 2026: instruction runs 28 September – 6 December 2026, and finals week is 7–11 December. The university is closed on Wednesday 11 November (Veterans Day), so Week 7 has a single meeting. Every assignment is due at 23:59:59 on the Friday listed.

Each week also has three short in-class exercises — a five-minute warm-up reviewing the previous week and two 10–15 minute hands-on blocks — collected on the Classroom Activities page. They rehearse the week’s skill on a different artifact than the homework uses, so doing them does not solve your assignment for you.

The sequence is deliberate, and it is the same sequence a real assessment follows: you cannot analyze what you cannot capture, you cannot capture what you cannot probe, and you cannot probe what you cannot identify. Weeks 1–4 build the ability to get a signal off a board. Weeks 5–6 turn signals into firmware. Weeks 7–8 do the same job over the air instead of over a wire. Weeks 9–10 turn firmware into understanding, and then ask what a defensible device would have looked like in the first place.

⚠️ Scope and authorization. Every technique in this course is applied to hardware you own or hardware provided by the course. Attaching a logic analyzer to someone else’s device, capturing someone else’s radio traffic with intent to decode it, or extracting firmware from a device you do not own ranges from a licence-agreement violation to a federal crime depending on the device and the jurisdiction. When in doubt, ask before you probe. The lab notebook discipline in Week 1 exists partly so you can demonstrate what you did and why.

Schedule at a glance (SUBJECT TO CHANGE – CHECK REGULARLY)

Week Meetings (MW) Topic Assignment Due (Fri, 23:59:59)
1 Sep 28, Sep 30 Course intro; IoT threat models; the lab notebook
Introduction to hardware: chip identification, pin identification, datasheets
Soldering and bench safety
HW #1 Lab 0 — Oct 2
2 Oct 5, Oct 7 UART: the bootloader console
Logic analyzers and instrumentation
Signal integrity, voltage domains, and level shifting
  Lab 1, HW #1 — Oct 9
3 Oct 12, Oct 14 I2C: addressing, ACK/NAK, bus sniffing
SPI: the four-wire bus and why flash lives here
Bus contention and passive tapping
HW #2  
4 Oct 19, Oct 21 JTAG and SWD: on-chip debug
Boundary scan, pin discovery, and the JTAGulator
Debug port lockdown and how it fails
  Lab 2, HW #2 — Oct 23
5 Oct 26, Oct 28 Firmware extraction from on-device memory
SPI-NOR flash dumping; in-circuit vs. chip-off
binwalk, entropy analysis, filesystem carving
HW #3 Final project proposal — Oct 30
6 Nov 2, Nov 4 Network hacking: a brief overview
WiFi and Bluetooth/BLE in the IoT context
Firmware extraction from packet captures (OTA interception)
  HW #3 — Nov 6
7 Nov 9 only
(Nov 11 — Veterans Day, university closed)
RF capture and spectrum analysis
SDR fundamentals: sampling, IQ, waterfalls
Modulation identification
HW #4 Lab 3 — Nov 13
8 Nov 16, Nov 18 Radio hacking: LoRa and LoRaWAN
Zigbee, Thread, and Matter
Replay, frame counters, and key management
  HW #4 — Nov 20
9 Nov 23, Nov 25 Software reverse engineering: Ghidra on embedded firmware
Cross-architecture RE (ARM, Xtensa, RISC-V)
Bootloaders and the chain of trust
HW #5  
10 Nov 30, Dec 2 IoT operating systems: OpenWRT, FreeRTOS, VxWorks, Mbed, Windows IoT
Secure architectures and certification baselines
Project work and wrap-up
  HW #5 — Dec 4
Finals Dec 7–11
no class meeting
No class meeting   Final Project — Dec 11

Week 1 — Introduction and hardware fundamentals

Objectives

Original material: the four questions of hardware recon

Every hardware assessment starts in the same place — a board you have never seen, covered in parts you cannot name. Work the following four questions in order, because each one narrows the next:

  1. What is the biggest chip? The part with the most pins is usually the main processor or SoC. Its markings tell you the architecture, which tells you what disassembler settings you will need in Week 9.
  2. What is next to it? A small 8-pin part beside the SoC is almost always SPI-NOR flash holding the firmware. That single observation drives all of Week 5. An 8-pin part with a crystal nearby may be an RTC on I2C instead.
  3. What connects to the outside world? Radios, Ethernet PHYs, and USB controllers define the remote attack surface. Antenna traces are visible to the naked eye — look for the meandering copper.
  4. What is left over? Unpopulated headers, test pads, and rows of vias are the manufacturer’s own debug access. They are left over because removing them costs money and nobody budgeted for it. These become Weeks 2 and 4.

The discipline here matters more than the speed. Photograph the board before you touch it, at high resolution, from both sides. You will want that photo when you have desoldered something and cannot remember which way round it went.

Original material: package markings and what they hide

Markings are not standardized, but they are conventional. A typical line reads as manufacturer logo, part number, then a date/lot code. The date code is usually YYWW — 2417 is the seventeenth week of 2024. That gives you a lower bound on the firmware’s age, which is a useful cross-check when a vendor claims a device shipped with a patched version.

Two things routinely defeat identification:

Original material: the lab notebook

The tools page lists the notebook as the single most important item in the kit, and that is not a joke. The rules — date and sign every page, never remove a page, single-line strikethrough for errors, no white-out — come from patent practice, and they exist so that the notebook is admissible as evidence of what you knew and when you knew it.

In this course the notebook is your submission, kept in Markdown in your GitLab repository. The same principles apply in a slightly different form:

See Technical Writing if Markdown is unfamiliar, and Using git for the mechanics.

Reading

Week 2 — UART and instrumentation

Objectives

Original material: why UART first

UART is the first interface you look for on any embedded device, and the reason is economic rather than technical. Bringing up a board requires a console. The console is how the firmware engineer found out that the DDR timings were wrong at 3 a.m. six weeks before shipping. Removing that console before production requires someone to decide to remove it, test that nothing depended on it, and absorb the risk of losing field-debug capability. That decision frequently does not get made.

What you find, when it is there, ranges across a spectrum:

What you get How common What it is worth
Silent pins Common on newer gear Nothing directly; try Week 4
Boot log only, no input Very common Kernel version, partition layout, hardware inventory
Bootloader prompt (U-Boot) Common Usually total compromise — see Week 9
Root shell, no password Still distressingly common Total compromise
Login prompt Common A password-guessing target, and a version banner

Even the “worthless” boot-log-only case hands you the kernel version, the partition table, and often the exact firmware build string — everything you need to go find the vendor’s GPL source drop and skip the reverse engineering entirely.

Original material: finding the pins

A UART is three or four pads: TX, RX, GND, and often VCC. To find them:

  1. Find ground first, with a multimeter in continuity mode, referenced against a known ground such as a shield can or the negative terminal of a large electrolytic capacitor. Getting ground wrong is how probes die.
  2. Find VCC — it sits at a steady 3.3 V (or 1.8 V, increasingly) relative to ground and does not move.
  3. TX is the one that talks at boot. Power-cycle the board with a scope or logic analyzer on the candidate pins. TX shows a burst of activity in the first second or two as the bootloader prints. RX generally idles high and does nothing.

⚠️ Check your voltage domain before connecting anything. Modern SoCs run 3.3 V or 1.8 V I/O. Connecting a 5 V FTDI cable to a 1.8 V pin will, at best, not work, and at worst destroy the pin, the pad, or the part. Measure the idle voltage on TX before you connect. The Tigard has a voltage-select jumper precisely because this mistake is so common.

Worked example: recovering baud rate from a capture

You have a capture of a signal you believe is UART, but the decoder produces garbage at every standard rate you try. Rather than guessing, measure.

UART has no clock line. The receiver recovers timing by assuming a fixed bit period, so the bit period is the only thing you need. In your logic analyzer, zoom in and measure the narrowest pulse in the capture — that is one bit time, because somewhere in the data there is an isolated 1 between two 0s or vice versa.

narrowest pulse measured: 8.68 µs
baud = 1 / 8.68e-6 = 115,207
nearest standard rate    = 115200

Now re-run the decoder at 115200. If it still produces garbage but the frame boundaries look right, the problem is framing rather than rate: try 8N1 first, then 8E1 and 7E1, which still show up on industrial gear.

If the narrowest pulse is not a clean multiple of anything standard, you may be looking at a non-standard rate — U-Boot on some SoCs uses 115200 derived from an odd crystal and lands a percent or two off. Decoders that let you type an arbitrary rate will still lock on.

Reading

Week 3 — I2C and SPI

Objectives

Original material: two buses, two philosophies

I2C and SPI solve the same problem — get a microcontroller talking to a peripheral — and make opposite trade-offs. Understanding the trade-off tells you what to expect when you probe.

  I2C SPI
Wires 2 (SDA, SCL) 4 (MOSI, MISO, SCK, CS) + 1 CS per device
Addressing 7-bit address in-band Out-of-band, via chip select
Speed 100 kHz / 400 kHz / 1 MHz typical 1–100 MHz+
Ack Receiver pulls SDA low for ACK None
Typical use Sensors, EEPROMs, RTCs Flash, displays, radios

For an attacker the practical consequences are:

Worked example: reading a JEDEC ID off a live bus

You have a logic analyzer on a suspected SPI flash. Power-cycle the board and capture the first few milliseconds. Nearly every bootloader begins by identifying the flash part:

CS   ‾‾‾\_______________________________/‾‾‾
MOSI     9F 00 00 00
MISO     -- EF 40 18

The host sends 0x9F (Read JEDEC ID) followed by three dummy bytes; the flash replies during those bytes. Decode the reply:

EF = manufacturer  -> Winbond
40 = memory type   -> W25Q series, SPI
18 = capacity code -> 2^0x18 bytes = 16 MiB = 128 Mbit

So: a Winbond W25Q128, 16 MiB. You now know the exact part, its datasheet, its command set, and the size of the dump you are about to take in Week 5 — all without desoldering anything.

⚠️ Passive means passive. When tapping a live bus, your probes must not drive it. Do not connect a Bus Pirate in active master mode to a bus that already has a master; you will get bus contention, corrupt the transaction, and possibly damage a driver. Sniff first, interact later, and only when the host is held in reset.

Reading

Week 4 — JTAG and SWD

Objectives

Original material: what JTAG actually gives you

UART gives you whatever the firmware chooses to print. JTAG gives you the silicon. That is the entire difference, and it is enormous: with working JTAG or SWD you can halt the CPU mid-instruction, read and write arbitrary memory including the internal flash, single-step, set hardware breakpoints, and in many cases read out the firmware directly regardless of what the running code wants.

JTAG (IEEE 1149.1) was designed for boundary scan — testing solder joints on assembled boards by shifting bits into a chain of cells around each pin. Debug access was bolted on afterward, which is why the interface feels architecturally strange. SWD is ARM’s two-pin replacement that drops boundary scan and keeps the debug half.

The signals:

Signal JTAG SWD Role
TCK / SWCLK ✔ ✔ Clock
TMS / SWDIO ✔ ✔ Mode select / bidirectional data
TDI ✔   Data in
TDO ✔   Data out
TRST optional   Reset (often absent)

Original material: finding the pins when nothing is labeled

Unpopulated headers are the giveaway, but the pin order is arbitrary. Three approaches, in increasing order of effort:

  1. Guess from the connector. A 10-pin 0.05” header on an ARM board is almost certainly the Cortex Debug connector, which has a standard pinout. A 20-pin 0.1” header is likely classic ARM JTAG. Try the standard pinout first; it costs nothing.
  2. Brute force with a JTAGulator. The JTAGulator drives every permutation of candidate pins and watches for a valid IDCODE response. This is what it exists for and it is very good at it.
  3. Boundary-scan the traces. If you have identified the SoC, its datasheet gives the JTAG pin numbers; then it is a continuity-tracing exercise from the package to the header.

The tell for success is an IDCODE: a 32-bit value that every compliant TAP returns after reset, encoding manufacturer, part number, and revision. A valid IDCODE with a 1 in the least-significant bit means you have found a working TAP. All-zeros or all-ones means you have not.

Original material: why lockout so often fails

Vendors can disable debug access. On most microcontroller families this is a fuse, a lock bit, or a protection level stored in one-time-programmable memory. It fails in recognizable patterns:

Reading

Week 5 — Firmware extraction from memory

Objectives

Original material: three ways to get firmware, in order of preference

  1. Download it. Vendor support sites, OTA update endpoints, and GPL source releases. Free, non-destructive, and legal for anything publicly posted. Always try this first; a surprising fraction of assessments end here.
  2. Read it off the running system. If Week 2 or Week 4 gave you a shell or debug access, dd the MTD partitions out over the console. Non-destructive and gives you the deployed image including device-specific configuration.
  3. Read the flash chip directly. In-circuit with a SOIC-8 clip if the board permits it; chip-off with hot air if it does not. This is where the course spends its bench time because it is the technique that always works.

In-circuit reading fails when the SoC contends for the bus. The standard fixes, in order: hold the SoC in reset; pull its power while keeping the flash powered (risky, and back-powering through protection diodes is a real hazard); desolder the flash. If you find yourself fighting contention for more than an hour, desolder — it is faster than being clever.

Worked example: from raw dump to filesystem

You have dump.bin, 16 MiB, off a W25Q128. First, confirm you got a real dump rather than 16 MiB of 0xFF:

$ ls -l dump.bin
-rw-r--r-- 1 student student 16777216 Sep  3 14:02 dump.bin
$ xxd dump.bin | head -3
00000000: 27051956 5b91d1d3 66d2a4c1 00600000  '..V[...f....`..
00000010: 001d6f42 00600000 8b5a1c74 05050200  ..oB.`...Z.t....
00000020: 4c696e75 78204b65 726e656c 20496d61  Linux Kernel Ima

0x27051956 is the U-Boot legacy image magic, and the ASCII confirms it. Now let binwalk map the whole thing:

$ binwalk dump.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage firmware image, header size: 64 bytes,
                              data size: 1929538 bytes, compression: lzma,
                              CPU: ARM, OS: Linux, image type: OS Kernel Image
64            0x40            LZMA compressed data, properties: 0x5D
1929602       0x1D7A82        SquashFS file system, little endian, version: 4.0,
                              compression: xz, image size: 8534016 bytes
--------------------------------------------------------------------------------

Analyzed 1 file for 85 file signatures (187 magic patterns) in 22.0 milliseconds

🛠️ binwalk 3 is a rewrite, and its output moved. Version 3 (Rust) replaced the Python version 2 that most tutorials were written against. The columns are wider, field names now carry colons (version: 4.0, not version 4.0), and it prints the signature-count footer above. If a guide’s output does not look like yours, check binwalk --version before you doubt your dump.

Extract, then look at what you have:

$ binwalk -e dump.bin
$ ls extractions/dump.bin.extracted/1D7A82/squashfs-root/
bin  dev  etc  lib  mnt  proc  sbin  sys  tmp  usr  var  www

Note the shape of that path. binwalk 3 writes to extractions/<file>.extracted/<hex offset>/, one subdirectory per signature it extracted, named for where in the image it was found. binwalk 2 used _dump.bin.extracted/ with a flat layout, which is what older write-ups show.

At this point the assessment becomes a Linux one: etc/passwd and etc/shadow, hardcoded keys under etc/, the web root under www/, and the init scripts that tell you what listens on the network.

⚠️ binwalk -e runs external extractors on untrusted data. That is a code execution surface pointed at a file you got from a hostile device. Extract inside a container or a throwaway VM, not on your daily driver. The same caution applies to any -e-style recursive extraction.

Worked example: entropy tells you whether to keep going

If binwalk finds nothing but one large blob, the question is whether the image is compressed, encrypted, or just unrecognized. Entropy answers it:

$ binwalk -E dump.bin

Read the resulting curve as follows:

Entropy Meaning
~0.0 Erased flash (0xFF) or padding
0.3–0.7 Code and data — normal executable regions
~0.8 Uncompressed filesystem: executables plus strings and metadata
0.99+ Compressed or encrypted — the number alone cannot tell you which

That last row is the one that matters, and it is where the common tutorial advice is wrong. A good compressor’s output is statistically indistinguishable from random data — that is close to the definition of “good compressor.” On the course target, the LZMA-compressed kernel measures 0.9998 and the encrypted keystore measures 0.9996. You cannot separate those, and no threshold you pick will.

So entropy tells you where the interesting regions are, and something else tells you what they are. Three discriminators, in the order you should try them:

  1. Is there a header? Compressed data in firmware is nearly always wrapped in something — a uImage header, a gzip or LZMA magic, a vendor container. Encrypted regions typically start immediately with ciphertext, because a header would leak structure.
  2. Does a decompressor accept it? The definitive test. If unlzma or gunzip consumes it and produces sensible output, it was compressed.
  3. What do the edges look like on the plot? Both compressed and encrypted regions sit near 1.0, but a compressed region usually shows a small dip at its header and ragged edges where padding begins. An encrypted region tends to start and stop abruptly at block boundaries.

A maximum-entropy region with sharp edges, no recognizable header, and nothing that will decompress it is the signature of an encrypted image. That does not end the assessment — it moves it. The decryption key has to exist somewhere the device can reach it, which means the bootloader, a secure element, or eFuses. That is a Week 9 problem, and one of the final project options.

Reading

Week 6 — Networks, WiFi, BLE, and firmware from the wire

Objectives

Original material: firmware extraction without touching the hardware

Weeks 2–5 assume physical access. This week removes that assumption. If a device downloads its own updates, and you can see that traffic, the device extracts its firmware for you.

The workflow:

  1. Get the device onto a network you control. A Raspberry Pi as an access point, or your own AP with a span port. This is what the course gateway Pi is for.
  2. Capture everything. tcpdump on the gateway, analyzed in Wireshark. See Network Traffic Capture for the mechanics.
  3. Trigger an update. Factory reset frequently does it, since devices check for updates on first boot.
  4. Find the transfer. Look for a large HTTP response, or a TLS session with a large data flow. tshark -z conv,tcp ranks conversations by bytes and finds it immediately.
  5. Carve it out. Wireshark’s File → Export Objects → HTTP does this directly for cleartext. See Pcap Analysis and Manipulation Tools.

The reason this works so often is that firmware-over-HTTP remains common. When TLS is present, the failure modes are their own finding: no certificate validation (so a proxy with a self-signed cert works), a pinned certificate that expired, or validation that checks the chain but not the hostname.

Original material: BLE in one page

Bluetooth Low Energy is not Bluetooth Classic and shares almost nothing with it above the radio. What matters for assessment:

Reading

Week 7 — RF capture and spectrum analysis

Objectives

Original material: the three numbers that define an SDR capture

Every capture is characterized by three numbers, and getting them wrong wastes the capture:

  1. Center frequency. Where you are looking. If the signal is not within your bandwidth of this, you will not see it.
  2. Sample rate, which sets bandwidth. Nyquist says you can observe a bandwidth equal to your complex sample rate. A 2 MS/s capture sees 2 MHz of spectrum. To see a 125 kHz LoRa channel you need at least 125 kS/s, and realistically 250 kS/s to have margin.
  3. Gain. Too little and the signal is in the noise; too much and the front-end clips, producing spurious signals across the whole band that look like real transmitters and are not.

The characteristic beginner failure is turning gain to maximum, seeing signals everywhere, and chasing artifacts. Set gain so the noise floor is visible and the strongest signal does not saturate.

Original material: identifying modulation by eye

Before demodulating anything, classify it. A waterfall and a time-domain view get you most of the way:

Appearance Likely modulation Common in
Single line, blinks on/off OOK / ASK Cheap remotes, doorbells, TPMS
Two parallel lines alternating 2-FSK Sub-GHz sensors, garage doors
A band that fills solidly Wideband FSK/GFSK BLE, proprietary
Diagonal sweeps, sawtooth Chirp spread spectrum LoRa
Hopping across a band FHSS Bluetooth Classic, some industrial

The diagonal-sweep signature is diagnostic and is why LoRa is a good teaching target: you can see the chirps in a waterfall, which makes the modulation concrete in a way that a constellation diagram does not.

⚠️ Receiving is not transmitting. Passive reception across most of the spectrum is legal in the US; transmitting is licensed, and transmitting on bands you are not licensed for is a federal offence. The 915 MHz ISM band our hardware uses permits unlicensed transmission under Part 15 rules with power and duty-cycle limits. Stay inside them, and do not transmit on anything else.

Reading

Week 8 — Radio hacking: LoRa, Zigbee, Thread, and Matter

Objectives

Original material: LoRa is not LoRaWAN, and it matters

This is the single most common confusion in the field, and it is a security distinction rather than a pedantic one.

LoRa is a physical layer: chirp spread spectrum modulation, patented by Semtech, implemented in the RFM95 on your Feather. It provides no security whatsoever. Bytes in, RF out. Anything you transmit is readable by anyone with a matching radio, and anything you receive can be forged by anyone with a matching radio.

LoRaWAN is a MAC layer and network architecture built on top of LoRa. It specifies device join procedures, two layers of AES-128 keys (a network session key for integrity, an application session key for confidentiality), and — the part that matters for replay — frame counters.

The consequence for Labs 2 and 3, and for HW #4:

The teaching point generalizes: replay protection is state, and embedded devices are bad at state. A counter that must survive power loss has to live in flash, flash has limited write endurance, so implementers cut corners, and the corner they cut is usually the one that protects you.

Original material: Zigbee, Thread, and Matter in context

All three sit on IEEE 802.15.4 as a physical and MAC layer. What differs is everything above it.

What Matter did not change: the device still runs firmware, that firmware still lives in a flash chip you can read, and attestation says nothing about whether the application logic above it is correct. The hardware techniques from Weeks 1–5 are entirely unaffected by Matter certification.

🛠️ Matter versions move quickly — 1.4 (Nov 2024), 1.4.1, 1.4.2, 1.5 (Nov 2025), 1.6 (2026). Check the current specification version before citing features.

Reading

Week 9 — Software reverse engineering and bootloaders

Objectives

Original material: the base address problem

Reverse engineering a Linux binary is comparatively easy: ELF headers declare the architecture, the entry point, and the section layout. A raw firmware dump declares nothing. You have a flat array of bytes and three unknowns:

  1. Architecture and endianness. From Week 1’s chip identification, or by letting a tool guess from instruction-frequency statistics.
  2. Load address. Where the code believes it lives. Get this wrong and every absolute pointer in the binary points at nothing, so no cross-references resolve and the listing is unreadable.
  3. Entry point. Where execution begins.

The load address is the one that blocks progress, and the standard trick is to recover it from the data rather than guess. Scan the image for 32-bit values that look like pointers — they cluster tightly around the true load base, because pointer tables, string references, and vector tables all use absolute addresses. Histogram the high bytes of every aligned 32-bit word; the spike is your base address.

On ARM Cortex-M there is a shortcut: the image begins with a vector table whose first word is the initial stack pointer and whose second word is the reset handler address. Read the second word, mask off the Thumb bit, and you have both the entry point and a strong hint at the load base.

Worked example: orienting in an unfamiliar image

Once loaded, you have no symbols. Find your footing through strings:

$ strings -n 8 -t x firmware.bin | grep -iE 'passw|key|http|/dev/|admin'
  1a4f0 /dev/mtdblock3
  1a53c Login incorrect
  1a558 http://update.example.net/fw/check
  1b2c4 %s: bad password for %s

⚠️ -n 8 hides exactly the tokens you care most about. The grep above asks for admin, but admin is five characters and never reaches the grep — strings dropped it. Short, high-value words (admin, root, key, pw) all sit under the default threshold of 4 as well as under 8. Run the sweep twice: once at -n 8 for readable sentences and URLs, once at -n 4 when you are hunting a specific short token, and accept the noise on the second pass.

Each hit is an anchor. In Ghidra, jump to the address, find the cross-reference, and you are inside the function that uses it — the login handler, the update checker, the partition mount. Working outward from string references is far faster than reading from the entry point down, and it goes straight to the code that matters.

Cross-reference this with the filesystem you extracted in Week 5: if /dev/mtdblock3 appears in both the binary and the init scripts, you have connected the running configuration to the code that consumes it.

Original material: secure boot and where the chain breaks

Secure boot is a chain: an immutable root of trust in ROM verifies the bootloader, which verifies the kernel, which verifies the root filesystem. Each link checks a signature before transferring control.

Real-world break points, roughly in order of frequency:

Reading

Week 10 — IoT operating systems and secure architecture

Objectives

Original material: the OS landscape, by threat model

The question that separates these systems is not features but isolation.

System Isolation Update story Notes for assessment
OpenWRT / embedded Linux Full MMU, processes, users Package manager, vendor images Everything you know about Linux applies. Usually the richest target.
FreeRTOS None by default (MPU optional) Whatever the vendor built A scheduler, not an OS. One task can corrupt another’s memory. No users, no permissions.
Zephyr MPU-based, userspace option MCUboot, well-specified Modern, security-conscious, increasingly the FreeRTOS alternative.
VxWorks MMU on supported targets Vendor-controlled Real-time, safety-critical, long-lived. The URGENT/11 TCP/IP stack vulnerabilities showed how far a bug propagates in this ecosystem.
Arm Mbed OS MPU (uVisor discontinued) Mbed tooling End of life July 2026. Present in deployed devices for years to come; not a choice for new work.
Windows IoT Full NT security model Windows Update Windows 10 IoT Enterprise LTSC 2021 mainstream support ends January 2027. Heavy, but genuinely hardened.

The practical consequence for an assessment: on a no-MMU system, any memory corruption bug is total compromise. There is no privilege boundary to cross, no ASLR, frequently no stack canaries, and the exploit mitigations covered in Memory Corruption largely do not exist. A stack overflow in a FreeRTOS network task is game over in a way it has not been on desktop Linux since roughly 2004.

Original material: baselines, and using them as a report structure

Three documents define what “reasonably secure” means for consumer IoT, and any of them makes a defensible structure for a findings report:

The ISTG device model maps almost one-to-one onto this course: its memory and firmware surfaces are Weeks 4–5, its wireless interfaces are Weeks 7–8, its internal interfaces are Weeks 2–3. Structuring your final report around it demonstrates coverage rather than asserting it.

The older OWASP IoT Top 10 (2018) remains widely cited and is still a reasonable vocabulary for describing findings, but it is a risk list rather than a methodology and has not been revised in some years — prefer the ISTG for structuring actual testing.

Reading

Assignments at a glance

Five assignments, each covering two weeks of material and each building on the last. Details and point breakdowns are on the individual pages.

# Covers Weeks Deliverable
HW #1 Bench bring-up, chip and pin identification, UART discovery 1–2 hw1/hw1.md
HW #2 I2C and SPI bus analysis, JTAG/SWD discovery 3–4 hw2/hw2.md
HW #3 Firmware extraction from flash and from the wire 5–6 hw3/hw3.md
HW #4 RF capture, LoRa analysis, replay 7–8 hw4/hw4.md
HW #5 Firmware reverse engineering and bootloader analysis 9–10 hw5/hw5.md

The final project offers three options with different audiences; read that page early, because the graduate-track option benefits from being chosen by Week 4.

Key takeaways

References


Related course pages: Course home · Tools of the Trade · Final Project · Networking Fundamentals · Wireshark · Threat Modeling

🛠️ Maintenance note: the fastest-moving items on this page are (a) the Matter specification version, which has shipped six releases since late 2024; (b) binwalk, whose v3 Rust rewrite changed the CLI relative to nearly every tutorial online; (c) OS lifecycle dates — Mbed OS reached end of life in July 2026 and Windows 10 IoT Enterprise LTSC 2021 mainstream support ends January 2027; and (d) hardware availability, since several tools in the course kit are small-batch products. Re-check these before each offering. Assignment due dates are deliberately expressed as week numbers so only the term calendar needs updating.