Statically assign a memory address in c program - c

I'm building very small test program and I wanted to have the program access the same memory address every time(I know its not a good practice) to simulate some behaviors. How can I just pick a memory address to hard code in the program an try it out? Is there a way to see unused blocks of memory addresses and just block them ?
I totally understand that this might create unwanted conditions/situation.

You can use ampersand operator (&) to point a pointer to a specific memory address. However, your program must be able to able to legally access that address which is decided by what address range your OS has assigned to your program otherwise you will a segmentation fault.
Sample code:
void * p1 = (void *)0x28ff44;
Or if you want it as a char pointer:
char * p2 = (char *)0x28ff44;
PS
You can find out the address allocated to your program and take one of the addresses from it into your program. For a single run, your program will access the same memory location but for another run, it will be different one assigned to your process but same for that run.
You can refer here to check how you can read memory address assigned to your process. You can take input at runtime to provide your process id to get the filepath.
Work around
Since you mentioned it is small test program, you can also save yourself your efforts by just disabling randomization of memory addresses by disabling ASLR for your testing your program, you just disable ASLR in linux using
echo 0 > /proc/sys/kernel/randomize_va_space
and then run your program, declare and initialize a variable, print its address and then hardcode that address in your program. Bingo!! Everytime that address will be used untill you enable ASLR again.
However it is not secure to turn off ASLR and after testing you should enable ASLR again by
echo 1 > /proc/sys/kernel/randomize_va_space

Related

Is it possible to "create" garbage memory data in one C program, and then later read in that same data in from another C program?

I would like to know if it is possible to in the first C program:
Allocate and declare an int to the value of 5 in memory
Print out the address of the variable (eg: 0x7ffee6a98ad8)
Terminate
And then in a second C program, after the first has completely finished executing:
Read in the data that was previously declared at address 0x7ffee6a98ad8
Print the correct value of 5
Is this a possibility in C?
If so, how would one go about accomplishing such a task?
I am using Linux, if that matters.
It once was possible. If you made a large C program in DOS and alllocated some RAM with malloc() you could in fact save that address somewhere (like on disk) and start another C program and read that memory.
I hear it's still possible on deeply embedded platforms, but on modern multi-user operating systems, when you allocate RAM from the OS it clears the RAM first so you can't see it.
Question edited to say Linux. Well no, but also yes. Open up the shell process with ptrace(), allocate some memory in the shell process and write to it, and the next program can find it there. This is nothing like wild pointer games, and is really quite tricky. https://techryptic.github.io/2018/04/07/Using-PTRACE-to-Inspect-&-Alter-Memory/ The window is closing; they're starting to tighten things so you can't debug any processes but your own child processes because they don't want a sudo disaster.

Why is this pointer program not overwriting all the RAM memory location?

This is the code I wrote to overwrite the RAM data and eventually leading in crashing the OS.
#include<stdio.h>
#include<conio.h>
int main(){
int i=10;
int *j;
j=&i;
int m=0;
while(true){
*(j+m)=m*m; //next location of i
printf("New Value is. %d \n",(m));
m++;
}
printf("Complete");
getch();
return 0;
}
But the only after m is 46 my program is crashing(the value of m can be different from compiler to compiler).
Why this program is behaving in such manner? Is it because our OS provides some fixed space of memory to load & run a program and overreaching the memory limit would cause crashing the program?
You are overwriting the stack, destroying data from local variables and return from procedure pointers from your current function through all other functions called before it, until you reach a part of memory that is read-only because it contains the actual code of your program, and this part is protected. When you try to overwrite that too, the system will prevent it and the application will crash with a "Memory cannot be written" error of something like that.
Not sure about Linux, but in Windows you can disprotect this memory with VirtualProtect(). But doing that will only make it crash a little down the road as you overwrite the loop code with garbage and die in a Segmentation Fault error.
But still, you won't have access to the actual RAM of your computer, you can't even know the actual address in the real RAM you are in. When you are a process under a operational system, you are in the realm of virtual memory, where the OS will guarantee you cannot interfer directly with the system's or other processes' memory, not without going through the channels the system offers you anyway.
The problem is, after the very first iteration, *(j+m) is invalid memory access, which causes undefined behavior. Then, nothing, absolutely nothing is guaranteed.
In your case, it just happens that until index 46, the memory location is accessible from the process (i.e, the location belongs to the process's virtual address space, though that does not mean you are allowed to access, you may be overwriting some other data) and past that index, the memory location is not accessible from your process, so the access violation happens, causing the segfault.
Understand one thing first... Accessing a block of memory that was not initially defined leads to undefined behavior according to the rules of C language!
Now undefined behavior is seriously not undefined. In my case when I run the program, it crashes only after m=1.
There is no logic behind defining the sense of undefined. Undefined behavior may not only depend upon what causes it but several other issues.
Besides the fact that you program contains an undefined behavior because you tried to access memory you didn't allocate in some way, what you observe is some protection ensured by OS your program is running on.
It is very common for OS to manage space allocated to running programs by chunks of space. Such a chunk is usually called a page. A page is the finer grain of memory an OS can manage on behalf the process. So even if accessing the next memory address of variable i is logically false (undefined behavior), the generated code for the machine probably obviously try to get the memory content. At that time OS/CPU/MMU only verify if that address is in a page of your process. So the crash appears only when you access a page that is not in the space of your process.
If you want more details, read about virtual memory, page fault...

scan memory of calling process

I have to scan the memory space of a calling process in C. This is for homework. My problem is that I don't fully understand virtual memory addressing.
I'm scanning the memory space by attempting to read and write to a memory address. I can not use proc files or any other method.
So my problem is setting the pointers.
From what I understand the "User Mode Space" begins at address 0x0, however, if I set my starting point to 0x0 for my function, then am I not scanning the address space for my current process? How would you recommend adjusting the pointer -- if at all -- to address the parent process address space?
edit: Ok sorry for the confusion and I appreciate the help. We can not use proc file system, because the assignment is intended for us to learn about signals.
So, basically I'm going to be trying to read and then write to an address in each page of memory to test if it is R, RW or not accessible. To see if I was successful I will be listening for certain signals -- I'm not sure how to go about that part yet. I will be creating a linked list of structure to represent the accessibility of the memory. The program will be compiled as a 32 bit program.
With respect to parent process and child process: the exact text states
When called, the function will scan the entire memory area of the calling process...
Perhaps I am mistaken about the child and parent interaction, due to the fact we've been covering this (fork function etc.) in class, so I assumed that my function would be scanning a parent process. I'm going to be asking for clarification from the prof.
So, judging from this picture I'm just going to start from 0x0.
From a userland process's perspective, its address space starts at address 0x0, but not every address in that space is valid or accessible for the process. In particular, address 0x0 itself is never a valid address. If a process attempts to access memory (in its address space) that is not actually assigned to that process then a segmentation results.
You could actually use the segmentation fault behavior to help you map out what parts of the address space are in fact assigned to the process. Install a signal handler for SIGSEGV, and skip through the whole space, attempting to read something from somewhere in each page. Each time you trap a SIGSEGV you know that page is not mapped for your process. Go back afterward and scan each accessible page.
Do only read, however. Do not attempt to write to random memory, because much of the memory accessible to your programs is the binary code of the program itself and of the shared libraries it uses. Not only do you not want to crash the program, but also much of that memory is probably marked read-only for the process.
EDIT: Generally speaking, a process can only access its own (virtual) address space. As #cmaster observed, however, there is a syscall (ptrace()) that allows some processes access to some other processes' memory in the context of the observed process's address space. This is how general-purpose debuggers usually work.
You could read (from your program) the /proc/self/maps file. Try first the following two commands in a terminal
cat /proc/self/maps
cat /proc/$$/maps
(at least to understand what are the address space)
Then read proc(5), mmap(2) and of course wikipages about processes, address space, virtual memory, MMU, shared memory, VDSO.
If you want to share memory between two processes, read first shm_overview(7)
If you can't use /proc/ (which is a pity) consider mincore(2)
You could also non-portably try reading from (and perhaps rewriting the same value using volatile int* into) some address and catching SIGSEGV signal (with a sigsetjmp(3) in the signal handler), and do that in a -dichotomical- loop (in multiple of 4Kbytes) - from some sane start and end addresses (certainly not from 0, but probably from (void*)0x10000 and up to (void*)0xffffffffff600000)
See signal(7).
You could also use the Linux (Gnu libc) specific dladdr(3). Look also into ptrace(2) (which should be often used from some other process).
Also, you could study elf(5) and read your own executable ELF file. Canonically it is /proc/self/exe (a symlink) but you should be able to get its from the argv[0] of your main (perhaps with the convention that your program should be started with its full path name).
Be aware of ASLR and disable it if your teacher permits that.
PS. I cannot figure out what your teacher is expecting from you.
It is a bit more difficult than it seems at the first sight. In Linux every process has its own memory space. Using any arbitrary memory address points to the memory space of this process only. However there are mechanisms which allow one process to access memory regions of another process. There are certain Linux functions which allow this shared memory feature. For example take a look at
this link which gives some examples of using shared memory under Linux using shmget, shmctl and other system calls. Also you can search for mmap system call, which is used to map a file into a process' memory, but can also be used for the purpose of accessing memory of another process.

Printing a malloc'd pointer always gives the same address

Am I printing it wrong?
#include <stdio.h>
#include <stdlib.h>
int
main( void )
{
int * p = malloc(100000);
int * q;
printf("%p\n%p\n", (void *)p, (void *)q);
(void)getchar(); /* to run several instances at same time */
free(p);
return 0;
}
Whether I run it sequentially or in multiple terminals simultaneously, it always prints "0x60aa00000800" for p (q is different, though).
EDIT: Thanks for the answers, one of the reasons I was confused was because it used to print a different address each time. It turns out that a new compiler option I started using, -fsanitize=address, caused this change. Whoops.
The value of q is uninitialized garbage, since you never assign a value to it.
It's not surprising that you get the same address for p each time you run the program. That address is almost certainly a virtual address, so it applies only to the memory space of the currently running program (process).
Virtual address 0x60aa00000800 as seen from one program and virtual address 0x60aa00000800 as seen from another program are distinct physical addresses. The operating system maps virtual addresses to physical addresses, and vice versa, so there's no conflict. (If different programs could read and write the same physical memory, it would be a security nightmare.)
It also wouldn't be surprising if they were different each time. For example, some operating systems randomize stack addresses to prevent some code exploits. I'm not sure whether heap addresses are also randomized, but they certainly could be.
https://en.wikipedia.org/wiki/Virtual_memory
This behavior is not entirely surprising. The malloc operation is simply returning a pointer to user addressable + allocated memory in the process. It's completely reasonable for the first memory request of the same size to return the same address through different invocations of a process
The behavior for q doesn't contradict this. You have given q no value hence it gets whatever the last value written to that portion of the stack was. It's unsurprising that undefined behavior would be different through different invocations of the same process (after all, it's undefined)
Your code is fine.
The same code, and the same algorithm for obtaining memory with malloc() is run each time, so there's no reason the addresses should be different.
Some malloc implementations could randomize the start of memory allocations, yours does not.
This is because of virtual memory. The physical memory address for memory of q is different, but your operating system provides each process with a virtual view of memory, mapping different physical memory addresses to the same virtual addresses in your processes. So all processes have a similar view of the memory (and cannot see the memory of other processes)
Heap allocators are not required to provide distinct / unique addresses each time you run the program. There is no guarantee either way on this, but it's entirely reasonable for an implementation of malloc() to have deterministic behavior and give you the same pointer each time you run the program.
The stack, on the other hand, usually is (but is not required to be) located at a different address. This is a protection measure against buffer-overflow exploits. By making the stack location non-deterministic, they make it more difficult for an attacker to inject direct memory addresses of code via buffer-overflow attack.
Finally note that all pointers in a program are virtual memory addresses, not physical addresses. So even though two concurrent processes might have the same memory address in a pointer, those two processes still have distinct memory in separate areas of physical memory. The operating system takes care of this via its virtual memory manager and page translation. Each process has its own virtual address space, various pieces of which are mapped transparently by the OS to physical memory as needed.

Debugging a clobbered static variable in C (gdb broken?)

I've done a lot of programming but not much in C, and I need advice on debugging. I have a static variable (file scope) that is being clobbered after about 10-100 seconds of execution of a multithreaded program (using pthreads on OS X 10.4). My code looks something like this:
static float some_values[SIZE];
static int * addr;
addr points to valid memory address for a while, and then gets clobbered with some value (sometimes 0, sometimes nonzero), thereby causing a segfault when dereferenced. Poking around with gdb I have verified that addr is being layed out in memory immediately after some_values as one would expect, so my first guess would be that I have used an out-of-bounds index to write to some_values. However, this is a tiny file, so it is easy to check this is not the problem.
The obvious debugging technique would be to set a watchpoint on the variable addr. But doing so seems to create erratic and inexplicable behavior in gdb. The watchpoint gets triggered at the first assignment to addr; then after I continue execution, I immediately get a nonsensical segfault in another thread...supposedly a segfault on accessing the address of a static variable in a different part of the program! But then gdb lets me read from and write to that memory address interactively.
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x001d5bd0
0x0000678d in receive (arg=0x0) at mainloop.c:39
39 sample_buf_cleared ++;
(gdb) p &sample_buf_cleared
$17 = (int *) 0x1d5bd0
(gdb) p sample_buf_cleared
$18 = 1
(gdb) set sample_buf_cleared = 2
(gdb)
gdb is obviously confused. Does anyone know why? Or does anyone have any suggestions for debugging this bug without using watchpoints?
You could put an array of uint's between some_values and addr and determine if you are overruning some_values or if the corruption affects more addresses then you first thought. I would initialize padding to DEADBEEF or some other obvious pattern that is easy to distinguish and unlikely to occur in the program. If a value in the padding changes then cast it to float and see if the number makes sense as a float.
static float some_values[SIZE];
static unsigned int padding[1024];
static int * addr;
Run the program multiple times. In each run disable a different thread and see when the problems goes away.
Set the programs process affinity to a single core and then try the watchpoint. You may have better luck if you don't have two threads simultaneously modifying the value. NOTE: This solution does not preclude that from happening. It may make it easier to catch in a debugger.
static variables and multi-threading generally do not mix.
Without seeing your code (you should include your threaded code), my guess is that you have two threads concurrently writing to addr variable. It doesn't work.
You either need to:
create separate instances of addr for each thread; or
provide some sort of synchronisation around addr to stop two threads changing the value at the same time.
Try using valgrind; I haven't tried valgrind on OS X, and I don't understand your problem, but "try valgrind" is the first thing I think of when you say "clobbered".
One thing you could try would be to create a separate thread whose only purpose is to watch the value of addr, and to break when it changes. For example:
static int * volatile addr; // volatile here is important, and must be after the *
void *addr_thread_proc(void *arg)
{
while(1)
{
int *old_value = addr;
while(addr == old_value) /* spin */;
__asm__("int3"); // break the debugger, or raise SIGTRAP if no debugger
}
}
...
pthread_t spin_thread;
pthread_create(&spin_thread, NULL, &addr_thread_proc, NULL);
Then, whenever the value of addr changes, the int3 instruction will run, which will break the debugger, stopping all threads.
gdb often acts weird with multithreaded programs. Another solution (if you can afford it) would be to put printf()s all over the place to try and catch the moment where your value gets clobbered. Not very elegant, but sometimes effective.
I have not done any debugging on OSX, but I have seen the same behavior in GDB on Linux: program crashes, yet GDB can read and write the memory which program just tried to read/write unsuccessfully.
This doesn't necessarily mean GDB is confused; rather the kernel allowed GDB to read/write memory via ptrace() which the inferior process is not allowed to read or write. IOW, it was a (recently fixed) kernel bug.
Still, it sounds like GDB watchpoints aren't working for you for whatever reason.
One technique you could use is to mmap space for some_values rather than statically allocating space for them, arrange for the array to end on a page boundary, and arrange for the next page to be non-accessible (via mprotect).
If any code tries to access past the end of some_values, it will get an exception (effectively you are setting a non-writable "watch point" just past some_values).

Resources