I get this code and I can not find the vulnerability. I think this code may be vulnerable to buffer overflow. How do I prove it?

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

typedef struct _AC_DATA
{   
    int the;
    int fan;
    bool rec;
} AC_DATA, *PAC_DATA;

typedef struct _RADIO_DATA
{
    char speakers_volume[4];
    int station;
} RADIO_DATA, *PRADION_DATA;

typedef struct _GLOBAL_DATA
{
    AC_DATA ac_data;
    RADIO_DATA radio_data;
}GLOBAL_DATA, *PGLOBAL_DATA;

void good()
{
    printf("Good!\n");
}

int update_volume(PGLOBAL_DATA pglobal_data, int index, int new_volume)
{
    char arr[100];

    if(index > 4)
    {
        printf("error invalid speaker.\n");
        return -1;
    }
    printf("updating the speaker %d to volume %d\n", index, new_volume);
    pglobal_data -> radio_data.speakers_volume[index] = new_volume;
}

void hacked()
{
    printf("Hacked!\n");
}


int main () {

    GLOBAL_DATA global_data = {0};
    int index;
    int new_volume;
    printf("address of main: 0x%X.\n", main);
    printf("enter volume index:");
    scanf("%d", &index);
    printf("enter new volume:");
    scanf("%d", &new_volume);
    update_volume(&global_data, index, new_volume);

    return 0;
}
  • 1
    add code as text – Paweł Łukasik Sep 13 at 14:30
  • @PawełŁukasik I add code – d.buff Sep 13 at 14:53
  • 1
    is this a homework exercise? are the values of all inputs to the program (index and new_volume) checked prior to being used in the program logic? have you been able to trigger an overflow, segfault, bug, error, unexpected behavior? what have you done to analyze this program for potential vulnerabilities? what is your approach to this problem? what is your reasoning? – SYS_V Sep 13 at 15:01
  • hey @SYS_V I input to program (index and new_volume) index = 102030405060708090 volume = 90 the program crush, the output is -504445190 to volume 90 the EIP= 004014C1 – d.buff Sep 13 at 15:12
up vote 3 down vote accepted

The bug is in update_volume.

pglobal_data -> radio_data.speakers_volume[index] = new_volume;

index is an int, it can take negative values too. Ideally you should not be able to access -ve indices in an array as it gives you read/write over memory area preceding the array. Here we just have a check to limit its max value to 4 but you can use negative integers to INT_MIN and overwrite a byte.

For exploitation, global_data belongs to main's stack frame. Accessing negative indices you can overwrite a byte in return address of update_volume (somewhere in main) on the stack. This gives you the primitive to jump to maybe hacked or good functions.

Resources: Use ASAN to verify your claims while fuzzing with inputs.

Here is the ASAN dump for this case.

ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer ./test
address of main: 0xCA77FE6F.
enter volume index:-36
enter new volume:65
updating the speaker -36 to volume 65
=================================================================
==27759==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffebfb3ff98 at pc 0x55f1ca77fe6f bp 0x7ffebfb3fed0 sp 0x7ffebfb3fec0
WRITE of size 1 at 0x7ffebfb3ff98 thread T0
    #0 0x55f1ca77fe6e in update_volume /tmp/re.c:39
    #1 0x55f1ca78004b in main /tmp/re.c:57
    #2 0x7f237a433b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #3 0x55f1ca77fcf9 in _start (/tmp/test+0xcf9)

Address 0x7ffebfb3ff98 is located in stack of thread T0 at offset 136 in frame
    #0 0x55f1ca77fe7e in main /tmp/re.c:47

  This frame has 3 object(s):
    [32, 36) 'index'
    [96, 100) 'new_volume'
    [160, 180) 'global_data' <== Memory access at offset 136 underflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /tmp/re.c:39 in update_volume
Shadow bytes around the buggy address:
  0x100057f5ffa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100057f5ffb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100057f5ffc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100057f5ffd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100057f5ffe0: 00 00 f1 f1 f1 f1 04 f2 f2 f2 f2 f2 f2 f2 04 f2
=>0x100057f5fff0: f2 f2 f2[f2]f2 f2 00 00 04 f2 00 00 00 00 00 00
  0x100057f60000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100057f60010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100057f60020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100057f60030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100057f60040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==27759==ABORTING

Please specify while posting if this a homework problem. We are happy to help but won't do all the job for you if you don't show any progress made/research done as @SYS_V mentioned in comments.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.