how virtual addresses assigned? - c

Take this C code for example
#include <stdio.h>
#include <stdlib.h>
int main() {
int x;
int* y = (int *) malloc(10*sizeof(int));
printf("%p\n",&x);
printf("%p\n",y);
printf("%p\n",&(y[1]));
while(1);
return 0;
}
Which will print virtual addresses that look something like this
0x7ffd4e96d214
0x908010
0x908014
The virtual addresses will be different every time you run the binary file which made me think how the virtual address are actually decided for a program ?

This is - probably - the effect of ASLR.
The decision should - as the name Address Space Layout Randomization tells - be random.

Related

Is there a way to print all memory addresses a variable is stored in?

I want to know if there is a way to print all the memory locations that say an int variable is stored in.
Example:
#include <stdio.h>
int main()
{
int x = 5;
int *y = &x;
printf("%p", (void*)y);
}
Example output: 0x100000000001
This will show the memory address that the first byte of x is stored in, but I want to see the memory address of each byte that it is stored in.
Is there any way to do this? Or do I just assume the following memory place values since they're consecutive?
i.e. the other memory locations of this int would be:
0x100000000002?
0x100000000003?
0x100000000004?
a way to print all the memory locations that say an int variable is stored in.
Sure. Form a loop [0...sizeof(int)).
int main() {
int x = 5;
void *y = &x;
for (size_t i = 0; i < sizeof x; i++) {
printf("%p\n", (void*)((char *)y + i));
}
}
If you know the variable type in the compilation time, you can use sizeof to determinate the variable memory size (in bytes) and then assume that the addresses range is from (char*)&var to (char*)&var + sizeof(var) - 1.
If the variable is received as an allocated memory, you better use malloc_usable_size from <malloc.h> in order to get the variable size and then find the addresses range.
Note that usually operating-systems allocates virtual memory for processes.

If I know the address (hex value of a function) then can I assing it to function pointer/or some variable with same signature if yes then how

I have a function like this
void abc()
{
printf("hello\n");
}
lets suppose I checked and know that the address of above function say 0x08000040 now if I assign it to function pointer in main like this
int main()
{
void (*p)()=(void *)0x08000040;
p();// and call it like
return 0;
}
will it call some how. I tried it does not work but suppose I have function in the same program then will it work after I some how found out the address of the function?
and also is this possible
to assign specific fixed address to some function in current C program
is it possible to export a function address (of abc()) in current program and so other programs can call the function in this program to call above abc() function with address hex values. it happens in kernel with exporting of sys-calls and gdb also does this with trap-handlers. So is there any easy way to make it work.
This works for me:
#include <stdio.h>
#include <stdlib.h>
void abc(void) {
puts("abc");
}
void cba(void) {
puts("cba");
}
int main(void) {
printf("type %p or %p\n", (void*)abc, (void*)cba);
char buf[100];
fgets(buf, sizeof buf, stdin);
long unsigned u = strtoul(buf + 2, NULL, 16); // ignore 0x
void (*p)(void) = (void(*)(void))u; // UB!
p(); // and call it
return 0;
}
The virtual address where a given function is located in memory is entirely implementation defined and further depends on many factors:
it is almost always different for different programs ;
it may change if you modify the program source code and recompile it ;
it may even change each time you execute the same program: modern systems perform address space randomisation in order to reduce vulnerability to certain classes of attacks. The same applies to the stack address.
Do not rely on the address values you observe in the debugger, they are likely to be different the next time you debug the program.

Finding return address of stack

I have this simple code:
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <ctype.h>
main(argc, argv)
char *argv[];
{
char line[512];
gets(line);
}
my goal is to find the distance between the end of the buffer and the return address of the stack.
So if my buffer (line) is 512 bytes, I could find the starting address, and add 512 and know where the start of that distance would be.. but how would I find the return address of the stack?
Basically I am just trying to figure out how to find the return address of the stack and the buffers start address.. I couldn't find it when disassembling main
#include <stdio.h>
int main()
{
long l, k;
asm("mov %%rsp,%0" : "=r"(l));
asm("mov %%rbp,%0" : "=r"(k));
printf("Stack pointer: 0x%16.16lX\n", l);
printf("Stack frame base: 0x0%16.16lX\n", k);
printf("Distance to return address: %ld\n", k-l);
}
snow ~ $ ./test
Stack pointer: 0x00007FFC95B793C0
Stack frame base: 0x000007FFC95B793D0
Distance to return address: 16
Obviously this is not portable, I'm assuming x64 and gcc here.
Caveat: BP isn't always going to point to the return address. Sometimes it's not used as a stack frame pointer, and some functions may not return their values on the stack. Register optimizations will break it. Local variables may break it. Variable word alignments may break it. Basically, don't count on it working. (I believe depending on the compiler/compile-time options you may need to add a constant offset to this, as well.)
I do really wonder if there isn't a better way to do whatever it is that you are trying to do... =)

"Visualization" of dangling pointer

While learning pointers I tried pointer declarations/dereferenciations.
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
int *call() {
int a = 3;
return &a;
}
int main() {
printf("call* is: %d\n", *call());
printf("call is: %p\n", call());
Sleep(2000);
printf("call* is: %d\n", *call());
printf("call is: %p\n", call());
Sleep(2000);
printf("call* is: %d\n", *call());
printf("call is: %p\n", call());
return 0;
}
So "obviously" the "a" is a local variable.
But my problem is,
when I'm reading out the address of "a", it's always the same address.
Why is that like this?
PS: I'm running a prime-number-calculator in the background to fill up as much memory as possible and I put in the "Sleep" to make the program wait, but still the address of "a" is always the same.
a is located on the stack of the current thread : every time the function call() is run, it "allocates" 4 bytes on the stack to stock a, return the address and then "frees" the space it uses on stack (it is not actually allocating/freeing anything, just offsetting the stack pointer).
So if you call it several times in a row, the state of the stack on input of the function will be exactly the same, so the actual address of a on the stack the same every time (please note that this address is invalid as soon as you exit the function).
You should do something like
int * call2(){
int a = 0;
int *b = call();
printf("%d",a);
return b;
}
and then
int *a = call();
int *b = call2();
You will see a and b will be different (the printf is there to make sure the compiler does not optimise anything away)
Since the stack is local to the current thread (not influenced by other processes/threads), your prime number calculator and Sleep are to no use at all.
"call" is to return a pointer to a variable? The problem here is that "a" is not statically allocated, but is on the stack. You can return its address at the moment (which may or may not be the same address, depending on whether "call" is invoked at the same depth each time), but there's no guarantee of what that address is pointing to once you return from "call". You put a 3 in it during the call, and that may be overwritten by something else by the time you get around to looking at the contents of that address.

Accessing specific memory locations in C

In assembly language we have instructions like:
movl ax, [1000]
This allows us to access specific memory locations.
But in C can we do something similar to this?
I know inline assembly code using asm() will allow you to do this,
but I would like to know about some C specific technique to achieve this.
I tried the following code and got segmentation error:
int *ptr=0xFE1DB124;
*ptr;
This again was confusing as the memory location was identified by the code given below:
int var;
printf("\nThe Address is %x",&var);
So the memory location is available, but I am still getting a segmentation fault.
Why?
Common C compilers will allow you to set a pointer from an integer and to access memory with that, and they will give you the expected results. However, this is an extension beyond the C standard, so you should check your compiler documentation to ensure it supports it. This feature is not uncommonly used in kernel code that must access memory at specific addresses. It is generally not useful in user programs.
As comments have mentioned, one problem you may be having is that your operating system loads programs into a randomized location each time a program is loaded. Therefore, the address you discover on one run will not be the address used in another run. Also, changing the source and recompiling may yield different addresses.
To demonstrate that you can use a pointer to access an address specified numerically, you can retrieve the address and use it within a single program execution:
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
int main(void)
{
// Create an int.
int x = 0;
// Find its address.
char buf[100];
sprintf(buf, "%" PRIuPTR, (uintptr_t) &x);
printf("The address of x is %s.\n", buf);
// Read the address.
uintptr_t u;
sscanf(buf, "%" SCNuPTR, &u);
// Convert the integer value to an address.
int *p = (int *) u;
// Modify the int through the new pointer.
*p = 123;
// Display the int.
printf("x = %d\n", x);
return 0;
}
Obviously, this is not useful in a normal program; it is just a demonstration. You would use this sort of behavior only when you have a special need to access certain addresses.
For accessing Specific memory from user space, we have to map the memory Address to Programs Virtual Address using mmap(), the below C code shows the implementation:
Take a file "test_file" containing "ABCDEFGHIJ".
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
int main(void)
{
char *map_base_addr; // Maping Base address for file
int fd; // File descriptor for open file
int size = 10;
fd= open("test_file", O_RDWR); //open the file for reading and writing
map_base_addr= mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);// Maping file into memory
char *ch= map_base_addr;
int i;
/*Printing first 10 char*/
for(i=0; i<size; i++)
fputc(*(ch+i),stdout);
printf("\n");
*(ch+1) = 'b';
*(ch+4) = 'z';
*(ch+7) = 'x';
/*Printing char after modification*/
for(i=0; i<size; i++)
fputc(*(ch+i),stdout);
printf("\n");
/* Finally unmap the file. This will flush out any changes. */
munmap(map_base_addr, size);
exit(0);
}
The output will be:
ABCDEFGHIJ
AbCDzFGxIJ
It works for me:
#include <stdio.h>
int main(int argc, char**argv) {
int var = 7456;
printf("Adress of var = %x, var=%d\n", &var, var);
int *ptr = (int*)0x22cd28;
printf(" ptr points to %x\n", ptr);
*ptr = 123;
printf("New value of var=%d\n", var);
return 0;
}
Program output:
Adress of var = 22cd28, var=7456
ptr points to 22cd28
New value of var=123
Note:
The address is usually not the same on every execution. When I tried my example I had to run it three times before I got the address to match.
char* can point to any adress (because sizeof (char) = 1). Pointers to larger objects must often be aligned on even adresses (usually one divisible by 4).
Your question doesn't really make much sense if you are running on linux/windows/mac/whatever
http://en.wikipedia.org/wiki/Virtual_memory
You can do that only if you are programming a device without virtual memory, or if you are programming the operating system itself.
Otherwise the addresses you see are not the "real" addresses on the RAM, the operating system translates them to real addresses and if there is not a map to translate your virtual address to a real one, then you can get a segmentation fault. Keep in mind that there are other reasons that can cause a segmentation fault.

Resources