Archive for December, 2006

Step into Kernel (SoftIce)

Saturday, December 23rd, 2006

Finally back from vacation. It has been nearly six years that I did not take vacations. Traveling, visiting new places and just relaxing were my main tasks during these last 20 days. Back to work, I’ve just arrived at the company and I was amazed by it. I could not believe they sent that old one away. We exchanged glances and obviously I got butterflies in my stomach. I got close enough to be able to smell it. I looked up and down. Simply perfect and it was an injustice to leave it alone. It didn’t take long and it was under my control. I had to prove everything it had to offer. After all, there were so many choices: Coffee, cappuccino, chocolate, tea with or without sugar. But it was all an illusion. “Oh my… that’s was a horrible coffee.” My friends, appearances can be deceiving. How can so beautiful machine make so bad coffee? I confess I miss the old machine. I didn’t mean that coffee was not so good, because the coffee was really horrible! Now I’m looking for alternative ways to keep my addiction. Perhaps there are caffeine patches to sell out there.

Don’t worry, this will no longer be an “Off Topic” post about changing coffee machines and the impact caused by them. In this post, which I had started last year and have just finished it now, I’ll take the steps needed to use SoftICE system debugger.

I still was new in SCUA and I was developing a GINA for our security product. For those who do not know, Gina is one small screen that appears during the Logon in NT platform. GINA is a DLL that is loaded by winlogon.exe process, which has the function of making the user’s interface to perform the login in the computer. The Msgina.dll GINA is the original one, but we can build our own GINA to provide alternative ways of authentication. A practical example of this is the product True Finger sold by SCUA. This product changes the system’s GINA, so that, with a biometric sensor help, it makes the system ask for the user’s fingerprint to logon the system. Debug GINA requires a few atypical steps, since to test it is necessary to do Logon, Logoff and things like that. You can also debug it using the Visual Studio Remote Debug, but at that time, debugging GINA was the need I had to learn how to use SoftICE.

There were two development teams, one for Kernel drivers and the other for applications. I still worked on application staff when in a meeting area, the team introduced me to SoftICE as an alternative to solve the problems about Kernel Debug I was facing. I was using techniques such as log files and MessageBox to debug GINA. You can imagine the MessageBox with the typical messages as “I called the X routine”, “Returning from Y routine.” After I learned how to use SoftICE, it solved many things for me. Specially since other Ginas had to be developed and as, the time passed by, I started to develop kernel drivers.

Most of the application team had a panicked about using SoftICE. A situation very similar to that described in my previous post. They said: “Oh no, using SoftICE is too complicated. I will continue with the MessageBox. If I cannot solve this, then I will use a Kernel Debugger.” I think it was just about getting used to it, SoftICE is not a rocket science and nor difficult to use. I found it amusing when one part of the team was caught trying to solve a particular problem, that kind of strange bug that nobody could find. I went around and asked: “Why don’t you just use SoftICE?”, “No, no, I guess it is not necessary.” they said. Later I also was called to help tracing the problem, and in most of the time I could, I’d picked up the problem that they’d chased for days in half an hour of Debug. I’m not saying I’m super Debug genius, or that they were technically incompetent. I’m saying that it is only a matter of using the right tool. You could dig a tunnel with a teaspoon, but with a shovel things would be much easier.

SoftICE is part of a development package called Driver Studio, which was sold by Compuware. For those who still do not know, Compuware has discontinued SoftICE and we cannot count on a version of this tool for Windows Vista. With SoftICE is possible to debug the kernel using only one machine, but the product still has the resources to do remote debug via serial ports or network adapters. Thus, they are also adopted the names Host for the machine that does the Debug and Target for the machine that will suffer the Debug (Similar to WinDbg). Here we will adopt the Host name for identifying the machine where we have the compiler and the installation type Host SoftICE. We will not do any remote debug on this post.

Very briefly, we can say that SoftICE works as it follows. At the Host machine, it is necessary to create a symbol file known as NMS. This file is copied along with the driver to be tested to the Target machine. In it, we load the symbols and start debugging the driver. We will describe these steps in more details next.

Installing the Host Machine

Installing SoftICE on the development machine is necessary for us to generate the NMS file. Don’t worry; you will not test your driver on your development machine. At least not while you’re sane. During the setup process, you will pass through the typical setup screens until you reach the screen shown above where you select installation type you want. Because we use only installation Host portion, select that option and skip to the next screen. Select only the option “SoftICE Host Components”, so that it appears on screen as below. The remainder of this process is next, next…

Installing the Target Machine

We will use the test machine in a way that it is not necessary to have two machines to do the debug, and so we will explore this feature that is usually used. To do this, select the “Full Instalation” in the first screen, then select only “SoftICE Host Components” items and “SoftICE Target Components” as it is shown below.

In this case, at the end of the register and file copy process, we will have to set some debugger properties. The first group of settings refers to initialization. We will select the Manual startup at this moment. All these settings can be changed after the product is installed. The setup screen should be as shown below.

The next group will be about general settings. In this item, we will change the field “Initialization” to stay with the configuration shown below. These are commands that are executed when the debugger is started. Each command is separated by a semicolon. These commands will make the following changes:

  • LINES 60; Change the total amount of lines to 60
  • WC 30; Change code window size to 30 lines
  • WL 10; Change local variable window size to 10 lines
  • X; And finally, the command that starts the system normal execution

The lack of “X” command will cause the system to become paralyzed at debugger startup time. This gives us the opportunity to put initial breakpoints and later we will be able to continue with the system execution by pressing F5, which is the hot-key for “X” command.

Now let’s set the video configuration. Right now you can ask me: “What do you mean by video configuration? Doesn’t Windows implement an abstraction layer called GDI?”

SoftICE is a system Kernel debugger. GDI is part of the system. How would you debug a video driver if the debugger itself utilizes this driver? The debugger should influence the debugged system as little as possible. It is for this reason that WinDbg need a serial cable and another whole machine to make the Kernel Debug possible. Similarly, SoftICE, once loaded, cannot use any system resource. This includes video drivers, disk, keyboard, mouse and so on. For the SoftICE being able to have a place in the video while debugging the system, it accesses the video memory directly and draws manually its entire interface. That’s why we have to configure the video.

This configuration can be chosen between two main options. The first is the “Universal Video Driver”, where the interface will appear in a window. This “window” is actually the result of writing in video memory that gives the impression of a window. This is not the type of window you’re used to seeing and drag with the mouse or even suffer the action of ALT + TAB. Remember, when SoftICE displays its user interface, the whole system is frozen. The other option is “Full screen”, where SoftICE switches the video to text mode to display its interface.

If you are installing SoftICE on a virtual machine, some steps are required:

  • Do not install tools such as video acceleration like VmTools.
  • Use the standard VGA driver in Windows and configure it so that, it is 640×480 with 16 colors. (Disgusting but necessary)
  • Select the “Full Screen” option in SoftICE.

If these steps are not followed, the machine will freeze when asked, but the debugger screen will not appear. Assuming that we are installing on a real machine, select the video option as shown below.

The remaining is next, next…

Generating the NMS File

On the Host machine, after compiling your driver (if you still don’t know how to do it, read this other post), you must now run the application “SoftICE Symbol Loader” that was already installed. This application does the symbol translation and generates the NMS file. Select Open… from the File menu and point out the driver you will debug. Once opened, the program must place the driver loaded name at the window title. I have numbered the three buttons you need for this operation.

  • Make sure that the second button is pressed. This will make any driver source code be appended to the resulting NMS.
  • Also make sure that the “3” button is released. This will prevent the program for asking for sources that it cannot find.
  • Click on “1” button that will do the symbol translation and the program will generate NMS file at the local directory.

Starting SoftICE

After installing your driver as usual in the Target machine, we will be ready to start the Debug of our driver. Remember that both our sample driver and SoftICE are configured to start manually. To start SoftICE, you can click the “Start SoftICE” icon that was installed in your Start menu or simply run the command “net start ntice” in the “Run…” window. To make sure that the debugger has loaded, press CTRL + D so that the system freezes and the screen is shown as the one below.

No, this is not a CRASH DUMP of your video card that has just exploded. Gentlemen, I am pleased to introduce you the SoftICE. Now can you understand the application staff panic? Don’t worry, it’s ugly but it doesn’t bite you. Pressing F5, the system returns to normal execution.

Now we have to load the NMS file into the debugger. This is easily done simply by double-clicking the NMA file. This file can be in any directory on the machine. The only time that this file is used is when you load it in the debugger. To verify whether the file was successfully loaded by SoftICE, use the “table” command that lists all loaded symbol tables. Several tables can be loaded simultaneously, but only one is active at a time. The “file *” command lists all files of a given table. To open a specific file, enter the file name in front of the command. See example below.

With the file already opened in the code window, press ALT + C to put the cursor into the source code. If this key sequence is not working, press ESC and then ALT + C. Note that you can only walk with the cursor up and down. Attempts to move the cursor sideways causes the command window to gain focus again. Place the cursor on the line you want to insert the breakpoint and press F9. At this time, the line was highlighted as shown in the picture below.

Now let’s press F5 to let the system return to normal operation. At the moment the driver starts, our breakpoint will interrupt this action and the SoftICE interface will be displayed. The highlighted line shows what the next instruction to be executed. Pressing ALT + L, the local variables window gains focus. You can navigate among the variables by moving the cursor up and down. Press ENTER key on the structures that begin with “+”, so that they are expanded. The image below shows register window and then, the local variable window.

I will leave a small table of commands here, but the full reference is in “SoftICE Command Reference” PDF file.

  • F5 : Run
  • F9 : Breakpoint
  • F8 : Step into
  • F10 : Step over
  • F12 : Step out
  • F7 : Run to cursor
  • WL : Local variable window
  • WW : Watch window
  • WD : Memory window
  • F3 : Swap among C source/Assembly/Mixed

Obviously there are numerous details and technical use, but let’s leave that to the documentations that coming with the product.

Wow, what a long post! You thought it would be easy, didn’t you? Until the next time …

Wow!! DDKBuild out of Vista

Tuesday, December 12th, 2006

About a year ago, I was reading the Windows Internals when I came in the chapter about Wow64, so I thought to myself: “Oh my… That’s a sort of thing that will bring us some issues.”

This week I’ve installed a Vista x64 copy on my computer to do some tests and I attempted to anticipate the problems I would have when it would be released. I almost had no problems. Actually, I had to configure some shortcuts to certain programs with compatibility mode set to Windows XP SP2. This is because these programs showed the message: “This program is not compatible with Windows 6.0”

After installing the Visual Studio 2005, DDK do Windows 2003 Server and DDKBuild, everything was working fine. A project was created, compiled and debugged in Visual Studio without problems. I also compiled a DDK example from the command line and also everything was OK. But at the time I was compiling one of the examples that I’ve already made available at the site using DDKBuild, I got the following error message:

'ddkbuild' is not recognized as an internal or external command

Executing the DDKBuild in a command prompt, it worked fine, but same error was always showing at the Visual Studio. After pooling out some hair, I tried to open the file DDKBuild.cmd from Visual Studio, that is, by selecting Open… from File menu and so on. When I got into the System32 directory, I saw that the file I was looking for was not there as it should be, at least, not for Visual Studio.

It took some time, but the penny dropped. Visual Studio is a 32 bit process and fell in the Wow64 (Windows-on-Windows 64) rules for File System redirection. For those who do not know, to maintain compatibility with the past, 64-bit platforms still use the directory C: \Windows\System32 folder to put the system DLLs, even though they were 64-bits.

But what happens with 32-bit system DLLs? Thirty-two bit processes still need to load these DLLs. When a 32-bit process tries to access the C:\Windows\System32 directory, the access is redirected by Wow64 to C:\Windows\SysWow64  (C:\Windows\System32\SysWow64 For Windows XP x64). Accesses to the registry are also reflected from 32 bits to 64 bits and vice versa. Please, refer to the MSDN site for Wow64 details.

Once the penny has dropped, it is ridiculous to solve the problem. Simply put a copy of DDKBuild.cmd in the C:\Windows\SysWow64 and everyone will live happily ever after.

Walter Oney for Managers

Monday, December 11th, 2006

The fact of writing a little unusual program has some consequences. Some of your friends at work, those ones who sometimes sit beside you, do not understand what you are doing (and vice versa). Others are seen whispering: “Look out! Is that guy the one who programs drivers.” This difficulty other people have to understand what we write, ends up also affecting the managers, directors and so on. Not that they were guilty of this. After all, if they were interested in the technical area at this point, probably they would not be managers, directors or whatever they are. This is not a rule, but at least it worked in companies where I have worked for; the minority of my superiors understood those problem complexities that ended up delaying a product release.

The worst case is when your manager thinks it’s simple to solve things. After all, when he programmed in COBOL, there was no problem he could not solve and you would probably be acting as a lazy guy or simply as a superstar for being able to solve blue screen problems. I particularly think it is beautiful when they ask: “But didn’t you already solve this blue screen problem?”, as there was only one problem what would result in a blue screen.

Well, so I think the recognized authority’s opinion on this could have some influence over those people’s opinions. In the first chapter of his book Programming The Microsoft Windows Driver Model (2nd Edition), Walter Oney gives some tips on how a company could consider driver development to obtain results closer to the expected. I have separated some sections that it follows below.

“The sad truth is that WDM driver programming is pretty hard, and only experienced (and expensive!) programmers are capable of doing it well.”

“Driver programming should start as soon as there is a reasonably firm specification for how the hardware will work. You should expect to modify the specification in light of unpleasant discoveries during driver development…”

“You should also expect driver programming to last longer and cost more that you initially imagine. All software is subject to time and cost overruns. Additional overruns in this kind of programming stem from communication difficulties between the hardware and software people, from ambiguity in specifications and in the DDK documentation…”

“Pay attention early on to how end users will install the driver software. Most vendors of add-on hardware prefer to ship a custom installation program on a CD-ROM, and writting the installer is a lengthy process that can consume en experienced programmer for several weeks…”

“Your driver executable will also probably include the text of messages in a special multilingual message resource, and it would be a good idea to have a trained writer compose that text. (I’m not saying your driver developer can’t do this, but he or she may not be the best choice.)”

“Finally, don’t treat your drivers as unimportant details. Having a good driver with a smooth installation is at least as important as the exterior appearance of the product… So a myopic decision to short-fund driver development could easily have a dramatic, negative effect on your bottom line for years to come. This advice is especially important for hardware manufacturers in developing countries, where managers have a tendency to look for every possible way to cut costs. I suggest that driver development is one place where cost-based decision making is inappropriate.”

Perhaps they will never read this, but for sure it will help us take a deep breath and continue programming. Now, you back to work because you are not getting paid for surfing the Internet! (This is also great) … 😀

Step into Kernel (Serial)

Friday, December 1st, 2006

I earned my first computer when I was 13 years-old, but seven years later, when I started my internship, I discovered that it was possible to debug programs that I used to write. Until then, my debug methods were always things like printing the variable value on screen. All right, in that time I didn’t use to develop complex programs enough to be stuck; over the time, I think I got used to working without the luxury as break-points and so on.

When I was introduced to a debugger, I even paid attention to it. I thought to myself: I can just put a printf and I’ll be OK. I don’t need all this stuff. At that time, we used the CodeView, a 16-bit debugger that runs on DOS which is displayed on the picture below.

It didn’t take long for me starting to depend on the debugger doing the simplest things, like brushing my teeth, for example. In fact, some situations, such as writing code for data collectors, writing firmware for hardware that has no display, situations in which we could not count on a serial port to see what was happening with the software, and the unforgettable situation where I had placed an oscilloscope on a particular processor pin to catch our software life signs, so, situations that we would give an arm to have a simple break-point made me realize that the debugger is really necessary.

The funny thing is that nowadays, in college, most students in my class don’t know how to debug software. I’ve tried to explain to my friends the tremendous advantage of using a debugger, but they end up having the same reaction I had years ago: “No way, Fernando, this is too complicated. Just by looking at the source code we end up finding the mistake”. So, that’s fine for me.

Well, we’re here to debug or to talk? Let us debug the driver generated by the traditional post Getting Started. This time we’ll do according to the tradition. We will need two machines, a Null Modem serial cable and last but not least, a copy of WinDbg. No, not worth reading this sentence again, you didn’t take it wrongly; you’ll really need two machines. I don’t know why some people have a certain resistance to believe in this. Well, I think we have overcome that phase and we can continue with the post.

If you do not have a copy of WinDbg, you can download it for free from the Windows Debugging Tools page at Microsoft site.

Let’s take this picture borrowed from the Windbg Help, which shows how we should set computers to do Kernel debug.

The machine named HOST is where WinDbg will run. This machine is, in most cases, the machine where the driver was developed. Let’s assume that this is the machine where the driver was developed and defer the details about how to set the symbol and source directory to another post. The machine named TARGET is where our driver is loaded by the system. The TARGET machine’s operating system don’t necessarily need to be Checked Build nor it is necessary to install any additional kit to the operating system. All you need is your driver and a serial port. All of the Windows NT platform (Windows NT, Windows 2000, Windows XP, Windows 2003 Server and Windows Vista) already bring their native debugger since its installation. Actually, this is a great feature in the use of WinDbg. Imagine that kind of problem that manifests itself on the client machine. You will not want to install anything aggressive or even that will change the scenario that would make the problem not manifest itself anymore. Believe me, this is not so rare as it seems to be. In these cases, simply enable the Debug mode on the TAGET computer and we’re done.

To enable the Debug mode in the TARGET machine, we need to edit some initialization parameters that are in the Boot.ini file located in the system root folder. This file has its attributes as system file, hidden file and also read-only. You may need to configure Windows Explorer to view these files. Using Windows Explorer, go to the root folder, remove the read-only property from the Boot.ini file, then open this file using a text editor like Notepad, for example. The contents of this file is similar to that shown below.

At Operating Systems section you will need to duplicate the referenced system line you will want to debug. Add to its end the /debugport=com1 /baudrate=115200 parameters that will configure the Debug mode. The first parameter selects the COM port being used, while the second selects communication speed. The serial protocol is not the fastest communication way between machines HOST and TARGET and in some cases is annoying having to wait for interactions between WinDbg and debugee system. There are other media that can be used if your computer does not have an available serial port or if you wish more speed and comfort during the Debug. See more details in the post Serial Killers.

The final result of our Boot.ini file should be something like shown below. I’ll skip the lines beginning that describe the operating system for better visualization putting “…” in their places.

[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(2)\WINDOWS
[operating systems]
multi(0)... /NoExecute=OptIn
multi(0)... /NoExecute=OptIn /debugport=com1 /baudrate=115200

After making these changes, you can save the file and restore the original file attributes on it. In Windows XP and Windows 2003, the same described steps above could be done with the help of a tool named Bootcfg.exe. In Windows Vista, the process is quite different and I will describe it in a future post.

Back on the HOST machine, start WinDbg and select Kernel Debug… from the File menu. You should see a window that sets the communication way. Make it so in a compatible way with what was set in the Boot.ini on the TARGET machine. In this case, we are using COM1 serial port and baud rate of 115200. Clicking on OK will make WinDbg opening the serial port on the HOST machine and it will wait until the TARGET machine be ready. At this point, we get the following messages in WinDbg command window .

While the HOST machine waits, make sure your driver is installed on the TARGET machine and restart it. After that, when system is starting, the system loader is  displaying the options found in the Boot.ini edited by you. Select the option which appears [debugger enabled] as shown below.

After selecting this option, the machines HOST and TARGET should connect each other and the Command window would show a text similar to that shown below.

Microsoft (R) Windows Debugger  Version 6.6.0007.5
Copyright (c) Microsoft Corporation. All rights reserved.
 
Opened \\.\com1
Waiting to reconnect...
Connected to Windows XP 2600 x86 compatible target, ptr64 FALSE
Kernel Debugger connection established.
Symbol search path is: *** Invalid ***
****************************************************************************
* Symbol loading may be unreliable without a symbol search path.           *
* Use .symfix to have the debugger choose a symbol path.                   *
* After setting your symbol path, use .reload to refresh symbol locations. *
****************************************************************************
Executable search path is:
*********************************************************************
* Symbols can not be loaded because symbol path is not initialized. *
*                                                                   *
* The Symbol Path can be set by:                                    *
*   using the _NT_SYMBOL_PATH environment variable.                 *
*   using the -y  argument when starting the debugger. *
*   using .sympath and .sympath+                                    *
*********************************************************************
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for
ntkrnlpa.exe -
Windows XP Kernel Version 2600 UP Free x86 compatible
Built by: 2600.xpsp_sp2_gdr.050301-1519
Kernel base = 0x804d7000 PsLoadedModuleList = 0x805531a0
 

Well, so far we know that the machines are connected. Pressing Ctrl + Break in Windbg, we will make the system freeze in the TARGET machine and the control is passed to the debugger. The debugger is ready to receive your commands when you get a command prompt KD indicated by the letters at Command window bottom left.

Just to make a simple test, type “lm” command and hit enter. This command lists the modules loaded by the system. Note that the Useless driver is not on this list yet. This happens because the driver instance is configured to have its execution started manually, so, the driver has not yet been loaded by the system. Then, select the item Open Source File… from File menu and open Useless.c file. Click on the DriverEntry function name and hit F9. Although there is no visible sign, we put a break-point on this function. The fact of having no visual change is due to the fact that our module has not been loaded yet. We can be sure that the breakpoint is installed listing the breakpoints with the “bl” command.

kd> bl
 0 e f9fb3430     0001 (0001) Useless!DriverEntry

Now we launch the “g” command that will cause the system to return to its normal execution.

Once the system is loaded, we will start the driver through the “net start Useless” command . When the driver starts, the DriverEntry entry point runs and consequently, we have its execution stopped at our breakpoint. The TARGET machine will freeze while the debugger has control over the system. Note that now our module is loaded, the breakpoints are easily identified by lines with red background color.

Well, the first steps have already been done, the commands and details on how to debug the kernel for Windows would be outside the scope of this post. But a good tip on how to obtain tons of details about this subject is the Windows 2000 Kernel Debugging book. The book is not one of my favorites; it gives a good introduction to the subject besides talking about how to use and build Debug Extensions, but does not bring the used techniques by real Kernel Debugging ninja masters. Another excellent information source on this subject is the discussion list Windows Debugger Users List dedicated to Windbg. That’s all without forgetting the Help.

This was an initial post about the subject, wait for future posts where I will give the steps about how to use Windbg with VMware and how to debug Windows Kernel with one machine using SoftIce (God rest his soul).

Have fun… 😉