# Csaw 2017 Minesweeper

Let's take a look at the binary:

```
$    pwn checksec minesweeper
[*] '/Hackery/pod/modules/custom_misc_heap/csaw17_minesweeper/minesweeper'
    Arch:     i386-32-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x8048000)
    RWX:      Has RWX segments
$    file minesweeper
minesweeper: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=90ec16e6be18b19942bf2952db17a7c1ed3ca482, stripped
$    ./minesweeper
Server started
```

So we can see that we are dealing with a `32` bit binary with none of the standard binary mitigations, and even `rwx` memory segments. We also see that the binary is some type of server. Let's try to connect to it:

```
$    netstat -planet
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       User       Inode      PID/Program name    

.    .    .

tcp        0      0 0.0.0.0:31337           0.0.0.0:*               LISTEN      1000       149341     11035/./minesweeper      
$    nc 127.0.0.1 31337

Hi. Welcome to Minesweeper. Please select an option:
1) N (New Game)
2) Initialize Game(I)
3) Q (Quit)
```

So we can see that the server listens on ip/port combo `0.0.0.0:31337`. When we connect to the server via netcat, we see that we are prompted

## Reversing

When we check the references to the strings, we find the function responsible for the main menu for our client:

```
undefined4 menu(undefined4 param_1)

{
  int local_30;
  int local_2c;
  undefined4 input;
  undefined4 local_24;
  undefined4 local_20;
  undefined4 local_1c;
  int bytesScanned;
  uint i;
  undefined5 *local_10;
 
  input = 0;
  local_24 = 0;
  local_20 = 0;
  local_1c = 0;
  local_10 = (undefined5 *)0x0;
  local_2c = 0;
  local_30 = 0;
  while( true ) {
    print(param_1,
          "\nHi. Welcome to Minesweeper. Please select an option:\n1) N (New Game)\n2) InitializeGame(I)\n3) Q (Quit)\n"
         );
    bytesScanned = customScan(param_1,&input,0x10);
    if (bytesScanned == -1) break;
    i = 0;
    while ((i < 0x10 &&
           ((*(char *)((int)&input + i) == ' ' || (*(char *)((int)&input + i) == '\0'))))) {
      i = i + 1;
    }
    if (i == 0x10) {
      print(param_1,"No command string entered! N, I, or Q please!\n");
    }
    else {
      switch(*(undefined *)((int)&input + i)) {
      case 0x49:
      case 0x69:
        local_10 = (undefined5 *)initGame(param_1,&local_2c,&local_30);
        break;
      default:
        print(param_1,"Invalid option, please try again N, I, or Q please!\n");
        break;
      case 0x4e:
      case 0x6e:
        newGame(param_1,local_10,local_2c,local_30);
        break;
      case 0x51:
      case 0x71:
        print(param_1,"Goodbye!\n");
        return 0;
      }
    }
  }
  print(param_1,"Goodbye!\n");
  return 0;
}
```

We can see that this function essentially just prompts us for our input. We are prompted with three options. The first is for a new game, the second is to initialize a game, and the third is to quit. When we take a look at the function responsible for initializing a game `initGame`, we see this:

```

char * initGame(undefined4 param_1,int *param_2,int *param_3)

{
  char *boardptr;
  void *hiTherePtr;
  void *menuPtr;
  char *Xptr;
  void *cowsayPtr;
  int iVar1;
  char local_3c [16];
  int bytesScanned;
  void *ptr0;
  uint i;
  int y;
  int x;
 
  print(param_1,
        "Please enter in the dimensions of the board you would like to set in this format: B X Y\n")
  ;
  x = customScan(param_1,local_3c,0x10);
  if (x == -1) {
    print(param_1,"Goodbye!\n");
    boardptr = (char *)0x0;
  }
  else {
    hiTherePtr = (void *)customMalloc(0xb);
    memset((int)hiTherePtr,0,0xb);
    memcpy(hiTherePtr,"HI THERE!!\n",0xb);
    print(param_1,hiTherePtr);
    customFree((int)hiTherePtr);
    menuPtr = (void *)customMalloc(1000);
    memset((int)menuPtr,0,1000);
    memcpy(menuPtr,
           "  +---------------------------+---------------------------+\n  |     __________________   |                           |\n  |  ==c(______(o(______(_()  ||\'\'\'\'\'\'\'\'\'\'\'\'|======[***  |\n  |             )=\\           | |  EXPLOIT  \\            |\n  |            / \\            | |_____________\\_______    |\n  |          /   \\           | |==[--- >]============\\   |\n  |          /     \\          ||______________________\\  |\n  |         / RECON \\         | \\(@)(@)(@)(@)(@)(@)(@)/  |\n  |        /         \\        |  *********************    |\n +---------------------------+---------------------------+\n                                                          \nIIIIII    dTb.dTb        _.---._       \n  II     4\'  v \'B   .\"\"\"\" /|\\`.\"\"\"\". \n  II     6.     .P  :  .\' / | \\ `.  : \n  II    \'T;. .;P\'  \'.\'  /  |  \\  `.\' \n  II      \'T; ;P\'    `. /   |   \\ .\'  \nIIIIII    \'YvP\'       `-.__|__.-\'     \n-msf                                   \n"
           ,1000);
    print(param_1,menuPtr);
    customFree((int)menuPtr);
    i = 0;
    while ((i < 0x10 && ((local_3c[i] == ' ' || (local_3c[i] == '\0'))))) {
      i = i + 1;
    }
    if (i == 0x10) {
      print(param_1,"Please send valid command! B X Y\n");
      boardptr = (char *)0x0;
    }
    else {
      if ((local_3c[i] == 'B') || (local_3c[i] == 'b')) {
        i = i + 1;
        if (i == 0x10) {
          print(param_1,"Not enough arguments to set board. B X Y\n");
          boardptr = (char *)0x0;
        }
        else {
          while ((i < 0x10 && ((local_3c[i] == ' ' || (local_3c[i] == '\0'))))) {
            i = i + 1;
          }
          if (i == 0x10) {
            print(param_1,"Not enough arguments to uncover. U X Y\n");
            boardptr = (char *)0x0;
          }
          else {
            y = 0;
            while ((((x = y, i < 0x10 && (local_3c[i] != ' ')) && (local_3c[i] != '\0')) &&
                   ((-1 < (int)local_3c[i] + -0x30 && ((int)local_3c[i] + -0x30 < 10))))) {
              y = (int)local_3c[i] + -0x30 + y * 10;
              i = i + 1;
            }
            if (i == 0x10) {
              print(param_1,"Not enough arguments to uncover. U X Y\n");
              boardptr = (char *)0x0;
            }
            else {
              while ((i < 0x10 && ((local_3c[i] == ' ' || (local_3c[i] == '\0'))))) {
                i = i + 1;
              }
              y = 0;
              while ((((i < 0x10 && (local_3c[i] != ' ')) && (local_3c[i] != '\0')) &&
                     ((-1 < (int)local_3c[i] + -0x30 && ((int)local_3c[i] + -0x30 < 10))))) {
                y = (int)local_3c[i] + -0x30 + y * 10;
                i = i + 1;
              }
              if ((x < 10000) && (y < 10000)) {
                boardptr = (char