top of page
Writer's pictureVlad

[THe Sinful COde - Eps1] - BUfferOverfl0W on C, Compromising an Account and Application Destruction

Bufferoverflow is the oldest vulnerabilities in the history of cybersecurity and computer science. From OWASP,


"A buffer overflow condition exists when a program attempts to put more data in a buffer than it can hold or when a program attempts to put data in a memory area past a buffer. In this case, a buffer is a sequential section of memory allocated to contain anything from a character string to an array of integers. Writing outside the bounds of a block of allocated memory can corrupt data, crash the program, or cause the execution of malicious code."


A glass is full, if liquid has occupied its entire solid space. Pouring in an extra more would cause an overflow of H20 on the entire container. A 500ml of a liquid container could only hold up 500ml of liquid, anything beyond that would cause the liquid to spill out from its container. Let's do some experiimentation, imagine you put up your most expensive necklace on an empty 1L liquid container. Then, pour some water on it. The continous flow of liquid as it approached the max limit of 1L, will cause an overflow of liquid from the container causing your necklace to drop. This is a better example of a buffer overflow vulnerability(specifically a stack-base buffer overflow), which this post is all about.


A buffer is a container where data or address is stored, that would be needed for the manipulation of a certain function. A stack is subdivided on a memmory space, where data has been stacked or stored. When certain user fed in too much data given that a certain memmory must meet its assigned size or space. When a user fed in too much input, memmory stacked on an application will be based on


This flaw could start from the obvious, and that is an insecure way of coding during the development stage. This has been one of the early developer's headache.


A stack buffer overflows happens when an unbounded copy from a variable-sized buffer to a local variable. Take for example the C function below,


void func(){

char password[16];

strcopy(password,pwd);

....

}


A variable buffer 'password' was assigned to contain 16 characters. If for any instance a feed exceeded the assigned character size, we can say that the buffer overflowed. Just one instance of this vulnerability.


Below is the sample C program that would perfectly demonstrate a programming flaw.




So the program's function is to guess a word and validate if the the word is correct or not. The function token_check is where the validation of input is made.At (1),I have set the character size of the variable 'password_buffer' initialized to 16. Parameter value from the user's input variable(password) was copied to the function's local variable(password_buffer) in case (2). On (3) are the conditions, that if the user input matched the variable's value, it will return a flag equal to 1, which means that the value matched. Else it will indicate a word mismatch.


With the code structured above, we can now proceed with some test runs.




Everything works as the source code intends to, so far...





An overflow leads to a contradictory behavior! Program just indicates a success authentication from a wrong input.


So what happened?


To better illustrate and grasp on the idea on how this happened, let's debug the program by using 'gdb'. This way we'll dig deep on the code and execute each line for us to determine the bug that leads to this flaw. Let's compile the code and execute the program by gdb.


After compiling let's set the break point to main(break main), which will cause the debugger to break when main function is called. This will also pause the execution as we continue to dig deeper. Then, we start or run the program...




We then go through the code and check by executing list gdb command. This way we'll be aware of the next execution we'll make as we proceed with the debugging process. We'll also take note of the line, this will be key on setting up break points.








After that, we set some break points on line 37, the line that contains strcpy(password_buffer, password), due to the fact that this is where parameter values has been passed from the user input(on main function) to the token_check function. This way we'll be aware how much data has been passed, as this will be a culprit.


Same reason for line 43(return flag), where we would know the value and condition when the 'flag' variable is returned.

For break point strcpy(password_buffer, password)





<1>Typing on 'c'(for continue) will proceed to the next step on the line of code, and that would compile and run the program. We input 30 chars of Ks. It then set's its 3rd break that indicates the behavior on the function call token_check.


Before the proceeding with line 37, we examine on the pointer <2>password_buffer(which was located on 0x22fdf0 of memmory) which does contain some data and <3>flag(located on 0x22fe0c)which at this moment does not contain any value for variable is not yet used on the function we are debugging.


<4> The difference of memmory address of flag and the password_buffer will show that flag is 28 bytes past the start of password_buffer.


<5>With the execution on <4> we can see the relation on these block of memmory of address.


Lets proceed with our next break point, return flag






<1> On the next step, next break point has been executed which contains the value for the buffers.

<2> On the address 0x22fdf0 lies password buffer buffer value, K which is repeated 30times.

<3> Let's check on the value of flag, which now is 0x4b(unicode value for 'K').

<4> We can see changes values from the code blocks as the process has been executed.

<5>We take a peek on the value of flag, which is from ASCII '75' which equals capital letter 'K'.

<6> We then execute command, x/dw &flag to check the decimal value for flag which is 19275.

<7> We then continue to the last part of the code, that renders us a positive output.


Where is the flaw?


If you check and look closely we can see that the value of flag is 19275 this will be treated as an integer. With that the function token_check will return 19275 instead of 0.


Looking back at the code, the if statement considers any non zero value to be authenticated, thus the execution flow will delve into the value of flag returned by the function, resulting in a segmentation fault.


Going in further...


Below is the illustration of the disassembled code of the main function. I have highlighted 2 instructions that we would focus on this function. The first instruction moves the address from rcx to rax. Wherein from the previous instruction the address from rax was loaded to the base pointer(rbp), which is pointing to rsp the top of the stack. The second instruction is the call to the token check function(with the address of 0x4015b0), that seems to be a jump to that particular function.




With that we disassembled token_check as execution will continue on the mentioned function. We can clearly see how the process from the token check function take place as it pushes values and address on the memmory.



We load the initial address block of esp, and heres' the result...





We then continue with the step, as we are prompted with the program input.




Let's simulate the process until finished and the output rendered same result.




When some of the bytes of the saved return address are overwritten, the

program will still try to use that value to restore the execution pointer register

(in this case EBP). This usually results in a crash, since execution is essentially jumping

to a random location.


Current esp block...


<krontek> halt


141 views0 comments

Comments


LET'S TAKE IT TO THE NEXT LEVEL!

bottom of page