Assign a value to a specific address

跟風遠走 提交于 2020-01-13 11:23:12

问题


It is an interview question, which I came across at a book for interviews, and later in an interview.

The question is

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

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

An address is a number which can be stored in a pointer, and we can assign a value to the address by a pointer, the value of which is the address, like:

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

However, it is not possible on a system with memory management, because the program does not have privilege to the specific address.

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

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


回答1:


Your code is correct but might crush on runtime if the OS defines 0x12345678 as read-only.

While a "regular" OS does that, "lighter" ones do not.

You want to write a kernel-space hacking program to do it.

I solved it for linux if you like 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's 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's 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's \"read only\" segment");
MODULE_AUTHOR("Elkana Bronstein");
MODULE_LICENSE("GPL");

2) add it to kernels modules:

$insmod example.ko

3) find the module's 'major' in the list:

$cat /proc/devices

4) make node associated with the device:

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

'c' is 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's buffer*/
    write(fd,&value,sizeof(value));
    /*read the device's buffer into the desirable object - without checking*/
    read(fd,0x12345678,sizeof(value));

    close(fd);
}



回答2:


It is (nearly) impossible to know which memory locations are available to write to.

You can ask the OS to give you an available address by using malloc() function and later freeing that location up by using free().

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

If you try to assign values to locations which are unavailable, you might end up with segmentation fault errors.

Hope this helps!




回答3:


That sort of thing most definitely IS possible even in systems with memory management, if the pointer is outside accessible space for the current process, it'll fault, but that's what's supposed to happen. If not, the value is set and on you go. Other than that, you're example seems fine to me.




回答4:


Maybe the answer is that there is no answer because it is impossible in a system with memory management.

In a system without memory management I would try with assembly code directly.

Hope it helps



来源:https://stackoverflow.com/questions/5400018/assign-a-value-to-a-specific-address

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!