CSE451 Spring 2008 Project #1

Out: April 3 2008

Due: April 17 2008 

Updates: Amendment #1

Objectives 

The projects in this class involve building and modifying the Microsoft Windows Operating System.  This is the first of four expected projects.  It is mainly a familiarization exercise leading into the subsequent projects.  The principal objectives for this first project are: 

  1. Learn to build and debug the Windows kernel.
  2. Learn the flavor and nature of some of the NT system calls
  3. Learn how to modify the kernel and keep track of system information between calls
 

Ancillary to all this is that you’ll learn some of the guiding principles used in the design of the Windows Operating System.

Getting Started 

You will need to become familiar with two main areas.  They are the building the Windows kernel and using Virtual PC for testing and debugging.  All of the sources and reference materials are located at o:\cse\courses\cse451\08sp and accessible from any machine in the lab.  There are currently four subdirectories in the 08sp directory 

  1. Project1 – The sources for the Windows kernel and sample test program.
 
  1. Reference Material – Useful and historical reference material for this class
 
  1. Tools – Tools needed for this project
 
  1. Virtual Machines – Base virtual hard disk containing the Windows OS.
 

The first two projects are individual efforts.  The last two will be done in groups of three.  Workspace for your group will be on o:\unix\projects\instr\CurrentQtr\cse451.  The TA’s will provide details assigning your group project space later in the quarter. 

- Building your own kernel 

Here are the steps for making a private copy of the Windows sources and building your private kernel. 

  1. Get a private copy: Copy the entire tree o:\cse\courses\cse451\08sp\Project1 to a directory on z: or your local hard disk.  For example from a cmd I would issue the instruction  
     
       
    xcopy /DECHKY o:\cse\courses\cse451\08sp\project1 z:\project1 
  2. Start a wrk window: Then from a cmd window run \project1\wrk.cmd. This will setup the path and aliases you need to build the kernel.  You can also setup a shortcut on your desktop that issues the target command  
     
       
    %windir%\system32\cmd /K “z:\project1\wrk.cmd” 
  3. Build the kernel: In the wrk window cd down into the ntos directory and build the kernel 
     
       
    cd \project1\base\ntos 
      nmake -nologo %arch%= 
     
    The resultant kernel is located in \project1\base\ntos\build\exe and it is called wrkx86.exe.  There are also a symbol file for debugging and a readable memory map.
 
  1. Build the sample test program: Then in the wrk window cd to the test directory and build the test program 
     
       
    cd \project1\test 
      makeit 
     
    The resultant executable is called test.exe
 

From steps 3 and 4 you now have two executables that you want transfer over to the virtual hard disk containing your bootable windows system. 

- Booting and debugging: 

On each lab machine in “\program files\Microsoft Virtual PC\images” is a readonly file called ws03esp1.vhd containing a bootable Windows system.  You will be creating what is called a Differencing disks that will essentially be the ws03esp1.vhd disk fronted by your private changes.   

  1. Create cse451project1.vhd: Without going into the complete step-by-step details you want to start Microsoft Virtual PC on the local machine and with the Virtual Disk Wizard create a new Virtual Hard Disk called cse451project1.vhd is a differencing disk whose parent is ws03esp1.vhd.  On my system my new vhd is 
     
     
    %USERPROFILE%\My Documents\My Virtual Machines\cse451project1.vhd
 
  1. Create cse451project1.vmc:  Without going into the complete step-by-step details you need to create a virtual machine using the New Virtual Machine Wizard in Microsoft Virtual PC.  Create a new Virtual Machine called cse451project1.vmc for Windows Server 2003, and specify cse451project1.vhd as your existing virtual hard disk.

  1. Setup COM2 on cse451project1.vmc:  Via the settings button for the virtual machine you need to specify a named pipe for COM2.  Specify the named pipe as “\\.\pipe\ws03com2
 
  1. [This steps works without VHDMOUNT]  Use this step until the lab machines get VHDMOUNT working.
 
    1. Start cse451project1:  The vhd contains two bootable kernels.  The default boot kernel is called “wrkx86”and the second choice is “Windows Server 2003 Enterprise”.  Start cse451project1 and boot the second choice.
 
    1. Share Folder: After the system fully booted, right click the small folder icon on the lower left side of the window.  Select “Share Folder” and choose a the local C: disk. (network drives won’t work)
 
    1. Login to the vmc: Login as Administrator no password.
 
    1. Copy files:  On the host system you first need to copy the files wrkx86.exe and test.exe from Z: onto the C: disk.  Then on the virtual machine copy wrkx86.exe off of Z: (which translates to C: on the disk) to c:\windows\system32.  And also copy test.exe from Z: to the subdirectory c:\test.
 
    1. Shutdown the vmc:  The machine needs to be rebooted.  Shut it down and go to step 6.
 
  1. [This step is only possible if VHDMOUNT is installed on the lab machines]  Skip this step until the lab machines get VHDMOUNT working.
 
    1. Mount cse451project1.vhd: After the vhd is created is can be mounted on the local machine using vhdmount.   The command is “vhdmount /p <filename>”.  In the wrk window there is a command called mount that will mount the file if is it located in “My Virtual Machines”
 
    1. Copy new files onto cse451project1.vhd: After it is mounted the local system will assign it a drive letter (for example “e:”).  You then need to replace the wrkx86.exe found in e:\windows\system32 with your new copy.  Also you will need to copy the test.exe program onto e:.  Please make a subdirectory called e:\test and copy the program there.
 
    1. Dismount cse451project1.vhd: Now you are ready to dismount the vhd using “vhdmount /u /c all” or “dismount” in the wrk window.
 
  1. Start cse451project1  and the debugger:  You are now ready to start the virtual machine and start the windbg (kernel debugger). Use the start button on the Virtual PC console to start cse451project1 and immediately afterward type “winbag” in the wrk window.  The winbag command alias will start windbg with the proper named pipe for debugging.
 
  1. Setup search paths in the debugger:  After windbg starts you will need to setup the search path for the kernel symbol, source, and image.  The symbol and image path are both the same, they are “z:\project1\base\ntos\build\exe”  The source path is “z:\project1\base\ntos”
 

You now should have a running system that you can login to and run the test program. 

Your assignment: 

Your assignment is to modify the windows kernel and a test program to monitor a set of system calls (nee APIs).  Here is some background information you will need to understand and complete this project.  All user programs that need to utilize an NT system service (e.g., opening or writing to a file) enter into the kernel code through what are called “NT” calls.  There are hundreds of different NT calls into the system; all begin with the two letter prefix “Nt”.  The names of some of the API’s are NtCreateFile, NtOpenFile, NtClose, NtQuerySystemInformation, NtSetTimer, and so forth.   

The “C” header files for these system calls are all declared in the directory “public\sdk\inc”.  Here is a partial list of the files in the directory with a brief description of its contents. 

ntdef.h    - basic definitions of common data types used by everyone

ntrtl.h    - runtime library for use by everyone in the kernel

ntstatus.h - all the possible return status values for system calls

bugcodes.h - system bug check codes

ntexapi.h  - executive routines

ntioapi.h  - I/O routines

ntkeapi.h  - kernel routines

ntlpcapi.h - local procedure calls routines

ntmmapi.h  - memory management routines

ntobapi.h  - object management routines

ntpsapi.h  - process/thread handling routines

ntseapi.h  - security routines 

Your assignment is to modify the system to monitor certain APIs.  You are to report the number of times certain classes of APIs are called and give a distribution of their return values.  The classes we want monitored are all the Query, Set, Open, Create, Close, Get, Read, and Write calls.  For example, there are four Read APIs called NtReadFile, NtReadFileScatter, NtReadRequestData, and NtReadVirtualMemory.  You are to collect statistics on how many times these four routines were called since boot time and the distribution and frequency of their return values (see ntstatus.h for return values).  Report the statistics for this API group, not individual APIs.  For example, some of the test program output might be: 

API     Called  Returned values 

NtOpen   56    success 50, access denied 6

NtRead   123    success 100, unsuccessful 20, Access Violation 3

   : 

You are to report all eight classes of APIs. 

If you “grep” the sources for CSE451 you will find three files were we started to expand upon the already existing NtQuerySystemInformation API.  This is skeletal code that the user program in the test directory uses to both send and retrieve information from the kernel.  Your task is to understand the CSE451 additions to the kernel and the test program. And then modify both to report back the class API statistics. 

How to test program formats the report is up to you.  However the report must be easy to read.  As the due date approaches we will provide you with a command script that will run the test program and spawn various other programs that exercise the API calls. 

Turn-in: 

Be prepared to turn in the following 

  1. Executables images of your test program, and the modified kernel.
  2. Source code for your test program and the modules that you have modified and added to your kernel.

You'll be submitting the source code and executables to Catalyst. Please seperately submit test.exe, wrkx86.exe, and a zip of your entire source directory (After running 'nmake clean').

Grading Criteria: 

Your project will be graded based on the following criteria: 

  1. [50%] Does it accomplish the assigned task?
  2. [15%] Are your modifications to the kernel clear and easy to understand?
  3. [15%] Are your modifications to the kernel correct?
  4. [10%] Is the output of the test program clear and easy to understand?
  5. [10%] Is the coding of the test program clear and easy to understand?

Amendment #1

The original return status accounting portion is more difficult than it need be. Instead of itemizing each individual return value, you can track the return values in four buckets (Success, Information, Warning, and Error). You will find a set of macros in public\sdk\inc\ntdef.h that can help accomplish this.

        //
        // Generic test for success on any status value (non-negative numbers
        // indicate success).
        //
        #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)

        //
        // Generic test for information on any status value.
        //
        #define NT_INFORMATION(Status) ((ULONG)(Status) >> 30 == 1)

        //
        // Generic test for warning on any status value.
        //
        #define NT_WARNING(Status) ((ULONG)(Status) >> 30 == 2)

        //
        // Generic test for error on any status value.
        //
        #define NT_ERROR(Status) ((ULONG)(Status) >> 30 == 3)

So your output can now be more uniform, and look something like.

        API       Total
        Class     Calls       Success     Information Warning     Error
      ------    --------    --------    --------    --------    --------

        NtOpen          56          50           2           3           1
        NtRead         123         100           0           0          23