6. Windows Stack Protection II: Exploit Without ASLR (20 pts)

What You Need

Purpose

Examine stack defenses on Windows in more detail.

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 2017", and click "Developer Command Prompt for VS 2017", as shown below.

Making the esp Program in C++

In the Developer Command Prompt window, execute these commands:
mkdir c:\127
cd c:\127
notepad esp.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 << "$esp = ";
   cout << hex << data;
   cout << "\n";

   cout << "Press Enter to continue\n";
   cin.ignore();
}

In Notepad, click File, Save.

Compiling the Program Normally

In the Developer Command Prompt window, execute these commands:
cl /EHsc esp.cpp
esp.exe
Press Enter. Execute esp.exe twice more.

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 esp.cpp esp2.cpp
cl /EHsc /c esp2.cpp
link /DYNAMICBASE:NO esp2.obj
esp2.exe
Press Enter. Execute esp2.exe twice more.

The ESP value remains the same each time the program runs, as shown below, because ASLR is turned off for this application.


Task 2: Making the Pwd3.exe Program

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

Enter this code, as shown below.

This is a program we used in the early Linux projects, which has a simple buffer overflow vulnerability. It also discloses information about the stack address.

#include <iostream>  
using namespace std;  

int test_pw()
{
   char pin[10];
   int x=15, i, data = 0;   

   __asm {
      mov data, esp
   }
   cout << "$esp = ";
   cout << hex << data;
   cout << "\n";

   cout << "Enter password: ";
   cin >> pin; 
   for (i=0; i<10; i+=2) x = (x & pin[i]) | pin[i+1];
   if (x == 48) return 0;
   else return 1;
}

void main()
{
   if (test_pw()) cout << "Fail!\n";
   else cout << "You win!\n";
}

In Notepad, click File, Save.

Compiling the Program Without ASLR

In the Developer Command Prompt window, execute these commands, to compile and link the program without a stack cookie, and with ASLR disabled:
cl /EHsc /c /GS- pwd3.cpp
link /DYNAMICBASE:NO pwd3.obj
pwd3.exe
The program asks for a password. Enter any value and press Enter. The program says "Fail!", as shown below.


Task 3: Debugging Pwd3.exe

Running pwd3.exe in Immunity

Launch Immunity as an Administrator.

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

Immunity loads the program. Note that eip, in the top right pane, is in "ntdll", and that the program is "Paused", as indicated in the lower right corner, as shown below.

Immunity has loaded the program and paused.

From the Immunity menu bar, click Debug, Run.

Immunity pauses again immediately. Click Debug, Run again.

At the bottom of the Windows screen, in the taskbar, click the rightmost button to bring the Command Prompt running "pwd3.exe" to the front, as shown below.

Enter a password consisting of 32 letters: the letters A through H four times each, as shown below, and then press the Enter key.

AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH

The program crashes, and the message at the bottom of the Immunity window says "Access violation when executing 48484848", as shown below.

In the top right pane of Immunity, notice that EIP contains 48484848. This is a classic buffer overflow exploit, letting us control the EIP.


Task 4: Finding the Target Address

Finding the Overflow

The lower right pane of Immunity shows the Stack at the point of the crash, as shown in the image above.

Notice the second word, marked "RETURN to pwd3.00409FB6 from pwd3.00401250". This was the code preceding the crash, so we want to look there.

In the lower right pane of Immunity, right-click the second line, as shown below, and click "Follow in Disassembler", as shown below.

Assembly code appears in the top left pane, as shown below.

In the top left pane, scroll to the top. The code starts at address 401000. Scroll down a few screens until you find the string "Enter Password", as shown below.

The PUSH instruction at address 4011E5, puts a pointer to the string "Enter password:" onto the stack.

The CALL at address 4011EF prints out the prompt message to the user.

The next "CALL" instruction, at address 401200, takes input from the user, and it's where the buffer overflow happens.

Placing Breakpoints

Click the second CALL instruction after the line containing "Enter password:". In the image above, it's at address 401200, but it may be different on your system.

Press F2 to set a breakpoint. If you are using a Mac, press fn+F2.

Set a second breakpoint on the next instruction after the CALL.

Both addresses are highlighted in aqua, as shown above.

Finding the "You Win!" Message

In the top left pane, scroll down a few pages, and find the "You Win!" Message, as shown below.

Make a note of the address of this instruction. In the image below, it's 401270. This is the address we want to inject into the EIP.

Restarting the Program

From the Immunity menu bar, click Debug, Restart.

A "Process still active" box pops up. Click Yes.

From the Immunity menu bar, click Debug, Run. Click Debug, Run again.

Viewing the Stack Before the Overflow

Immunity hits the breakpoint and stops, as shown below.

On the top right, find the values of ESP and EBP, which are the top and bottom of the current stack frame. When I did it, the values were 19FF10 and 19FF30.

In the lower right pane, highlight the stack frame, as shown in the image below.

The word after EBP contains a RETURN pointer, at address 19FF34 in the image below.

Performing the Buffer Overflow

From the Immunity menu bar, click Debug, Run.

At the bottom of the desktop, in the taskbar, click the rightmost icon to bring the command prompt to the front.

Enter a password consisting of 32 letters: the letters A through H four times each, as shown below, and then press the Enter key.

AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH

Immunity hits the second breakpoint and stops, as shown above.

In the stack, the address of the RETURN pointer now contains 48484848, as shown above, which are the ASCII letters "HHHH".

Inserting the Target Address

In the lower right pane of Immunity, right-click the line containing 48484848 and click Edit, as shown below.

Find the adress of the "You Win!" instruction, which you determined earlier. When I did it, that address was 401270, but your value may be different.

In the "Edit stack" box, click in the HEX +00 field and enter the address of the "You Win!" instruction in little-endian byte order, as shown below.

70 12 40 00

In the "Edit stack" box, click OK. Verify that the address appears correctly in the stack, as shown below.

From the Immunity menu bar, click Debug, Run.

The program runs and terminates.

At the bottom of the desktop, in the taskbar, click the rightmost icon to bring the command prompt to the front.

The "You Win!" message appears, as shown below.

Notice the message at the bottom left of the Immunity window, covered by a green box in the image above.

Enter that message into the form below to record your success, and then close Immunity.


6 Recording Your Success (20 pts)

Use the form below to record your success!
Your Name:
Message:

Task 5: Writing an Exploit in Python

Launch a Developer Command Prompt window as you did before, and execute these commands:
cd c:\127
notepad exploit1.py
A box pops up, asking "Do you want to create a new file?". Click Yes.

Enter this code, as shown below. Adjust the last four bytes to match the "You Win!" address on your system, which you determined previously.

print "AAAABBBBCCCCDDDDEEEEFFFFGGGG\x70\x12\x40\x00"

In Notepad, click File, Save.

In the Command Prompt window, execute these commands:

c:\python27\python exploit1.py
c:\python27\python exploit1.py | pwd3.exe
The first command shows you the exploit text, which ends in several strange characters, and the second command runs the exploit, which results in the "You win!" message, as shown below.

References

Disable Program Has Stopped Working Error Dialog in Windows

Posted 12-31-18