ARM buffer overflow: chapter 6 ಠ-ಠ (day 76) (bypassing stack canaries by utlizing format string exploit)
Last time in arm buffer overflow chapter we look at how an attacker can bypass NX and ASLR protection by simply brute force the location of the stack memory because of the low entropy of address randomization.
Although brute-forcing the address is easy but is not an elegant way to defeat further protection such as canary. Actually, there is a second way to defeat not just NX and ASLR but also canary protection by utilizing a technique called "information leaking" using the format string attack
For the sake of POC, we will be using source code from billy ellis exploit challenge (link: https://github.com/Billy-Ellis/Exploit-Challenges/blob/master/ROPLevel5.zip)
//
// roplevel5.c
//
//
// Created by Billy Ellis on 09/08/2017.
//
//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
char feedbackString[32];
char feedbackString2[32];
void give_feedback(){
printf("\033[1mLeave some feedback:\n");
char string[16];
scanf("%s",string);
if (strcmp(string,"q") == 0){
exit(0);
}
char leakme[] = "AAAA";
printf(string);
printf("\n");
sprintf(feedbackString,string,string);
char leakme2[] = "BBBB";
sprintf(feedbackString2,feedbackString,feedbackString);
FILE *f = fopen("./feedback.txt","w");
fprintf(f,"%s",feedbackString2);
fclose(f);
}
void secret(){
printf("\n\x1b[32myou win ;)\n");
system("ls -sail");
}
int main(){
printf("\033[1m\x1B[34m================================================\x1B[0m\n");
printf("\033[1mWelcome to ROPLevel5 by Billy Ellis (@bellis1000)\n");
printf("\x1B[34m================================================\x1B[0m\n\n");
int a = 1;
while (a){
give_feedback();
sleep(1);
}
return 0;

once you create a file with this source code try to compile the file using above command by using the following parameter we enable stack canary in the binary and don't forget to turn on your ASLR in full mode

once it's done try to load it into your favorite gdb tool

you can test the binary by just providing a long string of input

if it says stack smashing detected then you set to go. Next, is to find out where is the location of the canary value stored in the stack. After a couple of trial and error by decrementing the length of the value it stops showing error when I supply 16 bytes
the input was : "BBBBCCCCDDDDEEEE"

if you put a breakpoint after the scanf() function call and look at the stack we can see that after the character "EEEE" the next byte will contain the canary, the canary value always end with "\x00"
so we know where is the location of the canary but how do we predict this value when we to launch our exploit then?
simple!
take a look at the "give_feedback" function

after comparing our input with "q" string it will print the value using printf luckily the value was passed directly allowed us to control the output of the program this is what is called "format string attack"
We also notice that the function using unsafe scanf() function to process our input this is the function that causes a buffer overflow earlier
you can test this vulnerability by supplying this type of input to the program

cool so by using format string attack we can use this to leak the memory in the stack and we can retrieve the value of canary at runtime. But we need to determine at where is the canary can be accessed via format string, we can utilize direct access parameter

I use python to generate the list of direct parameter access, save it to the file and then pass it to the program

after taking a quick view of the result the canary can be directly accessed at the 13th parameter. We can test this by supplying "BBBB|%13$x" to the program inside GDB


from the above figure, we can see that we got the canary value at runtime. You can test it outside the GDB of course. Remember the canary value only change every time the program is started

so we know how to predict the canary value but how can we automate this task to employ it in our exploit. Well, we can use pwntools to make it easy but unfortunately when I try to install pwntools at the raspberry pi it didn't work and I have to reserve into a more traditional approach using pexpect.
note: before you can use pexpect you have to install via pip( sudo pip install pexpect)
so my python script will be like this

the first function called "sending_payload" will be handling the program when it startup, we can see at the beginning of the function there are a bunch of readline() function this responsible to handle the banner of the program when it first runs and receives "Leave some feedback:" then we supply an input "BBBB|%13$x" to leak the canary value
then we readline() again to get the return value, as you expected the result will be in this format "BBBB|<canary value>" so we need to split into two part using .split() function and then get the second part which is the canary value. Don't forget to strip the trailing "\r\n" from the result
At the end of the function, we will convert the canary value into little-endian. This is one of the neat tricks that you can use if you don't have pwntools p32(), we can create our own p32() function by utilizing lambda and struct together

the second function which is "post_payload" will be handling the rest of the interaction of the program and in this function, we will be sending the actual payload that contains canary that will overflow the stack and take over the program flow. The rest of the function code will be just used to print any response we get when we execute the secret function
notice at the main function, below the function post_payload we craft payload by filling the first 16th bytes of "A", follow with canary that we got from the function sending_payload(), append it with another 4 bytes of "A" so we can overwrite the return address and finally supply the new value which is the secret function location

run it and we are able to take control of the code execution and then circumvent the canary protection. Cool! so we can see here that by using format string attack it provide us with a very powerful capability to bypass not just ASLR and NX protection but also Canary
That's all folks :)
Hope you like this post and see you at the next post of ARM buffer overflow
Comments
Post a Comment