Search code examples
cperlbuffer-overflow

Perl code executed alongside C program writes incorrect byte length to memory in Windows


Disclaimer: i'm not worried about the syntax.

While learning about buffer overflows, I'm playing around with Perl code executed alongside my C program to demonstrate how the overflow works. However, when I input the code .\Buffer $(perl -e 'print "A"x16 . "\xef\xbe\xad\xde"') it only adds the $(perl to the first buffer in memory, buffer_two as shown here:

.\Buffer $(perl -e 'print "A"x16 . "\xef\xbe\xad\xde"')

[BEFORE] buffer_two is at 0061FF0C and contains two
[BEFORE] buffer_one is at 0061FF14 and contains one
[BEFORE] value is at 0061FF1C and is 5 (0x00000005)

[STRCPY] copying 6 bytes into buffer_two

[AFTER] buffer_two is at 0061FF0C and contains $(perl
[AFTER] buffer_one is at 0061FF14 and contains one
[AFTER] value is at 0061FF1C and is 5 (0x00000005) 

The bytes between buffer_two and value is 16 bytes ((gdb) print 0x0061ff1c - 0x0061ff0c $1 = 16), so I print "A" 16 times to fill the space. However, what should happen is the text following "A"x16 should overwrite the next memory address(es). When used on Linux, the code works fine, and I get the following output:

./Buffer $(perl -e 'print "A"x16 . "\xef\xbe\xad\xde"')
[BEFORE] buffer_two is at 0x7ffca168185c and contains two
[BEFORE] buffer_one is at 0x7ffca1681864 and contains one
[BEFORE] value is at 0x7ffca168186c and is 5 (0x00000005)

[STRCPY] copying 20 bytes into buffer_two

[AFTER] buffer_two is at 0x7ffca168185c and contains AAAAAAAAAAAAAAAAᆳ�
[AFTER] buffer_one is at 0x7ffca1681864 and contains AAAAAAAAᆳ�
[AFTER] value is at 0x7ffca168186c and is -559038737 (0xdeadbeef)

Here is the full code:

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

int main(int argc, char *argv[])
{

int value = 5;
char buffer_one[8], buffer_two[8]; //create two buffers of 8 bytes

strcpy(buffer_one, "one"); //copy strings one and two into buffers
strcpy(buffer_two, "two");

printf("[BEFORE] buffer_two is at %p and contains %s\n", buffer_two, buffer_two); //print initial address and value
printf("[BEFORE] buffer_one is at %p and contains %s\n", buffer_one, buffer_one);
printf("[BEFORE] value is at %p and is %d (0x%08x)\n", &value, value, value);

printf("\n[STRCPY] copying %d bytes into buffer_two\n\n", strlen(argv[1])); //copy first argument digits into buffer two

//if((int *)argv[1] > (int *)8) //test if argument input is greater than 8 bytes
//{
    //printf("[!!] Buffer error\n\n");
    //exit(-1); 
//}

strcpy(buffer_two, argv[1]);

printf("[AFTER] buffer_two is at %p and contains %s\n", buffer_two, buffer_two);
printf("[AFTER] buffer_one is at %p and contains %s\n", buffer_one, buffer_one);
printf("[AFTER] value is at %p and is %d (0x%08x)\n", &value, value, value);

}

While writing this post I notice it states only 6 bytes are being written, which I'm unsure as to why.


Solution

  • .\Buffer $(perl -e 'print "A"x16 . "\xef\xbe\xad\xde"')

    This syntax (run command in parenthesis and replace $(...) with its output) is a feature of (many) UNIX shells.

    Whatever shell you are using on Windows clearly doesn't do that.