Wednesday, February 13, 2008

Detours and Code Hooking

This post is going to concern writing your own detour function to hook into a target process' code. The first thing we need to go over is what a detour is. A detour is a patch written to a target location that switches control from the target process and gives that control to code you have written. The example function we are going to write is going to be in C++. Open a new source file in your IDE of choice (I use Visual C++ 2008). First we need to write up a prototype for our function. We should start by figuring out what parameters our function will take. It will need to know where to apply the patch, where to redirect program control to, and what type of detour to write (a one-way jump detour, or a function call that will automatically return control to the appropriate location). We should also implement padding. A situation could easily arise where there isn't a good spot for the detour to go, and will end up only partially overwriting a piece of code in the target process causing corruption. The most common technique is to fill the remaining space with NOP, or No Operation instructions. Another alternative is a short jump, which will skip over the remaining code fragment. The short jump approach will only work if you have 3 or more excess bytes to work with, because two bytes will need to be allocated for the jump instruction and you will need one more because a jump of zero bytes is illegal. I chose to implement NOP padding, and so that is what the article will use in the example. However, once you get more experienced you may wish to look at other alternatives. For NOP padding, our detour function will need to take how many NOP's to write as a parameter. If padding is not needed, we can simply pass zero and it won't add any. The addresses for the patch location and our hook location should both be double-words. We can use a boolean for the flag to decide the hook type (since for this example, we're only going to be using two types). The data-type for the number of NOPs can be any integral type, but I chose to implement it as a double-word for the sake of simplicity. Although, a byte would be more than enough, as I've never seen a detour require padding for a couple hundred bytes or more. With all that in mind, our prototype will look something like this:
void PlaceDetour(DWORD dwAddressToPatch, DWORD dwDetourAddress, DWORD dwPadSize, BOOL bFlag);

The very first thing we will need to do when defining our function is remove the virtual memory protection for the code we want to patch. We will assume we are already within the target process' address space (working from within an injected DLL), and therefore we will need to place a call to the VirtualProtect Win32 API function. It's implemented within Kernel32.dll, but in C++ we only need to include the appropriate header, 'windows.h'. VirtualProtect takes four parameters. The first is a pointer to the address we want to remove the protection from. We can simply pass the address and cast it as type LPVOID, and the API will never know the difference. The second parameter is the number of bytes from the base address to remove the protection from. The detour will require five bytes dedicated to it (four for the DWORD operand, and 1 for the instruction that takes that operand as it's parameter), and an additional byte for each NOP instruction we wish to write. Therefore we can use the expression (5+dwPadSize) to get the proper value. The third parameter is the new protection type. We will pass the constant 'PAGE_EXECUTE_READWRITE' which is defined in 'windows.h' as 0x40. The final parameter will be a pointer to an integer where the function can put the old protection type for temporary storage so that we can easily restore it when we are cleaning up. Before you make the function call, remember to create a variable for the final parameter. My example will use a DWORD type variable called 'dwOldProtect'. Keep in mind that instead of passing the variable as a value, we will instead want to pass a pointer to the variable. We will use the address-of operator (&) for this task. Note that this step isn't necessary on versions of Windows that pre-date Windows NT (95, 98) because at that time virtual memory protection hadn't yet been implemented and the functions do not exist within the Kernel32 library. To maintain compatibility with both systems kernels you should implement a system for checking the version of Windows being run on the machine and call a separate function depending on the results, but this article won't go into that. The finished function call should look like this:
VirtualProtect((LPVOID)dwAddressToPatch, (dwPadSize+5), PAGE_EXECUTE_READWRITE, &dwOldProtect);

Next we need to write an if...else block to handle the detour type boolean. If 'bFlag' is true we will place a JMP, and if it's false we will place a CALL. The byte code for a rel16/rel32 JMP is 0xE9, and the byte code for a rel16/rel32 CALL is 0xE8. We will want to write the proper byte to the address we are patching. Our block should look like this:
if (bFlag) { *(BYTE*)(dwAddressToPatch) = 0xE9; } else { *(BYTE*)(dwAddressToPatch) = 0xE8; }

The next step is giving the CALL/JMP instruction an operand, or parameter. We want to calculate the number of bytes the system will have to travel from the address of the instruction to reach the destination (our detour). This is easily calculated using the formula ((dwDetourAddress - dwAddressToPatch) - 5). Your code should look like this:

*(DWORD*)(dwAddressToPatch+1) = ((dwDetourAddress-dwAddressToPatch)-5);

Now we need to write our NOP instructions. We should use a for... loop to start at the final NOP instruction and work our way backward until we arrive at the final byte of the detour we wrote to memory. The loop will use a counter variable to keep track of how many times the loop has executed, and when it needs to stop. We will initialize the counter as the same value as 'dwPadSize' and it will execute until it is not greater than zero. This apporach has one definite advantage. We can use the counter variable along with the address we are patching with the detour and the size of the detour to determine where the next NOP needs to be written. Each execution of the loop will decrement the control variable. The code for the loop should look like this:

for (DWORD i = dwPadSize; i > 0; i--) { *(BYTE*)(dwAddressToPatch+5+i) = 0x90; }

We are at the final step. All we need to do now is restore the virtual memory protection. This will require another call to VirtualProtect. As a matter of fact, the function call will be exactly the same as the previous call with one caveat - instead of passing the 'PAGE_EXECUTE_READWRITE' constant as we did earlier, we will want to pass 'dwOldProtect' to restore the previous protection settings. You may still pass a pointer to 'dwOldProtect' for the final parameter, as well - it won't adversely affect the functionality of the sub-routine. It should look like this:
VirtualProtect((LPVOID)dwAddressToPatch, (dwPadSize+5), dwOldProtect, &dwOldProtect);
Congratulations! You have written a functional, albeit simple routine for writing detours to a target process' code. Aren't we just the ub3r h4x0r?

Tuesday, February 5, 2008

Giants Beat Patriots, I've Been Busy, and 2 Vista Reformatting Tips.

First of all I want to say congratulations to the New York Giants. I've never been a big Eli Manning fan, I was always more supportive of Peyton, but just as well he deserves credit for ruining Tom Brady's perfect season. Secondly, I want to say that I'm now using a new Blogging software for my blog. It's called ScribeFire. I particularly like how well it integrates with Blogger and Firefox, my web browser. Finally, sorry I haven't posted in a while, I've been busier than usual the last couple of weeks. Plus, on the 25th of January I underwent a quest to trim all of the bloatware of my new notebook. My 500GB external hard-drive got here and I decided that now was as good a time as any to pimp my laptop, reformat style. So because I don't really have anything else prepared, this post is going to be about reformatting tips. And just so you know, I couldn't be more satisfied; My Vista configuration boots in 7 seconds, and idle ram consumption is down to about 35%.

Vista has some strange quirks that may throw off the unwary. First of all, immediately following reinstalling Windows I hit my first patch of trouble. After going through all of the Dell reinstallation driver disks, I attempted to install the newest version of SPTD Layer, a component in the popular applications Daemon Tools and Alcohol 120%. It wouldn't install all the way and I couldn't figure out why. I thought surely there can't possibly be a software conflict, as the only things that had been installed were necessary device drivers and system software. I also immediately discounted it being a problem with Vista, as I had used both Alcohol 120% and Daemon Tools successfully before reformatting. Obviously, something was different now than it had been, the trick was figuring out what. My first thought was that I might have lacked some kind of runtime redistributable that the developers forgot to include. That happens more than the software industry likes to admit. At any rate, I immediately did as much research on what components went into making SPTD as possible. Unfortunately that was a dead end. My next idea was that perhaps my default security policies denied the installer some critical privilege. I went into regedit and opened up the group policies dialog. Unfortunately, that route also was a dead end. After having ruled out software conflicts, lack of run-time components, and my administrative settings as causes, I went back to the drawing board. The only remaining possibility was that some option had either been enabled or disabled between the reformatting process and my first attempt at the install process. Then, it hit me. I had used a batch script to set certain options via command-line switches to personalize my configuration; I hadn't counted on one of them disabling a vital service to SPTD. I looked through it and examined each command looking for what it modified and what that setting controls. After about half way down the list, I found it:

bcdedit.exe /debug -on


At first I didn't realize why it was important. This setting is Vista's way of controlling whether or not kernel-mode debugging can be performed locally on a machine. It doesn't necessarily mean that kernel-mode debugging is taking place, I just enabled it because I like the feeling of being able to take a gander at what the Kernel is up to. Then I remembered that SPTD has a dislike for local kernel-level debuggers. But, surely a setting like this isn't a reliable indication of whether a kd is active - the developers wouldn't use this as the only means of determining whether a kd is present? I was wrong; Upon disabling this privilege (use the same command, only with the "-off" parameter to the "/debug" switch.), everything fell into place after a reboot. This brings us to the first tip. Don't give developers too much credit. Get your software installed before you go fiddling with things, even if you know what they are and what they do.

My next challenge arose when I was customizing Windows. This however was one that had bested be before, and I was forced to give up on the answer. This time I was determined to find the solution. The problem was simple: Whenever Windows rebooted or experienced a logoff event, any custom cursor immediately took the form of the default white pointer. I quickly discovered that the effect was purely cosmetic; meaning that each time the anomaly occurred, the setting itself did not change - simply the form the cursor became that of the default file within the '%SYSTEMROOT%\Cursors' directory. Ahhh, the workings of a drag and drop named based file system! Don't ya just love it! The solution is both elegant and primitive, making it wonderful for those who lack certain technicial computer skills. Indeed, who needs to know how to operate the machine when they can simply circumvent whatever happens to work against them? Simply rename the custom cursor file to the default cursor's name and replace the original with your customized one (Actually, now that I think about it, append '.bak' to the default file then rename the custom file and move it to the desired directory. This allows you to revert back to the default should the system's functionality ever change.). For example, in my situation I use the Aero theme - so my default file name would be 'aero_arrow.cur'. I have tested the workaround to the effect that functionality between the '.ani' and 'cur' formats are the same, and can be interchanged; This does not mean however mean that it is advisable to leave the 'ani' extension in place; If your customized file has a '.ani' extension, simply change it to '.cur'. This brings us to the next tip: Sometimes the most elegant and effective workarounds are also the most crude and primitve. If an OS has a quirky behaviour that can be harnassed, you are encouraged to do so. Beware though, you must always make a backup of anything you change.

I think that's it for this post. Make sure to add an Atom/RSS feed for the blog, you never know when I might go and post about something somewhat interesting.

Monday, January 21, 2008

Obsidian's Developers Are Idiots

I had originally intended to publish an article on writing injectable DLL's today, however there is a rant that must be written down. It cannot wait. What is this important rant that must be published you ask? Well, let me answer that question with another question: If you were filling in property fields, where would you want the data to go? Most of you are probably thinking to yourself "WTF - go? Why would I want it to go anywhere? The entire point of typing it in the property field was so that it would define that particular property!" You would be right, too.

Well, the clever [read: moronic] folks at Obsidian Entertainment decided that the conventional wisdom we've all come to expect simply is unacceptable. Today I tried out the Neverwinter Nights 2 toolset for the first time. I've owned the game for quite some time, but due to bad developement (what a surprise) it had to be patched extensively before it would function, and I didn't get around to it until today. At any rate, our friends over at Obsidian got the bright idea that their toolset would be infinitely easier to use if the data from the field you defined gets moved (not just copied, MOVED) to the same property field of another object once clicked on. This wouldn't be too bad if the only way to save changes to the property fields is to, you guessed it, click on another object. This means that if you are filling in the description of an in-game item that is several paragraphs long, you have to select another property before switching focus to another object to save the changes. Worse yet, there is no mention of this in the help files. Personally I think they did a great job with the game itself, but this is rediculous. If they were writing a GUI using a WYSIWYG drag and drop editor, they would expect any labels that they filled in would be filled in with the appropriate strings. Not that their label's data suddenly get's put in a combobox when they decide to start defining another form control.

In short, Obsidian's developers need a desperate lesson in interface design. Maybe they should focus the vast majority of their open positions on designers for their developement software, instead of the single senior position they're advertising...