I spent the past month working to study, reconstruct, and play with the MK3 (not MK2) Coldcard and its weak RNG. I set out to reproduce what I speculated was the attacker's search behavior to identify victims rather than trying to follow the bitcoin transactions from known attacker wallets. First, I want to credit Coinkite, Galaxy Research, Wizardsardine, and Praveen Perera for their prior work since it formed my starting point.
The most strking thing I can't find any one talking about yet is that the attack also drained ETH from the weak-seed wallets. It was not much, only about 15.5ETH; however, it may help those who are much better at chain analytics than I am.
TLDR: I implemented the affected MK3 seed generation process independently and deployed it on a NVIDIA 3090 GPU, using bloom filters to accelerate the search and electrs to filter out false positives. So far:
- 1157 distinct week-seed wallet roots have been reconstructed.
- 2808 Bitcoin addresses matched to the wallets.
- All 2808 Bitcoin addresses are empty -- they were either drained in the attack or were previously emptied by their owners.
- Cross chain analysis of the wallets found 8 Ethereum wallets, all drained. There was one LTC wallet; however, all LTC was moved from it back in 2022. Future work may look at XRP, SOL, DOGE or other chains. I'm undecided.
I'm not going to publish mnemonics, private keys, or the PRNG coordinates that regenerate them.
The Vulnerability Reproduction
The vulnerability is now well understood publicly: affected firmware stopped getting seed entropy from the STM32 hardware RNG and then used micropython's non-cryptographic Yasmarng PRNG. For the MK3, the initial state reduces to a pad defined by:
pad = uid32 ^ SysTick->VAL
The uid32 is not a fold or hash of the STM32's full 96-bit unique ID. It is the first 32-bit word, read directly from the STM32 UID address: *(uint32_t*)MP_HAL_UNIQUE_ID_ADDRESS. On the MK3 this starts at 0x1FFF7A10.
The full 12 byte UID is read elsewhere in the firmware for other purposes but not used by the RNG to set its state.
The first UID word contains structured manufacturing information associated with die position, while SysTick->VAL contributes timing state. Everything after that is deterministic once the PRNG state and RNG-consuming sequence of events are known. This effectively means the pad, as represented by UID word 0, represents a unique hardware serial number.
This UID pattern is consistent with Wizardsardine's analysis that estimated approximately 2^22 initial states for the MK3. In my runs, I found that the pad dimension space was 2^24 bits wide.
There was an interesting consequence of using UID 0 word 0 and I think its worth mentioning. The first UID word is not uniformly random. The first UID word encodes the X/Y postion of the die on the silicon wafer. As I recovered more weak wallets, their candidate states showed clustering consistent with groups of STM32 parts entering coldcard's MK3 manufacturing suply chain together. Basically, the vulnerable RNG did not just reduce the cryptograph search space, it seems to have preserved traces of the physical manufacturing distribution used to build the cold card devices themselves.
Practical Search Cost
My implementation was a candidate search on a Nvidia 3090 from my old gaming PC. I computed a bloom filter and then performed the seed computation and path search on GPU using the filter loaded into the GPU. As results were reported back, I queried a locally hosted mempool/electrs instance to filter out false positives. A complete pass through the 24-bit pad dimension took just a bit more than four and a half hours.
Bitcoin Results
The search yielded 1,157 reconstructed weak wallets. Of those, 678 showed their last on-chain movement on or after July 15, 2026. The majority of transactions occurred starting July 30th. This group includes 104 wallets whose last movement was on July 30, 541 on July 31, and 25 on August 1. A small set of wallets were active between July 15th and July 29th, but I don't see evidence of a shared collector between them and the main wave, and the behavior seems like normal owner activity.
From what I saw, ~982.96 were drained during the attack. There was one wallet that was active during the attack that had a 0.051btc transaction during the attack, but since it used a common destination address for a little over a year, I excluded it from the total. That same address later received two small transactions on Aug 2nd and Aug 4th that were swept by the attacker.
Bitcoin Transaction Summary Table
These are transaction on or after July 30th where the destination address recieved a sweep from more than 1 wallet. I do not claim all of these are an attacker or that they are the same attacker. I consider any destination as receiving sweeps from more than one week MK3 wallet as suspect.
| Destination | Transactions | Wallets Involved | BTC Total | First Seen | Last Seen |
|---|---|---|---|---|---|
| bc1qsjrf5ze5tmulz7y2x4pc7qaex2a35sanp3rqlx | 794 | 200 | 34.917319 | July 31 04:54 | July 31 08:36 |
| bc1qnk4zh9qcnap2mycp56qjrgza3cc8ylrh8fecp0 | 414 | 187 | 527.402589 | July 30 01:36 | July 30 01:51 |
| bc1qc779m8gec84k3t0ffvu0pps94zheht7lr7ueyn | 212 | 82 | 279.792016 | July 30 01:32 | July 30 01:32 |
| bc1qmd5m5ktv7m5ffujxv4248fxv36myvdx79n8jp6 | 91 | 74 | 30.183625 | July 31 05:48 | July 31 05:58 |
| bc1qh0l7q0mca3ln7wsl9luwns0jc9jhgrtft025l4 | 62 | 31 | 0.435072 | July 30 1:10 | July 30 01:10 |
| bc1qdaarag7729c2n4l2wnyt3hkhfpcs66n98z7uuh | 55 | 18 | 20.642015 | July 30 01:10 | July 30 01:10 |
| bc1q0mh6rs0mjvv5ncdyqwhqma7hgup3aycucsc279 | 9 | 9 | 0.509860 | July 31 20:07 | July 31 20:16 |
| bc1qf2my39y2lfgp2pylnhu8q2xktqumlpjy2fur4d | 7 | 6 | 0.027447 | Aug 1 04:30 | Aug 1 09:35 |
| bc1qcr9wcc6k0dlqgwfze3dfvwlj4xgvnrfylrz5k7 | 6 | 3 | 0.341358 | July 31 18:51 | July 31 18:51 |
| bc1qgr36zfhfw2uph8w2545y0np65qgfw6v2r2drrx | 3 | 6 | 0.038280 | July 31 16:18 | July 31 17:07 |
| bc1q5z9gl2kl736hhwkrpau9m8n8656veyu4phew4z | 3 | 3 | 0.133538 | July 31 12:46 | July 31 12:46 |
| bc1qk87f7mxqxv63rxlp4kl43lltxf866fqhhzj46h | 3 | 2 | 0.134537 | July 31 03:27 | July 31 05:24 |
| bc1q9ancn2kw5malzz25395009zssmk6k5d443kjv5 | 2 | 4 | 0.000458 | July 31 19:13 | July 31 19:29 |
| bc1q4r63xh9l3vg7zn2zterjvf6me49xwyfscxvwpd | 2 | 2 | 0.553943 | July 31 12:38 | July 31 12:38 |
| bc1q69gptc6cmjmpmxkpjrhs960kp5df6avwuufqvx | 2 | 2 | 0.331536 | July 31 12:23 | July 31 13:30 |
| bc1qme77vs7vuxdj6rxf78m6xenv4v9fk7ftzxtnwe | 2 | 2 | 0.311292 | July 31 12:23 | July 31 13:30 |
| bc1qzrl67rtyaqdvtl78rlklxmraqjk7d9f6cf23jm | 2 | 2 | 0.089004 | July 31 16:03 | July 31 16:03 |
| bc1qjvufmqrhm6pk7cevyapc6mqpm5mk4anlk8ar99 | 2 | 2 | 0.059995 | July 31 13:04 | July 31st 13:14 |
| bc1qjd6tcd5ey96fdujpkr7zgn2zjzp29h208xlvxg | 2 | 2 | 0.010009 | July 31 19:53 | July 31st 19:53 |
ETH Results
On a hunch, I attempted to scan other chains for transactions associated with the wallets. I first focused on ETH. Out of all of the wallets checked, I found 7 ETH active roots. There seem to be two collector addresses, perhaps hinting at two actors? Again, I only consider these interesting of further research because they collect transactions from more than one weak mk3 wallet.
| Destination | Transactions | Wallets Involved | ETH Amount | First Seen | Last Seen |
|---|---|---|---|---|---|
| 0x968626a5769ac2B26FC01c2b9B1225d16a54B154 | 3 | 3 | 15.2130978 | August 1st 04:21 | August 1st 04:45 |
| 0x490F26D4BA65753F87c5885476F7d7d35026204A | 2 | 2 | 0.1931901 | August 3rd 22:31 | August 29th 08:51:59 |
Of note is that one wallet that was drained to 0x490F was receiving small amounts of funds during the month that were later transferred to the 0x490F wallet.
Sources and Prior Research:
- Coinkite — Technical Deep Dive into the Entropy Issue https://blog.coinkite.com/entropy-technical-backgrounder/
- Loïc Morel / Wizardsardine — Coldcard: the technical autopsy of an entropy failure https://wizardsardine.com/blog/coldcard-vuln-deep-dive/
- Praveen Perera — Inside Wave 1: Tracing the Attacker's Steps Through the 1,082 BTC Coldcard Drain https://praveenperera.com/blog/coldcard-mk3-weak-rng-wave1/
- Galaxy Research — Coldcard Exploit Abates as Total Losses Climb to (at Least) 1,700 BTC https://www.galaxy.com/insights/research/coldcard-exploit-abates-as-total-losses-climb-to-at-least-1700-btc
- TRM Labs — The Largest Hardware Wallet Exploit of 2026: Inside the USD 116 Million Coldcard Hack https://www.trmlabs.com/resources/blog/the-largest-hardware-wallet-exploit-of-2026-inside-the-usd-116-million-coldcard-hack
No comments:
Post a Comment