I'm a new C programmer, still learning the language itself.
Anyway -
I'm trying to access a specific memory address.
I've written this code:
#include <stdio.h>
int main()
{
int* p = (int*) 0x4e0f68;
*p = 12;
getchar();
}
When I try to access a specific memory address like that, the program crashes.
I don't know if this information is relevant, but I'm using Windows 7 and Linux Ubuntu.
(I've tried this code only on Windows 7).
Any explanations why the program crashes?
How can I access a specific memory address (an address which is known at compile-time, I don't mean to dynamic memory allocation)?
Thanks.
That's memory you don't own and accessing it is undefined behavior. Anything can happen, including crashing.
On most systems, you'd be able to inspect the memory (although technically still undefined behavior), but writing to it is a whole different story.
Strictly speaking you cannot create a valid pointer like this. Valid pointers must point to valid objects (either on your stack or obtained from malloc).
For most modern operating systems you have a virtual memory space that only your process can see. As you request more memory from the system (malloc, VirtualAlloc, mmap, etc) this virtual memory is mapped into real usable memory that you can safely read and write to. So you can't just take an arbitrary address and try to use it without OS cooperation.
An example for windows:
#include <windows.h>
#include <stdio.h>
int main(void)
{
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
unsigned pageSize = sysinfo.dwPageSize;
printf("page size: %d\n", pageSize);
void* target = (void*)0x4e0f68;
printf("trying to allocate exactly one page containing 0x%p...\n", target);
void* ptr = VirtualAlloc(target, pageSize, MEM_COMMIT, PAGE_READWRITE);
if (ptr)
printf("got: 0x%p\n", ptr); // ptr <= target < ptr+pageSize
else
printf("failed! OS wont let us use that address.\n");
return 0;
}
Note that this will give you different results on different runs. Try it more than once.
Just to clrify one phrase the OP wrote: strictly speaking, no address associated to a program (code or data) is known at compile time. Programs usually are loaded at whatever address the OS determines. The final address a program sees (for example, to read a global variable) is patched by the OS in the very program code, using some sort of relocation table. DLL functions called by a program have a similar mechanism, where the IDATA section of the executable is converted into a jump table to jump to the actual address of a function in a DLL, taking the actual addresses from the DLL in memory.
That said, it is indeed possible to know by advance where a variable will be placed, if the program is linked with no relocation information. This is possible in Windows, where you can tell the linker to load the program to an absolute virtual address. The OS loader will try to load your program to that address, if possible.
However, this feature is not recommended because it can lead to easily exploiting possible security holes. If an attacker discovers a security hole in a program and try to inject code into it, it will be easier for him if the program has all its variables and functions in specific addresses, so the malicious code will know where to make patches to gain control of that program.
What you're getting is a segfault - when you're trying to access memory you don't have permission to access. Pointers, at least for userspace, must point to some variable, object, function, etc. You can set a pointer to a variable with the & operator - int* somePtr = &variableToPointTo, or to another pointer - int* someNewPtr = somePtr. In kernel mode (ring 0) or for OS development, you can do that, BUT IT IS NOT ADVISED TO DO SO. In MS-DOS, you could destroy your machine because there was no protection against that.
Related
I found an interesting phenomenon when I execute a simple test code:
int main(){
int *p=(int *)0x12f930;
printf("%d",*p);
return 0;
}
Of course it crashed with a segmentation fault. but even I change the 0x12f930 to 0x08048001(0x08048000+1, that should be the text area when execute the elf binary), it still crashed with a SF.
then I changed my code as below:
int main()
{
int i=1;
printf("%x",&i);
return 0;
}
the output is 0xf3ee8f0c, but as I know, the address of user space should be <=0xc0000000, so I am quite confused.
Anyone can help?
First, don't ever do it, unless there's a specific need to.
But, certain embedded applications and legacy systems, might need the explicit memory access.So, here's and example code:
const unsigned addr = 0xdeadbeee;//This address is an example, which should always be >0xc000000 and const
const unsigned *ptr=(const unsigned*)addr;//Then you can assign it to a pointer after proper casting and keeping it const, unless there's a need to keep it not-const
Be careful, as you may hit an unallocated memory or worse thrash the memory and even cause system instability. Also, the above code is implementation defined and as such not portable among different systems.
If you are executing your program in that OS, you need to understand the memory addressing scheme, followed by OS.Specially, some OS assign random starting address of the stack and/or heap in order to make some difficult to attack memory/processes in the system.So, every time you will execute the program, that processes address will be different.
If you wish to examine a process's memory, you could refer to source of GDB and how they do it.
I have a couple of doubts, I remember some where that it is not possible for me to manually put a variable in a particular location in memory, but then I came across this code
#include<stdio.h>
void main()
{
int *x;
x=0x200;
printf("Number is %lu",x); // Checkpoint1
scanf("%d",x);
printf("%d",*x);
}
Is it that we can not put it in a particular location, or we should not put it in a particular location since we will not know if it's a valid location or not?
Also, in this code, till the first checkopoint, I get output to be 512.
And then after that Seg Fault.
Can someone explain why? Is 0x200 not a valid memory location?
In the general case - the behavior you will get is undefined - everything can happen.
In linux for example, the first 1GB is reserved for kernel, so if you try to access it - you will get a seg fault because you are trying to access a kernel memory in user mode.
No idea how it works in windows.
Reference for linux claim:
Currently the 32 bit x86 architecture is the most popular type of
computer. In this architecture, traditionally the Linux kernel has
split the 4GB of virtual memory address space into 3GB for user
programs and 1GB for the kernel.
Adding to what #amit wrote:
In windows it is the same. In general it is the same for all protected-mode operating systems. Since DOS etc. are no longer around it is the same with all systems except kernel-mode (km-drivers) and embedded systems.
The operating system manages which memory-pages you are allowed to write to and places markers that will make the cpu automatically raise access-violations if some other page is written to.
Up until the "checkpoint", you haven't accessed memory location 0x200, so everything works fine.
There I'd a local variable x in the function main. It is of type "pointer to int". x is assigned the value 0x200, and then that value is printed. But the target of x hasn't been accessed, so up to this point it doesn't matter whether x holds a valid memory address or not.
Then scanf tries to write to the memory address you passed in, which is the 0x200 stored in x. Then you get a seg fault, which is certainly sac possible result of trying to write to an arbitrary memory address.
So what are your doubts? What makes you think that this might work, when you come across this code that clearly doesn't?
Writing to a particular memory address might work under certain conditions, but is extremely unlikely to in general. Under all modern OSes, normal programs do not have control over their memory layout. The OS decides where initial things like the program's code, stack, and globals go. The OS will probably also be using some memory space, and it is not required to tell you what it's using. Instead you ask for memory (either by making variables or by calling memory allocation routines), and you use that.
So writing to particular addresses is very very likely to get either memory that hasn't been allocated, or memory that is being used for some other purpose. Neither of those is good, even if you do manage to hit an address that is actually writable. What if you clobber sundry some piece of data used by one of your program's other variables? Or some other part of your program clobbers the value you just wrote?
You should never be choosing a particular hard-coded memory address, you should be using an address of something you know is a variable, or an address you got from something like malloc.
Is the unused memory in address space of a process protected by just having read permission, so that writing to a location pointed by an unitialized pointer for example always cause a page fault to be trapped by the OS? Or is it not the case, and every memory location besides the code (which ofcourse is given read only access), is given write access?
I'm asking this because my friend was showing me his code where he didn't initialize a pointer and wrote in the memory pointed by it, but still his program wasn't crashing with mingw gcc compiler for windows but always crashing with visual c++, in mac or linux.
What I think is that the OS do not protect memory for unused areas and the crashing was being caused because in the code generated by the mingw, the random pointer value was pointing to some used area such as stack, heap or code, while in other cases it was pointing to some free area. But if the OS really doesn't protect the unused areas, wouldn't these sort of bugs, such as uninitialized pointers be difficult to debug?
I guess this is why it is advised to always assign NULL to a pointer after calling delete or free, so that when something is accessed with it, it really causes a visible crash.
Uninitialized pointers don't necessarily to point to unused address space. They could very well be values that happen to point to writeable memory. Such as a pointer on the stack that happened to be where a previously executed function stored a valid address.
In a typical, current server/desktop OS (and quite a few smaller systems such as cell phones as well) you have virtual memory. This means the OS builds a table that translates from the virtual address your code uses, to a physical address that specifies the actual memory being addressed. This mapping is normally done in "pages" -- e.g., a 4KB chunk of memory at a time.
At least in the usual case, parts of the address space that aren't in use at all simply won't be mapped at all -- i.e., the OS won't build an entry in the table for that part of the address space. Note, however, that memory that is allocated will (of necessity) be rounded to a multiple of the page size, so each chunk of memory that's in use will often be followed by some small amount that's not really in use, but still allocated and "usable". Since protection is also (normally) done on a per-page basis, if the rest of that page is (say) Read-only, the remainder at the tail end will be the same.
It depends on the implementation of the OS. In some configurations, for example, ExecShield will protect most of the memory that goes out of the bounds of the program, and also it is common that the first few bytes of the data segment to be protected (to signal access with NULL pointers), but it may be the case that the pointer actually points to a valid, arbitrary, memory address within the program.
Memory protection is not provided by c/c++. You may find that the pointer just happens to contain a pointer to valid memory, e.g. a previous function has a ptr variable on the stack and another function called later just happens to use the same stack space for a pointer.
The following code will print "Hello" if compiled and ran with gcc:
#include
char buffer[10];
void function1(void) {
char * ptr = buffer;
sprintf(buffer, "Hello");
return;
}
void function2(void) {
char * ptr2;
printf("%s\n", ptr2);
}
int main(int argc, char * argv[]) {
function1();
function2();
}
For debug builds some compilers (I know that Visual Studio used to do this) will secretly initialise all variables like ptr2 to a bad value to detect these kinds of error.
With C normally you find out that memory has been abused by the OS killing your program.
Simply, I assume the answer is "No, unused memory in address is not space protected." C isn't sophisticated enough to handle such instances.
How does this code work???
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *addr = (int*) 0x4888d0;
*addr = 30;
printf("%i %p\n", *addr, addr);
return 0;
}
It works by assuming 0x4888d0 is a the address of a writable block of memory of at least sizeof(int) bytes that does not interfere with the functionality of printf or the C runtime system.
Or rather, it doesn't work, at least not on my system (Segmentation fault).
There is nothing strange in it, however, it seems quite dangerous. What this program is trying to do is to write 30 at a specific location. i.e., the Location whose address is contained in 0x4888d0.
Why this code is written like this and why this particular address, well this is anybody's guess.
int *addr = (int*) 0x4888d0; will give addr an address =0x4888d0. This address might be a valid address. But there is no guarantee that it will always work.
As stated above this tends to segment value, or corrupt, normal applications. However,
Modern computers tend to have reserved memory addresses that do magic things, like control I/O, set CPU modes, update memory maps, etc. Memory pages with such are "real" addresses not mapped into the virtual memory regular applications get. Such is where the kernel communicates with hardware controllers. The fact that the provided fragment pokes a memory location and then promptly reads it back is typical of asking a controller for some type of status and then getting the status back (any write to a magic word can update the status the controller makes available to the software... the value may not be important).
So, if this code is from kernel space, or if this is in some micro-controller, or other strange system, the magic memory addresses could be available. Another possibility is that a privileged application has requested special virtual memory mapping from the kernel that can also expose magic pages to it. This can get weird as while the application requested something be mapped to virtual memory location including 0x4888d0, the real memory page could be quite different (and unavailable to the application).
I'm trying to debug a program I've written. According to the debugger a particular void * holds the value 0x804b008. I'd like to be able to dereference this value (cast it to an int * and get it's value).
I'm getting a Segmentation Error with this code. (The program with the void * is still running in the background btw - it's 'paused')
#include <stdio.h>
int main() {
int* pVal = (int *)0x804b008;
printf("%d", *pVal);
}
I can see why being able to deference any point in memory could be dangerous so maybe that's why this isn't working.
Thank you!
Your program (running in the debugger) and this one won't be running in the same virtual memory space; accessing that pointer (even if it were a valid one) won't give you any information.
Every program running on your machine has its own logical address space. Your operating system, programming language runtime, and other factors can affect the actual literal values you see used as pointers for any given program. But one program definitely can't see into another program's memory space, barring of course software debuggers, which do some special tricks to support this behaviour.
In any case, your debugger should let you see whatever memory you want while your program is paused - assuming you have a valid address. In gdb x/x 0x804b008 would get you what you want to see.
For more information:
Wikipedia article on Virtual Memory.
gdb documentation
It's quite simple. The OS knows that address does not belong to your program, so you can't print it without bypassing memory protection.