Bypassing ServerLock protection
From: Jan Rutkowski (jkrutkowski_at_ELKA.PW.EDU.PL)
Date: Fri, 18 Jul 2003 00:25:23 +0200 To: NTBUGTRAQ@LISTSERV.NTBUGTRAQ.COM
Bypassing ServerLock protection on
Jan K. Rutkowski
ServerLock for Windows 2000 is product of Watch Guard company. The
purpose of this tool is to protect integrity of the operating system
by ensuring that nobody can modify certain files (like DLLs or
drivers), some registry keys and load unknown drivers.
Watch Guard homepage: http://www.watchguard.com.
There are two bugs in the recent version of Server Lock for Windows
2000 which can be exploited to completely bypass its protection.
2. Bug #1 - loading arbitrary modules (using Runtime Process Infection)
It is possible to circumvent ServerLock protection, so that attacker
can load arbitrary module into kernel. Normally such action is
restricted by ServerLock, because:
a) it is not possible to create keys under
HKLM\System\CurrentControlSet\Services, so official Windows 2000
mechanism to load drivers cannot be used (SCM and ZwLoadDriver() which
is used by SCM, require that each driver has a dedicated subkey under
the 'services' key in the registry).
b) it is not possible to replace a 'legal' driver (files form
\Winnt\System32\drivers directory), because ServerLock protects these
files from write access.
c) there exists undocumented function: ZwSetSystemInformation(), which
can be used to load driver, and this function doesn't require any keys
in the registry. ServerLock protects these function, so that only
'trusted' programs can use it.
The method of attack, presented below, assumes ServerLock 2.0.1 for
Windows 2000. Prior versions have not been tested, but it is likely
that they are also vulnerable.
2.2. DLL injection
First of all, we should explain what 'trusted' program means. Every
EXE file, which is guarded (i.e. modification is not allowed) by
ServerLock is considered 'trusted'. The reason for this, is that
attacker cannot change the trusted program's code.
However this is not true, when we are considering running process.
Attacker can open process object by means of OpenProcess() function,
and then can use for example CreateRemoteThread() in order to inject
DLL library of his choice into the target process address space. This
is called 'DLL injection' and has been researched years ago, and can
look like this (simplified):
Of course before that, one must ensure that "bad.dll" string is
present in the target process address space. This can be done by means
of VirtualAllocEx() and WriteProcessMemory() functions.
As we all know, just after DLL is loaded into the process memory,
DLL's entry point, usually called DllMain, is executed.
We see, that attacker, with proper privileges, can supply arbitrary
instructions to 'trusted' process and these instructions will be
executed. It should be noted that DLL injection is not the only
technique to achieve this runtime process infection, but is the
simplest one. Other techniques do not requires creation of additional
file ("bad.dll") in the filesystem (which is not very stealthy).
2.3. Calling ZwSetSystemInformation()
Assuming that attacker's rootkit resides in file rootkit.sys, we can
copy this file into \WINNT\system32\drivers\ directory as a
rootkit.abc for example. ServerLock forbids creation only files with
some known extensions like .sys, but for ZwSetSystemInformation()
function extension doesn't matter.
Using DLL injection technique (described above) we can force any
'trusted' process to execute ZwSetSystemInformation()
(SystemLoadAndCallImage class), thus allowing attacker to load his
rootkit.abc module into kernel.
2.4. Other usage of OpenProcess()
Despite exploiting ZwSetSystemInfomration(), OpenProcess() function
can be used to do API hooking in other processes. This future is used
by some recently popular Windows usermode rootkis, like hxdef. It
would be a good idea to restrict OpenProcess() then.
3. Bug #2 - improper handling of symlinks to \Device\PhysicalMemory
Server Lock is trying to restrict access to \Device\PhysicalMemory to
disallow accessing kernel memory. However it is possible to create
some symlinks to this object and then, open this device via symlink.
The following output demonstrates just few possibilities:
creating link: \hak1 --> \Device
creating link: \hak2 --> \Device\PhysicalMemory
creating link: \hak3 --> \
creating link: \hak4 --> [failed]
creating link: \Device\hak5 --> \Device
creating link: \Device\hak6 --> \??\GLOBALROOT
trying to open for READ|WRITE:
opening \Device\PhysicalMemory ... [failed]
opening \hak1\PhysicalMemory ... [it worked!]
opening \hak2 ... [it worked!]
opening \Device\hak5\PhysicalMemory ... [it worked!]
opening \Device\hak5\hak5\PhysicalMemory ... [it worked!]
opening \??\GLOBALROOT\Device\PhysicalMemory ... [it worked!]
opening \Device\hak6\hak1\PhysicalMemory ... [it worked!]
It should be obvious that having possibility to open
\Device\PhysicalMemory for writing we can do whatever we want with the
system, like loading some rootkits and backdoors. It means complete
system compromise. Although this is not trivial, since we must
translate linear addresses to physical, proof-of-concept codes can be
found on the net.
4. Vendor response
17.02.2003: bug 1 has been reported to Watch Guard
10.03.2003: bug 2 has been reported to Watch Guard
28.03.2003: SL 2.0.3 has been released which fixed bug #1
02.07.2003: SL 2.0.4 has been released which fixed bug #2
SL 2.0.3 does not restrict OpenProcess(), but SL 2.0.4 does, which
should stop Runtime Process Infection efforts.
These bugs have been fixed and a patch made available to all current
subscribers on vendor's LiveSecurity Web site at:
Watch Guard refused to provide details about how they fixed the bugs.
Are You "Certifiable"? Summer's Hottest Certification Just Got HOTTER!
With a growth rate exceeding 110%, the TICSA security practitioner
certification is one of the hottest IT credentials available. And now, for
a limited time, you can save 33% off of the TICSA certification exam! To
learn more about the TICSA certification, and to register as a TICSA
candidate online, just go to