Rixstep
 About | ACP | Buy | Industry Watch | Learning Curve | News | Products | Search | Substack
Home » Learning Curve » Can't Take a Punch

The .NET Knockouts

Talk about merciless.


Get It

Try It

IE6 and later allow for .NET user (interface) controls embedded in webpages. These controls are .NET binaries run in a sandbox inside the browser process. They're loaded with the following tag.

<OBJECT classid="ControlName.dll#Namespace.ClassName">

The classid attribute is no longer a UUID but instead a 'URL' that points to the .NET binary and the namespace and class to be used. .NET controls can be embedded on any page in the 'Internet zone'. But no warning is issued to the user when a previously unknown .NET control is encountered. .NET controls are considered safe regardless of origin because they only run in a sandbox. [Ahem.]

.NET binaries cannot contain native code. They're set up otherwise as PE executables. The following document explains the tests performed on .NET controls.

http://download.microsoft.com/download/b/e/b/bebccc43-cce6-4cd8-b42f-a01b37a0c6a0/sscli20_20060311.tgz

dotnet-shellcode.rb

dotnet-shellcode.rb bypasses DEP: .NET binaries are mapped into memory as ordinary PE executables - all sections mentioned in the PE header are loaded into memory the same way. Page permissions are set according to the flags in the PE header. If the .NET binary contains an executable section then that section when loaded into memory will be marked as executable.

Thus a hacker can put shellcode in the .TEXT (code) section of a .NET binary and get the shellcode loaded at an executable page in the browser's address space. The base address of the binary on XP is also specified in the PE header - and the header of course is under control of the hacker.

This ability to place executable shellcode at a known memory location is great way to hack into a system.

  • Hackers are not limited by the contents of the shellcode.
  • Hackers can make the shellcode section of an arbitrary size.
  • Hackers can create complex data structures and load them at known locations.

A suitable place for creating the shellcode would be in the C++ constructor for the .NET control. The string is stored in the code section and marked executable for the loader. An exploit of the ANI buffer overflow can point to a return address to the shellcode.

Address Space Spraying

Address space spraying bypasses both ASLR and DEP. Hackers can use the gratefully malleable .NET binaries to exhaust parts of virtual memory in a fashion similar to the heap spraying technique - and often a lot faster as well. By supplying sufficiently large binaries the hacker can have a good idea of roughly where they might exist in virtual memory.

  1. Libraries using ASLR are packed together at the top of memory. Hackers will roughly know the base addresses as well as approximately how many libraries are loaded and how big those libraries are.

  2. If a library can't fit into the address range 0x50000000 - 0x78000000 then a base address is calculated the same way used for randomised executables: within 16 MB of the preferred base specified in the PE header. This behaviour can be forced with binaries of approximately 200 MB in size. Addresses mapped in the library can thus be guessed. The idea is to make a library small enough to fit into the range 0x50000000 - 0x78000000 but big enough to take a large portion - or else specify a larger library guaranteed to not fit in the range.

Java and .NET Stack Spraying

Stacks can be useful for more than just storing shellcode - they can contain metadata and so might be useful for memory corruption attacks. Both Java and .NET have thread constructor functions that take stack parameters.

public Thread(ThreadStart start, int maxStackSize)
public Thread(ThreadGroup group, Runnable target, String name, long stackSize)

These correspond to native thread creation APIs where sizes of the stack's default reserve and commit (as per the PE header) can be overwritten. (The stack size arguments in the above code both refer to the new reserve size.)

Hackers can thus allocate contiguous regions of memory as large as they want and can further supply the functions that control stack space - they can therefore control what data is put on the stack.

Stacks can be sprayed with return addresses, with shellcode, or with pointers.

Stack Spraying & ASLR

ASLR searches through memory a random number of times for a hole big enough for the stack; attempting to create a stack of 128 MB should normally fail. But the size passed to the randomisation function is not the reserve size - it's the commit size. So the search function will look for relatively small holes rather than huge ones.

The address returned is used only as a 'hint' to NtAllocateVirtualMemory(). If the address doesn't point to a big enough reserve block the address space will be searched linearly for a big enough space instead. So big stacks always get allocated in the lower part of the address space.

So how bad is it? So what do Sotirov and Dowd say?

About | ACP | Buy | Industry Watch | Learning Curve | News | Products | Search | Substack
Copyright © Rixstep. All rights reserved.