I'm currently taking a class through sans and in the buffer overflow section i am getting a different memory address than what the course says i should get. i get "Overflow the buffer to execute the function at memory address: 0x56556207" the course suggests i should be receiving it at memory address 0x56555c7.
Ive checked the code multiple times and have even started from scratch and still get the same output. i am brand new to the field and not sure what is causing it
Related
I am using the Xilinx SDK to debug an application running on a CORA-Z7-10 microcontroller.
When I use the debugger memory view sometimes the view shows the memory as expected, while sometimes it shows a bunch of question marks instead of the actual memory contents.
I know that in that areas of memory there is a binary file and I don't understand why the view shows a bunch of question mark instead. What does these questions marks represent? Why are they there?
To be more clear let's make an example: I put my binaries for the execution at addresses 0x00100000, 0x04000000, 0x08000000 (all in the same DDR3 memory address space). When I stop the execution, let's say at address 0x00101550 (which it is in the first binary), I cannot see memory at 0x04000000 but I can see memory at 0x08000000.
The disassembly view give me an "Memory read error at 0x04000000. Memory read aborted. Fault status 0x8, Domain 0x0". Any clue?
Assume a process is allocated a certain region of virtual memory.
How will the processor react if the process happens to access a memory region outside this allocation region?
Does the processor kill the process? Or does it raise a Fault?
Thank you in advance.
Processes are not really allocated a certain region of virtual memory. They are allocated physical frames that they can access using virtual memory. Processes have virtual access to all virtual memory available.
When a high level language is compiled, it is placed in an executable. This executable is a file format which specifies several things among which is the virtual memory in use by the program. When the OS launches that executable, it will allocate certain physical pages to the newly created process. These pages contain the actual code. The OS needs to set up the page tables so that the virtual addresses that the process uses are translated to the right position in memory (the right physical addresses).
When a process attempts to jump nowhere at a virtual address it shouldn't jump to, several things can happen. It is undefined behavior.
As stated on osdev.org (https://wiki.osdev.org/Paging):
A page fault exception is caused when a process is seeking to access an area of virtual memory that is not mapped to any physical memory, when a write is attempted on a read-only page, when accessing a PTE or PDE with the reserved bit or when permissions are inadequate.
The CPU pushes an error code on the stack before firing a page fault exception. The error code must be analyzed by the exception handler to determine how to handle the exception. The bottom 3 bits of the exception code are the only ones used, bits 3-31 are reserved.
It really depends on the language you used and several factors come into play. For example, in assembly, if you try to jump in RAM to a random virtual address. Several things can happen.
If you jump into an allocated page, then the page could contain anything. It could as well contain zeroes. If it contain zeroes, then the process will keep executing the instructions until it reaches a page which isn't present in RAM and trigger a page fault. Or it could as well just end up executing a jmp to somewhere else in RAM and in the end trigger page fault.
If you jump into a page which has the present bit not set (unallocated page), then the CPU will trigger a page fault immediately. Since the page is not allocated, it will not magically become allocated. The OS needs to take action. If the page was supposed to be accessed by the process then maybe it was swapped to the hard disk and the OS needs to swap it back in RAM. If it wasn't supposed to be accessed (like in this case), the OS needs to kill the process (and it does). The OS knows the process should not access a page by looking at its memory map for that process. It should not just blindly allocate a page to a process which jumps nowhere. If the process needs more memory during execution it can ask the OS properly using system calls.
If you jump to a virtual address which, once translated by the MMU using the page tables, lands in RAM in kernel mode code (supervisor code), the CPU will trigger a page fault with supervisor and present error codes (1 0 1).
The OS uses 2 levels of permission (0 and 3). Thus all user mode processes run with permission 3. Nothing prevents one user process from accessing the memory and the code of another process except the way the page tables are set up. The page tables are often not filled up completely. If you jump to a random virtual address, anything can happen. The virtual address can be translated to anything.
Would it be accurate to call the Heartbleed bug a stack overflow? In my understanding, this is quite a typical example. Is this technically correct?
The heartbleed bug is not a stack overflow error, but a type of a buffer overrun error. A stack overflow error happens when a program runs out of stack space. This usually results in a crash, and is not directly exploitable.
A stack is a data structure with "last in, first out" as its primary characteristic. It allows a caller (a piece of a program) to "push" information onto the stack, and to "pop" off the last item pushed. For a strict stack, no other operations are allowed.
The stack is used for programs when they call subprograms (functions, methods, subroutines are all subprograms, they have different names in different contexts). When a program calls a subprogram, a bunch of information needs to be saved so that it's available when the subprogram returns. So this "execution context" is pushed onto the stack, and then retrieved on return. This operation is so vital to computers that computer hardware supports it directly; in other words, there are machine instructions to do this so that it doesn't have to be done (slower) in software.
There is usually an amount of memory in the computer dedicated to this runtime stack, and even usually to a stack for each program running and a few for the operating system, etc. If subroutines calls get so "deep" that the amount of stack space allocated won't hold all the information needed for a call that occurs, that is a stackoverflow error.
This was not what the heartbleed problem was about. It allowed an exertnal program to set an amount of buffer space to be returned to it, and returned whatever happened to be in the memory beyond the little bit of data that this external program sent.
So the real answer to the question is "no", and I cannot imagine who would have thought that this was a typical example.
Technically, yes. But not in the traditional overflow sense where you try to smash the stack and fiddle with return values and try to execute code. This was purely a "leak private data" problem.
The OpenSSL specification requires that a client sent a chunk of randomish data in its heartbeat packet. The server is required to turn that data exactly as is to the client.
The bug is that the client basically sends two bits of data:
size_of_heartbeat (16bit integer presenting heartbeat data size)
heartbeat_data (up to 64k of data)
A malicious client can LIE about the data it's sending, and say:
size_of_hearbeat = 64k
heartbeat_data = '' (1 byte)
OpenSSL failed to verify that the size_of_hearbeat == actual_size(heartbeat_data), and would trust the size_of_heartbeat, so basically you'd have:
-- allocate as much memory as the client claims they sent to you
-- copy the user's heartbeat packet into the response packet.
Since the user claims they sent you 64k, OpenSSL properly allocated a 64k buffer, but then then did an unbounded memcpy() and would happily copy up to 64k of ram past where there client's heartbeat data actually occurred.
Given enough attempts at this, you could build up a pretty complete picture of what's in the server's memory, 64k at a time, and eventually be able to extract things like the server's SSL certificates, temporary data from previous users who'd passed through the encryption layers, etc...
Using some software in Windows XP that works as a Windows service and doing a restart from the logon screen I see an infamous error message
The instruction at "00x..." referenced memory at "00x...". The memory
could not be read.
I reported the problem to the developers, but looking at the message once again, I noticed that the addresses are the same. So
The instruction at "00xdf3251" referenced memory at "00xdf3251". The memory
could not be read.
Whether this is a bug in the program or not, but what is the state of the memory/access rights or something else that prevents an instruction from reading the memory it is placed. Is it something specific to services?
I would guess there was an attempt to execute an instruction at the address 0xdf3251 and that location wasn't backed up by a readable and executable page of memory (perhaps, completely unmapped).
If that's the case, the exception (page fault, in fact) originates from that instruction and the exception handler has its address on the stack (the location to return to, in case the exception can be somehow resolved and the faulting instruction restarted when the handler returns). And that's the first address you're seeing.
The CR2 register that the page fault handler reads, which is the second address you're seeing, also has the same address because it has to contain the address of an inaccessible memory location irrespective of whether the page fault has been caused by:
complete absence of mapping (there's no page mapped at all)
lack of write permission (the page is read-only)
lack of execute permission (the page has the no-execute bit set) OR
lack of kernel privilege (the page is marked as accessible only in the kernel)
and irrespective of whether it was during a data access or while fetching an instruction (the latter being our case).
That's how you can get the instruction and memory access addresses equal.
Most likely the code had a bug resulting in a memory corruption and some pointer (or a return address on the stack) was overwritten with a bogus value pointing to an inaccessible memory location. And then one way or the other the CPU was directed to continue execution there (most likely using one of these instructions: jmp, call, ret). There's also a chance of having a race condition somewhere.
This kind of crash is most typically caused by stack corruption. A very common kind is a stack buffer overflow. Write too much data in an array stored on the stack and it overwrites a function's return address with the data. When the function then returns, it jumps to the bogus return address and the program falls over because there's no code at the address. They'll have a hard time fixing the bug since there's no easy way to find out where the corruption occurred.
This is a rather infamous kind of bug, it is a major attack vector for malware. Since it can commandeer a program to jump to arbitrary code with data. You ought to have a sitdown with these devs and point this out, it is a major security risk. The cure is easy enough, they should update their tools. Countermeasures against buffer overflow are built into the compilers these days.
In Windows, stack is implemented as followed: a specified page is followed committed stack pages. It's protection flag is as guarded. So when thead references an address on the guared page, an memory fault rises which makes memory manager commits the guarded page to the stack and clean the page's guarded flag, then it reserves a new page as guarded.
when I allocate an buffer which size is more than one page(4KB), however, an expected error haven't happen. Why?
Excellent question (+1).
There's a trick, and few people know about it (besides driver writers).
When you allocate large buffer on the stack - the compiler automatically adds so-called stack probes. It's an extra code (implemented in CRT usually), which probes the allocated region, page-by-page, in the needed order.
EDIT:
The function is _chkstk.
The fault doesn't reach your program - it is handled by the operating system. Similar thing happens when your program tries to read memory that happens to be written into the swap file - a trap occurs and the operating system unswaps the page and your program continues.