ED 303: Windows Stack Protection III: Limitations of ASLR (15 pts)

What You Need

Purpose

Examine ASLR on Windows in more detail.

Here's what Microsoft says about ASLR randomness:

It seems like there's a 1 in 256 chance of guessing correctly for many EXE files!


Task 1: Observing ASLR on Windows

ASLR (Address Space Layout Randomization) prevents many buffer overflow exploits by making the location of the stack difficult to predict.

Launching a Developer Command Prompt

You must already have Visual C++ Build Tools installed.

Click the Start button, scroll to the V secton, expand "Visual Studio 2019", and click "Developer Command Prompt for VS 2019", as shown below.

Making the esp3 Program in C++

In the Developer Command Prompt window, execute these commands:
mkdir c:\127a
cd c:\127a
notepad esp3.cpp
A box pops up, asking "Do you want to create a new file?". Click Yes.

Enter this code, as shown below:

#include <iostream>  
using namespace std;  

void main() {
	int data = 0;   
	__asm {
	    mov data, esp
	}
   cout << hex << data << endl;
}

In Notepad, click File, Save.

Compiling the Program Normally

In the Developer Command Prompt window, execute these commands:
cl /EHsc esp3.cpp
esp3.exe
esp3.exe
The ESP value changes each time the program runs, as shown below. This happens because ASLR is activated by default in Windows.

Compiling the Program Without ASLR

In the Developer Command Prompt window, execute these commands:
copy esp3.cpp esp4.cpp
cl /EHsc /c esp4.cpp
link /DYNAMICBASE:NO esp4.obj
esp4.exe
esp4.exe
The ESP value remains the same each time the program runs, as shown below, because ASLR is turned off for this application.


Task 2: Testing the Randomness of ASLR

We'll make a simple Python script to see how many possible values ESP has when using ASLR.

In the Developer Command Prompt window, execute these commands:
Skip first command if you are still in that directory.

cd c:\127a 
notepad test.py
A box pops up, asking "Do you want to create a new file?". Click Yes.

Enter this code, as shown below. It will run the esp3.exe program 5 times and print out the results.

import os
for i in range(5):
  os.system("esp3.exe")

In Notepad, click File, Save.

Running the Program

In the Developer Command Prompt window, execute this commands:
c:\python27\python test.py
The results are all different, as shown below.

Running the Program 10000 Times

In the Developer Command Prompt window, execute this command:
notepad test.py
Change the "5" to "10000", as shown below.

In Notepad, click File, Save.

Running the Program

In the Developer Command Prompt window, execute this command:
c:\python27\python test.py > 10k.txt
It will take a few minutes to run. There are no visible results, because they all go into the "10k.txt" file, as shown below.

How Random Are They?

In the Developer Command Prompt window, execute this command:
notepad 10k.txt
The numbers appear random, as shown below, but how random are they?

Removing Duplicates

We'll use a simple Python script to remove duplicate values.

In the Developer Command Prompt window, execute this command:

notepad clean.py
A box pops up, asking "Do you want to create a new file?". Click Yes.

Enter this code, as shown below. It will run the esp3.exe program 5 times and print out the results.

with open('10k.txt') as f:
   lines = f.read().splitlines()
n = len(lines)
u = len(set(lines))
print n, "values, but only ", u, "unique"

In Notepad, click File, Save.

Running the Program

In the Developer Command Prompt window, execute this commands:
c:\python27\python clean.py
The result shows that only about 70% of the numbers were unique, as shown below. That's more than the 256 I expected from the Microsoft literature, but still not a very large number.


Task 3: Viewing Memory Sections

Running esp3.exe in Immunity

Launch Immunity.

From the Immunity menu bar, click File, Open. Navigate to C:\127\esp3.exe and double-click it.

Immunity loads the program.

From the Immunity menu bar, click Debug, Run.

Click Debug, Run again.

From the Immunity menu bar, click View, Memory.
Note: You may have to change the font to make it easier to read as we did in Project 302.

Notice the Address of these items, as shown below:

Reloading esp3.exe in Immunity

From the Immunity menu bar, click Debug, Restart.

From the Immunity menu bar, click Debug, Run.

Click Debug, Run again.

From the Immunity menu bar, click View, Memory.

Notice that the "stack of main thread..." address changes, and so does the "data block of main thread..." address, but the other items are always at the same address, as shown below.

Viewing Memory Sections from C++

In the Developer Command Prompt window, execute these commands:
cd c:\127a
notepad mem.cpp
A box pops up, asking "Do you want to create a new file?". Click Yes.

Enter this code, as shown below.

#include <cstdio>  
#include <cstdlib>  
#include <iostream>  
using namespace std;  

int d;                        /* in .data section */

void main()
{
    int i=1, j;
    int * p;                 /* pointer */

    char buf[5];             /* Activate stack cookie protection */
    strcpy(buf, "HERE");     /* To help find code in IDA */	

    __asm {mov edx, LABEL
          mov d, edx
          LABEL: NOP};       /* in .text */

    char * heapbuf;
    heapbuf = (char*) malloc(1); 	/* on heap */

    printf("Address in .text: %08x\n", d);
    printf("Address in .data: %08p\n", (void *) &d);
    printf("Address in .heap: %08p\n", (void *) heapbuf);
    printf("Address in stack: %08p\n", (void *) &i);

    printf("\nStack:\n");
    p = &i;
    for (j=0; j<9; j++) {
        printf("%d %08p %08x\n", j, (void *) p, *p);
        p++;
    }
    __asm int 3
}

In Notepad, click File, Save.

Compiling the Program with All Protections

In the Developer Command Prompt window, execute these commands. This compiles the program with ASLR enabled, and with stack cookies.
cl /EHsc mem.cpp
mem.exe
The program runs, showing memory information, as shown below, and then crashes when it hits the "INT 3".

Viewing Memory Usage for mem.exe in Immunity

Launch Immunity.

From the Immunity menu bar, click File, Open. Navigate to C:\127a\mem.exe and double-click it.

Immunity loads the program.

From the Immunity menu bar, click Debug, Run.

Click Debug, Run again.

From the Immunity menu bar, click View, Memory.

Press Alt + Tab to make the Command Prompt running "mem.exe" visible, as shown below.
Note: Option + Tab on a Mac.
You can also click the Command Prompt icon in the bottom Windows tool bar.

Notice these items:

Viewing the Stack

From the Immunity menu bar, click View, CPU.

Press Alt + Tab to make the Command Prompt running "mem.exe" visible, as shown below.
Note: Option + Tab on a Mac.
You can also click the Command Prompt icon in the bottom Windows tool bar.

To make the command prompt text bigger, click the icon in the top left corner, choose Properties, Font, and 20.

Notice these items, referred to by the item number that count from 0 to 8 in the Command Prompt window:
DOUBLE CHECK, UPDATED info from previous project

Close Immunity.

Removing the INT 3

In the Notepad window, delete this line from the mem.cpp code, as highlighed below.
    __asm int 3

Click File, Save to save the file.

In the Developer Command Prompt window, execute this command to compile the program again, with ASLR enabled, and with stack cookies.

cl /EHsc mem.cpp

Animating the Display

In the Developer Command Prompt window, execute this command line:
cls && mem
By pressing Up-Arrow and then Enter, you can repeat the command several times to see what values change.

You should see the values outlined in yellow in the image below changing, while the other values stay the same.

Note these items:
DOUBLE CHECK, UPDATED info from previous project

Compiling the Program with No Protections

In the Developer Command Prompt window, execute these commands. This compiles the program with ASLR enabled, and with stack cookies.
copy mem.cpp mem0.cpp
cl /EHsc /c /GS- mem0.cpp
link /DYNAMICBASE:NO mem0.obj
mem0.exe
The program runs, showing memory information, as shown below.

Notice that the .text section is near the classical value of 400000, which we've seen before.

Animating the Display

In the Developer Command Prompt window, execute this command line:
cls && mem0
By pressing Up-Arrow and then Enter, you can repeat the command several times to see what values change.

You should see the values outlined in yellow in the image below changing, while the other values stay the same.

Note these items:
INCORRECT INFO, NEEDS UPDATE


ED 303.1 Item 6 (15 pts)

Find the value of item 6 on the stack, covered by a green box in the image above. That's the flag.

References

Disable Program Has Stopped Working Error Dialog in Windows
Software defense: mitigating common exploitation techniques

Updated: 7-20-19
Posted: 11-9-18
Typo in C code: i -> j 12-11-18
Ported to Google Cloud by Travis Knapp-Prasek
Minor edits 8-2-19