简体   繁体   中英

Simple Buffer Overflow in C

So I am doing an excercise where I am attempting to get the following program to output Welcome to Overflow by changing the relevant variables using a buffer overflow. Here is the code.

#include <stdio.h>

int main(){
  int a = 10;
  char c = 'X';
  char array2[] = {'A', 'B', 'C', 'D', 'E', 'F'};
  char array[4];
  printf("please enter: \n");
  scanf("%s", array);

  printf("c = %c\n", c);
  printf("a = %d\n", a);
  printf("array = %s\n", array);
  printf("array2 = %s\n", array2);
  printf("array[2] = %x\n", *(array + 2));
  printf("array2[3] = %x\n", array2[3]);


  if (c == 'X' && a == 11999 && *(array + 2) == 0x99 - 0x34 && array2[3] == 'X') {
    printf("Welcome to overflow!\n");
  } else {
    printf("This is normal output!\n");
  }
}

What I need is for c == 'X' && a == 11999 && *(array + 2) == 0x99 - 0x34 && array2[3] == 'X' .
So I have gotten every variable to be what I want it to be except one.
By inputting the following I am able to change them. I input "XXeXXXXXXXXB" This changes array[2] to be 65 , array2[3] to be X , c to 'X' but the variable I cannot change is 'a'. By making the 12th char of input a B it changes a to '66', which is the decimal equivalent of the char 'B'. If I input a 13th char, variable a will then be changed to the decimal equivelent of the char * 257. Since a needs to be 11999 I am lost.
I tried dividing 11999 by 257 but it comes out to 46.6 so there is no char with that value, I even tried the char closest to 46.6 which were '.' and '/' but then a is too big or too small.

What char or chars can I make the 12th and 13th input in order to change a into 11999? Also if you do not want to give me the flat out answer I would appreciate a point in the right direction.

This is an interesting exercise. Because you are invoking undefined behavior, there isn't exactly one answer to your question, it has to be evaluated on a case-by-case basis. This attack may not even work on some machines.

First, for this kind of test you should be using printf to see where the data is:

printf("a is at %p\n", &a);
printf("array is at %p\n", array);
...

This should give you an idea of how many bytes you need to offset. Next determine whether you are working on a little-endian or big-endian system. If you are working on little-endian then 11999 is 0xDF2E0000, if you are using big-endian it is backwards.

So given your program on a little-endian system, assuming all data is in the correct order in memory for it to work, and the integer is 4 bytes, you need the string "--" + (0x99-0x34) + "-...X..X" + 0xDF2E0000

EDIT: The reason for this string is as follows:

  • first 4 bytes: "--e-" fills in your input array
  • Next 6 bytes: "...X..X" fills in array2 and c, with correct placement of X's
  • Last 4 bytes: 0xDF2E0000 fills in your int (little endian) with 11999

You can test this by adding:

#include <string.h>
char str[] = {16};
sprintf(str, "--%c-...X..X%c%c\0\0", 0x99 - 0x34, 0xDF, 0x2E);
memcpy(array, str, 14);
printf("The string is: \"%s\"", str);

In place of your scanf. Obviously you can figure out the characters associated with those values and paste them in, but this is the fastest way to get the correct data.

Of course, this is subjective to change based on system, and the code I have above may not even work on your machine. This is still a very real thing, and a good demonstration of why you should always limit the number of characters you are reading and writing, as well as make sure you use proper ending characters.

If I missed any assumptions/factors above I would appreciate if someone lets me know so I can add them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM