chml and regil: Utilities To Manage Windows Integrity Levels

NEW: CHML 1.53 released 16 July 2009, fixes a subtle bug.

NEW: REGIL 1.0 released 26 Feb, the first tool to let you work with Registry integrity levels!

Integrity Levels?  What are They?

Vista and later versions of Windows include a new notion of what were originally called "Mandatory Integrity Controls" but eventually became "Windows Integrity Levels," (WILs) often shortened further to "integrity levels" or ILs.   Under WIL, every object that can have permissions can also have a label, stored in roughly the same place as it stores permissions, that identifies its "integrity level." Another way to think of an integrity level is a measure of how trustworthy it's considered by the system.  There are six integrity levels, from highest trustworthiness to lowest:

  • Trusted Installer
  • System (operating system processes)
  • High (administrators)
  • Medium (non-administrators)
  • Low (temporary Internet files)
  • Untrusted

Files, folders and Registry keys have integrity levels, as do processes (including user sessions -- if you're logged on as administrator, your session has higher integrity ("high") than it would normally ("medium").   What good are these "trustworthiness levels?"  Well, they act as a kind of second, overriding level of Windows permissions.  When a lower-integrity user tries to modify a higher-integrity object, then Windows integrity controls blocks the modification attempt, and blocks it even if the object's permissions list contains a "full control" permission for that user.  It is, thus, a sort of set of uber-permissions, albeit a simple one:  think of it as "ILs trump ACLs."  (It sounds better when you say it out loud.)

Sounds neat?  I thought so, and when I found that Microsoft had installed this new plumbing in Vista, 2008, Windows 7 and 2008 R2 Server  but weren't doing anything with it, I set out to learn a bit of C++ and write a couple of apps:

  • Chml ("change mandatory label," a now-outdated name) lets you view and change ILs on files and folders. Version 1.5 brings some big changes to Chml, so if you've got an earlier version, give the revision notes a look.
  • Regil ("Registry integrity levels"),  a companion app released in February 2009 -- lets you view and change ILs on Registry keys.  It also contains a step-by-step tutorial on modifying Registry integrity levels.

What chml Does

When I set out to write my book Administering Windows Vista Security:  The Big Surprises, I knew that the book would be incomplete without an in-depth look at Windows integrity controls.  But no tools existed that could let me modify an integrity level.  Microsoft eventually came out with a tool "icacls" that allows some basic manipulation of integrity levels, but it didn't work properly until just a few weeks before Vista shipped, and I needed a tool much earlier than that, hence Chml.  Nor was my time wasted because, as you'll see, it turned out that icacls is too rudimentary to really showcase Windows integrity controls' capabilities.  Furthermore, Chml's design goals were simple.  I wanted a tool that would:

  • Install simply and with a minimum of trouble.  Chml is, therefore, a command-line tool that is just a simple EXE file, with no setup program required.  Just copy it anywhere on your system's path and you can start it from any command line (although you'll need to be elevated to change an IL).
  • Allow me to view a file or folder's integrity level.
  • Allow me to change a file or folder's integrity level.
  • Allow me to experiment with extensions of the basic Windows integrity control, and go beyond the standard "no write up" policy (no low-integrity process can modify a higher-integrity object) to the implemented but unused "no read up" policy, which blocks any attempts by a lower-integrity process or user to read the object.  This seemed like a potentially nice feature in a world beset by Web-borne spyware!

If You're Using Windows 7...

Between Vista and Windows 7, Microsoft changed something -- I haven't figured out what, yet -- that broke the -fs ("force system") switch on chml.  That means you can't force an integrity level to or from System directly from chml under Windows 7.  You can work around this by running chml under Sysinternals' psexec tool.  Just use the -s switch on psexec and start a command prompt like so:

psexec -s cmd

The command prompt window now runs as System (you can verify that by running the  "whoami" command) and now chml will let you work with items that have the "System" integrity level.  Sorry for the inconvenience, I'll get around to figuring it out eventually.

Downloading Chml and Regil

Here they are:

  • chml.exe is about 110K.
  • regil.exe is about 120K (lots more help and tutorial stuff than Chml currently has, as command-line Reg hacking is somewhat less familiar to most and easier to crash one's system with)

Installing them is trivial.  Just right-click the hyperlinks above and save the EXE somewhere on your Windows path.  (I usually store it in the \windows\system32 folder.)  There's no setup, just open a command prompt and type "chml" or "regil" followed by whatever options you need.  (There's lots of help if you don't include any options.)

What Rights/Permissions Do I Need to Use Chml/Regil?

You can use chml "right out of the box" to view a file or folder's integrity level just by typing chml fileorfolder, as in

C:\>chml \windows\notepad.exe

But if you want to modify an object's integrity level, then there are several rules.  To modify a file/folder's IL, you

  • Need the ability to take ownership (or already have ownership) and the ability to modify the file/folder's permissions
  • It appears that you've got to be running as a member of the Administrators group
  • Alternatively, you need the "Modify an object label" privilege

You don't need the "Modify," privilege despite what I said in my book; I was working from pre-release materials and apologize for the error.  Just being a member of the Administrators group should be all you need to do anything that you want with chml, particularly with the -fs option.

I was quite surprised to find that the rules for changing Registry entries are quite different:  you've got to be either an admin with the ability to take ownership or be the owner, but -- here was the strange part -- as an owner you can actually modify a Registry key's integrity level from a non-elevated command prompt, which you can not do with files or folders.  With Regil, I can (while sitting at a non-elevated command prompt with an integrity level of Medium) assign a Medium IL to a Registry folder.  Odd!

There's online help for other stuff (or feel free to email me), but here are few quickstarts.

Modifying an Integrity Level

To see chml's basic powers in action, open an elevated command prompt and create a folder.  In my example, I'll create one named c:\test.  Then set it to low integrity by typing

chml c:\test -i:l

Your run will look something like this:

C:\>chml c:\test -i:l

Chml v1.50 -- View and change Windows file/folder integrity levels
by Mark Minasi (c) 2006-2009 www.minasi.com email:xxx
Successfully changed c:\test's integrity level.

Folder c:\test's integrity level: Low
Inheritance flags:
Containers in this container should inherit IL (CI)
Objects in this container should inherit IL (OI)
Integrity policies:
No read up: disabled
No execute up: disabled
No write up: enabled

The syntax is simple:  just follow chml with the name of the folder, followed by a lowercase "i," a colon, and then one of the letters u, i, m, h, or s, which signify Untrusted, Low, Medium, High, or System.  (By the way, if you want to skip the copyright banner, just add the "-b" option.)  Now create a file inside c:\test named "testfile.txt" -- it doesn't matter what text is in it, or if there is any text there at all.  Then ask chml what integrity label the file has, like so:


C:\>echo Hi there>test\testfile.txt

C:\>chml c:\test\testfile.txt

C:\>chml c:\test\testfile.txt

Chml v1.50 -- View and change Windows file/folder integrity levels
by Mark Minasi (c) 2006-2009 www.minasi.com email:xxx

File c:\test\testfile.txt's integrity level: Low
Inheritance flags:
This object inherited this IL (ID)
Integrity policies:
No read up: disabled
No execute up: disabled
No write up: enabled

What you're seeing here is that just as objects in folders can inherit permissions from their parent folders, they can also inherit integrity levels.

Seeing the Effect of "No Write Up"

Recall that the main value of Windows integrity controls is to keep lower-integrity processes from modifying higher-integrity objects.  We'll demonstrate that by setting a file's integrity level to High, then we'll open up a non-elevated command prompt (which will run at Medium) and see that we can't erase the file.

From the elevated command prompt, raise c:\test to High integrity like so:

C:\>chml c:\test -i:h -b

Successfully changed c:\test's integrity level.

Folder c:\test's integrity level: High
Inheritance flags:
Containers in this container should inherit IL (CI)
Objects in this container should inherit IL (OI)
Integrity policies:
No read up: disabled
No execute up: disabled
No write up: enabled

(Notice that I added the "-b" option, which stops Chml from printing the copyright banner.)  Now, open a second command prompt, but don't elevate it.  Try to erase c:\test\testfile.txt and you'll get an "Access is denied" error.

Setting Something to "No Read Up"

Now we'll take it a bit further and try out that "no read up" policy.  There are actually three Windows integrity control policies:  no read up, no write up, and no execute up, and you can apply any combination of them to any object using the -nr, -nw and/or -nx switches.  Set c:\testfile's policy to "no read up/no write up" like so, from the elevated command prompt:

C:\>chml c:\test -i:h -b

Successfully changed c:\test's integrity level.

Folder c:\test's integrity level: High
Inheritance flags:
Containers in this container should inherit IL (CI)
Objects in this container should inherit IL (OI)
Integrity policies:
No read up: disabled
No execute up: disabled
No write up: enabled
C:\>

Now try to examine the file or folder at all from the non-elevated command prompt, or even from Explorer for that matter, and you'll again see an "access is denied."  Wondering why I had to once again assign an integrity level of High, rather than just using a -nr?  Integrity labels are simple:  each object only gets one, so to modify one you can't just specify changes, you've got to redefine the whole thing.

Setting an Integrity Level to/from "System:" the -fs and -nfs Options

In the "trustworthiness" hierarchy, non-admin users are Medium admin users are High and some operating system things are System.  The problem with System are a couple of basic rules about Windows integrity-wise:

  • You can only raise objects as high as your integrity level, no further, and
  • You can only lower objects whose integrity equals yours, or lower.

Thus, the problem with System, it seemed to me early on, was "what would happen if a bad guy installed some malware and gave it an IL of System somehow?"  We admins, who are merely High, couldn't delete a System file or folder!  The answer would be to run Chml as System somehow... but how?  When I first wrote Chml, I figured out how to run it as System three ways:

  • Create a WinPE CD, boot the computer from the CD and run Chml.  WinPE logs you on as System, so when you run Chml, you've got the juice to raise a file to System or, more important, lower an unwanted file with System integrity to something lower, enabling you to delete it.
  • Schedule a Chml task with the Task Manager, taking advantage of Task Manager's option to run a scheduled task as System.  (That's the System account, and when it's running, it runs at System integrity level, not surprisingly.)
  • Download Sysinternals' "psexec" tool and use its -s option to run Chml at System integrity.

Those are all still possible, but they're clumsy, which was one of the main reasons that I built Chml 1.5.  It can now lower files from System or raise them to System.  How'd I do it?  Simple:  I just construct a scheduled task that executes Chml, tell the system to run it immediately, and then delete the task.  Chml doesn't go the task scheduler route -- it's called "forcesystem" mode inside Chml -- by default unless it sees an explicit "-i:s" command, so if you ever need that extra juice, add "-fs" to your Chml command.  Again, this is easiest to grasp with an example or two.

First, let's raise test's integrity to System, like so:

C:\>chml test -i:s

Chml v1.50 -- View and change Windows file/folder integrity levels
by Mark Minasi (c) 2006-2009 www.minasi.com email:xxx

Successfully changed C:\test's integrity level.

Folder C:\test's integrity level: System
Inheritance flags:
Containers in this container should inherit IL (CI)
Objects in this container should inherit IL (OI)
Integrity policies:
No read up: disabled
No execute up: disabled
No write up: enabled

As I said above, whenever Chml sees "-i:s" then it automatically activates "forcesystem," creating the scheduled tasks.  But now try to lower test's integrity to Medium:

C:\>chml test -i:m

Chml v1.50 -- View and change Windows file/folder integrity levels
by Mark Minasi (c) 2006-2009 www.minasi.com email:xxx

UPDATEIL: Access denied when trying to write new integrity label.

Chml was unable to update test's integrity label, no change occurred.
Check that you are running at sufficient integrity and the right
permissions -- you need to either own the folder or have the Take Ownership
right and the ability to change permissions on it. Also, Chml must run
at an integrity level greater than or equal to both the object's current IL,
and the IL that you want to raise it to. (Thus, it takes System integrity
to raise a file to System integrity, and it takes System integrity to drop
a System integrity file down to something below it.)

Folder test's integrity level: System
Inheritance flags:
Containers in this container should inherit IL (CI)
Objects in this container should inherit IL (OI)
Integrity policies:
No read up: disabled
No execute up: disabled
No write up: enabled

That's because you were running as a mere administrator with High integrity, so that System file merely laughed when you tried to change its integrity.  You canna do tha' job on impulse, laddie... add "-fs" to engage warp drive!

C:\>chml test -i:m -fs

Chml v1.50 -- View and change Windows file/folder integrity levels
by Mark Minasi (c) 2006-2009 www.minasi.com email:xx

Successfully changed C:\test's integrity level.

Folder C:\test's integrity level: Medium
Inheritance flags:
Containers in this container should inherit IL (CI)
Objects in this container should inherit IL (OI)
Integrity policies:
No read up: disabled
No execute up: disabled
No write up: enabled

-fs has one problem, though: what about WinPE?  It's a great, basic, simple and free operating system for troubleshooting and repairing Windows systems (look at Newsletter #59 for the skinny on it) but it doesn't have a task scheduler and wouldn't need it in this case anyway because, again, it lets you run as System anyway.  Sometimes, then, you want to keep Chml from trying to use the Task Scheduler altogether and you can do that with the "-nfs" option.  The only time you'd need it would be if you ever ran a command with the "-i:s" option, recall.

That's not all that's new in Chml 1.5, though... take a look at the revision history below.  Download the latest Chml and please drop me a line to let me know how you like it.

I Want To Change Entire Folders!

I know, I know, you want chml to be able to do stuff like "chml *.txt" to work on all text files in the current folder, or "chml *.txt /s" to work on all text files in the current folder and all subfolders.  One of these days I'll figure it out, but I've not had the time... but here's a great workaround:  the "for" command.  It looks like

for [/r]%f in (filepattern) do [whatever you want chml to do, putting "%f" where the filename would go]

For example, to lower the integrity level of all text files in the current folder, type

for %f in (*.txt) do chml %f -i:l

To recurse folders, change "for" to "for /r."  I hope this fills a gap until I can get the time to figure out wildcards.  Thanks!

Using Regil

Regil's designed to work very similarly to chml, but for Registry entries.  It's got a lot more help built-in than chml does:

  • regil -? shows syntax
  • regil all by itself offers some cautions (you do not want to blow up your Registry)
  • regil -st offers a short list of working examples
  • regil -lt ("long tutorial") explains integrity levels and offers a multi-step (and completely safe, if followed!) tutorial in modifying Registry integrity levels
Some examples (from regil -st):

Viewing Current ILs

Just invoke regil with the Registry key's name, as in

regil hkcu\software\AppDataLow

(That's one of the few Registry keys with a built-in IL; most are unlabeled.)

Modifying a Registry Key's IL

Use the -i: option to raise/lower the IL:

regil HKEY_CURRENT_USER\Iltest -i:l

That changes HKCU\Iltest's IL to be low and to set the 'inherit' flag, so any subkeys created under that key will also be low.

I strongly suggest that you NOT mess with any out-of-the-box Registry key settings until you've gotten some experience with regil. (Really. Trust me.)

Removing Existing Integrity Labels

To remove an explicit IL, use -rl:

regil hklm\software -rl

Viewing an Existing SDDL String

Simplify understanding ILs under the hood; use -ss

regil HKCU\Software\AppDataLow -ss

Directly Modify an IL Via an SDDL String

use "-ws:"

regil hkcu\iltest -ws:S:(ML;OICI;NWNR;;;ME)

Sets the iltest subkey in the HKCU key (which doesn't exist by default) to integrity, any subkeys inherit, and both a no-write-up and a no-read-up policy.  

What about System?  Unfortunately I've not had the time to add warp drive to Regil, but I will when I can.  Until then, try one of the three routes that I outlined above.

If experimenting with ILs interests you, give Regil a try and let me know what you think.

Revision History

16 July 2009:

  • Version 1.53:  Again Peter Strelecki's eagle eye picked up a problem: you can't pass chml a folder parameter that points to a root directory, like "chml c:\" or "chml \" or the like.  Looking into it, I found that I was validating file or folder names (checking that they existed in the first place) with an API recommended by many, the "FindFirstFile" API.  A closer look at the API's docs note that it will specifically blow up you pass it -- you guessed it -- stuff like c:\, \ or the like.  So I recoded it to use a different, older, more useful (in this case) API, GetFileAttributes.  And in the process of testing the new chml, I discovered something very interesting:  the root of the C: drive on Vista seems to always be set to High integrity.  Note that you can reset your C:\'s integrity level, but be warned that it'll take about 30 seconds.  Thanks again to Peter.

26 April 2009:

  • Version 1.52: User James Gentile discovered that file specifications larger than 127 characters killed chml; max has been upped to 2048 chars.  Thanks to James for his detective work!
  • Note on chml limitation:  I used the ANSI APIs, not the Unicode APIs, so it won't work on folders with Unicode names (Chinese characters, etc.) -- I'll Unicode-ize it eventually but haven't yet.

April 2009:  chml 1.5 adds

  • Discovered that if (1) your logon name has a space in it and (2) you have disabled 8.3 names on NTFS then chml can't use the "force system" option.  The root problem is a bug in schtasks that makes it unable to handle folder names with spaces in some cases.
  • While fixing that, I realized that a file name with a space in it might also keep chml from using "force system."  Fixed now, and debug output helps track any future problems of this sort better.

Feb 2009:  chml and regil are now code-signed.  chml 1.5 adds

  • -fs "forcesystem" option to allow elevation or de-elevation to/from System.
  • -nfs option blocks Chml from using the forcesystem method.
  • -so  is a shortened debug output that summarizes all current options and inputs; good for smoking out oddities.
  • Reporting is now cleaner and more complete.  There are two reports:  a verbose report that details the integrity level, integrity policies (no read up, no write up, no execute up) and inheritance flags on a file/folder, and a short display of the SDDL string.  By default, Chml shows the verbose report, not the SDDL string.  The -ss ("show SDDL") and -sv ("suppress verbose report") let you control what Chml shows you.  The "-ss" option replaces the older "-showsddl" option.
  • Chml now includes a larger tutorial and set of built-in examples that expand beyond what's on this Web page.  The "-ex" option ("examples") has been replaced by the "-st" ("short tutorial") option.
  • Chml, when run with no options, now offers a couple of pages of overview information in integrity levels and Chml use.
  • The "-wsddl:" option (which lets you hand-craft any SDDL string that you like, great for experimentation, has been renamed "-ws:"
  • The -rl ("remove label") option removes any labels from a file or folder, restoring it to pre-experimentation state.
  • You can now use the -to ("test only") option to see what a command would do.  It shows you the report that you would see if you'd actually made a given modification of a file/folder's IL.

Jan 2009:  fixed a bug that caused chml to sometimes think that a folder was a file.  Thanks to Peter Strelecki for pointing out the bug.  Added "-rl" option that will remove any existing mandatory labels, returning a file to "unlabeled" status, like

C:\>chml test.txt -rl -b
Integrity level reset to "unlabeled", object treated as medium.

Why Not Use icacls?

Well, again, I didn't use icacls in my experimentation because it didn't work throughout almost all of the Vista beta process, so it was of no value to me then.  But Chml can do several things that icacls cannot:

  • It cannot set integrity levels at Untrusted or System.
  • It cannot assign "no read up" or "no execute up" integrity policies.
  • It will not let you view the "raw" integrity control label, as chml's -ss: option does.
  • It will not let you create and apply a hand-crafted raw integrity control label, as chml's -ws: option does.

Windows integrity controls aren't well-understood by many because there's so little information on them.  That's why I wrote chml and, now, regil.  I hope you find it useful and if you'd like more detail both on integrity levels and chml, then please consider buying my Administering Windows Vista Security:  The Big Surprises book, which I've seen at Bookpool for as little as $21.

You can send me email at the "minasi.com" domain under the name "help."  Drop me a line and tell me how you're finding Chml and/or Regil useful, and thanks for visiting!