Assign a value to a specific address

This is a question of an interview that I came across a book for an interview, and then in an interview.

Question:

How to assign a value (say 0 ) to an address (say 0x12345678 ).

My best attempt for this question (after a long time after the interview)

An address is a number that can be stored in a pointer, and we can assign a value to an address with a pointer whose value is the address, for example:

  int* p = 0x12345678; *p = 0; 

However, this is not possible in a memory management system, because the program does not have privileges for a specific address.

According to my own experience, the only time this operation was valid was an experiment on an 8086 chip without any operating system, and the language I used was the build time.

Please help me fix, improve and complete my answer. Thanks.

+4
source share
4 answers

Your code is correct, but may cause a crash at runtime if the OS defines 0x12345678 as read-only.

While a "regular" OS does this, a "lighter" one does not.

You want to write a kernel space hacking program for this.

I solved this for Linux if you want to take a look:


1) build this module (example.ko):

 #include <linux/module.h> #include <linux/fs.h> /* for file_operations */ #include <linux/uaccess.h> /* copy_from & copy_to */ char* g_value=0; size_t size =0; int driver_open(struct inode *inode, struct file *filp) { printk("open driver"); return 0; } int driver_write(struct file*, /*ignored*/ const char __user *umem,/*source in user-space address*/ size_t size, /*max size to be writen*/ loff_t*) /*offset - ignored*/ { unsigned long ret = 0; g_value = (char*) kmalloc(size, GFP_KERNEL); if (!g_value) { printk("ERROR:allocation failure\n"); return -ENOMEM; } ret = copy_from_user(g_value, /*destination*/ umem, /*source*/ size); /*size*/ if (ret<0) { printk("ERROR:copy failure\n"); return -EACCES; } return g_size = size;; } int driver_read(struct file*, /*ignored*/ char __user *umem, /*destination in user-space address*/ size_t size, /*max size to be read*/ loff_t*) /*offset - ignored*/ { /* don't use copy_to_user(umem, &value, size)!! we want to do exectly what it is made to protect from */ int i = ((g_size>size)?size:g_size)-1; /*MIN(g_size,size)-1*/ for (; i>=0; --i) { umem[i]=g_value[i]; /*can be done more effectively, thats not the point*/ } return size; } int driver_close(struct inode *inode, struct file *filp) { if (g_value) free(g_value); g_value = 0; printk("close driver"); return 0; } /***interface***/ struct file_operations driver_ops = { open: driver_open, write: driver_write, read: driver_read, release: driver_close }; /***implementation***/ static int g_driver_fd = 0; static void driver_cleanup(void) { printk("ERROR:driver exit\n"); unregister_chrdev(g_driver_fd, "driver"); } static int driver_init(void) { printk("driver init\n"); g_driver_fd = register_chrdev(0,"ROM-bypass", &driver_ops); if (g_driver_fd<0) { printk("ERROR:failed to register char driver\n"); return -1; } return 0; } module_init(driver_init); module_exit(driver_cleanup); /***documentation***/ MODULE_DESCRIPTION("write on OS \"read only\" segment"); MODULE_AUTHOR("Elkana Bronstein"); MODULE_LICENSE("GPL"); 

2) add it to the kernel modules:

 $insmod example.ko 

3) find the module "major" in the list:

 $cat /proc/devices 

4) create a node associated with the device:

 $mknod /dev/rom_bypass c <major> <minor> 

'c' for character device, and "minor" can be any of 0-255

5) use the device in your code as a file:

 int main() { int fd; int value = 0; fd = open("/dev/rom_bypass",O_RDWR); if (fd<0) { fprintf(stderr,"open failed"); return -1; } /*write the desirable value into the device buffer*/ write(fd,&value,sizeof(value)); /*read the device buffer into the desirable object - without checking*/ read(fd,0x12345678,sizeof(value)); close(fd); } 
+3
source

It is not possible to know which memory locations are writable.

You can ask the OS to provide you with an accessible address using the malloc () function, and then free this location using free ().

Another way is to use stack memory. Just define the variable int * p = 0; & p will provide you the address of this location.

If you try to assign values ​​to locations that are not available, you may encounter segmentation error errors.

Hope this helps!

+1
source

These kinds of things are certainly possible even in systems with memory management, if the pointer is outside the available space for the current process, it will be to blame, but this should happen. If not, the value is set and starts. In addition, it seems to you that it seems good to me.

0
source

Perhaps the answer is that there is no answer, because this is not possible on a memory-managed system.

On a system without memory management, I would try to execute the build code directly.

Hope this helps

-1
source

Source: https://habr.com/ru/post/1344860/


All Articles