DRM Secrets Revealed At Nate Lawson’s Blog
Thomas Ptacek | March 24th, 2007 | Filed Under: Uncategorized
Nate Lawson (blog rated: M for Mandatory) continues his series on software protection —- DRM, copy protection, and client security.
Yesterday he gave a capsule summary of “Media Binding”, the techniques used to make sure content delivered on a plastic disk is always read off that same plastic disk using a real plastic disk reader. He breaks this down into “verification” (ie, using timing quirks to detect emulated or modified readers), “encoding” (ie, using nonstandard plastic disk formats that off-the-shelf readers can’t handle), and “attack” (ie, injecting metadata into the format the blows up off-the-shelf reader software).
Today he’s moved on to “Protection Code”. The challenge with writing code that tries to protect itself is that almost any intuitive code will devolve to a few critical “if” statements:
if(everything-ok)
go-on
else
a-splode
The problem with “critical if statements” is that an attacker can alter them with a single byte, for instance by changing a JZ opcode to a JNZ. It is one of the really satisfying things about software cracking, which many people learn in high school, to locate the one or two bytes in a whole program image that you need to change to totally negate a protection scheme.
Nate outlines two strategies for defenders here:
Obfuscation: change the program image so that it implements the same core logic using an expanded, permuted, convoluted equivalent sequence of instructions. You have two closely related aims: make the logic extremely expensive to unravel, and defeat any off-the-shelf tools (or even algorithms) the attacker might be relying on.
Encryption: completely conceal program logic (or, better yet, the data the program relies on —- ie, the underlying assets) using an encryption algorithm.
Other blogs have covered attacks on IDA Pro. Nate mentions a few more techniques. I’ll add: the 80% solution here is to defeat cross-referencing, the disassembler feature that tells us which functions are used by which other functions. Even without symbols, a list of functions and their cross references is an strong foothold; take that away and now I have to actually read all those functions. You can beat IDA cross referencing without modifying your compiler output.
Nate’s encryption stuff is really cool. The problem with encrypting code or data is, you gotta store the key somewhere. Any place you can get the key, the attacker can get it, too. The attacker doesn’t even need to read code; she just scans memory for randomized key-sized blocks.

What you do here is called white-box encryption. The idea is straightforward. Instead of taking a standard AES implementation and feeding it your data and a key, you embed the key directly into the AES code. In the process, you introduce a huge amount of noise, abetted by a custom encoding scheme.

Your AES code used to look like this:
plaintext = aes(ciphertext, key)
But now it looks like this:
encoded-plaintext = aes+key+noise(encoded-ciphertext)
Think of the embedding of the key into the algorithm the same way you would a SecurID token, which is itself an AES key and implementation embedded in a piece of hardware. That’s called “specializing” the AES implementation on the key.
White-box schemes don’t just embed the key; they do so in a way that makes the resulting algorithm hard to analyze, essentially by injecting key-dependent noise (bijections —- random lookup tables) into the AES rounds. This makes the resulting code bigger, much slower, and much, much harder to analyze; ostensibly, way outside the boundaries of what the XBox hackers or DeCSS people are going to attempt.
The scary thing about Nate is that he has all the details behind all of this, and I suggest we start poking him to fill us in.


Ryan Russell
March 24th, 2007 3:56 amOnce again, you have failed to document the tool(s) used to create your pretty pictures.
Thomas Ptacek
March 24th, 2007 11:31 amDIN Neuzeit (the Matasano typeface), boxes with 2px stroke and 2px rounded corners, and the Apple “crayon” color selector with varied saturation and value.
Ugo Enyioha
March 31st, 2007 7:25 amSounds like an interesting approach. Although, I wonder how re-keying the “specialized” AES implementation would work in systems that ideally perform strict re-keying after specified amounts of data have been encrypted under a key.
Thomas Ptacek
March 31st, 2007 1:29 pmYou wouldn’t use white-box AES in that situation; re-keying a white-box AES implementation is a bit like re-keying a SecurID token.
Leave a reply