Microsoft® Windows® Hacking 101

The latest Internet worm, "MSBlaster" (or "LoveSAN", or "W32.Blaster.Worm", or whatever spiffy name you want to call it), has been worming its way up the asses of hundreds of thousands of Microsoft® Windows® computers this week. It's made national headlines, generated incredibly inaccurate descriptions on CNN, and forced groggy IT geeks to get out of bed before nine in the morning. Even the US Department of Homeland Security issued a warning about this worm. (I'm surprised they didn't raise the "threat level" to chartreuse and duct tape, then detain, the keyboards of anyone with a Coppertone tan.)

So, what kind of evil genius is behind this attack? So far, MSBlaster's author is unknown. However, I can offer some helpful advice to investigators: Keep a keen nose out for the smell of Clearasil. I feel sure MSBlaster's author would want to rid his face of zits before beginning his 10th grade "keyboarding class" this school year.1

You see, you don't need a doctorate in computer science to pull off an attack like this. All you need to do is take advantage of yet another one of Microsoft's big, giant, glaring, gaping, sloppy security holes.

Don't believe me? How about I show you exactly how MSBlaster worms its way up Window's butt? Even if you know nothing about programming, I'll bet I can teach you how to hack Windows in about ten minutes. Ready? Go grab yourself some Clearasil and a Mountain Dew, and I'll soon have you seizing control of zillions of Windows computers.

First, some background. (Remember, I'm assuming you know absolutely nothing about programming.)

Windows, like any other computer program, is nothing more than a list of instructions for the microprocessor in your PC to execute. When you turn your computer on, it grabs Windows off your hard drive and loads these instructions into memory. The microprocessor then fetches the first of these instructions out of memory, and executes it. Then, it moves on to the next instruction, executing it. It repeats this over and over again, millions of time a second.

If you were to look into your computer's memory after Windows has loaded, you'd see this list of instructions is nothing more than a series of numbers. The microprocessor interprets each of these numbers as an instruction to be executed. At first glance, these numbers might look a little weird. Computers use a numbering scheme with 16 digits rather than the 10 digits everyone's accustomed to. (It's a long story.) So, a computer counts like this: 0,1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, 10, 11, 12, and so on. This numbering scheme is called "hexadecimal", or "hex" for short.

I'm sure you'd heard the term "byte". The amount of memory in your computer is measured in bytes. A byte is nothing more than the amount of memory required to store a hex number between 00 and ff. Some instructions are one byte long. Others are several bytes long.

The memory in your computer is used for one other thing besides storing instructions. It's also used to temporarily store numbers that the program may need later on. One of the first things every program does is to set aside a hunk of memory for just this purpose. This hunk of memory is commonly called the "stack". As you'll soon see, the stack is very important to a budding hacker like yourself.

So, how does a microprocessor keep track of all this memory containing instructions and the stack? It assigns each byte of memory an "address". These addresses are similar to street addresses. The first byte has an address of 0, the next an address of 1, and so on.

As you might imagine, any program, including Windows, often has to perform the same task over and over again. For example, Windows must check to see if you've moved your mouse over and over again, millions of times a day. It would be mighty tedious to replicate the list of instructions to perform this task over and over again. So, programmers devised something called a "subroutine". A subroutine is just a short list instructions you want to be able to execute over and over again. There are a couple of microprocessor instructions specifically designed to allow you to use subroutines: "call" and "ret" (short for return).

The "call" instruction is always accompanied by an address, telling the processor where in memory the subroutine to be executed resides. The processor then jumps to this memory location, and begins executing the instructions there. However, right before jumping to this subroutine, the "call" instruction performs one other very important task. It saves, or "pushes", a "return address" onto the stack. This is much like leaving a trail of breadcrumbs for the processor, so it can find its way back to the right memory location when it has finished executing the subroutine.

Every subroutine eventually ends with a "ret" instruction. When the processor encounters this instruction, it retrieves, or "pops" the return address from the stack. This is how the processor finds its way back to the list instructions it was executing before it was asked to call a subroutine.

To summarize, a "call" instruction pushes a return address onto the stack. A "ret" instruction pops a return address off the stack. Remember that, because we'll soon be using this fact to hack Windows.

Besides "call" and "ret", there are a couple more instructions that allow us to push and pop data onto and off of the stack. Fittingly, these instructions are named "push" and "pop". They do exactly what their name implies.

By now, you may be wondering how the processor keeps track of where on the stack bytes should be pushed and popped. It keeps track by using a little piece of memory inside the processor itself called a "register". The Intel processor inside your Windows PC contains around a dozen of these registers. The particular register it uses to keep track of the stack is called the "ESP" register. (No, that doesn't stand for Extra Sensory Perception. The full name of this register is the Extended Stack Pointer.) Folks often call the ESP register the "stack pointer".

The processor uses this ESP register to store the address of the next byte of data to be popped. When it encounters a "pop" instruction, it uses the address stored in the ESP register to go fetch the byte of data being popped. It then increments the ESP register so that it points to the next byte of data to be popped. Pushes work just the opposite. They cause the ESP register to be decremented, so that it points to the next free memory in the stack where a byte may be pushed.

If a programmer needs a place to temporarily store some data, he will often manipulate this ESP register to make some room on the stack for this data. For example, if the programmer wants to store five bytes of data, he can set aside room on the stack for these bytes simply by decrementing the ESP register by 5. Little hunks of memory like this are called "buffers".

One last thing before we start looking at the guts of Windows. Remember I said your processor contains a couple dozen registers? You already know about the very important ESP register. Well, there's another register called EBP. It's nothing special. It's just a general purpose register we can use to temporarily store things. We'll see how this register is typically used in just a couple of seconds.

As you might imagine, Windows contains thousands and thousands of subroutines. Let's take a look at a typical Windows subroutine that builds itself an eight-byte buffer on the stack. The instructions for the subroutine look like this:

[line 1] push ebp
[line 2] mov ebp,esp
[line 3] sub esp,8

--- here would be a bunch of instructions to read data into the buffer ---

[line 4] mov esp,ebp
[line 5] pop ebp
[line 6] ret

When another piece of Windows calls this subroutine, a return address is pushed onto the stack. So, the stack looks like this:

Stack containing return address.

The first thing the subroutine does (line 1) is to push the contents of the EBP register onto the stack. There's a good reason for this. Programmers, out of politeness, always try to put registers back like they found them before returning from a subroutine. After all, whoever called this subroutine might have something very important stored in the EBP register. So, if the subroutine is going to play around with EBP, it needs to remember what EBP contains before messing it up. To do this, the subroutine will push the contents of EBP onto the stack. Later on, just before returning, it will pop this value back off the stack, restoring EBP so that it's just like it was found. Polite, huh?

At this point, the stack looks like this:

Stack containing return address and EBP.

Because the subroutine will soon also be messing with the ESP register, it needs to remember what ESP contains, too. But, you can't just push it onto stack like the EBP register was stored. Remember, the ESP register is the stack pointer. So, once it's been messed with, it will be pointing to the wrong place on the stack, and "pops" won't work right! But, there's a way out of this pickle. You can just temporarily copy the ESP register into the EBP register (line 2). Clever, huh?

Line 3 is where the subroutine makes room on the stack for an eight-byte buffer. It's so easy! All that is required is to subtract ("sub") 8 from ESP. Now, there's an empty place on the stack where 8 bytes of data may be stored, and the stack looks like this:

Stack containing return address, EBP, and buffer.

At this point, the subroutine is primed and ready to do whatever kind of work it might need to do. For example, it can suck data in over the Internet, and store it in the 8-byte buffer it has created for itself on the stack.

Once the subroutine has finished its work, it must clean things up, restoring any registers it has messed with, before returning back to whoever called it. First (line 4), it restores the value of ESP by pulling its original value out of EBP, where it was stored earlier. Now that ESP (the stack pointer) has been restored, the stack is in working order. It looks like this:

Stack containing return address and EBP.

The original value of EBP can now be restored by popping it off the stack (line 5). At this point, the stack now looks like this, with nothing but a return address left on the stack:

Stack containing return address.

Now that the subroutine has put everything back like it found it, it may return (line 6). The processor sees the "ret" instruction, pulls the appropriate return address off the stack, and the program jumps back to where it was before the subroutine was called.

Pretty nifty, huh? There are thousands of subroutines exactly like this one inside Windows.

Now, once a programmer has written a subroutine like this - one that creates a buffer on the stack - he needs to be a little careful about how he copies data into this buffer. In particular, if a programmer creates an eight-byte buffer, then he'd better be damned sure that he never, ever attempts to store more than eight bytes of data into that buffer! To understand why, let's once again take a look at the stack after this buffer has been created:

Stack containing return address, EBP, and buffer.

Let's imagine this subroutine's job is to suck in bytes of data over the Internet, then store these bytes into the buffer. The first byte would go into "buffer location 1". The next byte would go into "buffer location 2". And, so on. Finally, the eighth byte we suck in would be stored in "buffer location 8".

Now, if a smart programmer wrote this subroutine, he would have been keeping track of how many bytes had been sucked in and stored in the buffer. At this point, the program should know that the buffer is full. It had better not suck in any more data and attempt to store it on the stack!

But, what if a stupid programmer wrote this subroutine? What if the subroutine was written so that it failed to keep track of how many bytes had been sucked in and stored? What if it just kept on sucking in bytes and storing them in the buffer until the data stopped coming in? If a ninth byte comes in, it would be written onto the stack, destroying the value of EBP that had been so carefully stored away earlier! What if a tenth byte comes in? It would overwrite the return address stored on the stack! Holy shit! Now, the next time the processor hits a "ret" instruction, it will pop this boogered up return address off the stack, then jump to wherever in memory it points!

As luck would have it, the boys at Microsoft did this exact thing. They screwed up and failed to count how many bytes they're sucking in over the Internet. So, being a crafty, newbie hacker, you can take advantage of their stupidity. Here's how:

As you've seen, you can send as many bytes over data over the Internet to a Windows PC as you want, and Windows will just keep on sucking them in. The first 8 bytes you send get stored properly by Windows. The next byte you send will bugger up the stored value of EBP. Who cares. But, the next byte you send is going to overwrite the return address. So, why not send a very specific address that will cause the processor to jump to an address of our choosing? If we can also manage to put some instructions at this address, then the user's processor will execute them. Their PC will do anything we tell it to do! We'll own it!

So, how are we going to get some instructions into the user's machine? Why not just pump them over the Internet, just like we did the bogus return address. Remember, if we keep on sending bytes, stupid old Windows will just keep on sucking them in and storing them on the stack. We can just transmit our evil set of instructions over the Internet, and Windows will store them on the stack for us!

Now, we've got just one last problem to solve. So far, we know we can send a bogus return address over the Internet to anyone's PC, forcing their processor to jump to this address whenever it hits a "ret" instruction. We also know we can send a bunch of evil instructions we want to execute. Unfortunately, there's one thing we don't know. We don't know the precise memory address where our evil instructions will be stored. All we know is that they will be stored somewhere on the stack. So, we don't know the precise bogus return address we should send to the machine we're trying to hack. What's a newbie hacker to do?

Well, there's one more Intel microprocessor instruction I haven't told you about. Its name is "nop" (short for "no operation"). It tells the processor to do nothing. That's right - do nothing, then move on to execute the next instruction. So, why not make use of this instruction? Before sending our list of evil instructions, why not first send a whole pile of "nop" instructions. Then, send our evil instructions. Stupid Windows will store all these nops, followed by our evil instructions, on the stack. Now, the bogus return address we come up with doesn't need to be very precise. As long as the processor jumps somewhere into the middle of all those nops, it will eventually execute it's way down through all the nops to our evil code! Bwhaaaa-ha-haaaa!

To summarize, all we have to do to control a Microsoft Windows machine on the Internet is to send the following data: eight bytes of data (which get properly stored), one byte of data (which destroys EBP, but we don't care), a return address (which sloppily points somewhere into the stack), a pile of nops (allowing our bogus return address to be sloppy), and the evil set of instructions we wish to execute on someone else's machine.

This little trick is known as a "buffer overflow" exploit. This is precisely how MSBlaster has been installing itself on unsuspecting Microsoft Windows users' machines all over the world.

Congratulations! You graduate. You're now a Junior Hacker. You now know the precise trick MSBlaster's author used. Maybe you should send the guys at Microsoft a thank you note for making their operating systems so very easy to hack.

(Okay, maybe I shouldn't use the word "precisely". In truth, I've left out a few very minor details in the interest of brevity. For example, I failed to mention that many of the registers we played with are actually 4 bytes wide rather than one. However, all the principles I've described are completely accurate. Before some smarty pants geek sends me an email pointing out one of these minor details, I'll say this: Technically, MSBlaster exploits a hole in the DCOM interface with RPC over TCP/IP port 135. It overflows a 100 byte buffer intended to store the null-terminated contents of UDP datagrams. However, as long as the data contains no nulls, stupid Windows will gladly overflow this buffer. So, don't be a smarty pants. I was overflowing buffers before your mommy had you potty trained. It wouldn't get you locked up back then.)

I was not born a Microsoft/Bill Gates basher. I'd be the first to admit that Microsoft has produced some useful software, and I certainly don't fault a man just because he gets rich. However, I am getting sick and tired of loading patch after patch to close sloppy security holes like this one. This particular hole had the potential to be disastrous. With a little ingenuity, it could have been used to bring the Internet to its knees. No exaggeration.

As things stand now, thousand and thousands of innocent people's computers are infected. These machines, unbeknownst to their users, are busy infecting other computers.

Maybe the boys at Microsoft should heed the advice contained in a string of bytes inside in the MSBlaster worm. These bytes spell out the following message: "billy gates why do you make this possible ? Stop making money and fix your software!!"

Amen.


Footnotes:

1. I was wrong. The perpetrator (at least of the of the "B" variant of this worm) turned out not to be a 10th grade student. Instead, he was 18 years old. Still, he looked like he might could use a little Clearisil.

There are tons of news articles on the Net concerning the arrest of "teekid", a.k.a Jeffrey Lee Parson. The most balanced one I've run across can be found here. To tell the truth, I feel a great deal of sympathy for this poor kid. He now has the wrath of a nation (and federal prosecutors) upon him, and faces a lengthy prison sentence and huge fines. His young life is basically ruined. In my opinion, the real guilty party in this whole mess is Microsoft. They're the ones who left the candy dish unattended.