Platform index / Wireless conference system
Shure MXCW
A conference platform that is closed on the inside and unusually generous on the outside: every application payload in the access point is encrypted, while the control interface is plain ASCII on an open port that pushes a report every time anything changes.
The load-bearing finding. The access point signs its updates — 256 raw bytes of detached signature over a manifest carrying a SHA-256 per payload — and encrypts the Linux image, the application and the web GUI on top, so none of its software has been read. Two things ship in the clear: the Xilinx bitstream, and the charging station, which is not encrypted at all and hands over the client half of Shure's private device protocol.
Verdict. Closed inside, generous outside. Nothing of the access point's software has been read — the Linux image, the conference application and the web GUI are all encrypted behind an RSA-signed manifest, and the conference unit's entire payload set with them. What ships in the clear is the Xilinx bitstream that is almost certainly the radio, and the charging station, which is not encrypted at all and gives up the client half of Shure's private device protocol: ACN/DMP over a binary WebSocket, carrying the one primitive the public interface lacks. And the public interface is genuinely good — plain ASCII on an open port, unauthenticated, reporting every change unsolicited so a controller never has to poll. It has exactly one hole, and it is a load-bearing one: eight uplink slots are metered individually and nothing in the protocol says which seat is in which slot, so anything that wants to know who is loudest has to leave TPCI and take the audio.
Method
Static analysis of the 7.1.3, 7.1.4 and 7.3.0 firmware packs for all three devices, obtained through Shure Update Utility, read against Shure's own MXCW Command Strings and MXCW User Guide publications. The application payloads are encrypted and none was decrypted; the readable findings come from the pack containers, the plaintext FPGA bitstream, and the charging station's unencrypted web application. No hardware was inspected and no frame of the control protocol has been observed on a wire.
Artifacts examined
MXCWAPT.7.3.0.pack— a plain zip:BuildInfo.json,MXCWAPT.manifest.xml, a 256-byteMXCWAPT.manifest.xml.sig,UpdateInstructions.xml(UploadCommand, per-file Copy, then Execute), and the payloads. The manifest also carriesDCIDdevice-class UUIDsapt_fpga.bin(9.7 MB) — a plaintext Xilinx configuration image:FFpadding, the bus-width detect pattern000000BB 11220044, the sync wordAA995566, then type-1 configuration packetslinux.bin(13.3 MB),app.tge(5.0 MB),gui.tge(13.3 MB) — the access point's Linux image, conference application and web application, all encryptedvxWorks,QtApp.tar.gz,m4app.bin,dsp.bin,QtLib.tar.gz,QtFonts.tar.gz,dsp.tar.gz— the MXCW640 conference-unit payload set (29.7 MB), encrypted throughoutm4app.zandOdinGui.z— the MXCWNCS charging station's payloads, plain zlib and not encrypted;OdinGuidecompresses to its web application in the clear (AngularJS 1.8 + Angular Material)microflex-complete-9.4.0— the wired MXC / DCS 6000 update bundle, read as background:cu_DIS-CCU_*.discentral-unit images,FUU_Library.xml, and theaction2flash script
No manufacturer firmware, binaries or documentation are redistributed here. Artifacts are referenced by name and version only. See the method and legal statement for the basis on which this analysis was performed and the boundaries it observes.
Hardware architecture
| Item | Finding | Confidence |
|---|---|---|
| System composition | Three devices on one platform: the MXCWAPT access point (RF master, audio matrix, web server, Dante endpoint and third-party control endpoint, PoE powered), the MXCW640 battery conference unit (gooseneck mic, loudspeaker, 4.3-inch touchscreen, NFC card slot, SB930 smart battery), and the MXCWNCS ten-bay charging station, which has its own web application and its own control endpoint on 2202. One access point serves up to 125 units on one RF channel | Public |
| RF layer | IEEE 802.11 a/g PHY across 2.4 GHz ISM and 5 GHz UNII including DFS, AES-128 on the link. Slot allocation is asymmetric and fixed: 8 uplink channels, allocated only to active speakers, and 9 downlink — one floor mix plus eight interpretation channels — broadcast continuously to every unit. Four power steps from 1 mW to 25 mW, and a built-in spectrum analyser that ranks channels continuously and quarantines a dirty one for 30 minutes | Public |
| What actually runs the radio | Shure runs a proprietary TDMA scheduler over a commodity Wi-Fi PHY rather than a bespoke radio: the spec table names 802.11 a/g, but fixed slot counts, deterministic 16 ms latency and 125 units on one channel are not CSMA behaviour. The scheduler most plausibly lives in the access point's FPGA — that is what an unencrypted 9.7 MB bitstream is for — but nothing in the pack says so, and the encrypted Linux image or a separate DSP are the competing readings | Inferred |
| Access-point FPGA | apt_fpga.bin is a plaintext Xilinx configuration image, opening with the standard preamble — FF padding, bus-width detect 000000BB 11220044, sync word AA995566, type-1 packets. So the access point carries a Xilinx FPGA, and its bitstream is the one payload of the three devices' application images that is not encrypted. The file is raw .bin and names no part | Verified |
| Conference-unit processors | The MXCW640 pack ships vxWorks, QtApp.tar.gz, m4app.bin and dsp.bin, so the unit is VxWorks with a Qt UI, an ARM Cortex-M4 companion and a DSP. The filenames and sizes are read directly from a manifest that carries a SHA-256 for each, and the Qt lineage is shared with the wired MXC640 (whose bundle ships 6kU_MXC640_QtLib_5.5.1.96) — but every one of those payloads is encrypted and none has been opened, so the naming is the entire evidence | Inferred |
| Audio architecture | 24-bit / 48 kHz throughout. Latency mic → speaker 16 ms, mic → analogue out 9.2 ms, analogue in → speaker 7.7 ms. The access point carries one analogue XLR in and one out plus 10 Dante in and 10 Dante out, with an internal matrix mixer whose sources are the floor mix, eight arbitrary group mixes, or one of the eight uplink slots taken directly | Public |
| Charging station — the readable device | The MXCWNCS is not encrypted at all: m4app.z and OdinGui.z are plain zlib, and its 7.1.4 and 7.3.0 packs are identical in size, so the charger did not change between those releases. OdinGui decompresses to 4.1 MB that is 83 % printable — its web application in the clear. Odin is a Shure platform name spanning at least the access point and the charger | Verified |
Software architecture
| Item | Finding | Confidence |
|---|---|---|
| Pack format | A .pack is a plain zip holding BuildInfo.json, a manifest naming a key, a version and a SHA-256 for every payload, a detached signature over that manifest, and UpdateInstructions.xml — an UploadCommand, a Copy per file, then an Execute. The manifest's DCID entries are device-class UUIDs, matching the controllerDCid concept in the charging station's protocol code | Verified |
| Access-point software | linux.bin, app.tge and gui.tge — a Linux image, the conference application and the web application, in that order of size. All three are encrypted and none has been read: the split between them is read off the manifest, not off any code | Inferred |
| TPCI — the published control interface | ASCII, one message per < … > pair, on TCP 2202. Four message types: GET, SET, REP and AUDIO_SAMPLE. The load-bearing fact is that REP is pushed unsolicited whenever a parameter changes by any means — front panel, web app, chairperson, or a participant's own speak button — so a controller connects once, seeds with a GET, and never polls. Seat numbers run 1–65535, index 0 on a GET fans out over online registered seats, free text is brace-wrapped UTF-8, gain and volume are offset by 30 and metering RMS by 98 | Public |
| The seam TPCI does not close | AUDIO_SAMPLE carries slot1Peak slot1Rms … slot8Peak slot8Rms, and no command in the published set maps a slot to a seat. Per-speaker level is therefore not obtainable over this interface at all; the ways round it are per-slot Dante outputs with your own detection, or the private protocol below. The reading is a complete enumeration of a published command reference rather than a stated absence, and the private API may well expose the mapping | Inferred |
| Shure's private device protocol | The charging station's unencrypted web application talks to its own device over a binary WebSocket with subprotocol dmp, framed with DataView writes, MAX_BUF_SIZE 2462, a five-second discovery timeout and 16-byte device UUIDs. Its constants are in the clear: clusters DMP 162, KEEP_ALIVE 163, SDT 164, DISCOVERY 167, SID 168; DMP vectors GET_REPLY 3 through DEALLOCATE_MAP 16 including SUBSCRIBE 7 and EVENT 4; discovery vectors ANNOUNCE 1 … ATTR_RSP 7; address types SINGLE / RANGE_SINGLE / RANGE_FIXED / RANGE_MIXED with VECTOR_FLAG 0x4000 | Verified |
| What that protocol is | ACN — ANSI E1.17: SDT carrying DMP, the same pair Shure's own port table lists on UDP 5568 multicast and 57383 unicast, and one of the charger's property groups is named NETWORK_ACN. The vocabulary is standard ACN rather than a bespoke invention. The reading rests on the constant names and the port table, since no frame has been captured — and it matters because DMP has the primitive TPCI lacks: SUBSCRIBE on an arbitrary property address, answered with pushed EVENTs | Inferred |
| The property map | Knowing the protocol is not knowing the vocabulary. The charging station's application carries only charger-domain properties — CHRG_SLOT, BATTERY_PRESENT, NUM_SLOTS, SLOT_BAYS, CHARGE_STATUS — and no seat or microphone properties whatever. The access point's own property IDs live in gui.tge, which is encrypted | Unknown |
| Build provenance | The tar headers inside the conference unit's wrapped payloads leak the build hosts: Administrators / buildmaster_ATE on a Windows box for QtLib (February 2019) and buildmaster / buildmaster for QtFonts (December 2020) | Verified |
Update path & security model
| Item | Finding | Confidence |
|---|---|---|
| Signed updates | The integrity chain is authenticity, not just integrity: the manifest signature is 256 raw bytes → RSA-2048 over MXCWAPT.manifest.xml, and that signed manifest carries a SHA-256 for every payload file. Nothing in the pack can be swapped without breaking one or the other | Verified |
| The encryption container | Every encrypted payload has the same shape — [ciphertext, length a multiple of 16][md5(ciphertext) as 32 ASCII hex]. Confirmed on all three access-point payloads: strip the last 32 bytes, MD5 the rest, and it matches the trailer exactly | Verified |
| The cipher | Shannon entropy 7.9999 over the first 2 MB of each payload, zero repeated blocks at 8, 16 or 32 bytes across 4 MB, and a body length always ≡ 0 mod 16. That is consistent with AES in CBC or CTR and rules out ECB. There is no key, no IV and no header identifying either — presumably both live in the bootloader or the running system. No key was recovered and nothing has been decrypted | Inferred |
| The `.tar.gz` payloads are a wrapper, not content | QtLib.tar.gz, QtFonts.tar.gz and dsp.tar.gz each gunzip to a tar holding exactly one member named after the archive, and that member is encrypted. QtApp.tar.gz is not gzip at all — it is encrypted from byte zero, despite the name | Verified |
| Network posture | From Shure's own port table: no HTTPS and no authentication documented anywhere. TCP 2202 is open by default and unauthenticated, so anything with IP reachability to the access point can turn microphones on and off; TCP 64000, Shure's firmware update channel, is also open by default, while FTP, SSH, Telnet, HTTPS and the 8023 debug console are closed. Discovery is mDNS on 5353, with SLP multicast on 8427 and SDT on 5568/57383 as Shure's undocumented inter-device fabric. This is a control-VLAN device by construction | Public |
| Against the wired ancestor | The signing is a marked change from the wired MXC / DCS 6000 line — the same manufacturer, the same product family name, an entirely different posture. Those central-unit images are unsigned, covered only by an md5 that ships in the same archive as the image it protects | Verified |
These rows describe how a platform validates a firmware image, because that is a structural fact about its architecture. They are not a vulnerability disclosure and no exploit, bypass or circumvention technique is published here. Licensing and entitlement mechanisms are out of scope throughout — seescope boundaries.
What is programmable
- 1TPCI on TCP 2202 — the published, push-based control interface
ASCII, documented by Shure, open by default, and it reports every change unsolicited, so a third-party controller connects once, seeds with a
GET, and reacts. This is the whole useful surface and it needs no firmware access at all: a mic-follows-camera sidecar was built on it and runs end to end against a simulator, with no access point ever in the loop. - 2Dante, for anything the protocol will not tell you
Ten Dante outputs, and an output can be fed directly from one of the eight uplink slots — so per-active-speaker audio leaves the box even though the slot's identity does not. Level-driven work belongs here, not on
AUDIO_SAMPLE. - 3The private ACN/DMP WebSocket
Richer than TPCI, with
SUBSCRIBEon a property address answered by pushedEVENTs. The framing and vocabulary are known from the charging station's unencrypted application; the access point's property IDs are not, and enumerating them viaATTR_RSPneeds a real device on a bench. - 4Nothing inside the firmware
The application payloads are encrypted with no key in hand, and the update path is RSA-signed over a SHA-256 manifest. The images are closed by construction, and everything worth doing is on the network side of the box.
Traps
Mistakes this analysis actually made, or came close to making. They are recorded because each one produces a plausible-looking wrong answer rather than an obvious failure.
- Treating the one other public implementation as corroboration. The Bitfocus Companion MXCW module was read in full — every commit and every issue — and it is a careful transcription of the same Shure publication this work uses: four substantive commits in three and a half years, and not one report of hardware behaving differently from the document. Two readings of one document agreeing is not confirmation, and an earlier draft here claimed independent corroboration and had to be corrected. The module contributes exactly two things of its own, a keepalive pattern and an explicitly-guessed
RSSIoffset. - Predicting the private API from the wired ancestor. The wired DIS-CCU serves its own web UI from a JSON-over-WebSocket endpoint, so MXCW was expected to do something similar. That a richer private API exists was right; the guessed shape was wrong. It is binary ACN/DMP with a
dmpsubprotocol, and a JSON parser pointed at it sees nothing at all. - Reading
AUDIO_SAMPLE's eight slot pairs as eight seats. The frame looks exactly like per-participant metering and it is not — slots are uplink channels, occupancy is dynamic, and no message attributes a slot to a seat. Anything built on that reading behaves perfectly in a two-person test and points at the wrong person in a real meeting. - Believing a filename.
QtApp.tar.gzin the conference-unit pack is not gzip; and the three payloads that genuinely are gzip each contain a tar holding one member named after the archive, which is itself encrypted. The wrapper is not the content, twice over. - Working from Shure's consolidated ports PDF. It still lists the web application on 8180 unconditionally, while the MXCW user guide's own table says 8180 is legacy-firmware-only and current units serve port 80. The stale document is the more official-looking one.
- Assuming at most one index before a parameter name.
VOTING_BUTTON_NAMEtakes two —< GET 3 0 VOTING_BUTTON_NAME >— and it is the only command in the protocol that does. A parser that treats the token after the first integer as the parameter name reads the parameter as2and drops the message silently rather than failing, which is exactly what the Companion module does.
Open questions
- The payload plaintext.
linux.bin,app.tge,gui.tgeand the whole MXCW640 set are encrypted, no key was recovered and nothing was decrypted — so every claim about the access point's and the conference unit's software rests on filenames in a manifest. - The access point's DMP property map. The charging station's application carries only charger-domain properties, and the access point's live in the encrypted
gui.tge. Whether per-uplink-slot occupancy is exposed as a subscribable property is the single question that would close the slot-to-seat gap, and it cannot be answered without a device. - Which Xilinx part, and whether it really is the TDMA scheduler. The bitstream is raw
.binnaming no device, and the RF-engine reading comes from the timing budget rather than from anything in the image. - Whether a second, read-only controller on 2202 is harmless. Shure says "use only one controller per system to avoid messaging conflicts", which reads as a warning about conflicting
SETs — reports are broadcast and the protocol has no session concept — but that is a reading, not a tested fact. - The
RSSIencoding. Shure documents the units and not the encoding; the only prior art applies an offset of −120 and its own comment calls the offset assumed. - Whether the interface needs a keepalive at all. None is specified, a dead TCP session is indistinguishable from a quiet meeting, and the 30 s probe / 60 s timeout pattern in general use was invented by one third-party module for reasons nobody recorded.
Status of this entry. Substantial findings recorded, but whole subsystems remain unexamined. Nothing on this page has been verified against physical hardware — no unit of this platform has been opened, connected to or modified.