In my post for today, I will be discussing a vulnerability that I
found within the TCP/IP driver as implemented by Microsoft within
their Windows 2003 Operating System with Service Pack 2 installed
(advisory here).
If an attacker has obtained unprivileged access into the operating
system, this vulnerability may be used to elevate their privilege to
that of SYSTEM. This is accomplished by abusing a null near pointer
dereference within code that runs during the processing of a specific
unprivileged IOCTL call.

This vulnerability was issued identifiers: KL-001-2015-001,
MS14-070, and CVE-2014-4076.

In order to avoid duplicating content from the advisory issued for
this vulnerability, I will only provide a brief tl;dr before diving
into the exploit.

By using nt!NtDeviceIoControlFile() it is possible to leverage a
handle into the Tcp device along with the IOCTL code 0x00120028 and
specific inputBuffer to trigger a near null pointer dereference within
the extended stack index register. This register is used as a pointer
to memory containing a dword that is used to determine the code path
to be taken. This can be abused through a combination of reverse
engineering (in order to understand what values have what effect on
code flow) and attacker memory allocation near null.

In this post, I will discuss in detail the methodology leveraged
during exploit development. I would like to note that Microsoft has
confirmed this vulnerability exists on both x86, x64, and Itanium
architectures. I will only focus on the x86 architecture in this
post.

The original crash that led to the exploitation of this
vulnerability was found as such:

The ???????? indicates that the memory being reference is not
allocated and therefore can not be copied from. The ESI register
contains 0x00000000, a value that is user-controlled during the IOCTL
call. By modifying that value, it is possible for an attacker to
control memory used during decisions by the driver relating to code
flow. This allows an attacker to influence those decisions in a way
that benefits him. Let's review some of what that looks like.

The BL register contains the last byte in a dword value obtained
from ESI+28, or 0x00000028. No problems there, we'll just write any
four-byte value we like there. In my exploit, I ended up with the
following:

Only the first and last bytes are really needed to accomplish
exploitation. I did not go any further to figure out the meaning of
the inner two bytes.

The last byte is tested first using this instruction:

test bl, 40h

Basically, this becomes a bitwise AND (i.e., 0x38 & 0x40). The second
test is then encountered. This test determines whether the word pointer
at 0x00000038 is 0x0000 or not. Since this also falls within range of
memory that I can write to, my exploit does the following:

This code does a bitwise AND operation on the AL register. The
value of the AL register is set as a result of the call to
tcpip!IsBlockingAOOption. This code leverages the EAX register, which
also becomes tainted with a null value earlier on in the code
flow.

From here, we can release code flow until the instruction pointer
is dereferenced.

Writing 0x0000 at 0x2b will change the EIP value to 0x2000, we can
then have our shellcode waiting at 0x2000. An alternative to this,
would be to write a dword pointer to your shellcode at 0x000000ec. Both
cases act as a trampoline into the shellcode.

A metasploit module to leverage this vulnerability has been
released by another member of our team along with this blog post; pull
request here. In the meantime, exploit code written in Python can
be found in
the advisory we published.