Search code examples
cassemblygdbbuffer-overflow

How to exploit Lottery Game?


After exploiting this code and finding out if you enter 16 different digits Output using exploit I am trying to understand why this is the case. Is it because of the memory location?

#include <stdio.h>
#include <stdlib.h>
#include<time.h>

int main(int argc, char *argv[]) {
  int entry[6];
  int results[6];
  int i = 0, tmp = 0;

  /* Generate power balls */                                                                   
  srand(time(NULL));                                                                         
  for (int i = 0; i < 6; i++) {                                                       
    results[i] = rand() % 99;                                                           
  }


  printf("RULE: You are to enter a sequence of six two-digit numbers between 10 and 99. \n");
  printf("  - The numbers should be separated by a single space. \n");
  printf("  - The seventh number should be -1, indicating the completion of the sequence \n");
  printf("Enter the numbers: \n");
  while(tmp != -1) {
    scanf("%d", &tmp);
    if (tmp == -1) break;
    entry[i] = tmp;
    i++; 
  }

  /* Check results */
  int match = 0;
  for (int i = 0; i < 6; i++) {
    printf("The lottery number is: %d\n", results[i]);
    printf("Your guess is: %d\n", entry[i]);
    if (results[i] == entry[i]) {
      match++;
    }
  }

  if (match != 6){
    printf("Unfortunately, there has been a mismatch! Better luck next time!\n");
  }
  else {
    printf("Congratulations, all the numbers match! You have won a gazillion dollars \n");
  }
  return 0;
}

I tried finding the memory location of each array: Entry / Results

But I don't understand how they are related or even if they are part of the exploit.


Solution

  • On my machine, where sizeof (int) is 4, these arrays align 32 bytes apart

    (gdb) print &entry
    $1 = (int (*)[6]) 0x7fffffffe7b0
    (gdb) print &results
    $2 = (int (*)[6]) 0x7fffffffe7d0
    

    with results being placed after entry, and have 8 bytes of padding between them.

         |entry                  |padding|results                |stack
         | 0 | 1 | 2 | 3 | 4 | 5 | P | P | 0 | 1 | 2 | 3 | 4 | 5 | ? | ? | ? |
    i   =  0   1 ...               6   7   8   9 ...      12  13  14  15  16
    tmp = 10  12 ...          16  17  18  10  12 ...          16  17  18  -1
    

    Until tmp is -1, i will continue to increment, writing the value of tmp into entry[i]. This eventually overflows entry, and starts writing to the padding bytes, and then the results array.

    On my machine, i, tmp, and match are placed before the arrays, and what follows the arrays are likely canaries, that trip the stack protection when their values are changed.

    Entering only 14 values, instead of 16, and then -1, causes the results array to be overwritten exactly, without tripping any stack protection.

    This does all fall under the purview of Undefined Behaviour, though.