Call function with arra out of bounds access

Viewed 32

so I've got a buggy C file in which i need to find an exploit. I have found a bug when accessing the following struct:

#define BOARD_SIZE 10

typedef int (*turn_function_t)(struct board *);
typedef void (*win_function_t)(struct board *);

struct board {
    uint8_t f1[BOARD_SIZE][BOARD_SIZE];
    uint8_t f2[BOARD_SIZE][BOARD_SIZE];
    win_function_t win;
    turn_function_t turn;
    int avail;
};

int do_shot(struct board *board, int strength, int x, int y) {
    if(!(x >= 0 && x <= BOARD_SIZE && y >= 0 && y <= BOARD_SIZE)) {
        return SHOT_ERR_EINVAL;
    }

    /* If there was already a sunken ship, return error */
    if(board->f1[x][y] && !board->f2[x][y])
        return SHOT_ERR_SUNKEN;

    /* Now perform shot */
    if(!board->f2[x][y])
        return SHOT_WATER;

    board->f2[x][y] -= strength;

    if(!board->f2[x][y])
        return SHOT_SUNKEN;
    return SHOT_HIT;
}

The bug I found is a wrong index check when accessing array f2. I can chose the index as input (index can be anything from 0 to 10 inclusive). I need to find a way to call the function win (doesn't matter which parameter). My question now is is there any way I can use that out of bounds access to call the function win since the function pointer is stored directly after the array f2 inside the struct?

1 Answers

of cause it can be done easily.
I show you an example code below.
I use pragma pack(1) for byte align and use print to find the address of the function, and finally I got it.
the code may can not be run on your computer.
but your can find the address by print to make bounds address equal to function address.
it may be f[0][-1] on your computer

#include <stdio.h>

typedef int (*turn_function_t)(struct board *);

#pragma pack(1)
struct board
{
    turn_function_t win;
    int f[10][10];
};
#pragma pack(0)

int win(struct board *b)
{
    printf("Win!\n");
    return 0;
}

int main()
{
    struct board b;
    b.win = win;
    // printf("%p\n", &b.f[0][-2]);
    // printf("%p\n", &b.win);
    (*(turn_function_t *)(&b.f[0][-2]))(&b);
    return 0;
}
Related