Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between - buffer overflow and return to libc attack

I want to comprehend the exact difference between these two types of attack. From what I have read:

Buffer Overflow: It overwrites the ret address on the stack to point to another section of the code where the malicious code is inserted. So effectively - here we need to modify the source code of the program to actually carry out the attack.

Return to Libc- Here instead of modifying the source code, run time function calls provided by the C library are used (to say open up a shell). Here the parameters used for the function call are also passed in the overwriting buffer, ending up after the ret part of the stack.

Is the above an accurate description ?

And another related question - would it be possible to have a buffer overflow attack without actually modifying the source code of the original program? Probably if we write a new program and allow that to modify certain sections of memory (which is the new ret address in the corrupted stack of the original program). Then again, I think this might not be possible due to memory protection offered between processes in the kernel.

like image 428
Hari Avatar asked Sep 05 '11 00:09

Hari


3 Answers

In the classic buffer overflow exploit, the stack buffer being overflowed was filled with both the machine code to be executed (called the shellcode, because it typically invoked a shell process) and the new return address. The new return address would be crafted to point back within the overflowed stack buffer itself. Obviously, this requires knowing or guessing the address of that stack buffer in the attacked process.

In those days, the memory layout of processes was typically highly deterministic - the location of the stack buffer could usually be predicted quite well by the attacker (particularly if they knew exactly which version of the target software was being attacked). To improve the chances of success when there was some guesswork involved, the active shellcode would often be preceeded by a large quantity of executable machine code that performed no useful operation - called a "NOP sled" or "NOP slide", where "NOP" is the typical name for a machine code instruction that performs "No Operation". Returning to a point anywhere in the the NOP sled would have the desired effect.

A "return-to-libc" exploit, on the other hand, does not cause the hijacked process to return directly to the shellcode. Instead, it causes the process to return, one by one, to the start of a chain of library functions. These library functions might directly perform the operations the attacker wants, but more commonly they will be used to indirectly execute the attacker's shellcode.

like image 108
caf Avatar answered Nov 07 '22 23:11

caf


The part of overwriting a ret address is shared between both attacks. As the above reply indicates, you used to simply return into assembly code you had written. This assembly code would then, say, spawn a root user shell.

In neither attack you would 'overwrite' the source code. Viewing it from an assembly perspective, the source code is in the .text segment and has always been (or at least all the time I know of) write-protected. What you used to take advantage of was to write code that you had priorly assembled into memory segments, and then jump to this code. The code was most typically located in or near the 'stack segment', and by overflowing whatever you choose to overlow, you'd re-direct traffic from the ret address (say) there. Other attack venues included an environmental variable you had priorly created and filled with your shellcode; or also the heap, or function pointers, or the PLT. The code so inserted would usually use the system() call to execute what was desired - but for this, you need to be able to 'execute' on memory areas (or have the relocation entries you intend to use being declared writable).

The difference between the two attacks is that once memory had been made largely non-executable, attack type a (stack overflow) was pretty much screwed. An attempt to bypass this type of attack was then, as you write, to instead access shared library functions directly - aka, you had no longer need to write your code first into the stack segment or elsewhere and execute it there. However, I believe libc type attacks are also largely patched by now; I don't have the details handy; and maybe I'm wrong.

If you'd like to see how any of these attacks are being thwarted these days, or at least read about some key ideas, google 'Smashing the Stack in 2011' (or 2010) to get started.

like image 24
gnometorule Avatar answered Nov 08 '22 00:11

gnometorule


I would say buffer overflow is a class of programming error and return to libc is a exploitation technique. It is best not to mix the concepts together.

For example, you can use return to libc to exploit a buffer overflow vulnerability. Or you can use other techniques such as return to .text, or return to shellcode. Conversely, you can also use return to libc to exploit other bugs such as format string too.

like image 4
Nam Nguyen Avatar answered Nov 07 '22 22:11

Nam Nguyen