Recover A Private Key From Process Memory
Thomas Ptacek | January 25th, 2006 | Filed Under: Reversing
Or, “Doing Things The Hard Way, And Cheating At It Anyways”.
Scene setting: I’m a SPAN session watching traffic between an IDS sensor (S) and the management application (M) that polls it over a proprietary protocol. Can the sensor be attacked? We reconstruct the protocol off the wire:
M -> S: NEW-SESSION PUBKEY: RSA:afbfdfc83fc3fc3g378gcfcg78 ... fcg7g S -> M: SESSION-KEY: 0ce62ea2b046c167d7962257905ca2bd ... 8b676a87b M -> S: 7f0f4450425db53fa4181c ... 0f0d8235e2c6471c0896ae0405ac2cfc M -> S: f846ec56b94bf9f5aff554c1696ef4c4e9 ... c45c81845cc10ca43ab6
… and so on.
In other words:
- M sends S her public key
- S replies to M with a session key, likely random, probably encrypted with the public key
- S and M now share a key, and subsequent messages in the protocol are encrypted.
There’s an obvious problem with this protocol: it’s secure only if you trust TCP, and if you do, you might as well not encrypt. But I’m a SPAN listener, without a non-disruptive way of getting in between the participants.
My crap-dar sensors are screaming. They’re not using SSL/TLS! They invented their own broken protocol! The case against this system is open and shut —- the only thing missing is something to charge it with.
I’ve got access to the management server; I’ll RDP in and waste an hour or two trawling the filesystem looking for the private key. It’s not in the registry, a la CryptoAPI. It’s not in any standard keystore file I can find. The problem begins looking suspiciously like a nail, and out comes IDA Pro.
$*&(!. It’s C++, stripped clean, everything triple-indirected. Gotta be a better way.
“Want help?” asks my friend Ex-PFC Wintergreen. “Getting a private key out of memory? That’s easy. Try looking for the PKCS identifiers.”
10 standards documents later: the “PKCS identifiers” are the DER-encoded ASN.1 values attached to a PKCS#8 private key. Oh, sorry, yeah, me too —- here’s decoder ring:
- PKCS: The RSA standards —- think “crypto RFC”.
- PKCS8: The “private key” RFC.
- DER: says the number “0” is really 0x0201000 (type, length, value).
- ASN.1: a language like XML, except that instead of data interchange, its goal is to amplify the pain of dealing with DER. The reason your SNMP agent still has stack overflows in 2006.
A PKCS#8 RSA private key is (with likely defaults)
SEQUENCE INT version (0) OID algorithm (.1.2.840.113549.1.1.1, ie, RSA) [0] attributes (NULL) OCTET STRING key
Everything in ASN.1/BER/DER is “tagged” —- prefixed with bytes that identify its type. SEQUENCE has tag 0x30. INT is 0x02. OID is 0x06.
We start by getting some data to search for. Attach to the manager with Ollydbg. Click ‘M’ for the Memory Map. Right-click, “search”. Enter a few bytes of the RSA key from the captured protocol message (dehexified). Paydirt: there’s a segment with the whole public key in it. Right-click, “backup”, “save to file”. Copy it over to the Mac.
133 lines of C code later and I bring you: roid rage! (and blackbag 0.5): sweep a file looking for BER/DER-encoded ASN.1 OIDs. Try to greedily print valid BER following the OID (buggy, broken), and print the leading and trailing 128 bytes of context (works just fine).
Filter to OIDs starting with .1.2 —- no false positives, 5 hits of .1.2.840.113549.1.1.1. Open up HexEdit (I love you HexEdit), jump to the first offset I found. Find:
- The OID (06 09 2a 86 48 86 f7 0d 01 01 01)
- NULL (05 00)
- An OCTET STRING (04 [length])
Cut and paste [length] bytes out of the OCTET STRING. Write to a file. “openssl rsa -in [file] -text”:
Private-Key: (512 bit) modulus: 00:a1:23:01:33:21:50:7a:3f:6e:19:76:b6:39:92: d5:5d:43:a3:6c:fd:ef:7e:f5:8e:5f:18:5f:13:58: 52:26:52:6c:f3:92:d5:14:18:f9:e9:5c:b5:ae:b2: 74:2b:7e:44:9b:c6:91:74:a5:21:08:43:61:d7:e3: 8b:76:b8:84:7f publicExponent: 65537 (0x10001) ...
The key length looks like an RSA key length! The exponent looks like a valid exponent! The primes actually test prime! The snozzberries taste like snozzberries! The rest of this post is left as an exercise for the reader!
(Incidentally: blackbag 0.5 also adds “unify” and “deunify”, which convert Unicode to ASCII-with-HTML-entities and back in a shell pipeline).


Erin Ptacek
January 25th, 2006 10:09 amThis post has been removed by the author.
Erin Ptacek
January 25th, 2006 10:10 amThe links to the blackbag bundle are broken, darling.
Leave a reply