CHAPTER 8: Security
498 Using GetSID to View Account SIDs
502 Viewing Access Tokens with the Kernel Debugger
517 Viewing Process and Thread Security Information
EXPERIMENT
Viewing Control Areas
To find the address of the control area structures for a file, you must first get the address of the file object in question. You can obtain this address through the kernel debugger by dumping the process handle table with the !handle command and noting the object address of a file object. Although the kernel debugger !file command displays the basic information in a file object, it doesn't display the pointer to the section object pointers structure. However, because file objects are defined in the public DDK header file Ntddk.h, you can look up the offset (0x14 in Windows 2000). So, simply examine the pointer at offset 0x14 into the file object, and you'll have the section object pointers structure. That structure is also defined in Ntddk.h. It consists of three 32-bit pointers: a pointer to the data control area, a pointer to the shared cache map (explained in Chapter 11), and a pointer to the image control area. From the section object pointers structure, you can obtain the address of a control area for the file (if one exists) and feed that address into the !ca command.
Another technique is to display the list of all control areas with the !memusage command. The following excerpt is from the output of this command:
kd>!memusageloadingPFNdatabase
loading(99%complete)
Zeroed:9(36kb)
Free:0(0kb)
Standby:2103(8412kb)
Modified:300(1200kb)
ModifiedNoWrite:1(4kb)
Active/Valid:30318(121272kb)
Transition:3(12kb)
Unknown:0(0kb)
TOTAL:32734(130936kb)
Buildingkernelmap
Finishedbuildingkernelmap
UsageSummary(inKb):
ControlValidStandbyDirtySharedLockedPageTablesname
8119b60830005280000mapped_file(WINWORD.EXE)
849e7c689600000NoNameforFile
8109c3882400000mapped_file(DEVDTG.PKG)
8140248823600000NoNameforFile
80fba0a826800000mapped_file(kernel32.pdb)
810ab16815043800000mapped_file(OUTLLIB.DLL)
81126a0802760000mapped_file(H)
81112d2865600000NoNameforFile
The Control column points to the control area structure that describes the mapped file. You can display control areas, segments, and subsections with the kernel debugger !ca command. For example, to dump the control area for the mapped file Winword.exe in this example, type the !ca command followed by the Control number, as shown here:
kd>!ca8119b608ControlArea@8119b608
Segment:e2c28000Flink0Blink:0
SectionRef1PfnRef372MappedViews:1
UserRef2Subsections6FlushCount:0
FileObject8213fb98ModWriteCount0SystemViews:0
WaitForDel0PagedUsage3000NonPagedUsage100
Flags(90000a0)ImageFileHadUserReferenceAccessed
File:\ProgramFiles\MicrosoftOffice\Office\WINWORD.EXE
Segment@e2c28000:
Baseaddress0TotalPtes86aNonExtendPtes:86a
Imagecommitd7ControlArea8119b608SizeOfSegment:86a000
ImageBase0Committed0PTETemplate:919b6c38
BasedAddr30000000ProtoPtese2c28038ImageInfo:e2c2a1e4
Subsection1.@8119b640
ControlArea:8119b608StartingSector0NumberOfSectors8
BasePtee2c28038PtesInsubsect1UnusedPtes0
Flags15SectorOffset0Protection1
ReadOnlyCopyOnWrite
Subsection2.@8119b660
ControlArea:8119b608StartingSector10NumberOfSectors3c00
BasePtee2c2803cPtesInsubsect780UnusedPtes0
Flags35SectorOffset0Protection3
ReadOnlyCopyOnWrite
Subsection3.@8119b680
ControlArea:8119b608StartingSector3C10NumberOfSectors5d8
BasePtee2c29e3cPtesInsubsectc1UnusedPtes0
Flags55SectorOffset0Protection5
ReadOnlyCopyOnWrite
Subsection4.@8119b6a0
ControlArea:8119b608StartingSector41E8NumberOfSectorsa8
BasePtee2c2a140PtesInsubsect15UnusedPtes0
Flags55SectorOffset0Protection5
ReadOnlyCopyOnWrite
Subsection5.@8119b6c0
ControlArea:8119b608StartingSector0NumberOfSectors0
BasePtee2c2a194PtesInsubsect1UnusedPtes0
Flags55SectorOffset0Protection5
ReadOnlyCopyOnWrite
Subsection6.@8119b6e0
ControlArea:8119b608StartingSector4290NumberOfSectors90
BasePtee2c2a198PtesInsubsect12UnusedPtes0
Flags15SectorOffset0Protection1
ReadOnlyCopyOnWrite
EXPERIMENT
Viewing Access Tokens with the Kernel Debugger
The kernel debugger !tokenfields command displays the format of an internal token object. Although this structure differs from the user-mode token structure returned by Win32 API security functions, the fields are similar. For further information on tokens, see the description in the Platform SDK documentation.
The following output is from the kernel debugger's !tokenfields command:
kd>!tokenfields!tokenfields
TOKENstructureoffsets:
TokenSource:0x0
AuthenticationId:0x18
ExpirationTime:0x28
ModifiedId:0x30
UserAndGroupCount:0x3c
PrivilegeCount:0x44
VariableLength:0x48
DynamicCharged:0x4c
DynamicAvailable:0x50
DefaultOwnerIndex:0x54
DefaultDacl:0x6c
TokenType:0x70
ImpersonationLevel:0x74
TokenFlags:0x78
TokenInUse:0x79
ProxyData:0x7c
AuditData:0x80
VariablePart:0x84
You can examine the token for a process with the !token command. You'll find the address of the token in the output of the !process command, as shown here:
kd>!process3801!process3801
SearchingforProcesswithCid==380
PROCESSff8027a0SessionId:0Cid:0380Peb:7ffdf000ParentCid:0124
DirBase:06433000ObjectTable:ff7e0b68TableSize:23.
Image:cmd.exe
VadRoot84c30568Clone0Private77.Modified0.Locked0.
DeviceMap818a3368
Tokene22bc730
ElapsedTime14:22:56.0536
UserTime0:00:00.0040
KernelTime0:00:00.0100
QuotaPoolUsage[PagedPool]13628
QuotaPoolUsage[NonPagedPool]1616
WorkingSetSizes(now,min,max)(261,50,345)(1044KB,200KB,1380KB)
PeakWorkingSetSize262
VirtualSize11Mb
PeakVirtualSize11Mb
PageFaultCount313
MemoryPriorityFOREGROUND
BasePriority8
CommitCharge86
kd>!tokene22bc730
!tokene22bc730
TOKENe22bc730Flags:9SourceUser32b"AuthentId(0,ae6d)
Type:Primary(INUSE)
TokenID:1803a
ParentTokenID:0
ModifiedID:(0,12bf5)
TokenFlags:0x9
SidCount:9
Sids:e22bc880
RestrictedSidCount:0
RestrictedSids:0
PrivilegeCount:17
Privileges:e22bc7b4
EXPERIMENT
Viewing Process and Thread Security Information
You can view process and thread security descriptors and access tokens with the Process Explode utility (Pview.exe). (This tool is part of the Windows NT 4 resource kits, but it isn't included with the Windows 2000 resource kit tools. You can, however, download it from www.reskit.com.) The numbering of the six buttons in the Security and Token sections of the Process Explode utility matches up with the process and thread security structures shown in Figure 8-7.
In this example, buttons 4 (ACL for thread token) and 6 (thread access token) are grayed out (disabled) because the currently selected thread (number 1700) has no thread-specific access token.
Try looking at the process ACL for a process in your interactive session—you should see your user ID and SYSTEM in the ACL with full control permissions.
To see process security in action, try the following:
1. Create a local username named "test." To add a user, start Computer Management. (In Control Panel, open Administrative Tools and then click on Computer Management; or select Run from the Start menu and enter compmgmt.msc.) Expand Local Users And Groups (under System Tools), right-click on Users, and select New User. Enter the username test (no password), clear the User Must Change Password At Next Logon flag, and press Create. (Note: Your domain or local group policies might require that you enter a password.)
2. Open a Windows 2000 Command Prompt window. (From the Start menu, select Programs/Accessories/Command Prompt.)
3. Type runas /user:test cmd to create a command prompt running under the test username you just added. (Note: You might need to prefix test with the machine name or domain name, as in runas /user:machine\test cmd.)
4. From this command prompt, run Pulist from the Windows 2000 resource kit. Notice that you can't see the security ID of the processes on the system other than the one running Cmd.exe and Pulist.exe under the security context of the test username. The reason you can't see this security ID is that the test username isn't in the ACL on the process access token on any of the other processes—therefore, you have no permission to see who these processes are.
5. Now switch back to the command prompt started in step 2 (running under whatever account you were logged on to for this experiment), and run Pulist again. You should see the security IDs of all the processes in your interactive session (and the system processes if your account is a member of the local Administrators group). However, you shouldn't be able to see the security ID of the process running Cmd.exe under the test username (created in step 3) for the same reason that from the test username you can't see the processes not running under test.
6. Now run Process Explode again, select a process in your interactive session (such as Explorer.exe), and change the ACL on the process and the process access token to allow the user test to have read access. Modify the process by pressing the Process button to bring up the Process Permissions dialog box. Press Add to add an entry to the process ACL. When the list of groups is displayed, press the Show Users button, scroll down the Names list, select the test username, press Add, and then press OK. You should now see the test username in the ACL. Press OK to make the change on the Explorer process. Follow the same steps again for the process access token, this time pressing the P.Token button instead of the Process button.
7. Now go back to the process running Cmd as user test, and run Pulist again. This time, you should be able to see the security ID of the process Explorer.exe because you've granted read access to that process's access token.
The following steps don't work on Windows 2000 server systems that have Terminal Services installed. The reason they don't work in this context is explained after step 10.
8. As a final test, start Task Manager, click on the Applications tab, right-click on "cmd (running as test)," and select Go To Process. This takes you to the Processes tab with the cmd.exe process highlighted. Click on this process, and then press the End Process button. (Press Yes in the warning message box that appears.) You should get an access denied error because you're not in the process ACL for that process.
9. As an added exercise, rerun Pview.exe from the command prompt running under test and alter the process access for the Cmd.exe process running under test to grant full access to the username you're currently running under. (Press the Process button in PView, press Add, and then add your username to the ACL, remembering to select full control access.)
10. Retry step 8—this time, you should be able to terminate the command prompt running under the test username because you granted yourself full access to that process.
The reason that steps 8 through 10 don't work on a system with Terminal Services installed is because the steps rely on the fact that, on systems without Terminal Services, Task Manager uses the TerminateProcess function to end processes. However, when you direct Task Manager to end a process on a system running in a Terminal Services environment, Task Manager calls on Termsrv.exe, the terminal services service, to perform the process termination. Because Termsrv.exe is a service process running in the System account, it has the debug privilege, which it uses to open a process it's terminating without regard to the process's token or process security settings.