Posted May 26 2009 I needed some valid SWF files with constrained character sets for an injection PoC. Putting them here in case someone else needs some. PHP has finally taken the plunge into the 1960s by implementing GOTO. Here's an implementation for Java. A patch for a serious Java bug. No longer needed as of June 16. Max & Michael have written a Max/MSP driver based on the multitouch code.
My CSS-fu is weak; please use a recent browser. Random, semi-related image by Lounger. |
Spotify vs OllyDbgSpotify for Windows contains code so awesome that OllyDbg can't look at it without crashing. The protection exploits, among other things, a Borland library bug that apparently has gone undetected since 1991. Let's start at the beginning. If you haven't seen it, Spotify is a music player similar to iTunes, except that it uses a massive distributed music library. It's ad-supported (banners + occasional radio ads), but comes with a nice party mode: If you're using it as a jukebox for your party, you can pay a token $1 to disable the ads for the day. OllyDbg is a lovely Windows debugger written by Oleh Yuschuk. For some reason, they trust Mac usersThe Macintosh version of Spotify has no anti-debugger protection at all, which is extremely odd for a product like this. It even logs readable debug output directly to the console, so you can pinpoint e.g. the ad loading routines using nothing but dtrace: sudo dtrace -n 'syscall::write*:entry /execname == "Spotify" && arg0 == 2/ { trace(copyinstr(arg1)); ustack(); }' This prints a stack trace every time something is written on stderr. Just by looking at the stack traces, you can get a reasonable overview of what is going on:
The blue part is common to every log entry. Presumably the entries in the 0x71000 range correspond to the printf family of functions, the function at 0xb461b is a custom log() function, and the red part is ad-related :) On WindowsOn Windows, it's an entirely different matter. The application is suitably paranoid, and merely starting a debugger on the same machine is enough to make it run for cover. The first stage of the loader is a simple xor/add decryption loop. First decryption loop Being lazy, you could try stepping through it using OllyDbg. If you do, an interesting thing happens. As soon as you try to step through the jump to the newly-decrypted code, OllyDbg locks up. If you go back and try again, it turns out you don't actually have to run the decrypted code for it to crash; merely looking at it is enough. The application hasn't accessed anything outside of its own memory space yet, so it shouldn't be able to influence the debugger. Maybe some obscure opcode sequence is able to throw Olly's disassembler into an infinite loop? If you suspect a bug in your debugger, the obvious thing to do is to debug it. Now, if you try loading a copy of Olly into Olly, then loading Spotify into the innermost debugger, something rather baffling happens: Both debuggers crash. In fact, you can crash a whole stack of debuggers at once. The Medusa floatBy having a disassembly window open while stepping through the decryption routine, you can narrow it down to a single float-point constant which apparently is impossible to display (this screenshot is from the patched version of OllyDbg): "Dangerous" floating point constant (in Spotify) The crash happens in this routine, which is supposed to convert an 80-bit floating point number (long double) into an unsigned 64-bit integer (long long): Float-to-int conversion routine (in OllyDbg) In pseudo-C, the routine does something like this:
// convert a float to an unsigned integer, given 0 <= float < 2^64
void float80_to_uint64(float80* in_ptr, uint64* out_ptr) {
if (float < 2^63) {
// the number won't overflow, so it's safe
// to use a signed conversion
float80_to_int64(in_ptr, (int64*) out_ptr);
} else {
// 80-bit floats have an explicit 1 in the mantissa, so we can just
// copy the raw bits if the exponent is exactly 63
*out_ptr = *(uint64*)in_ptr;
}
}
... where the float80_to_int64 subroutine is implemented using the FIST instruction, which raises a floating point exception if the number does not fit into a signed 64-bit integer. The red comment, of course, is wrong. An 80-bit float has 64 bits of precision, so with an exponent of 63 it is possible to pass in a value of 2^63 - 0.5 = 111111111111111111111111111111111111111111111111111111111111111.1 ... which, while intially less than 2^63, will round up to 2^63 when converted to an integer. That number is not representable as a signed 64-bit int, and the FPU throws an exception. The debugger dies, and since the bad number is still on the FPU stack, it is able to kill the next debugger as well. To see it in action, try setting one of the FPU registers to 403D FFFFFFFF FFFFFFFF hex. As soon as the last character is typed, the debugger dies: Try this at home The faulty routine is actually part of the run-time libraries shipped with the Borland C++ compiler. To verify, you can compile the following program with bcc32 and watch it crash in printf(). The middle window shows the result as compiled with GCC; the right shows the buggy version: One bit of accuracy is lost in the conversion, and the last printf() crashed. A workaroundLoad OllyDbg in itself, and search (Ctrl-S) for the instruction sequence fld [ra] fistp [rb] When you find this routine, Original float-to-int routine ... replace it with something like Patched float-to-int routine The and will clear the least significant bit of the float before doing the conversion, narrowly avoiding the bad case. To make room for the added code, the patch exploits the fact that the function is called with input and output to the same buffer, so the last 5 lines of the original are unnecessary. CommentsWow, nice catch mr! And thanks for a very interesting read.
(there are btw a few open source Spotify libraries and applications out there, though inofficial, just checkout http://despotify.se)
I could hook you up with some Hex-Rays images of how that routine used to look like some months ago if there was just an email I could reach you on.
— bugtraq.org 2009-05-26 The loader is Themida but judging from your debugger sk1llz you already know this..
— ;ppPPppPpp 2009-05-26 That's some fascinating stuff. Great writeup. I always love seeing the nuts and bolts of stuff explained, especially in a writing style that makes it read like an interesting short story. — Unindignant 2009-05-26 I would guess that the reason for this is that it was written on windows or by someone who write noid code for windows. When it was ported to mac, the care wasn't necessary. Or the mac dev is a lazy hippy. :)
— JT in MI 2009-05-26 Reading this reminded me of the copylock protection scheme from way back. Good times.
— I fought the lock and I won 2009-05-26 [Nice. Apparently you can still buy it!] You sir are insane, and insane people can't write flawlessly.
Did the ads really bother you that much?
— Josh 2009-05-26 [Not really. It's just for fun.] This is ridiculous! How do you know how to do this? Good sleuthing.
— Alfonscius 2009-05-26 [If I had known, it wouldn't be any fun.] Grats on rediscovering a known/public anti-debugging trick. It's used by Themida <which BTW is what Spotify is now protected with>. You can google some things like "spotify themida" or take a look at:
[link]
Also, your text editor won't let me use a closing parenthesis.
— Huhu 2009-05-27 [Text editor?! It's your browser!] Doesn't surprise me. I have never seen an ad on spotify. I don't know why, because I've never paid anything. I even looked for an ad, but still nothing.
— Scogle 2009-05-27 [They seem to come in waves. I didn't see anything for the first few weeks.] <BODY ONLOAD=alert('lmao')< — Aussie 2009-05-27 [Really? Well, at least you didn't try to end it with an </alert> tag like the last guy.] Reminds me of some magic numbers and 'unlikely' instruction combos that would make pentiums lockup.. guess how they found those out?
— 2009-05-27 You might want to check out the related reddit discussion at: [link] — Anonymous 2009-05-27 [Thanks, I noticed :-) I was more surprised to find that someone had posted this to the scifi reddit.] I would have just paid the $1 token to remove the adds...
— One with common sense 2009-05-27 [Now where's the fun in that?] |