3948 stories
·
4 followers

Claude Fable 5.1 made me a really nice animated pelican

1 Comment

1st September 2026

Today is Claude Fable (and Mythos) 5.1 day. Anthropic say that Fable 5.1 “sets a new standard for coding, knowledge work, and long-running problem-solving tasks”. Their announcement spends a notable amount of time on scientific research, boasting of a 52.6% score on the brand new Terminal-Bench-Science 0.1 benchmark (first announced on August 27th), up from 24.7% for Fable 5, 29.0% for Opus 5 and 22.4% for GPT-5.6 Sol. Other benchmarks show slightly improved scores, but none as impressive as the Science one.

But how well can it pelican?

Back in July I wrote about how I was losing faith in the pelican benchmark—its connection to how good the models were at other tasks didn’t seem to hold as strongly as it did back in 2025. The most interesting insights I get from it now are comparisons within model families, and particularly comparisons for the same prompt at different reasoning effort levels.

Fable 5.1 has five reasoning levels: low, medium, high, xhigh, max—and no option to turn off reasoning entirely.

I fixed an issue in llm-anthropic which caused reasoning traces not to be correctly recorded, then ran some prompts.

Here’s the full set of pelicans for all of the reasoning levels, each with the full reasoning transcript. I’ll replicate them here:

Low and medium, both without reasoning? #

Next, a bit of a mystery. This is what I got for effort low:

Minimalist flat illustration of a white pelican with an orange beak riding a black bicycle to the left, its orange legs pedaling and wings gripping the handlebars, with motion lines behind on a light blue background.

The transcript doesn’t show any summarized reasoning tokens, and the output token count is 1,998. With Claude that output token count includes reasoning tokens. It took 23.8 seconds and cost 10.017 cents.

I bumped that up to medium and got this:

Minimalist flat-style illustration of a white pelican with an orange beak riding a black bicycle to the right, with motion lines behind it, on a light blue background.

Weirdly, that one also shows no reasoning text and used 1,977 output tokens—21 tokens less than low. It took 23 seconds and cost 9.912 cents.

So for this particular prompt (“Generate an SVG of a pelican riding a bicycle”) Fable 5.1 appeared to skip reasoning entirely at both low and medium settings.

High #

Here’s high—29.6 seconds, 2,612 output tokens, 13.087 cents:

Minimalist flat illustration of a white pelican with an orange beak riding a black bicycle, its orange legs pedaling, with motion lines behind it on a light blue background.

This one did do a bit of reasoning, summary here:

I’m planning the SVG layout for a pelican riding a bicycle, with a sky and ground background, a bicycle with two spoked wheels, frame, seat and handlebars, and a white-bodied pelican with a long neck and orange beak positioned on top.

Really not much difference from low and medium, though.

At xhigh things got radically different. 36,767 output tokens, 7 minutes 51 seconds, $1.83!

Minimalist flat illustration of a white pelican with an orange beak riding a black bicycle to the left, its orange legs pedaling, with motion lines behind it on a light blue background.

The reasoning trace is pretty lengthy, and includes details like this:

Adding the eye, wings stretching down to the handlebar grip, orange legs reaching to the pedals, and a small tail feather, while keeping the pelican intentionally oversized compared to the bike for comic effect. [...]

I’ll accept the slight thickness as charming rather than overengineering it.

Max #

Setting effort to max gave me the best pelican I’ve seen from any of Anthropic’s models. 65,927 output tokens, 13 minutes and 54 seconds, $3.30:

Minimalist flat illustration of a white pelican with an orange beak riding a black bicycle, its orange legs pedaling, with motion lines behind to indicate speed, on a light blue background.

There’s a lot to like about this. The background is tasteful, the legs are clearly on either side of the frame, the feet are on the pedals, the wing is on the handlebars, the pelican has a cute blue hat and there’s a basket with a fish.

It’s still not showing nearly the same level of flair as Gemini 3.7 Flash, but I didn’t ask for flair—I asked for an SVG, and that’s what I got.

Some highlights from that reasoning trace:

Adding pedal shapes near both feet, with the far foot on the second leg partially visible behind the frame. I’m considering whether to add a small scarf or cap for extra character, but leaning toward keeping it simple to avoid clutter.

Now I’m debating a bicycle helmet on the head versus the pelican’s signature crest—the beak and pouch already read clearly as “pelican,” so a helmet could reinforce the bicycle theme without losing identity, though it might compete with the crest for visual space.

I realize the beak at (484,84) would overlap with the dome helmet, so I need to shrink the helmet so it only covers the top of the head, adjusting its arc endpoints to sit higher and narrower so the beak can attach cleanly at the front without collision. [...]

I’m adding a darker tip region to represent the primary feathers, then reconsidering the trailing edge to include scalloped feather curves instead of one smooth line for a more natural look. [...]

Now I’m checking the vent line placements on the helmet, making sure they sit far enough inside the helmet’s edge given the stroke width and rounded caps, and confirming each vent stays within the helmet’s circular boundary. [...]

I decide skipping a handlebar bell and tire highlights since they’re unnecessary additions. Now I’m reconsidering the front fork’s curve — the current control point pulls the shape backward when it should bow forward for a proper rake, so I need to shift the control point rightward to fix the fork’s lean.

OK, let’s animate it #

On Hacker News, swalsh commented on that Max pelican:

Now that it’s a solved benchmark, can we get the animated version?

I didn’t want to spend another $3 so I took the Max pelican and piped it into the default thinking level of High:

llm logs -cx | llm -m claude-fable-5.1 -s 'animate this'

6,121 input, 26,201 output = $1.37. The result looked like this, exported here as video since some people have trouble viewing animated SVGs:

The wheels in the video are rotating in the wrong direction, but I think that’s an artifact of the conversion to MP4—they seem to be going in the correct direction in the original SVG.

Read the whole story
emrox
4 hours ago
reply
I love that series and to see the models evolving
Hamburg, Germany
Share this story
Delete

Effort

1 Share

Effort

And more effort.

Read the whole story
emrox
1 day ago
reply
Hamburg, Germany
Share this story
Delete

Clarity: AI writing skill and editor

1 Share

Useful

Write for one person you can picture #

A piece written by you, to a specific audience: a specific set of people, at a specific point in their lives, in a specific set of roles. It might be the engineer who's been writing software for three years and now wonders if they're keeping up well enough with AI. It might be you, back when you thought that you'd never write well enough for others to take your words seriously.

This is not hypothetical: you are, right now, writing. So consider that you are making some decisions. What's the best way to explain this stuff? What words should I use? Where should I start? Does this joke land? All these decisions become softer when you write to everyone. You know that you'll be helping someone at one end of the bell curve who needs clarity while frustrating someone at the other end who knows all that stuff already and is missing something subtler. But writing with deliberate direction helps you, and it helps your reader, see which part you need to land on.

Your whole duty as a writer is to please and satisfy yourself, and the true writer always plays to an audience of one.

Strunk & White, The Elements of Style

Know what they bring, and what they need from you #

Underlying both decisions and clarity is this: the reader has something in their head as they sit down to read. Some of it's correct, some of it's stale and outdated and needs replacing, and some of it's a misconception that you're writing to correct.

Throughout a single piece of writing you'll face two different questions: What context does the reader already have? and, crucially, What context does the reader need? The gap between those two answers defines the piece. That is to say, this is the main point where writers of technical material fail in their first draft: they go straight from the question they want to answer to the answer that they want to give, completely bypassing the reader-side question of what the reader actually knows already.

Decide what they take away #

Your piece must center around a single thing. That thing should be stated in a sentence, ideally somewhere close to the beginning. (No, even now, you feel an internal twitch that says "I should start with the bigger picture before getting down to specifics," but just stick with it.) It should be stated in a way that someone could reasonably argue with.

That is to say, the difference is between subject and claim. A subject lets you talk about the subject as fully as you can, but risks slowly drifting away from your topic. A claim invites you to argue; it demands that you persuade.

Every successful piece of nonfiction should leave the reader with one provocative thought that he or she didn't have before. Not two thoughts, or five, just one.

William Zinsser, On Writing Well

Say something only you could say #

Doesn't this apply to everyone? A check you can do on each paragraph is: could this paragraph (nearly) word for word appear in someone else's article on the same subject? If something passes this test, then it's filler, even if it's well made.

What tends to survive the test is your stuff: specific observed details, measured numbers, incidents of which you were a party, lived arguments, changed beliefs.

This is the stuff that can't be borrowed. If your piece isn't full of it, then it's sourceless. It's why writing exists at all. A draft that lacks it has a sourcing problem, not a prose problem.

Make every sentence pay #

Now, try this: each sentence should leave the reader with more than the prior one. Don't repeat the same point in different words. Don't throat-clear.

Most padding is caused not by not having enough to say, but by choosing to make a piece longer than is needed to make your point. The other source is writing that follows someone else's form expectations, such as writing an introduction that introduces nothing and writing a conclusion that concludes nothing.

So cut both causes of padding and move that beautiful, short piece in front of your reader. A short piece that lands beats a long piece that covers.

Clear

Be specific enough to be wrong #

Vague writing can't be verified, so it can't be trusted.

Try to be as specific as you can. Take a sentence like "a dependency that made us vulnerable." It has the grammar of a specific and the content of an abstraction, and it tells the reader nothing that "supply chain risk is real" did not already tell them. The obvious course of action is to name the package, to name the month, and to say how you caught it. When a writer fails to do so, they have written the abstraction with more words.

Prefer the specific to the general, the definite to the vague, the concrete to the abstract.

Strunk & White, The Elements of Style

If you can't think of a verifiable example, then delete it rather than blurring it. If you can't think of a sensible example, then don't invent one, because when you fabricate a detail, you destroy any residual trust.

Put someone in the sentence #

Give people agency. Decisions, cultures, and data don't act; people do.

Sentences like "bad things tend to happen in March" have no human actor. Find a more concrete subject. Try: "Most people find March a difficult month for things to go according to plan." Now you can see who is doing the action.

Use the second-person "you" when no specific person fits. It makes you engage the reader directly.

Use the plain word, and break the long sentence #

Prefer shorter words and sentences rather than longer ones. Short words and single-idea sentences read more easily than long words and sentences that express more than one idea.

A simple style is the result of thorough thinking. Ornate prose often indicates that the writer still doesn't have a clear picture of what they are trying to say.

Simple writing is persuasive. A good argument in five sentences will sway more people than a brilliant argument in a hundred sentences.

Scott Adams

Cut what does no work, then stop #

When editing, flag every passage that you suspect might be superfluous. Then consider whether the piece still works without it. If it does, remove it.

Over-stripping qualifiers yields inhuman prose. True writing contains a certain amount of hedging to reflect the writer's own uncertainty.

Strip qualifiers that hide a claim. Keep those that honestly represent genuine uncertainty.

Say the relation instead of implying it #

Putting two sentences next to each other can create a sense of logical connection between them based only on rhythm. "The benchmark is saturated. The model still fails in production." Is the second sentence the cause of the first, or the consequence? The rhythm implies an answer, and while you are reading it feels like reasoning.

Try to supply the word: because, although, once, where, so that. If you cannot supply it without inventing the relation, then the relation was never there.

Although the benchmark is saturated, the model still fails in production, which means the benchmark has stopped measuring what ships. Adding an explicit connector, such as although, as we did here, turns a mere juxtaposition into a real claim.

Yours

Take a position, and say where it is weak #

Presenting both sides without taking a position isn't balanced. It feels empty, and readers know you are evading.

State your leaning and say what makes you uneasy. Give the strongest real objection its own paragraph near the end. Answer or concede it. Conceding costs you nothing and gains you respect.

The objection has to be one that someone actually holds. Fabricating a weak opponent is as dishonest as inventing a statistic, and readers detect it quickly.

Write the way you would say it #

Read a sentence aloud. If you would not say it to a colleague over lunch, you should not publish it.

This is why contractions, sentence-initial "but," and the first person are appropriate: writing is a transaction between two people, and hiding one of those people discards half the power.

Never say anything in writing that you wouldn't comfortably say in conversation.

William Zinsser, On Writing Well

Do not perform #

Avoid fake erudition or humility, or a voice that sounds rough or as if it were studied.

Making it

Give the first sentence its one job #

Make the reader want to hear the second sentence of the piece.

Effective openings are often a startling fact, a scene-setting description, a number, a provocative claim, or a leading question. A definition of the topic or an explanation of your intent will not work.

Make each paragraph earn the next #

Each paragraph should answer the question the previous one raised or raise the question the next one will answer.

Test your progress by covering the page and seeing if you can predict what will follow. If your headings are doing all the work of organizing your ideas, your writing is merely a list of items that might be arranged in a table of contents.

Stop where the thought stops #

When the point is made, stop.

Bad endings usually result from the writer's summarizing a litany of traps, pitfalls, and opportunities or from his or her offering the quotable line. A good ending often returns to a concrete item or circumstance from the story, states what will carry over, and stops. You may feel that it is abrupt and unfinished, but that is better than vague optimism.

Rewrite by cutting and reordering #

Rewriting always means that you have moved the third paragraph to the top, deleted the proudest section of the first version, and found the true sentence buried inside the one you wrote.

Smoothing is not rewriting. Smoothing turns a rough authentic sentence into a bland one and polishes away the only interesting thing in your draft.

Rewriting is the essence of writing well: it's where the game is won or lost.

William Zinsser, On Writing Well

Read it aloud #

Reread every time before sending.

Your ear catches what a checklist misses: plodding paragraphs, breathless clauses, repetitive sentence shapes; where reading stumbles, the sentence is wrong.

Read the whole story
emrox
1 day ago
reply
Hamburg, Germany
Share this story
Delete

Tailcat: Tailscale without Tailscale, by Tailscale

1 Share

Today we’re releasing tailcat, a remix of pieces of Tailscale that gives you a way to use the open-source Tailscale data plane (WireGuard® + NAT traversal + DERP) without the Tailscale control plane, written by the people who made Tailscale. It’s Tailscale without Tailscale, by Tailscale.

Specifically, tailcat is both an open-source Go package and a CLI tool using that package. It lets you run a server-side listener and a client to connect to that server, moving bidirectional bytes back and forth.

That is, it’s like netcat but flowing over Tailscale’s magicsock (WireGuard encryption + NAT traversal + DERP rendezvous/fallback relay).

Notably, tailcat has:

  • no IP addresses
  • no accounts (no logins, no passwords, no SSO)
  • no control plane
  • no users
  • no admins
  • no administrative controls
  • no root or admin OS access requirement
  • no relationship with or dependence on Tailscale as a company (if you run your own cmd/derper DERP server, at least)

What does “Tailscale” even mean?

When you watch people describe Tailscale to each other online, you see very different interpretations of what “Tailscale” means to them.

One group of people, often seen saying things like “I’ll just run WireGuard myself,” focuses on the WireGuard part and doesn't consider (or care about) parts like NAT traversal, DERP fallbacks, centrally managed firewall (ACL) rules, SSO login, tagging, MDM policies, audit logging, etc. Maybe they only want or need the WireGuard part on a public IP. That’s fine.

Another group of people talks more about the company, corporate structure, long-term viability, founders, funding stage, pricing, certifications, reliability, responsible handling of security disclosures, etc.

Another group of people talk about whether Tailscale is open source or not. As a reminder: our core is open source (with a real OSI-approved license!), our DERP server is open source, and our clients are open source on platforms that are themselves open source: Linux and Android. Our server-side control plane is not. A lot of people in this audience appreciate that Headscale (which we love and partially fund development of) exists, either to use today, or use in the future, as a fallback plan.

All of those interpretations are fine. Whether you’re using our official GUI client wrappers around our official control plane, with a corporate SSO identity provider, or you’re at the other extreme, using only tsnet on Linux nodes against your self-hosted Headscale server, there are many ways to wire up and use Tailscale and its many pieces:

  • Its WireGuard + NAT traversal + DERP fallback data plane
  • Its control plane
  • Its company (paying us to run and support things for you)
  • Its open source code

tailcat gives you another way to use a subset of Tailscale.

How it works

Let’s say you want to run a tailcat server. Here’s what it does:

  • generates a keypair (either ephemeral or named & reused)
  • picks a DERP server (either one you specify, or an auto-selected bandwidth-limited Tailscale-run one)
  • generates a tailcat address, which is a string of the form: tc + base64(CBOR( public key + DERP bootstrap info ))
  • you then share that address string with somebody out of band, either directly, or by putting it in a DNS TXT record, and sharing that DNS hostname out of band

The client side is about the same:

  • pick a key (ephemeral or locally named & reused)
  • connect to the rendezvous DERP server specified in the tailcat address
  • send a MEOW message to the server’s public key over DERP to add yourself to the netmap

At that point, if the server is cool with that client’s public key (it can be optionally locked down), then it replies with a happy MEOW reply.

The client then proceeds to make a TCP connection to the other side using an embedded userspace TCP stack atop WireGuard. There are actual IP addresses on the wire (IPv6 ones derived from your public key), but they’re never visible to users. Your operating system is never involved at the TCP layer and never sees the synthetic tailcat IPs. All your operating system does is send the DERP TCP messages and/or NAT-punched UDP WireGuard messages.

Two terminal windows. On top, Brad's sandbox runs a tailcat listener, piping the output to a tar command to extract any incoming content. The output shows a tailcat listener responding with a tailcat address and bootstrapped from a New York City relay server, and the directory llms and the files CODEX.md and CLAUDE.md being unrolled. The terminal at the bottom shows Kabir's macbook compressing the local llms directory with the tar command and sending the resulting content over a tailcat pipe using Brad's tailcat address.

Because it goes over Tailscale’s magicsock data plane, NAT traversal automatically kicks in and tries to get a direct connection, so data transfer (WireGuard UDP packets) ends up going directly between the client and server, without a DERP relay involved. But if both sides are behind a hard NAT without any port mapping services available, the data packets are relayed over DERP as a fallback. If you use Tailscale-hosted DERP servers, those are rate-limited (bandwidth costs us money). But if you run your own DERP server, you can control any rate limiting.

In the default mode where you don’t specify a port number on the tailcat server, the default is to just pipe the received data to the server’s stdout, like netcat. But it can also run in a client mode, where it runs a SOCKS server on an ephemeral local port and then runs a provided child process (e.g. curl or whatever) with an environment variable set to use said SOCKS server, letting tailcat-oblivious programs use tailcat transparently. (tailcat is currently always userspace-only, never reconfiguring your system’s networking stack … no TUN devices, no routing table changes, etc.)

Why?

I wrote tailcat in September 2023 on a long ten-hour flight while catching up on bad movies. At the time, tailcat was mostly a fun novelty. I presented it internally, and I’d use it occasionally myself, but I mostly forgot about it. But then a number of customers approached us with use cases where it was a perfect fit, so we gave them copies of it, with arrangements where we’d host the DERP fallback relays for them in cases where tailcat’s use of Tailscale’s magicsock fails to get a direct connection.

Fast-forward to a few months ago, when all this AI agentic coding stuff was in full swing. It’s been really powerful to just give my sandboxed AI agents access to make their own also-untrusted nested VMs and give them tailcat. With access to exotic hardware in faraway places, I let the AI go wild wiring things up to each other and running experiments. Off the top of my head, I can recall:

  • giving an agent access to a fleet of every Raspberry Pi generation
  • giving an agent access to a sandboxed EC2 instance that had ambient access to control a nearby EC2 instance and kexec reboot it repeatedly, while porting Tailscale to run in EC2’s UEFI environment, including porting the Amazon Nitro ENA network driver to pure Go (under Tamago)
  • giving an agent access to a Windows host to repeatedly create and destroy Hyper-V VMs to debug and fix a stack corruption bug in the Go runtime and standard library

In most of these cases, I probably technically could’ve just used Tailscale proper, but it would’ve been more tedious to the point that I probably wouldn’t have even done it, and would’ve just set up a few port forwards instead, or opened up some ports on a firewall somewhere. I find that tailcat is often the perfect tool when I already have two shells open on two machines in two very different worlds and I just want to connect the two together, for a quick file copy, or port forward, or letting one SSH to the other. Especially when one side is untrusted or ephemeral or I’m afraid to touch its system configuration.

When we launched Taildrop in 2021, one of the first requests was for netcat-like sharing between nodes. tailcat now provides that, and more. We’d still like to do something tailcat-like in the main Tailscale client too, but we’ll have to figure out how that fits into the rest of the Tailscale product.

Another reason to open source tailcat is that it’s kinda obvious and inevitable. We’d selfishly rather people be using, improving, and filing bugs against our data plane, which then makes the rest of the Tailscale product better.

I would be remiss if I didn’t mention that you should contact us if you have fun use cases where tailcat might help you, and where we can help you integrate tailcat or run a global fleet of DERP relays for you. (e.g. IoT, P2P games, distributed GPUs, etc.)

The DERP server fleet we’re running for tailcat is throttled and only available in a handful of regions around the world. The idea is that, most of the time, our magicsock NAT traversal will do its thing and DERP isn’t relevant, with tailcat getting a direct UDP WireGuard connection between the two peers. But in cases where that fails, we’d be happy to exchange money for goods and services.

Or, hey, run your own DERP fleet or single server. It’s open source too.

Enjoy!

We look forward to seeing what you build and how you use this. Give tailcat a spin here.

Read the whole story
emrox
1 day ago
reply
Hamburg, Germany
Share this story
Delete

How To make your own kick drums in Diva

1 Comment

With so many kick drum samples available, it’s easy to overlook the benefits of programming your own. It only takes seconds.

Kick drums, eh? You can’t live with ‘em, but you can’t live without programming ‘em. Except, of course, you can – there are bloody millions of kick samples to choose from! So why bother programming your own? Three reasons, really.

  • 1. It’s a great way to really tailor your kick to your track.
  • 2. It helps your productions stand out.
  • 3. It’s good for the soul to go beyond presets and make your own sounds.
  • And… er…. 4. It’s too easy not to give it a go.

STEP 1

First thing’s first: the meaty bit of pretty much every electronic kick you’ve ever used is based on applying a pitch envelope to a simple oscillator like a triangle or sine wave. That’s how the 808 did it. That’s how the 909 did it. And that’s how we’ll do it. So start by loading Diva and selecting an INIT patch.

STEP 2

Now let’s configure Diva’s modules. Choose DUAL VCO (oscillators), HPF PRE (high pass filter), MULTIMODE (low pass), and Analogue (both envelopes). Then program a four-four kick pattern on F#1. And let’s use a short 1/16th length as that allows plenty of length control later.

STEP 3

DCO settings next. Start with Osc1 to triangle (the 909-style layer) and Osc2 to sine (808 vibes). Then set Tune MOD mode to BOTH, to make sure the pitch envelope applies to both. And apply SYNC so both trigger together without intermittent phase cancellation between them.

STEP 4

Now let’s turn it into a kick drum. First set the Tune MOD Env to fully +. Envelope 2 is now controlling the oscillator pitch so start by setting Sustain and Release to 0. See how you can hear the pitch coming down quickly already? Now slowly pull the Decay down to 32… and there’s our kick drum!

STEP 5

Let’s look at the different ways of tailoring our kick next, starting with the amp envelope. First bring Sustain down to zero and then try raising Release from 20 to 50. Release is the key length control for our kick. But, as you can hear, it’s also central to the tonality of the kick, ranging from tight 909-style to tonal hardcore techno.

STEP 6

The filter section is the key to adding some of that distinctive 909 kick click we all know and love. Set the lowpass Env2 amount to fully + and then start lowering the cutoff down to around 34. Now we’ve got a click. We can also try flicking the Mix between Osc1 and Osc2 to hear the difference. Osc1 is that tight, clicky 909, Osc2 is the more tonal, saturated-sounding 808 style.

Filtered

Filtered Osc1

Filtered Osc2

STEP 7

Finally, try tweaking the Fine Tune to adjust the tuning of the kick. And you can also experiment with different MIDI trigger note values and lengths, but that will only really make a lot of difference on kicks with longer release times for more tonality. This can be fun for edits, as you can hear below.

Fine-tune up

Fine-tune down

Pitch edit 1

Pitch edit 2

BONUS TIP 1

You can use these kicks as a powerful sub bassline tool by layering them with another kick sample… and then raising the amplitude envelope a tiny bit. That way you have the huge bassline power of a long kick but without overloading the transient section or taking away from your chosen kick sample. But there’s a snag. Have a listen…

BONUS TIP 2

 As you can hear, the sound of each synth kick varies a little from the previous because their long decay tails are causing interactions with the following ones. To avoid this, render out your Diva kick and simply loop the audio over the ¼ bar section you like the sound of. Listen to how much more effective that is now…

BONUS TIP 3

As we just saw, analogue synth-style kicks like this do have a tendency to have minor little variations (more or less click or slight timing / phase variations. This is the nature of analogue emulation, and can sound great in organic electronic music, but for tight, club bangers it’s often worth sampling out a single kick you’re happy with and using that for every beat instead.

So there it is - a fully customisable kick with a blend of classic 808 and 909 vibes. We’ve made it in a bog-standard subtractive synth configuration in Diva, to show how easy it is, but imagine how much more detailed, individual control and processing you can get over the two oscillators with a modular or semi-modular option like Zebra 3! And don’t forget, these are all dry and unprocessed. Be sure to fire up your compressor and EQ to sharpen them up in the mix.

Find out more about Diva on the u-he website, including the free trial.

[social-links heading="Follow Attack Magazine" facebook="https://www.facebook.com/attackmag" twitter="https://twitter.com/attackmag1" instagram="https://www.instagram.com/attackmag/" youtube="https://www.youtube.com/user/attackmag" soundcloud="https://soundcloud.com/attackmag" tiktok="https://www.tiktok.com/@attackmagazine"] [product-collection]

Read the whole story
emrox
8 days ago
reply
For the time when I actually find time to enjoy making music again
Hamburg, Germany
Share this story
Delete

Everything I own, owned

2 Shares

Over the past couple weeks I’ve been doing agent-driven reverse engineering of peripherals that happen to be within arm’s reach. From those devices, I’ve come away with a full plaintext command shell inside my microphone, a webcam whose activity LED I can switch off while it records, and a key light that hands out memory writes to anyone on the WiFi. Peripherals have proven to be an ideal target for agentic RE - they’re tiny computers attached to my computer, with a data connection to the host and usually a firmware update mechanism, so an agent has something to iterate against. The net outcome is better control and understanding of my machine.

My process was pretty much the same for each of these devices: grab a copy of the device’s firmware and associated update tool from the manufacturer, throw it into my reverse engineering environment, tell Claude Opus 5 what my goals are, and let it churn. Depending on the device, the goals were somewhat different, but they usually looked something like:

In this directory is the firmware and update utility for ___. The device is also attached to this computer, and you may interact with it in non-mutating ways. Exhaustively document and cross-validate the entire firmware, including the following goals:

* reverse engineer the firmware update format and update protocol
* implement our own update utility
* determine the security properties of the update protocol, including checksums, signature validation, secure boot
* use static and dynamic analysis to determine all protocol surfaces and completely enumerate functionality
* find any hidden or debug functionality in the product and how to access it

Depending on the results, there were different directions of follow-up, but you should get the general idea. Let’s run through the list - each device links to a GitHub repo full of generated-slop docs and scripts, most of which have been validated live against real hardware. I’ve also included the effort each device took, pulled out of the Claude Code session transcripts. “Churn” is the time Claude was actually working, with the long idle gaps removed. “Prompts from me” is every message I typed, including the one-word ones telling it to keep going. All five devices together came out to about 13 hours of churn and 98 prompts, spread across two weeks of evenings.

Everything I own

GitHub repo - 3.7 hours of Claude churn, 33 prompts from me

Insta360 Link webcam, its green activity LED lit

I use an Insta360 Link webcam, which is a nice gimbaled pan-tilt-zoom camera that does face tracking for automatically framing the shot. I wanted to know if it was possible to subvert the activity LED, like in the classic iSeeYou exploit.

Interestingly, it was immediately obvious that this camera has a lot going on inside it. It turns out that it runs a whole RTOS (ThreadX) sourced from the upstream SoC vendor, Ambarella. The RTOS hosts several small vision models that provide things like the aforementioned face tracking, as well as gesture detection for controlling settings. Pretty amazing complexity inside a tiny webcam, but it also means there’s some exciting attack surface here.

Over the USB Video Class interface, there’s an XU (Extension Unit) command that kicks the device into “mass storage” mode. This then lets us transfer a staged firmware update to the device’s internal FAT filesystem, which the device then applies to itself on reboot. This route does require user intervention to reboot with a replug, but there’s actually another command channel that exposes arbitrary read/write of files and a reboot command over the USB vendor class. With this, we can fully flash the device without any user interaction. Once the firmware is in the right place, there’s effectively no anti-tamper, just an appended MD5 hash to ensure integrity.

The indicator LED turns out to have a well-structured set of “patterns” in the firmware that dictate color, blink pattern, etc. that are indexed into for various device states. I had Claude write a tool to patch out the table entry for camera activity, fix up the integrity hash, and flash it to the camera. A quick test showed that the green LED that normally illuminates while recording no longer turned on. Horrifying! On this device, the gimbal itself also deflects down when not recording, so it’s not completely stealth, but it still doesn’t feel great.

The LED behavior before and after patching.

ASUS ROG Swift PG42UQ monitor

GitHub repo - 1.2 hours of Claude churn, 13 prompts from me

ASUS ROG Swift PG42UQ monitor

My ASUS ROG Swift PG42UQ monitor was actually where I started, because I got annoyed at the pop-up overlay that comes up every once in a while that tells me to run “pixel cleaning”. I have never intentionally run pixel cleaning on this monitor and I never will, I don’t care, and I would like for that overlay to go away forever. Maybe there’s a debug menu or something that can turn it off, or worst case we patch a branch in the firmware?

Claude found that the firmware has effectively no protection whatsoever - there’s a two-slot A/B scheme and a simple checksum, but ultimately we can write whatever we want to the thing. Firmware updates run over an I2C bus bridged over USB.

The pixel cleaning warning turns out to have no native way to disable it, and it’ll always show up after 8 hours of runtime. Oh well. Claude did find the appropriate area to patch to kill the functionality though. I haven’t actually been brave enough to write a modified firmware to the thing yet - it’s a pretty expensive monitor - but I’ll get there at some point.

Another neat thing was exploring the DDC/CI interface. This is the control channel available over the display cable itself, allowing the host to change inputs and other settings. I believe ASUS offers this through their Windows utility, DisplayWidget, but that does little for me on Linux. So, now I have a shell script that can flip through some of the DDC/CI features like the hardware crosshair or zoom overlays, FPS counter, and countdown timer. I might set up some of these on hotkeys in the future for easy access.

Shure MV7 microphone

GitHub repo - 4.2 hours of Claude churn, 32 prompts from me

Shure MV7 microphone

At this point, there’s less actual incentive to keep popping these devices and more just morbid curiosity. My microphone, the Shure MV7, connects over USB and obviously has some amount of smarts to it, with on-device digital volume controls and such.

The firmware for this one turned out to be hidden inside the Windows software, MOTIV Mix, so Claude installed that in Wine, found the update server, and pulled it down. I wasn’t on the latest, so there was actually a reasonable incentive here to get this working just to update my microphone from Linux. The firmware turned out to contain both DSP and MCU firmware, and was honestly pretty boring as you might expect. Again, no real security on the firmware flash itself.

However, the update protocol revealed that the entire thing actually runs over a USB HID vendor class protocol that implements a full plaintext command shell, with 48 different commands. Since it’s HID, we can actually hit this over WebHID from a webpage in Chrome, so I had Claude build a web interface for using the shell. There’s all sorts of interesting settings in here including a dozen DSP knobs, arbitrary memory read/write, LED control, and a 4-tier user privilege system whose entire authentication is a string comparison against the name of the tier you asked for. su sup just works, and the top tier can disable the touch panel so you can’t mute at the device, and drive the mute LED independently of whether the microphone is actually muted. It’s the webcam LED trick again, on a microphone. Obviously, be aware that you could probably break your device if you use that UI and do something stupid with it.

WebHID interface for the MV7’s command shell, showing DSP settings and a console The WebHID shell interface. The DSP knobs on the left are the device’s own settings; the console on the right is the plaintext command shell talking over HID.

GitHub repo - 1.5 hours of Claude churn, 10 prompts from me

Elgato Cam Link 4K video capture dongle

The Elgato Cam Link 4K is just an HDMI video capture device, and honestly was just more of the same. The interesting thing for this one was that I let it go fully unattended - I literally kicked off the process before going to sleep and woke up to a teardown and functioning firmware updater. The firmware contains an MCU image and an FPGA bitstream for the actual HDMI handling, so you could potentially do something fun with the FPGA if you went deep enough into the reverse engineering there. There’s no protection on the firmware update path.

I was able to pull out all the EDID information used for negotiating video parameters, so we know exactly what resolutions, refresh rates, color spaces, and chroma subsampling options are offered to devices.

The vendor HID protocol does include tunneled access to the internal I2C bus, which is kinda neat as you can poke the internal HDMI receiver registers.

Elgato Key Light Mini

GitHub repo - 2.4 hours of Claude churn, 10 prompts from me

Elgato Key Light Mini

Finally, I poked at something that wasn’t connected over USB but WiFi instead, the Elgato Key Light Mini. This one turned out to be way more interesting than I expected: it’s the only one with meaningful firmware integrity protection. Elgato signs the firmware updates with Ed25519 over a SHA-512 hash of the firmware payload, and rejects firmware that doesn’t validate. This makes sense to do, as the device basically connects to a WiFi network and then provides unauthenticated access to anyone on the same network, so the threat model is inherently different.

Unfortunately, while that’s an improvement over all of the other devices we’ve looked at, it protects the firmware at exactly one point in time: when an update is happening. It’s not a boot time check enforced by the bootloader or any other kind of secure boot scheme, and the updater happens to be running while everything else in the device is still operating, meaning there’s huge attack surface to try to disable that signature validation. I asked Claude to look for an exploit that might enable this, and it found a doozy: an HTTP POST request that drops a payload straight into the internal UART, which includes a memory poke command. This means that a single HTTP POST of ATSE=0200ED94,0E001009 turns the signature check into a no-op, and we can freely update to a firmware image without a legitimate signature. I successfully tested this with a simple patch that changed the name of the device, so uh, yeah, don’t put these on an untrusted network.

…, owned

I have a lot of feelings about this whole thing. As I wrote back in March, this is incredible for interoperability and fixing things that don’t work how we want them to. Hardware is almost universally “open” for tinkering at this point with just a couple hours of mostly hands-off machine-driven labor each, and I look forward to a near future where I can add features to my webcam firmware as easily as I can to software that runs on my Linux machine itself.

On the other hand, as a security professional, this scares me for several reasons. I would work from the operating assumption that any device attached to a computer could have had a malicious firmware implant performed, where previously that required significant per-model investment and was stereotyped as a “state actor” kind of activity. Operating systems aren’t really equipped to work with the user to ensure that a microphone stays a microphone, and doesn’t spontaneously turn into a keyboard that hits Win+R and drops a payload to steal all your data when the room is quiet enough that it can assume you aren’t watching. And the existence of WebUSB, WebHID, and WebBluetooth mean that for some devices, depending on the specifics of which classes are used, a moment of user indiscretion in accepting a permissions prompt could permanently backdoor one of their attached devices.

Network-connected devices seem near universally fucked at this point? There are a few others I’ve poked at that I haven’t documented here, but I’ve gotten a root shell on a commercial Dell display, and RCE on an Eaton UPS. Obviously it was never best practice to let untrusted clients touch these things, but the speed and scale at which this can be executed makes the risk so much higher now.

Finally, I can’t help but think about what an AI-equipped automatically-reverse-engineering worm could do today. It’s only a tiny leap to imagine that someone could make a self-replicating piece of malware that probes its environment, relaying reconnaissance back to a smart command-and-control that actively works to push itself into accessories and IoT devices and industrial equipment found adjacent to an infected target. Two things have kept this from happening: every device model needs its own reverse engineering, and validating any of it needs the hardware in hand. The first is the labor I just handed to an agent. The second is free to malware already sitting on an infected host. Honestly, I wouldn’t be surprised if this already exists, and I think the next few years are going to be extremely interesting. 🫠

Read the whole story
emrox
9 days ago
reply
Hamburg, Germany
Share this story
Delete
Next Page of Stories