4

I am learning format string attack from my book Hacking : Art of Exploitation. I have this small program and this is the code :

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

int main(int argc, char *argv[]) {
   char text[1024];
   static int test_val = -72;

   if(argc < 2) {
      printf("Usage: %s <text to print>\n", argv[0]);
      exit(0);
   }
   strcpy(text, argv[1]);

   printf("The right way to print user-controlled input:\n");
   printf("%s", text);


   printf("\nThe wrong way to print user-controlled input:\n");
   printf(text);

   printf("\n");

   // Debug output
   printf("[*] test_val @ 0x%016x = %d 0x%08x\n", &test_val, test_val, test_val);

   exit(0);
}

I want to input address to my program and print it. The address is 0x00600b98 because of little endian byte order I input "\x98\x0b\x60\x00"

this is my bash code : ./fmt_vuln $(python -c 'print "\x98\x0b\x60\x00"')%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.

But the problem is, the first address (\x00) its become null and not inputed to my address and when the memory is printed it become 25600b98. So my question is, why this problem happen and how to input address of 00 ?

This is the output:

The right way to print user-controlled input:
�
 `%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.
The wrong way to print user-controlled input:
�
 `f7ff5000.f7dd7970.f7b128c0.f7fd8700.0000002b.ffffe3b8.f7ddb72d.25600b98.
[*] test_val @ 0x0000000000600b98 = -72 0xffffffb8
Cristik
  • 30,989
  • 25
  • 91
  • 127
AlbertusFar
  • 145
  • 3
  • 10

2 Answers2

0

It's because null bytes (/x00), at least in C, are used to terminate a string. So, when you printf them, they are interpreted as the end of the string.

A great explanation on this, coupled with information on how to properly incorporate null bytes into your code can be found here.

I hope this helps.

Community
  • 1
  • 1
0

argv[1] points to a character array with the contents "\x98\x0b\x60\x00". Notice this is 5 bytes: 4 plus a null character.

The following code only copies until reaching a null character, which results in only 4 bytes being copied as argv[1][3] is a null character.

strcpy(text, argv[1]);

Suggest adding optional 2nd parameter and calling the program with an additional parameter indicating the length.

size_t size = 0;
if (argc > 2) {
  long i = atol(argv[2]);
  if (i >= 0 && i < SIZE_MAX) {
    size = (size_t) i;
  }
else {
  size = strlen(argv[1]) + 1;
}
// strcpy(text, argv[1]);
memcpy(text, argv[1], size);

Note that the following code will still only print to first 3 characters

printf("%s", text);
printf(text); // UB if it contains '%'

BTW: Suggest doing debug output before printf(text); and fixing its mis-matched formats

// printf("[*] test_val @ 0x%016x = %d 0x%08x\n", &test_val, test_val, test_val);
printf("[*] test_val @ 0x%016x = %d 0x%08x\n", 
    (unsigned) &test_val, test_val, (unsigned) test_val);
// or
printf("[*] test_val @ %p = %d 0x%08x\n", 
    (void*) &test_val, test_val, (unsigned) test_val);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256