I'm having problems with stack overflows and would like to see exactly what the contents on the stack are.
How can I examine the stack frame with GDB? is kind of the same question, however info locals looks fine here (few variables, most of them std::vectors and std::maps), so I wouldn't expect the stack to overflow from this. Moreover, I have set the stack limit to 32MB, so this should be plenty and no recursive functions are used.
Is there a tool that can show the complete contents of the stack, maybe ordered by size?
Stack overflows are better caught by special profilers rather than manually looking at variables in gdb. It is more likely that you have buffer overrun rather than stack overflow. In either case, here is a list of some profilers that can help you to point out the problem:
Valgrind
Purify
Insure++
Electric Fence
Good luck!
Even if you have no functions that call themselves, it's possible you've created a situation in which two or more functions are mutually recursive.
A good starting point would be to examine not the current stack frame, but a list of stack frames, using the "backtrace" (or "bt" for short) command. If you see a repeated pattern of two or more functions calling each other, then you have mutual recursion.
You can examine the current stack frame using the backtrace command.
You can also get the current stack pointer in gdb (e.g., by running 'info registers') and then dump the memory around that location using the examine (or 'x') command. Just be aware that the stack pointer points below the stack, so you need to start dumping from stack pointer - N to see the first N bytes on the stack.
Related
I have i binary that can be exploited with a buffer overflow, but it has a stack canary
I can get many addresses and values through a gets() call, but i cant locate the stack canary in pwndbg( version of gdb) so i can find out what of the values i get is the stack canary
I tried looking on the stack but cant find it and looked at a script that can already exploit it and it uses a canary value (by this i mean index of the leaked addresses from the gets() ) that i cant even find in the disassembler
I am missing some key details here, but I'll try to give this a go.
Firstly, the canary is not going to be on the stack, but between stack frames:
https://manybutfinite.com/img/stack/bufferCanary.png
Googling "stack canary location gcc" yields a couple images to help you understand this mechanism more easily.
Secondly, I am not quite sure what do you mean by using gets() to read. gets() reads the stdin and puts it into a buffer. You will not be able to use it to read program memory.
Regarding the script that is already working: I am skeptical.
From the gcc docs (https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html):
The guards are initialized when a function is entered and then checked when the function exits.
It might be possible that the code that manages to exploit it either has stack protector turned off in the binary, or it finds another way to bypass this protection by some other means. You can, for example overflow a local function pointer and not trigger the stack protector at all. The stack protector only protects against overflowing into the stored RBP and RIP (32bit: EBP and EIP), not against overflowing into local variables.
I'm currently tasked to perform post-mortem debugging using gdb, binary and a core file. Often I encounter the phenomenon of stack trashing where the stack cannot be reconstructed by bt. However, by examining memory I can often recover contiguous parts of the stack area that are still intact, including their frame pointers.
My question now is if I can recover such a frame pointer, is there a gdb command that allows me to reconstruct and print the stack up to this point, including all local variables? Or will the bt command only work up from the current frame pointer?
Regards
When does it cause a stackoverflow error in recursion in c++? What is the size of memory consumed while working with recursion? Is it 4 times the function invoked(4 being the size of pointer)? Does that mean there is a different pointer associated with each call?
Every platform has limits on the number of stack frames you can use in a program. When a recursive function does not meet its terminating criteria soon enough, it will lead to stack overflow.
In Microsoft Visual Studio compilers, you can specify the stack size using the compiler option /F (There is also a linker option, /STACK). Without this, the stack size is 1 MB. You can get more information at http://msdn.microsoft.com/en-us/library/tdkhxaks.aspx.
Each stack frame needs different amount of memory -- they are determined by the number and types of local variables, the type of the return value, the number and types of parameters. Hence, the number of stack frames you can use without causing stack overflow varies.
g++/gcc also have a way of specifying stack size using -Wl-stack_size. You can find more on that subject at Change stack size for a C++ application in Linux during compilation with GNU compiler.
C++ as a language has no notion of a "stack" or "stack overflow".
The stack is an implementation detail. The amount consumed per call depends on your platform, your compiler, the actual code etc. As a rule of thumb, you can expect the return address and all of the function's arguments to be pushed onto the stack. Additionally, automatic variables usually live on the stack (but see below).
This is, however, a simplification: in some cases the compiler might be able to eliminate function calls altogether or turn them into jump instructions. Arguments are commonly passed in registers. Automatic variables can be optimized away or stored in registers. Etc etc.
If you want to know for sure, compile your code to assembly and carefully study the result. Alternatively, rig up some representative benchmarks and run them until the stack is exhausted.
Last but not least, the amount of stack available to an application is often configurable at the OS level.
For example when we call say, a recursive function, the successive calls are stored in the stack. However, due to an error if it goes on infinitely the error is 'Segmentation fault' (as seen on GCC).
Shouldn't it have been 'stack-overflow'? What then is the basic difference between the two?
Btw, an explanation would be more helpful than wikipedia links (gone through that, but no answer to specific query).
Stack overflow is [a] cause, segmentation fault is the result.
At least on x86 and ARM, the "stack" is a piece of memory reserved for placing local variables and return addresses of function calls. When the stack is exhausted, the memory outside of the reserved area will be accessed. But the app did not ask the kernel for this memory, thus a SegFault will be generated for memory protection.
Modern processors use memory managers to protect processes from each other. The x86 memory manager has many legacy features, one of which is segmentation. Segmentation is meant to keep programs from manipulating memory in certain ways. For instance, one segment might be marked read-only and the code would be put there, while another segment is read/write and that's where your data goes.
During a stack overflow, you exhaust all of the space allocated to one of your segments, and then your program starts writing into segments that the memory manager does not permit, and then you get a segmentation fault.
A stack overflow can manifest as either an explicit stack overflow exception (depending on the compiler and architecture) or as a segmentation fault, i.e., invalid memory access. Ultimately, a stack overflow is the result of running out of stack space, and one possible result of running out of stack space is reading or writing to memory that you shouldn't access. Hence, on many architectures, the result of a stack overflow is a memory access error.
The call stack is being overflowed, however the result of the overflowing is that eventually call-related values are pushed into memory that is not part of the stack and then - SIGSEGV!
I just ran into an issue where a stack overflow in a threaded c++ program on HPUX caused a SEGV_MAPERR when a local object tried to call a very simple procedure. I was puzzled for a while, but luckily I talked to someone who recognized this as a stack size issue and we were able to fix the problem by increasing the stack size available to the threads.
How can I recognize when the stack overflows? Do the symptoms differ on windows/linux/hpux?
Assuming you're not on a platform thats going to stop your app and say "stack overflow" I suspect you'll see the same behavior that you would see from any kind of buffer overflow. The stack is just another preallocated chunk of memory for your program, and if you go outside those bounds... well good luck! Who knows what you'll stomp on!
You could write over the temperature readout from the CPU, it could be the email you're typing to Larry, it could be the bit saying that the kernel is locked, causing a fun deadlock condition! Who knows.
As for C++, there's nothing saying how the stack should be laid out in relation to other things in memory or that this thing even needs to be a stack!
How can I recognize when the stack overflows?
If you know the stack size, where the stack starts and the direction it grows in memory, you can simply check the address of the stack pointer and see if it past the end of the stack. C++ does not allow direct access to the stack pointer. You could easily write a small function in assembly to perform this analysis and link it into you program.
Exception code 0xC00000FD on Windows.
Usually it's easier to diagnose when you realize your SEH stops working.
Perhaps a bit off topic, but the analagous issue in Ada (running out of stack space in tasks) is a rather common "uncommon" error. Many compilers will stop the task (but not the main task) with a PROGRAM_ERROR exception.
In a way, you almost have to be able to sniff out this one. It tends to start with something like, "I moved this big array inside my task, and suddenly it quit working".
Output text to screen became mixed with lines of code from program under test. Also present were previous bash commands and other text of unidentified origin. Added to all that the program text became corrupted.