Showing posts with label Windows. Show all posts
Showing posts with label Windows. Show all posts

Tuesday, February 2, 2016

Page Heap

A large class of vulnerabilities in software is memory corruptions due to buffer overflows and underflows. An example of this type of vulnerability is an attempt to write more data into a buffer than the size of the buffer itself (buffer overflow). Page Heap is a class of Heap Allocation Policies that can be used when diagnosing or fuzzing for new buffer mismanagement vulnerabilities.

The difficulty of dealing with buffer mismanagement vulnerabilities is that the memory corruption is often not observable at the time that it happens. In the best case, memory gets corrupted badly enough at the time of the corruption, such that the program crashes immediately. In the worst case, although the memory corruption occurred, memory doesn’t get corrupted badly enough at the time of corruption (a “silent” corruption) and therefore there is no immediate crash. Rather the effect of the corruption is observable through some indirect misbehavior of the program later on in execution. An example of this worst case scenario is that an unexpected variable might have its value changed, thereby leading to a different and unexpected code execution path later on. Page Heap is useful for forcing a “fail-fast” policy for memory safety. Page Heap aims to trigger the crash immediately when the memory corruption occurs.

How it Works

In the x86 architecture, Virtual Memory gives each process the appearance that it has 4 GB of address space, whether the memory pages are actually committed or not. When an address on a page that is reserved but not committed is dereferenced, a page fault is generated by the hardware. Page Heap exploits this fact by reserving a guard page at the beginning or end of a page to make sure that any adjacent reads or writes to a buffer cross a page boundary onto a page that is not committed, leading to an immediate page fault.

Guard Pages are Reserved rather than Committed. Using the !address command returns MEM_RESERVE for the State, and PAGE_NOACCESS for the Protection, thereby disallowing reading, writing or executing on the page without taking up any physical memory or space in the page file. Due to the fact that guard pages are inaccessible but are taking up Virtual Address space, Virtual Address space is wasted. For this reason, page heap is useful for debugging, but could lead to problems in a production environment.

For the 3 main types of Heap Policies below, the following code (compiled to PageHeap.exe) will be used as an example, and the “vulnerable line of code here” comment will be replaced by one of the multiple lines of code in each section to trigger the crash.


#include "stdafx.h"

class Buffer
{
public:
       Buffer()
       {
              //initialize our buffers
              memcpy(buffer1, "AAAAAAA", 8);
              memcpy(buffer2, "BBBBBBB", 8);
       }

       char buffer1[8];
       char buffer2[8];
};

void main(int argc, char* argv[])
{
       Buffer * myBuffer = new Buffer(); 
       //vulnerable line of code here

       delete myBuffer;
       while (true){}
}


Full Page Heap

Command: “gflags /p /enable PageHeap.exe /full”

Description:

This Heap Allocation Policy allocates buffers at the END of the memory page. A buffer OVERflow would attempt to access memory PAST the END of the page into the guard page, triggering an immediate page fault.

Vulnerable line of code:


memcpy(myBuffer->buffer2 - 9, myBuffer->buffer1, 8); //Buffer Underflow (write)
memcpy(myBuffer->buffer2 + 1, myBuffer->buffer1, 8); //Buffer Overflow (write)
memcpy(myBuffer->buffer2, myBuffer->buffer1 + 9, 8); //Buffer Overflow (read)


Allocation:
Full Page Heap-allocation at end of page with guard page following

Reverse Page Heap

Command: “gflags /p /enable PageHeap.exe /full /backwards”

Description:

This Heap Allocation Policy allocates buffers at the BEGINNING of the memory page. A buffer UNDERflow would attempt to access memory BEFORE the BEGINNING of the page into the guard page, triggering an immediate page fault. Due to the way Full Page Heap handles Buffer Underflow write, one might expect Reverse Page Heap to catch Buffer Overflow writes, but it does not.

Vulnerable line of code:


memcpy(myBuffer->buffer2, myBuffer->buffer1 - 1, 8); //Buffer Underflow (read)
memcpy(myBuffer->buffer2 - 9, myBuffer->buffer1, 8); //Buffer Underflow (write)


Allocation:
Reverse Page Heap-allocation at beginning of page with guard page preceding

Standard Page Heap

Command: “gflags /p /enable PageHeap.exe”

Description:

This Heap Allocation Policy tries to save Virtual Address space by avoiding allocating extra guard pages for each allocation. Rather, it adds a special pattern before and after each allocation. This allows it to detect Buffer Overflow writes and Buffer Underflow writes, but not Over/Under flow reads of any kind. One noteworthy point is that the integrity of the surrounding patterns are not checked until the buffer is freed. The significance of this fact is that it does not provide a perfect “fail-fast” scenario because a corruption only causes failure on free, not at the time of corruption.

Vulnerable line of code:


memcpy(myBuffer->buffer2 - 9, myBuffer->buffer1, 8); //Buffer Underflow (write)
memcpy(myBuffer->buffer2 + 1, myBuffer->buffer1, 8); //Buffer Overflow (write)


Allocation:
Standard Page Heap-allocation with pattern preceding and following


References:

http://msdn.microsoft.com/en-us/library/ms220938(v=vs.90).aspx

Monday, November 16, 2015

Visual Heap Spray

Prerequisite Reading:
Previous “Low Fragmentation Heap ReAllocation for Use After Free Exploitation” article
Previous “Attacking V-Table Pointers” article
Heap Sprays are a common method attackers use to introduce determinism in a program’s address space. They aim to control a program’s memory layout in such a way that an attacker can reliably predict what will be in memory at a certain address (Address of Interest) at a certain point in execution.

For example, if there is a Use-After-Free bug, on an object with a V-Table, the object can be reallocated and the offset of the V-Table pointer in the object can point to an address that the attacker knows will contain the spray (Address of Interest). This knowledge often comes from trial and error when writing the exploit.

The Address of Interest makes a big difference in the quality of the exploit. For example, a very popular Address of Interest is 0x0c0c0c0c. The reasoning behind this Address of Interest is that the address must be low in the process’s address space (the highest Nibble of this address is 0x0), yet must be at a higher address in memory than the heap being sprayed (the second highest Nibble is 0xc) so that when the heap grows due to the memory pressure of the spray, it will grow into this address. Using high addresses such as 0xc0c0c0c (the highest Nibble is 0xc) would require that the application freezes for a longer period of time before the heap spray is complete. A victim that is being targeted might get bored and close the process (web browser in this case) due to the fact that it has appeared to freeze during the long time taken to spray, thereby precluding any possibility of successful exploitation.
Visualizations:
Below are some memory usage visualizations taken with the vmmap tool from SysInternals before and after the heap spray. The orange color represents the Backend Heap in the process’s address space. Two things to notice are the large growth in the orange segment of the graphs below and the difference in the “Committed” usage before and after the spray (it grows from about 136 MB to about 698 MB).
Before Spray:

Memory Usage before Heap Spray
 After Spray:
Memory Usage after Heap Spray
Below are graphical representations of the memory layout before and after the spray. The “After Spray” visualization has the approximate address of 0x0c0c0c0c marked for the reader’s convenience. One might make the argument that since 0x0c0c0c0c is relatively early in the heap spray, the heap spray could have been reduced to minimize the time the victim has to wait for the spray to finish.

Before Spray:

Memory Layout before Heap Spray

After Spray:
Memory Layout after Heap Spray

How to Heap Spray in Internet Explorer:

In IE, heap sprays are often done by allocating and assigning large strings from JavaScript. Sprays are often done on the Backend Heap (rather than the Low Fragmentation Heap). In order to get strings allocated on the Backend Heap, the strings must be larger than 16KB. Example JavaScript follows:

for (var z = primeAmount; z < numObjects; z++)
    objectArray[z].title = pattern;

The Heap Spraying technique does not come without some drawbacks, leading to some researchers referring to heap sprays as “For the 99%”. In some cases, exploitation can be made more reliable by finding multiple "good" bugs rather than heap spraying:
  • It might take a long time to spray (user might get impatient and terminate the program).
  • Depending on preexisting memory layout due to external factors (loaded plugins, other webpages visited prior to this one, etc), spraying can be unreliable.
  • Too much spraying might cause the Operating System to swap memory pages out to disk (depending on how much physical memory the victim’s machine has) and JavaScript Exceptions.
  • New IE mitigations might prevent highjacking virtual function calls.
  • There is no guarantee that the Address of Interest will contain the spray-an executable image or something else might be mapped at the Address of Interest, depending on the address space and system configuration unique to the victim. 
Libraries:
The community has done some great work to reduce the barrier of entry into this space. Multiple open source libraries have been written by researchers to abstract away the details of heap mechanics. In the example presented in this article, the heap reallocation/spray was done manually, but libraries such as HeapLib by Alex Sotirov and HeapLib2 by Chris Valasek allow users to just call into them in order to perform reallocation/sprays. Code review of HeapLib2 shows that this article, the prerequisite readings and HeapLib2 all use the same technique to reallocate and spray the heap.

Wednesday, December 12, 2012

Windows 8 Kernel Debugging

Starting with Windows Vista, Microsoft changed the Windows Boot Manager, thereby changing the way we debug the Windows Kernel. Now, there is a new tool called bcdedit.exe which can be used to modify the boot configuration of a Windows installation.
The goal is to set up kernel debugging via virtual serial port, on a Windows 8 guest VM running on a Windows 8 host via the built in Hyper-V that comes with Windows 8. The pipe name will be “debug” in this example. The first step is to enable the COM port of the guest VM in the VM’s settings:


Next, enable kernel debugging on the guest VM by running the following commands from an elevated command prompt on the guest:
bcdedit /debug on
bcdedit /dbgsettings serial debugport:1 baudrate:115200
The next step is to prepare the host for debugging the guest VM. The host had the Windows 8 SDK, WDK, Visual Studio 2012, and the Visual Studio 2012 coinstaller installed, in that order. There are 2 ways to debug kernels in guest VMs from a Windows 8 host. The first is to use Visual Studio 2012 (new method), and the second is to Windbg (old method). Visual Studio 2012 now has integrated kernel debugging support using the same debugging engine as Windbg. Once the host machine has everything installed, the steps to debug using Visual Studio 2012, are as follows:
  1. Run Visual Studio 2012 as Administrator
  2. Under the Tools->Attach to Process window, select "Windows Kernel Mode Debugger" for Transport.
  3. Click "Find" next to "Qualifier"
  4. In the "Configure Computers" window use the following settings:
    Transport=Serial
    Port=\\.\pipe\debug
    Baud=115200
 
To use the old Windbg method:
  1. Run Windbg as Admin on the host
  2. Hit ctrl+k to connect to the serial port exposed by the VM
  3. Use the following settings
  
 
 Further Reading:

Tuesday, October 23, 2012

Single Step Debugging Explained



Single Step debugging of machine instructions is a technique often used during vulnerability research and exploit development to debug a program at an atomic level. At this level of granularity, one can see the individual assembly instructions as they are being executed by the CPU chip, and the states of the registers and memory as each instruction is executed.


Single step debugging is supported in part by the operating system and in part by the CPU. On Intel's x86 architecture, the EFLAGS register's bit 8 is the TF(Trap Flag) bit. If this bit is set before an assembly instruction is executed, the CPU raises an exception (Interrupt 1) after the execution of the assembly instruction is completed. Once the CPU raises the exception, the following events happen in order(see Windows Internals 5th Edition, Chapter 3):

  1. The TF bit is cleared. This is why the 3rd least significant digit of "efl" register as displayed in windbg is always an even digit when single stepping. The CPU clears the TF bit before calling the exception handler, which is invoked much before the debugger ever gets it.
  2. The kernel looks up entry number 1 in the system's IDT(Interrupt Descriptor Table).
  3. If a debugger is attached, it is alerted about the single step exception.
  4. If no debugger is attached or the exception is not handled by the debugger, the Operating System's Exception Handling mechanism is invoked.
  5. If the Exception Handling mechanism still does not handle the exception, the debugger is given a second chance to handle the exception.
  6. If no debugger is available, the process is killed.

The following test program manually sets the TF bit in the EFLAGS register:

#include <stdio.h>

void main()
{
    while(1)
    {
        printf("inside loop\n");
        __asm{
            pushfd
            pop eax
            or eax, 0x00000100 //set TF bit in EFLAGS
            push eax
            popfd
        }
    }
}

This program was run with and without a debugger(windbg) attached. When run with a debugger attached, there were no breakpoints set, but single step exceptions were set to be handled, as seen by the following:

0:000> sx
sse - Single step exception - break

When the test program was run with the debugger attached, a single step exception was caught by windbg:

(bf4.d98): Single step exception - code 80000004 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.

This proves that setting the TF flag from within a program will cause an exception that an attached debugger can catch for single stepping. In this case, the exception mentioned in step 3 above is handled by the debugger.

The next experiment was to run the program again, but without a debugger attached. Below is the result:

step 6 was reached, and the process was killed due to the unhandled exception(no debugger to handle it)
 As is clear, single step debugging is supported in part by hardware, and in part by software.

Sources:
Windows Internals 5th Edition, Chapter 3
Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 3A, 3B and 3C