Smash the stack.

dr3f.k0
6 min readJun 23, 2021

--

Hello people I wish you are doing good , lately I started to learn basic binary exploitation so I thought I would document this journey of mine through medium blogs 💛.

Contents:

This blog is divided into three parts the first part I will go write a basic vulnerable C program which contains stack overflow bug and also explain them, the next part I will demonstrate the stack overflow and on the third and last part I will do a static analysis of the vulnerable binary and exploit it so I can land up into another function 😋, so let’s get started without further delay.

Part 0 :

So, let’s write a simple code before a vulnerable code and explain it :

#include <stdio.h>#include <string.h>#include <stdlib.h>int main(){char array1[14] = "aaaaaaaaaaabbb" ; //A character array of size 16 //declared & initializedchar array_to_copy[13];   //A character array of size 13 initializedvoid *address = &array_to_copy;printf("%p\n", address);strcpy(array_to_copy, "helloworld");puts(array_to_copy); //This prints  hello worldreturn 0;}

Here in the above code, we declared a character array of size 16 and then just declared another character array of size 13 and a pointer variable which prints the address, next on the UN-initialized array, we copy a string “helloworld” and print it! The program runs well & prints the address & the string!

Part 1:

Now after this let us make a small change and copy the content of array1 to array_to_copy & check out what actually happens:

strcpy(array_to_copy, array1);

Oops! Stack smashing is detected 😳, so what exactly is stack smashing detected error? It’s a sort of defense mechanism against buffer overflow attacks, so why did this happen? The array_to_copy which can hold characters up to just 12 characters and a null terminator \0 was now holding 13 characters and a null terminator which caused the buffer to overflow, and here we have a new guest in this buffer overflow play known as canary it can be explained in layman’s terms as a method by which the compiler detects that there was a buffer overflow, and in case of buffer overflow the canary is overwritten and then it gets compared with the known value and we land up with stack smashing detected .

Part 2: Writing a vulnerable C program which leads to a unauthenticated part of program.

#include<stdio.h>int main(void){int check = 0;
char actual_name[9] = "drefdotk0";
char password[9];
printf("Welcome %s please enter your password \n", actual_name);
scanf("%s", password);
printf("The password you have entered is %s \n" , password);
//printf("Your password is wrong\n");
if (strcmp(actual_name, password) == 0){check = 1;}if (check) {printf("Welcome %s you have successfully authenticated \n", actual_name);}}

Now, let us compile this program, this time to avoid detection of stack being corrupted we need to disable the canary using the -fno-stack-protector-g -z execstack & then we need to compile it along with these flags.

Now, let us understand this program, this program is quite similar to the previous program except this time we used the strcmp string comparison function which checks values of two string and then sets the value of the variable to 1, if both the actual_name & password are same, now let us run this program with following inputs :

Input 1 : aaaaaaaaa ✔️

As expected the program can take up 9 characters

Input 2 : aaaaaaaaaaaaaaaaa(16) ⚠️

Well, what just happened ? wasn’t our program just capable of taking input of 9 characters? Well of course but now it used up an excess amount of buffer from other part of the program may be from the array of actual_name, so let us assume we our program can take up 16 characters and one null terminator /0 that is 17, let’s now use more variables.

Input 3 : aaaaaaaaaaaaaaaaaaa(19)

Damn, finally we can say our input is now divided in both the arrays and it the predefined array named actual_name has been finally overwritten 🎉. Congrats we just exploited and gained access to unauthenticated part of program using buffer overflow. Now let us try beyond this if we enter more than 19 characters…

Input 4 : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa (39 chars) 😶

Segmentation fault core dumped! So what’s actually this ? Basically this occurs when we are trying to access/write the part of memory which is just read only we pop up with this 😃 , this also signifies typical memory corruption issue.

Bonus : Did you think what if you didn’t have the source code and you had to exploit ?

We did not talk about reversing the binary, now let us give a try to read and understand it via disassembly 😄.

Let us open IDA and then we would be presented with the graph view & then give a right click for text view, if you are comfortable with graph view feel free to use it.

.text:00000000000006FA ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00000000000006FA public main
.text:00000000000006FA main proc near ; DATA XREF: _start+1D↑o
.text:00000000000006FA
.text:00000000000006FA password = byte ptr -16h
.text:00000000000006FA actual_name = byte ptr -0Dh
.text:00000000000006FA check = dword ptr -4
.text:00000000000006FA
.text:00000000000006FA push rbp
.text:00000000000006FB mov rbp, rsp
.text:00000000000006FE sub rsp, 32
.text:0000000000000702 mov [rbp+check], 0
.text:0000000000000709 mov rax, 'ktodferd'
.text:0000000000000713 mov qword ptr [rbp+actual_name], rax
.text:0000000000000717 mov [rbp+actual_name+8], '0'
.text:000000000000071B lea rax, [rbp+actual_name]
.text:000000000000071F mov rsi, rax
.text:0000000000000722 lea rdi, format ; "Welcome %s please enter your password"
.text:0000000000000729 mov eax, 0
.text:000000000000072E call _printf
.text:0000000000000733 lea rax, [rbp+password]
.text:0000000000000737 mov rsi, rax
.text:000000000000073A lea rdi, aS ; "%s"
.text:0000000000000741 mov eax, 0
.text:0000000000000746 call ___isoc99_scanf
.text:000000000000074B lea rax, [rbp+password]
.text:000000000000074F mov rsi, rax
.text:0000000000000752 lea rdi, aThePasswordYou ; "The password you have entered is %s"
.text:0000000000000759 mov eax, 0
.text:000000000000075E call _printf
.text:0000000000000763 lea rdi, aYourPasswordIs ; "Your password is wrong"
.text:000000000000076A mov eax, 0
.text:000000000000076F call _printf
.text:0000000000000774 lea rdx, [rbp+password]
.text:0000000000000778 lea rax, [rbp+actual_name]
.text:000000000000077C mov rsi, rdx ; s2
.text:000000000000077F mov rdi, rax ; s1
.text:0000000000000782 call _strcmp
.text:0000000000000787 test eax, eax
.text:0000000000000789 jnz short loc_792
.text:000000000000078B mov [rbp+check], 1
.text:0000000000000792
.text:0000000000000792 loc_792: ; CODE XREF: main+8F↑j
.text:0000000000000792 cmp [rbp+check], 0
.text:0000000000000796 jz short loc_7B0
.text:0000000000000798 lea rax, [rbp+actual_name]
.text:000000000000079C mov rsi, rax
.text:000000000000079F lea rdi, aWelcomeSYouHav ; "Welcome %s you have successfully authen"...
.text:00000000000007A6 mov eax, 0
.text:00000000000007AB call _printf
.text:00000000000007B0
.text:00000000000007B0 loc_7B0: ; CODE XREF: main+9C↑j
.text:00000000000007B0 mov eax, 0
.text:00000000000007B5 leave
.text:00000000000007B6 retn
.text:00000000000007B6 main endp

Coool, this is the disassembly of the main function which interests us!

Now if we could see at before this address 0x00000000000007C [rbp + password] is moved to destination register rdx & [rbp+actual_name] into destination register rax using the mov instruction which moves bytes from the source to destination, then at address 0x000000000000077F the rax is moved to rsi, and then _strcmp is called and then test instruction ANDs the value between eax and eax registers which might set the zero flag to zero or may not as we have not checked the status of flags inside a debugger, now then the flow of the program jumps to label loc_792 where it sets check to 0 and then again jumps to label loc_7B0 now one more interesting thing out here if actual_name is moved inside rax and then rax is moved to rsi our program finally reaches to the point where it prints Welcome you have successfully authenticated . So, if we run this inside a debugger and set the values equal we can gain authentication to the part of code, which usually does not execute/print. Then after this our program finally ends !

So, that was it all hopefully you enjoyed this ❤ ! I look forward to continue a binary exploitation series.

до свидания я люблю тебя ❤

--

--

dr3f.k0

Люблю вредоносные программы, баги и дизассемблеры. ( EN/RU)