Constructing quine loops with QCC

[This is a follow-up on a previous blog post on QCC, the Quining C Compiler which is designed to transform any single-file C program into a valid quine.]

Recall that a quine is a program that can print its own source code, or more generally, perform some meaningful computation that includes its own source code as an input. One of the logical questions once we have an application for automatically constructing quines is asking whether it can be generalized to multiple programs. The objective is creating programs A and B such that:

  • A can print the source code for B
  • B functions as the mirror image and can print the source code for A

This is true in a trivial way when A and B are the same program, so there is an implied assumption of A≠B to make it worthwhile. Of course, the criteria “unequal” itself is subjective: if the two programs differ in a trivial way, the problem can reduce to the case of the single-quine. We will not try to formalize this definition of A and B being “meaningfully different” but the following examples will clarify the intent.

1. Simple quine-loop with multiple languages

Here we construct a simplified version of the well-known quine Ouroboros. limiting our cycle to two languages for simplicity: C and Python. The objective is to come up with two program A and B such that:

  • A is a valid C program that prints out the source code of B
  • B is a valid Python program that prints out the source code of A

The use of different languages here serves as the separation between A and B. 1

The construction proceeds along the same lines of using QCC in general: first we write a “prequine”— an almost-valid C program relying on a nonexistent get_self() function, assumed to return its own source code. QCC converts that bogus C program into a proper quine by applying source-level transformations and supplying an implementation of the mystery function consistent with the modified source.

Prerequisite: writing programs that output strings

There is one more building block necessary for this construction. It happens to be quite straightforward, involving no recursive self-reference or strange loops: we need to be able to convert a string into a Python program that prints that string when invoked. That is, we want a C program that takes as input a string and outputs a valid Python program whose only function is to print that string. This may sound complicated, but notice the end product is a minor variation on the canonical Hello World application for Python.

Main difference: instead of printing a greeting, our target Python program is hard-wired to print some other constant string determined at construction time. About the only tricky aspect involves escaping special characters from that input. The text we are supposed to output may contain arbitrary ASCII or even Unicode symbols. So we cannot simply enclose it in single quotes as in the hello world example and call it a day. If there was a single quote present in the included string, it would terminate the Python string prematurely and cause parsing errors on the remainder. Instead, we process the input one character at a time and special-case some characters consistent with the way Python expects string escaping to work.

With a little help from Claude 4.8, the result is a small C program characterized by this behavior:

  • Expects to receive one command line argument as string
  • Writes a Python3 program to stdout
  • Where this Python code is constructed to print that exact string to stdout when invoked by a Python interpreter

From prequine to quine

Stepping back, we have created a pair of programs A and B in two different languages:

A: C program that outputs a Python program (call it “B”) based on external input S
B: Python program that outputs this hard-coded string S

This is starting to resemble the A-B quine loop defined in the objectives. The missing piece holding back the closure of the loop is that free-floating, external string S provided as input. If we could replace S by the source code of A, the cycle will be complete. Looked another way, we need to modify A such that it ignores the command line arguments and runs the same Python-generation logic on its own source code.

This is exactly what QCC solves for. First, we create the prequine, by rewiring A to use its own source code get_self() as the input. This is also an opportunity to clean up the now redundant niceties around checking command line arguments and printing helpful error messages. Next, we run QCC on the prequine to generate the final quine. Compiling that and running through the steps proves the output from the final Python program is identical to the original C code:

Expanding the cycle

It is straightforward to expand this cycle to include multiple languages, by modifying only the starting C program. Recall that the driving force behind A is a function that writes Python programs. What if we add a second function that writes Rust in an analogous manner? That is we define a function that:

  • Receives as input an arbitrary string S
  • Returns a valid Rust program R such that when compiled and executed, R will print S

This function will be similar to the Python example, but instead use the hello-world template for Rust and apply Rust-specific string escaping rules.

Armed with this additional capability, we can extend the cycle by taking the output of the Python-writer and feeding it as input to the Rust-writer. Drawing out the sequence of transformations, the original chain looked like:

Self source-code ⟶ String-to-Python ⟶ Final output

Adding one more link to the chain:

Self source-code ⟶ String-to-Python ⟶ String-to-Rust ⟶ Final output

Instead of being a valid Python program, the output from the initial invocation is now a valid Rust program. When compiled and executed, it prints the Python program— its predecessor in the sequence— which in turn will print the original C code if invoked.

In principle there is no limit to the number of additional links that can be added here. In practice, one may need to watch for line limits of certain languages, as each transformation adds space overhead to the string being passed as input to the “printf” equivalent. At some point it may be necessary to break up the string into multiple lines.

2. Quine loops with useful programs

One limitation with the above example is that all programs in the cycle after A perform no “useful” work: their behavior is strictly predetermined to print something to stdout and exit. Meanwhile A as the starting point of the cycle can include arbitrary functionality, since QCC makes no assumptions about what its input program is doing. That raises a logical question: is there a way to apply QCC transformation to a pair of arbitrary programs A and B?

More precisely, suppose we have two programs A and B with arbitrary function— maybe A retrieves weather forecasts while B reports on World Cup scores. The objective is to create a quine loop out of these such that:

  • A and B retain their existing functionality
  • Both are augmented with the ability to print the source-code of the other app (That behavior would become conditional on some external input, such as a specific command line argument. This is similar to how the quine-version of QCC selects between doing its usual job of converting C programs to quines or printing its own code.)

This is straightforward with QCC alone provided both programs are written in C. The core idea is to create the prequine by “splicing” the two programs, interleaved with preprocessor macros to control which one actually gets compiled. Conceptually the merged version looks like:

#ifdef COMPILE_A
/* source code for A... */
#elifdef COMPILE_B
/* source code for B... */
#endif

Absent any other macro definitions, this code is equivalent to an empty file. But by prefixing the contents by a single line of code containing a #define directive, it can be cajoled to act as A or B. Both A and B are then developed under the assumption that get_self() will return this single, merged version regardless of whether it is called from A or B. By prepending one of the above macro definitions to the returned string, each app can choose to print its own code or that of its peer.

The Github repository for QCC has an example quine-loop constructed with this pattern.

  • Invoked without any arguments, program A prints the standard greeting, along its own identity “Alfa” (This is the intrinsic, non-quine related functionality.)
  • If the first argument is non-zero, A prints its own source code
  • Otherwise it prints the source code for B

Program B is the mirror image: it identifies itself as “Bravo” in the greeting and features conditional logic to print out either A or B based on the supplied command line argument.

There is a helper script in the same repository to merge the files, producing the combined A/B chameleon referenced above. That combination becomes the input to QCC, which supplies the necessary get_self() implementation. Finally the actual A and B quines are constructed from the QCC output by prepending a single line of code that defines the appropriate macro for selecting either A or B.

Putting it all together:

Two observation about this construction:

  1. Quines A and B differ by a single line— in fact a single letter in that line— even if their behavior at runtime can have arbitrary differences. This is an artifact of a shortcut taken here: recall that each program is “carved out” of a single block of code returned by get_self() using preprocessor macros and conditional compilation. As expedient as that approach is, it results in each program containing a lot of dead-code that is never compiled. With a little bit more work, we can avoid this by moving the carving-out process to runtime. Instead of relying on preprocess macros to select which block of code is visible to the compiler, we can have A and B perform basic text processing: locate the starting #ifdef line and corresponding #endif directive, then capture the section between those lines as a substring. (Note we still have to include the trailer following the conditional blocks, as the quine machinery is located there.) This will remove redundant. uncompiled code and make the underlying differences between A and B more prominent.
  2. The trick also extends naturally to more than two programs— in fact, the combination script is designed to accept any number of source files as input, automatically assigning successive letters of the alphabet to each program when crafting preprocessor macros. Once that merged file is run through QCC and individual quines created by prepending the appropriate macro definition, we end up with something more than a cycle: the collection resembles a complete graph. Every program in the collection can output the source-code for any other program in that collection. Contrast that with the standard Ouroboros cycle, where movement goes strictly in one direction. Here one can navigate the graph freely by asking any program for the source code of any other program.

CP

1 While it is possible to create C/Python polyglots to satisfy this trivially, this example will not be using that escape hatch.

Mark-of-the-web and pinning installers to sites

Is it possible to create an application that behaves differently based on which website it is downloaded from? At first glance, this seems impossible if the problem is interpreted strictly: the downloaded content must be identical byte-for-byte. (It would be trivial if each site was allowed to alter the contents.) The success criteria could be summarized as:

  • Serve the application from original URL #1.
  • Copy the downloaded file and mirror it from another URL #2.
  • The application behaves differently when downloaded from the mirror compared to the original location.

Recap: dark ages of web security & mark-of-the-web

Zone of naivete

In the late 1990s when the web was taking off, Microsoft’s web-browser Internet Explorer security model was predicated on a laughably over-simplified division of the world into zones. While one could define custom zones, there were 5 built-in:

  • Local machine
  • Intranet
  • Trusted sites
  • Internet
  • Restricted sites

Browser security policies were then configured based on zone. Consider ActiveX controls: arbitrary, unconfined native Win32 code that runs with full privileges of the user— which on most Windows installations meant administrator—and could wreak havoc on the machine. What happens if the user visits a webpage trying to run an ActiveX control? If that page hails from the friendly territory of the internal enterprise network (aka “intranet” zone) no problem: run the code, no questions asked. But a random website out on the wild-wild-web (aka “internet” zone) would require more caution: the user must click through a cryptic modal dialog with information about Authenticode signatures before allowing that code to execute.1

While this model “works” in the rudimentary sense intended for content rendered inside the browser, it poses an obvious problem with downloaded attachments. Suppose the attachment malware.exe is downloaded first and later opened from the Windows shell called “explorer” (which naturally bequeathed its name to the web browser, following MSFT’s creative naming conventions.) In principle the same zone-based distinctions should apply to the user experience: whether any warnings are shown and what type of scary language explains the consequences of proceeding with the decision to open the file should be a function of whether the file originated from the friendly confines of the corporate intranet or the terra incognita of the dangerous internet.

Mark-of-the-web

This is the problem mark-of-the-web (commonly abbreviated MoTW) solves. Whenever a file is downloaded, IE saves additional metadata about that file, including its origin URL and zone mapping.2 How this is done without altering the contents themselves and guaranteeing the metadata is permanently attached to the file is nonobvious. If IE simply wrote a second hidden file in the same directory, the connection would be severed as soon as the user copied the original file—the only file that the user is aware of— to another directory. Instead MoTW leverages an ancient feature of the NTFS file-system: each file can have multiple “alternate data streams.” Most files only have one stream: the default one which we normally consider as the contents. But additional streams can be created to store arbitrary data, without altering the original content. (Linux has extended attributes, MacOS has a similar concept as well as named forks.) MoTW uses a specific data-stream to store the information about the provenance of the file when it is downloaded, preserving that context for future security decisions.

Leveraging MoTW: from PoC to defense-in-depth

Introspection with MoTW

While MoTW is intended for the operating system and other origin-aware applications such as MSFT Office to make security decisions, an executable can also access its own MoTW. This is the basis for a proof-of-concept with a simple Win32 GUI application:

  • Downloaded from Github and executed, it displays a “Hello world” message.
  • Downloaded from another location it will instead display an error message about unrecognized origin.

Both files have the same SHA256 hash: 002d0bdbaaad909c8a6b49939b7f19ed8e897debce7aceb82732c2d590359bf2

(One caveat: because this executable does not have an Authenticode signature, SmartScreen can interfere in the demonstration. Clicking through the SmartScreen warning to continue to run the executable will delete the mark-of-the-web, and replace it by a different alternate data stream used by ScreenConnect. That behavior is by design; it is intended to avoid repeated warnings when the user has already indicated a binary is safe. To avoid such interference, simply open a terminal window and directly execute the binary from a command line instead of going through the Windows shell.)

This meets the criteria outlined in the introduction for an app with behavior conditional on distribution point. Before discussing a more realistic scenario where such tricks can be useful, it is important to recognize the limitations around threat model: MoTW can be trivially tampered with or deleted by the user. It is not authenticated. (Although the URL itself may contain a signature that the application can verify, since query-string parameters allow attaching arbitrary data. But in the same threat model the user can also tamper with the binary itself, since we are assuming write-permission to the file.) That means it cannot be relied on to implement arbitrary policies against the machine owner, such as enforcing license restriction on software.

Malicious repurposing of dual-use apps

Recall the case of ScreenConnect from 2025: ScreenConnect is a dual-use remote control application published by ConnectWise, ostensibly intended for IT departments to manage their fleets. Due to a combination of dubious design decisions and own-goals from ConnectWise, it turned out ScreenConnect had become very popular with threat actors using authentic, signed installers signed by ConnectWise to take over the PCs of unsuspecting consumers and hijack their accounts. The attackers’ modus operandi involved sourcing legitimate installers from ConnectWise, modifying some “free form” data without invalidating the Authenticode signature and serving these malicious installers from their own website, under a different pretense. For example, in the campaign picked apart here, it was renamed RiverDesktop.exe to impersonate a non-existent desktop application for River Financial.

Had the ScreenConnect installer used MoTW introspection— or really, any type of introspection, starting by looking at its own name— it could have easily detected this repurposing and refused to proceed with the installation. Even an installer customized to trust a malicious distribution URL specified by the attacker would have gone a long way to minimize blast radius: malicious sites are taken down quickly and attackers rely on being able to cycle through multiple look-alike domains in a game of whack-a-mole with defenders. An installer that does not care about its distribution point can be served from any host; one pinned to a specific distribution point is useless after the first abuse report.

Despite the previous caveat around users being able to tamper with the MoTW, there are three reasons why this mitigation still works for this specific threat-model:

  1. What matters is that the remote attacker serving malware can not tamper with the MoTW. It is the user’s own trusted web browser— Chrome, Edge, Firefox, Safari etc.— that dictates the contents of that alternate data stream. While the attacker can register any domain and serve the malicious binary from a URL of their choice, an MoTW will still be created and that URL reflected verbatim.
  2. The user has no incentive to remove the MoTW or otherwise tamper with it. Recall the attack depends on tricking the user to downloading and running what they believe is a legitimate application. A user could fire up Notepad and edit the ADS containing MoTW, but the attacker has no way to make that happen.
  3. Attackers can not tamper with the installer to remove MoTW introspection, without greatly undermining the persuasiveness of their scam. Recall that any alterations to the binary would invalidate the original software publisher’s Authenticode signature on the binary. These scams work precisely because Windows extends trust to code signed by ConnectWise, a reputable vendor of enterprise IT applications. An invalid signature or unsigned application will throw all kinds of additional warnings. (If the attackers did not care about the trust inherited from the signature, they would not have any reason to bother with ScreenConnect. They could have used any number of purpose-built, malicious RAT applications available for sale on the dark web.3)

CP

1 Later versions of IE tried to improve security by making it more and more difficult to run ActiveX controls. For example instead of the modal dialog which required an explicit yes/no decision, the user would have to notice a subtle notification above the status bar indicating that the page wants to run a control.

2 Note the obvious TOCTOU issue here: if the zone mappings are changed, the metadata will still reflect the original categorization.

3 Sure enough, in the 2026 iteration of a similar campaign, they were observed using code-signing certificates handed out by MSFT’s own ID verification CA. This frees them from having to use “factory-original” ScreenConnect binaries and in theory allows modification of the vendor logic.

Building quantum canaries and tripwires with smart-contracts

There is great uncertainty about when “Q-day” arrives for blockchains— when a cryptographically relevant quantum computer (CRQC for short) will exist that can recover private keys that control major digital assets, such as bitcoin and ethereum. Reflecting that uncertainty, there is a wide range of opinions on the urgency of post-quantum transition. Some voices are already sounding the alarm, while others dismiss such talk as crying wolf and urge a cautious, incremental upgrade path. Meanwhile a proposal from BitMEX research tries to make the concept of Q-day more concrete, by attempting to create a challenge on-chain such that when the challenge is successfully cracked, it becomes indisputable proof of a quantum computer in existence. This blog post will take a look at the options for constructing such “quantum canaries” and outline why smart-contract capable chain such as Ethereum can host even more powerful constructs, without requiring any changes to the underlying blockchain.

Recap: proof-of-quantum

The idea behind a quantum challenge is exactly same as the one around creating unusable public keys covered in a previous post: we invert the usual order of operations for key generation. Instead of generating an ECDSA private key first and deriving the public-key from the private scalar, we start by picking a public-key as the output of some hash function or other pseudo-random process operating on a natural input such as digits of pi or an English sentence. In the literature these are known as “NUMS” schemes, for nothing-up-my-sleeve: anyone else can verify those bytes were generated as part of a deterministic process without sneaking in arbitrary choice of parameters that could influence the result. Assuming the resulting public key is valid— in the sense of being a valid curve point, and there is roughly 50% chance of that for any random starting point— there is good reason to believe the private key was not known in advance. Recovering that unknown private key from the public key we picked is computationally intractable for classical computers. This is why we treat such keys as “unusable:” no one can sign with them, even the person who generated the corresponding public key. If a lock is designed to only open for those in possession of the private key, we can assert that door will never open.

Quantum computers invalidate that core assumption: they can efficiently solve the discrete logarithm problem and recover the private key. This provides a straightforward way to prove the existence of a quantum attack: pose a suitable challenge and wait for a solution.1

Quantum challenges on blockchains

On paper a blockchain would be a great platform for posing such a challenge: anyone can participate and if the challenge is structured appropriately, the winner does not have to worry about whether they will get paid. Contrast this with competitions run by a centralized entity with private submissions: whether the reward is given is very much at the discretion of that organization.

In fact, many observers have wryly pointed out that all blockchains operate a massive, unofficial bug-bounty with all attacks considered fair-game, including quantum computing. If one can recover private keys— or at a lower bar, trick the legitimate owner into signing with those keys— they can “collect a bounty” or in more colloquial terms, commit theft.

Unfortunately when any attack is fair-game, it becomes difficult to distinguish a ground-breaking quantum computer advance from garden-variety security breach or disgruntled insider. This is where the NUMS approach comes into pay: if one can prove no one could have known the private key to begin with, it could only have been a quantum attack.

There are some subtleties around realizing this purely on-chain. The first problem is that blockchain addresses are not same aspublic-keys. Addresses are typically commitments to public-keys that are derived from the key. For example a Bitcoin address is obtained from the ECDSA public-key by applying two hash functions in a sequence. This process is one-way: it is not possible to infer the public-key from the address. The original public key is not revealed until withdrawing from that address. That means merely depositing the bounty bitcoin at some address is not enough; one must also disclose the public-key.

That could be done either by:

  1. Out-of-band, for example in a blog post announcing the challenge
  2. On chain, by withdrawing a symbolic fraction of the bounty while leaving the majority of the funds at the same address.

The second solution is appealing in that it operates entirely on-chain without relying on additional communication channels. That also means it can be used to create tripwires: quantum-canaries that are not publicized ahead of time, and therefore unknown to attackers. A rational attacker armed with a quantum computer may deliberately want to stay under the radar, and avoid attacking known bounty addresses. But if some collection of coins looks like any other address on chain, there is a real possibility they will accidentally target that address and unwittingly herald the arrival of Q-day.

Unfortunately this design also runs into a circularity: if the private key is not known to the organizer of the challenge, they can not execute an ordinary withdrawal to deliberately leak the public-key either. One might suspect multisig could solve that problem. For example, one could create a 1-of-2 multisig address, with one known and one provably unknown key. Then a withdrawal using the known key ends up revealing both public keys. But this also poses a problem for the canary: since both keys are exposed, the attacker also gets their choice of targets. In fact a rational attacker would always choose to break the private key that was already used on-chain instead of the canary, since that pattern blends in with existing attack patterns. At that point we are back to the original problem: was it a garden variety compromise of the known private-key or was it a quantum attack?

Taproot addresses as ideal tripwires

This is where the new Taproot addresses come in, solving both problems at once. Unusual among blockchain address formats, Taproot addresses are public keys. They are also commitments to alternative spending paths, defined by ordinary Bitcoin script and efficiently compacted into a compact Merkle tree. Funds can be spent either by doing a Schnorr signature with the public-key defined in the address or by disclosing the internal structure of the address, including the specific node in the Merkle tree selected for a particular transaction.

This structure allows for an optimal bug-bounty structure:

  • Merely depositing funds into a taproot address creates a target for a quantum computer. No withdrawals or publishing additional data offline requierd.
  • That address looks no different than any other taproot address. In other words, the setup can also function as a tripwire if one does not publicize it in advance. (You can still prove after the fact that it was generated in a NUMS fashion.)
  • If no one trips the alarm after a given period of time, it is possible to reclaim the funds. This solves for another problem with the deposit-and-publish approach: if the private key is truly unknown, those funding the reward program will never be able to get their funds back, even if the reward is never claimed and the early-warning system is no longer necessary.

Canaries and tripwires with smart-contracts

Not surprisingly, it is possible to construct much better canaries on layer-ones with smart-contract capabilities. Turing completeness overcomes two limitations of the Bitcoin canary approach:

  1. Each canary requires recovering a specific private key. Consider a benevolent quantum capable intelligence agency that wants to tip off the world or for that matter a Snowden-type insider who wants to signal that capability exists. In order to announce the discovery using the Bitcoin blockchain, they would have to break that specific private key. But what if they had already solved other NUMS-style challenges internally as part of demonstrating that capability? Those demonstrations can not be used to meet the canary requirement. (Of course they can be leaked through other traditional channels whistle-blowers have historically relied on.)
  2. Finding out about Q-day is one thing, taking action is another. While a tripwire getting hit would be front-page news, it leaves everyone scrambling to decide on how to protect their funds. This is why the BitMEX proposal is coupled to a soft-fork that freezes certain funds if the canary is ever triggered.

Purpose built contracts for quantum-canaries

Smart-contract capable blockchains can improve on both of these aspects. This sketch will use Ethereum for concreteness but the same ideas translate equally well to layer-two rollups or Solana.

First a smart-contract can be written to accept a much more generalized type of CRQC proof. Instead of requiring that the prover solve any specific challenge, they can be broaden criteria to accept a much wider selection of NUMS-type schemes. This ideas has been explored in previous work, such as Brace for impact: ECDLP challenges for quantum cryptanalysis. Adopting it to the Ethereum setting involves creating a smart-contract to validate more generalized proofs:

  • Prover supplies a seed W, scalar Y, message M and signature S
  • A cryptographic hash function such as SHA256 is applied to the seed to generate 32 bytes that are interpreted as the X-coordinate of a public key point.
  • This is combined with the supplied Y value to get an alleged2 curve point <X, Y>
  • The public-point is hashed with Ethereum’s own variant of pre-standard SHA3 (“Keccak”) to generate the corresponding 20 byte address A.
  • The built-in ecrecover() primitive is used to recover the expected address E, which corresponds to a public key that would have generated a valid signature S on M
  • Check if A ≟ E
  • If equality holds, send all funds held by this contract—the reward for disclosing the existence of a quantum computer— to the prover.

Effectively this logic checks that the prover was able to sign some message using a private-key corresponding to a public-key that was generated deterministically from a hash function. Note how much freedom the prover has: they can sign any message. It does not have to be a Bitcoin or Ethereum transaction. (But if a BitMEX-type canary did trigger on Bitcoin, the exact same signed message could be replayed on Ethereum and accepted as proof that Q-day arrived.)

Second, other contracts can be written to depend on this canary. For example, before performing an important operation such as releasing funds, an institutional wallet can check on the canary status to ensure that ECDSA signatures are still reliable. (Recall that Ethereum contracts can call other contracts to retrieve information as part of their execution flow. Retrieving a yes/no answer from another contract would be a relatively “cheap” operation in gas terms.) Every other application is free to use this information as they see fit: for example, a contract could fall-back to an “emergency mode” where it will only accept signatures from a set of backup-keys that have never been used on chain before.

Alternatively one could implement a contract with two authorization paths:

  1. Standard ECDSA-based signing. Efficient because ECDSA signature verification is a native operation for Ethereum.
  2. Quantum-safe hash based signatures. These would be more costly and possibly have limitations such as a limit on how many messages can be signed.

As long as the canary has not been tripped, the first path is executed. But once the canary signals Q-day, only the second type of authorization is accepted.

Paradoxically, the same power that makes it possible to create such generalized canaries makes it much harder to create tripwires. Recall that a tripwire must be stealthy and look like any other vulnerable blockchain address. A smart-contract carefully crafted to serve as early-warning system to be invoked by other contracts clearly does not fit the bill. Using a plain “externally owned” address controlled by a single ECDSA key runs into the same problem as bitcoin: it is not possible to deliberately leak the public-key without doing a withdrawal, and by definition withdrawal is impossible without the unknown private key. (Ethereum does not have an alternative address format comparable to Taproot that directly reveals public keys.)

Designing for incentives

Dealing with front-running on Ethereum

Building a bug-bounty is one thing. Whether it will work to incentivize disclosure is a different problem. Same goes for tripwires: they are only effective if the attacker is likely to stumble into one early on in their rampage through the blockchain, otherwise the warning comes too late. Before exploring this complex topic of game-theoretical incentives for the hypothetical attacker, we need to address one flaw in the design sketched above.

Let’s posit that the actors deliberately signaling the canary are financially motivated. (Note this does not apply to an attacker unwittingly hitting the tripwire.) They want to collect the associated financial reward. By design the bitcoin held in the Taproot canary is only claimable by the entity who wields the private key corresponding to that address and can sign a specific message. More importantly, that signed message is a bitcoin transaction and unambiguously specifies where the rewards are to be sent: those are the outputs of the transaction. That is not the case on Ethereum: any signed message for a suitably constructed key works and that message need not have any particular structure.

That leads to a problem: since transactions sit in mempool before they are confirmed, there is a window of vulnerability where anyone can observe the proof before it has been officially recorded. They can then construct another transaction with higher gas to tempt the block builders into prioritizing it ahead of the original. If this second transaction executes first, the reward for proving a quantum attack goes to the copycat reporter, not the original person who deserves credit.

There are two complementary ways of dealing with this, depending on the expected disclosure mode:

  1. If the entity triggering the canary has access to the full private key, they have full control over what message is getting signed. The protocol sketched above assumed no particular structure in that message, which is useful for accepting the widest spectrum of evidence as proof-of-quantum. While keeping that property we can add an additional check: if the message consists of exactly two blockchain addresses, one being the address of the canary contract, interpret the second address as the destination where rewards will be sent. These transactions can still be front-run but now doing so has no effect: the address where rewards are sent is hard-wired in the signed message. Racing to broadcast the same evidence from a different address only delivers the bug-bounty faster to the deserving recipient.
  2. That still leaves open the question of how to safely submit evidence in cases where the person does not control the private-key. For example, a conscientious employee working for an organization that achieved a surreptitious CRQC breakthrough. In this case, they may only have access to a handful of signed message examples, but not the ability to use the CRQC for a selected public-key of their choice. To prevent front-running in that scenario, the contract logic must be modified. Instead of disclosing the evidence outright, there is a two step commit-and-reveal protocol:
  • First the reporter commits to the triple <message, signature, rewards address> by sending its hash to the contract. This alone does not trigger the canary since anyone can make up commitments. The canary contract still makes a note of all such commitments, along with the time when they were first made.
  • Only after that first transaction has executed and the contract recorded the commitment, the reporter follows up by disclosing the full evidence. The contract checks the evidence as before and also confirms there is a prior commitment serving as a promise to deliver the evidence. There is also a deadline imposed, to make sure commitments are opened within say 24 hours.
  • The canary is immediately triggered to indicate proof of a quantum attack. However the rewards payout will have to wait until a few checks are cleared.
  • In the best case scenario, there are no earlier unopened, unexpired commitments. In that case the bounty can be paid out immediately.
  • Otherwise the priority of the disclosure is being contested. A countdown begins to select among multiple submissions, with the current reporter becoming the leading contender for the reward.
  • If any earlier commitment is successfully opened by providing valid evidence consistent with that commitment, it becomes the new leading contender.
  • At the end of the 24 hour period, the winning submission can make a final call to the contract to collect the reward.

Note it is still possible to front-run all transactions from the original prover and resubmit them with identical payloads, with higher gas to ensure they are processed ahead of the legitimate submission. But since an adversary has no way to open binding commitments to reveal a different payout address, all they accomplish is accelerating the reward payout to the rightful owner.

Questioning incentives

Underlying all this discussion is an implicit premise: that establishing a high-enough monetary reward is enough to incentivize disclosure on-chain. We now turn our attention to sanity-checking that.

The original BitMEX proposal hinges on a core assumption: a benevolent organization with a CRQC will choose to deliberately reveal that capability on-chain by solving one very specific challenge and reaping the modest associated rewards. This is at best a dubious assumption. If they are financially motivated, there is no need for an artificial bug-bounty. There are exposed public-keys controlling BTC collectively worth billions of dollars that are vulnerable to recovery by a CRQC. As long as compute time on CRQC remains precious, incentives favor chasing after the maximum gain possible with the targeted private key. For example the third-highest balance bitcoin address today has an exposed public-key and a balance north of 140,000₿, a figure that dwarfs any reasonable bounty. An unscrupulous actor can help themselves to a fraction of that amount while retaining plausible deniability that it was an ordinary security breach or human error.

At best a monetary reward can incentivize disclosure by a legitimate organization such as one of the pioneering quantum-computing companies who are already committed to operating within the bounds of the law. But even in that case, why should that company have to jump through the hoops of solving one particular challenge on one particular blockchain? Why not put out a press release with a solution to one of the many previous quantum-computing challenges published in the literature?

By contrast, a quantum-tripwire is useful precisely because it does not depend on good faith actions by the CRQC owner. One would expect an actor unconstrained by legal or ethical rules to chase moderately concentrated holdings of bitcoin first: not too large to panic the market with a major theft—even if there is plausible deniability on root cause— and not too small to waste precious CRQC time on economically unprofitable targets. If the tripwire address falls into that sweet-spot, an attacker could accidentally end up revealing their capabilities. On the other hand, it is also easy for threat actors to avoid that fate: while Taproot transactions account for 15-20% of activity today, they only account for ~1% of stored value. So an attacker can avoid hitting a tripwire by simply steering clear of all Taproot addresses, without meaningfully reducing their expected gain.

The more generalized quantum-canary for Ethereum opens up new incentives, by exploiting the schism between the organization wielding the CRQC and individuals associated with that work. An organization may have no official policy around wanting to protect the bitcoin community by warning of impending capabilities. But there may well exist conscientious whistle-blowers within that organization with access to CRQC development, who choose to take matters into their own hands by disclosing a cryptographically verifiable proof on-chain. These individuals need not even harbor a profit motive. Since the protocol is flexible enough to specify that the bug-bounty is burned (by using the 0 address for rewards destination) it is compatible with disclosure motivated by ideological reasons. On the flip-side of the coin, there is a clear lesson for CRQC operators hoping to remain under the radar: avoid solving any NUMS challenges, even for internal testing purposes. This is rational guidance anyway. By definition a NUMS challenge is an artificial target: no one relied on that key to encrypt highly sensitive traffic or authenticate critical actions. Therefore recovering the corresponding private key will not result in learning useful intelligence from intercepted traffic or impersonating some high-value target to gain access to some system. Given that CRQC time is going to remain extremely valuable, wasting cycles on such a demonstration is unwise even without the added risk of creating undeniable proof that can be leaked.

CP

1 Assuming that discrete logarithm problem is indeed as intractable as believed— it is worth nothing that there is no mathematical lower-bound established on its complexity.

2 Note “alleged” part because there is no guarantee this point is actually on the curve. This turns out not to matter for the correctness of the protocol, because the address generated from such an off-curve point can not be equal to one returned by ecrecover.

ScreenConnect redux: the limits of certificate revocation

An earlier post from 2025 covered the case of ScreenConnect, a popular remote-administration utility developed by the vendor ConnectWise for IT administrators to remotely manage Windows PCs. Such applications are inherently “dual-use:” they work equally well for legitimate IT departments to manage their corporate PCs as they do for criminals looking to take over unwitting consumers’ machines. Combined with a number of questionable design decisions in the ScreenConnect client around lack of notice/consent, it was no surprise the threat actors jumped on the chance to leverage this application for their campaigns. Typical modus operandi: targets are sent a phishing message suggesting they install a new Windows desktop application associated with a service they already use. Not surprisingly, that application was just a renamed ScreenConnect installer, which grants remote-control of the machine to the attacker as soon as installation is complete.

Multiple reports and eventual escalation of these incidents to Microsoft and DigiCert— the certificate authority who issued the code-signing certificate used by ConnectWise to sign their Windows binaries— resulted in a number of disruptive changes to the application and the associated cloud service. Two stand out from a security perspective:

  • ScreenConnect installer no longer uses the “unauthenticated data” field in Authenticode signatures to stuff critical configuration. As the name implies, this field is not covered by the signature and could have been trivially altered by attackers to modify settings of a legitimate install, redirecting the C&C server away from the original customer (eg the IT department using ScreenConnect) to one controlled by the threat actor.
  • ConnectWise no longer digitally signs installers for on-prem versions. Instead customers themselves are responsible for getting their own Authenticode certificate to sign the binary.

One would expect this to have been the end of the story. Fast forward to 2026, and more renamed ScreenConnect installers are showing up in the wild. This post takes a look at how the attacks have evolved.

Suspect binary

Phishing site that offers an alleged native DocuSign app

The suspect binary comes from a malicious website sporting generic DocuSign branding but registered under domain names intended to impersonate a financial service. Targets receive phishing emails with a false pretext involving new policy documents that they are required to review and sign for continued access to their account. Clicking the download button on this page returns a file named “DocuSignSetup.exe” Interestingly while the fine-print under the button claims both Windows and MacOS are supported, the exact same file is served for all platforms, including Linux. Presumably the threat actors concluded Windows is a sufficiently target-rich ecosystem and saw diminishing returns in chasing other platforms despite ScreenConnect having cross-platform support.

Looking closer at the binary:

1. Running strings on the binary turns up references to ScreenConnect, as well as XML configuration snippets observed in previous samples of the real installer:

It is possible these strings and XML configuration were planted as a false-flag operation, as unused resources embedded in the binary to confuse attribution. Far more reliable evidence comes from running the installer in an isolated VM and observing changes to the system. Sure enough there is a ScreenConnect directory created under \Program Files (x86) and the helpful autoruns utility from SysInternals shows persistence components associated with ScreenConnect— including a DLL that is in fact signed by ConnectWise itself. While there is no guarantee that the threat actor did not make changes to the original installer prior to signing it, there is no question that real ScreenConnect components are installed and activated after running the malicious binary.

2. It carries a valid Authenticode signature chaining up to a publicly trusted root— specifically one of Microsoft’s own code-signing CAs. (Signer name has been redacted for privacy reasons explained below.) This is a very short-lived certificate with a mere 3 day lifespan, and the trusted timestamp on the binary shows it was signed about six hours after issuance, within the validity window of the certificate. Corollary: this binary will not result in a warning about unknown publisher when invoked on standard Windows versions.

3. This is a garden-variety Authenticode signature. There is no evidence of the bloat associated with hiding configuration data in unsigned fields characteristic of ScreenConnect incidents from 2025. That rules out an installer created for a legitimate ConnectWise customer somehow landing in the hands of crooks who repurpose it by tampering with unauthenticated, free-floating configuration parameters.

Conclusion: crooks are still able to leverage ScreenConnect to remotely take over consumer PCs despite all steps taken by ConnectWise.

Microsoft in the middle

Accidental doxxing

What stands out in the above investigation is that the code-signing certificate was issued by MSFT itself. The common name on the immediate issuer reads: “Microsoft ID Verified CS AOC CA 04” This turns out to be part of the Azure Artifact Signing program, Microsoft’s own entrant in the increasingly popular code-signing-as-a-service category. After watching software publishers fumbling security around high-value signing keys— failures seized on by threat actors in high-profile incidents to sign exploits, including the Stuxnet worm discovered in 2010 that sabotaged Iran’s nuclear enrichment facilities— the industry has collectively given up on the idea that companies can be entrusted to manage their own keys. Instead a cloud service holds the keys on behalf of the software publisher and signs binaries subject to governance rules defined by the customer. DigiCert, SSL.com and other certificate authorities offer this functionality.

Regardless of whether keys are self-custodied or held by a trusted cloud service, requirements for issuing code-signing certificates are identical: the CA must verify the identity of the software developer. There are three levels of verification available, ranging from the most accessible to most stringent: individual/independent developers, organization validated and extended validation. In this case MSFT has issued the code-signing certificates to a specific individual rather than corporate entity. According to Azure artifact-signing documentation, the necessary identity verification for this type of certificate is outsourced to the third-party service Au10tix. Au10tix documentation suggests they can scan and validate government issued ID documents using smartphones. This type of remote identity verification is increasingly common for onboarding with fintech applications.

The surprising part: Azure Artifact Signing has an option to include the verified street address in the issued certificate. That is not a required field; its inclusion is controlled by a command line parameter or checkbox. Yet the persons who provisioned these certificates went out of their way to include their street address. (This is why the X509 subject name was redacted from the image above.) Whether or not they realize it, the developers who signed this binary doxxed themselves.

Verifiable criminality

There are three ways to interpret these observations:

  1. Threat actors are willingly signing malware under their true identity. This could be a matter of bad opsec: maybe they are not aware of how Authenticode works in general or do not realize that Azure’s artifact-signing exposes their identity to all targets receiving the malware. Or it could be calculated risk taking, assuming that law enforcement will not have resources to pursue this matter even when they are leaving their fingerprints all over the attack.
  2. Threat actors are enlisting unwitting accomplices to “borrow” their identity and complete Azure’s verification process. Support for this is mixed, given the limited data points. Of the three different signing certificates observed in the wild for this sample, one belonged to an individual in Oklahoma but two were associated with residents of Texas in close geographic proximity. If this hypothesis is true, there is still an investigative trail leading from individuals named in the Authenticode certificates to the perpetrators.
  3. Threat actors are using stolen identities to bypass Au10tix. This is the optimal choice for a seasoned criminal: it causes misattribution, framing someone else if law enforcement pursues the matter.

Malware bundle

There is another crucial difference between this campaign and previous ones built around ScreenConnect: this time around the installers appear to contain a veritable kitchen-sink of additional components. Standard ScreenConnect installers clock in at a few megabytes. The installers observed in this campaign vary in size from under 10MB to over 50MB. Additional reverse engineering is necessary to identify exactly what these components are but it can not be explained as natural variation in the size of the authentic installer. More likely the threat actor is bundling additional malware alongside ScreenConnect, such as a backup RAT in case ScreenConnect stops working in the future. This is a legitimate risk for the attacker— depending on configuration, the command & control channel is a cloud service operated by ConnectWise. That gives the company broad leeway to take action against any customer abusing the product, by disabling that account and disrupting the remote-control capability.

In a way, attackers are much better off than 2025 when they had to work with the installer provided by ScreenConnect. While they could make some changes to the configuration left unprotected by the Authenticode signature, they could not bundle arbitrary code. That constraint no longer applies. Empowered by Azure Artifact Signing to sign any executable, the threat actor is free to bundle additional malware or even tamper with safeguards in ScreenConnect if they wanted to. Suppose the ScreenConnect client added a mandatory notification for the user whenever remote-control sessions are started. An attacker can directly patch the binary to strip this out and then sign the whole bundle with their own certificate. That latter signature is just as good for appeasing Windows’s requirement for code provenance and suppressing scary warnings about unknown publisher.

Limits of revocation

As of Jun 3, at least one certificates that signed a malware sample has been revoked retroactively, while another one remains valid. In a sense, it may not matter even if revocation had been more timely and comprehensive. For consumers who were already tricked into installing the malware, the damage is already done: their PCs have already fallen under the threat actor’s control. Windows does not retroactively check Authenticode signatures for already installed applications in hopes of catching ones that were later revoked. EDR software can provide continuous monitoring, and there is some reason for optimism there: Windows Defender is categorizing the binary with revoked signature as malicious. But it is unclear how far that generalizes to all other variants with their variable payloads and for that matter, whether Defender will take the drastic step of neutralizing the ScreenConnect persistence mechanism on an existing PC. It is after all a “dual-use” application that can have legitimate uses in a managed IT environment. The distinction between “RAT” and “corporate fleet management” is not in the eye of the beholder, but it does depend on context: who paid for the PC, who is using it and whether they consented to remote management. ScreenConnect is better poised to neutralize an unauthorized use of their remote-control software by bringing the hammer down on specific instances of abuse. But that mechanism operates out-of-band in a messy world subject to human discretion, outside the regimented structures of PKI.

CP