Research pertaining to Games for Windows Live (GFWL) xlive.dll.
This tool is a standalone C++ program that implements the major cryptographic functionality of xlive.dll. It does not require xlive.dll.
Features include:
- PanoramaCryptoCBC
- g_pcbcObfuscation
- g_pcbcSystemLink
- g_pcbcXLiveDRM
- g_pcbcXLiveUserData
- XeKeysObfuscate
- XeKeysUnObfuscate
- XLiveProtectData
- XLiveUnprotectData
If you just want the AES keys, then the aes.cpp file is what you're looking for.
The ImHex patterns are for the on-disk format of XeKeysObfuscate/XeKeysUnObfuscate and XLiveProtectData/XLiveUnprotectData data. "Debug" refers to the development dlls which have all the crypto stripped and "Release" refers to the normal dlls.
The ScyllaHide config should keep the anti-debug off your back. The patch file for xlive 3.5.95.0 neutralizes the PEVerifyHash check (the famous 8B FF 55 8B EC 83 EC 20 53 56 57 8D 45 E0 33 F6 50 FF 75 0C 8B F9 signature) which should let you put breakpoints in more places without getting killed. There are countless other checks for IAT, single step exceptions, etc..., but this gets you 99% of the way there. And a lot of that other stuff gets patched at runtime by WARBIRD so it's harder to nop out like this. You'll also want exceptions set to Break On: Second Chance, Logging: Log exception, Exception handled by: Debuggee, since xlive uses SEH to catch divisions by zero and access violations it causes on purpose.
The scripts are mostly scraps from when I was testing stuff while writing xwife. They shouldn't be too useful on their own but I've included them anyway in case someone finds them useful. The dll emulation script is for the peacestoned xlive 1.2.241.0 (more info in the next section, use my fork). The frida agents are for xlive 3.5.95.0 and assume ScyllaHide is already doing its job (more info in the previous section).
Microsoft WARBIRD is a code obfuscator used on xlive. The older versions aren't the worst thing in the world and several tools exist to deobfuscate the protected code: peacestone and warturd. I haven't looked at the newer versions at all, but I can't imagine it's too much of a step up. I chose to modify peacestone (with help from WitherOrNot and cross referencing warturd) to work better on xlive 1.2.241.0. Since Microsoft can't change the crypto or file formats without breaking everyone's stuff we're lucky that we can reverse engineer the old dlls and it will "just work" with the new dlls. No need to deal with newer WARBIRD versions!
For some reason Microsoft decided that they wanted to protect XLiveProtectData and XLiveUnprotectData with Syncrosoft MCFACT. Nothing else in the dll uses this from what I can tell. It's really annoying. A few comments across hacker news and reddit have mentioned it (1, 2, 3), but I couldn't find much beyond that, I guess it wasn't that popular. I'd never heard of it before.
This Syncrosoft MCFACT PowerPoint from the Re-trust Sixth Quarterly Meeting (March 11, 2008) is the holy grail. It details how it works and shows code snippets. Unfortunately MCFACT is pretty good and I believe them when they say it can't be decomposed. So I just yanked the lookup tables and driver code out of the dll wholesale.
A lot of the sensitive internal functions take byte array arguments in the form of a protected/secure buffer. Types like SB_PTR<unsigned char> (secure buffer pointer), __SecureBufferHandleStruct *, and CSBPseudoPtr (C small buffer pseudo pointer) are frequently seen around this code. The general idea is to make it harder to find/peek/poke the contents of these arrays in memory, shocker.
In XLiveInitialize a number derived from the tick count is stored on the heap and remains constant until it is deallocated in XLiveUninitialize. __SecureBufferHandleStruct * is a pointer to a CSBPseudoPtr that has had the constant added to it. It is then subtracted every time it is accessed. CSBPseudoPtr has a mechanism to, instead of storing the array value directly, store two arrays with values that XOR together to make the original array value. This means that all accesses to these arrays have to flow through functions like SBufferGetByte and SBufferSetByte.
This is the mechanism behind XLIVE_PROTECTED_BUFFER (which is just a type erased __SecureBufferHandleStruct *) and the associated exports: XLivePBufferAllocate, XLivePBufferFree, XLivePBufferGetByte, XLivePBufferSetByte, XLivePBufferGetDWORD, XLivePBufferSetDWORD, XLivePBufferGetByteArray, and XLivePBufferSetByteArray.
The AES block cypher code is a "whitebox" implementation, if you even want to call it that. They just bake the primitives and round keys into lookup tables instead of doing it procedurally. Since the AES functions all use the secure buffer construct it is trivial to hook the get/set functions and trace the whole data flow. It only takes at most 3 of these traces to pin every round key.
This whitebox isn't MCFACT, it's their own thing. I don't know why they decided to do their own thing when MCFACT advertises a comprehensive cryptography toolbox that includes AES, but maybe that wasn't available at the time, I'm not certain on the timeline.
g_pcbcSystemLink uses standard AES-128. Its round keys really are the output of a normal AES-128 key schedule, and that schedule is invertible, so you can run it backwards from any complete round key and collapse them all into a single 16-byte master key. I did exactly that and compared it with the known Xbox 360 key and it matched.
g_pcbcObfuscation, g_pcbcXLiveDRM, and g_pcbcXLiveUserData are a different story. They use a non-standard number of rounds and none of their round key transitions follow the schedule, so there's nothing to invert and no 16-byte master key to collapse them into. None of this is about recovering the keys, the round keys aren't hidden, they're sitting in the lookup tables and I've already extracted them. The only question is whether they compress back down to a smaller master key, and for these three they don't. The round keys themselves are the complete key material.
The one thing I can't rule out is that Microsoft cooked them up from some smaller seed with a custom routine instead of the standard schedule. But even if they did, it still wouldn't get you a master key. A key schedule worth using is indistinguishable from random without the seed, so the round keys won't leak it, and whatever seed existed wouldn't be an AES master key you reach by inverting a schedule anyway. Cracking that generator would be its own project, not a matter of squeezing the round keys down a little harder. For the round keys themselves, what we have is everything there is to get.
- cxkes.me - XUID Lookup - Online XUID Lookup tool
- GfWLUtility - Utility for working with Games for Windows - LIVE
- spaday - GFWL/Xbox 360 SPAFILE parser