/*
 * grade.c
 *
 * by Aaron Bloomfield, 2018.  This is part of the aaronbloomfield/ics
 * github repository, and is released under the same license (CC
 * BY-SA) as that entire repo.
 *
 * This program is designed to be vulnerable to a shellcode-based
 * buffer overflow.  Students must have it print a grade other than an
 * F to receive any credit.
 *
 * To run it, be sure to invoke `setarch x86_64 -v -LR bash` first
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>

// used to indicate if we are printing the buffer address
int print_buffer_address = 0;

// we use this to pass the name back from the vulnerable() function to
// main()
char global_name[100];

// the vulnerable function
void vulnerable() {
  char name[200];
  if ( print_buffer_address ) {
    unsigned long addr = (unsigned long) name + 0x20;
    printf("%lx\n",addr);
    exit(0);
  } else {
    printf ("Please enter your name:\n");
    fgets (name, 1000000, stdin);
    strncpy (global_name, name, 199); // look, ma, no buffer overflow possible here!
  }
  return; // not necessary, but useful to set a breakpoint at grade.c:38
}


void main(int argc, char *argv[]) {

  if ( (argc == 2) && (!strcmp(argv[1],"--print-buffer-address")) )
    print_buffer_address = 1;

  // we use this to help find the address of the stack in the next command
  int on_stack;

  // we set the stack to allow execution; it already allows reading
  // and writing
  mprotect((char *)((long)&on_stack & -0x1000), 1, PROT_READ | PROT_WRITE | PROT_EXEC);

  // we set the executable code (the .text section) to be writable; it
  // already allws reading and execution
  mprotect((char *)((long)&main & -0x1000), 1, PROT_READ | PROT_WRITE | PROT_EXEC);

  // call the vulnerable function
  vulnerable();

  // remove trailing newline
  global_name[strlen(global_name)-1] = 0;

  // print the grade
  printf ("\n%s, your grade on this assignment is a F\n", global_name);
}