Yes, I know what you're thinking, because I thought the same thing. "You're trying to tell me that a non-privileged user can tell winlogon.exe to jump to an arbitrary location in memory?". Yes folks, I am. You can. It works. Send enough crap WM_TIMER messages to any system process through PostThreadMessage, and eventually the structured exception handling (SEH) will fall over, the process will die, and the machine will bluescreen. Injecting code is a little more tricky, but I've certainly got it working (No, I will NOT give out my code so don't even ask) and I'm sure other people will too. Anyone still have any arguments that Shatter attacks are the fault of the people who put localsystem windows on the desktop? Anyone think of a way to not have any LocalSystem message queues on the system? Theoretically, it's potentially possible. I doubt it though. Looks like Microsoft are going to have to extend the Win32 API, and recode several very critical system processes. Fun fun fun.
There's a few new ideas here as well, for ways to get your code into your target process. Some are easier than others, but all (in principle) work.
SetWindowText() This function sets the caption for any window on the system. Or the contents of any edit box. Or the title for any static labels. Or the label on any button. You get the idea? Binary code is absolutely allowed, and you get a LOT of space to play with. Smashing uses SetWindowText() to inject half a megabyte of NOPs before my shellcode; as far as I can tell, the only limit is the stack size of the receiving process. Pass in a meg of NOPs and you get a stack overflow, although there may even be a way around that. This technique does have a few drawbacks, but nothing that can't be fixed with a bit of clever assembler. Like I said, the first version of Smashing was based around SetWindowText - it works reliably.
GlobalAlloc() Peter Arnold suggested using GlobalAlloc (specifying GMEM_FIXED) to grab a chunk of memory at a fixed location for all processes, filling it with your shellcode, and specifying that as your callback address within WM_TIMER. I've not had time to research this, but MSDN seems to support the idea in theory. While it clearly states that "Windows memory management does not provide a separate local heap and global heap, as 16-bit Windows does." supporting the theory of using shared heap-space to inject shellcode, it also says that "Memory objects allocated by GlobalAlloc and LocalAlloc are in private, committed pages with read/write access that cannot be accessed by other processes". Might work, might not - I'll try it when I get time and update this page.
Other buffers As Kristian Koehntopp pointed out, you just have to get your code into the address space of the process - any kind of file buffer, I/O buffer or network buffer will do. Connect to a named pipe / network socket / whatever, send your shellcode, and then send the callback before you get kicked off. Should work nicely, assuming you don't kill the process with an SEH overload before you find your shellcode...
Well, that's all for the moment on new techniques. Like I said, a sizeable chunk of this stuff has come from people who read the original paper and are thinking along similar lines; I see no problem in telling people what others are already thinking about / working on / exploiting. After all, local security on Windows is an oxymoron, isn't it?
This is not a Microsoft problem, it's a VirusScan problem.
Reading our newsletter every Monday will keep you up-to-date with security news.
Receive a daily digest of the latest security news.