Показать сообщение отдельно
Старый 01.07.2011, 16:53   #6
SynQ
 
Регистрация: 11.07.2010
Сообщений: 953
Репутация: 352
По умолчанию

Оставлю здесь, может кому-нибудь пригодится однажды.

kleak LKM для просмотра или дампа памяти ядра. Вроде аналога когда-то существовавшего /dev/kmem.

Использование:
Цитата:
$ echo 0xc1234567 > /proc/kleak; cat /proc/kleak | ndisasm -u -
$ echo "0xc1234567 1600" > /proc/kleak; cat /proc/kleak | hexdump -C // если нужен больший размер
Однажды выставленный размер сохраняется.

На x64 тоже должно работать.


Код:
/*
 * kleak LKM for kernel memory dump
 *
 * Author: SynQ, rdot.org
 * 7/2011
 * 
 * I know the code is ugly, don't blame me.
 * Usage: echo 0xc1234567 > /proc/kleak; cat /proc/kleak | ndisasm -u -
 */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/string.h>

#define MAX_SIZE       PAGE_SIZE

static char input_buffer[25];

unsigned long size;
unsigned long *addr;

static int kleak_proc_write( struct file *filp, const char __user *buff,
    unsigned long len, void *data )
{
    if (len > sizeof(input_buffer) - 1) {
        printk(KERN_ERR "kleak: Input too long! (%lu)\n", len);
        return -ENOSPC;
    }

    memset(input_buffer,'\0',sizeof(input_buffer));

    if(copy_from_user(input_buffer, buff, len))
    	return -EFAULT;

    input_buffer[len]='\0';// ? no need bc of memset
    char *space = strchr(input_buffer,' ');
    char **end;

    if(space==NULL) {
    	addr=simple_strtoul(input_buffer, end, 16);
    	printk("kleak: no size, addr: 0x%p\n",addr);
    }
    else {
    	addr=simple_strtoul(input_buffer, end, 16);
    	size=simple_strtoul(space+1, end, 10);
    	printk("kleak: got size, addr: 0x%p, size: %d\n",addr, (int)size);
    }

    return len;
}

static int kleak_proc_read(char *page, char **start, off_t off,
    int count, int *eof, void *data)
{
    if (off > 0) {
        *eof = 1;
        return 0;
    }
#if defined(__i386__)
    if(addr >=0xc0000000 && addr <=0xffffffff && size < MAX_SIZE)
#elif defined(__x86_64__)
    if(addr >=0xffffffff80000000 && addr <=0xffffffffffffffff && size < MAX_SIZE)
#endif
    	memcpy(page, addr, size);
    else return -EFAULT;

    return size;
}


static int __init init_kleak(void)
{
    struct proc_dir_entry *kleak_entry = create_proc_entry("kleak", 0666, NULL);// 600? nigga, plz

    if (kleak_entry == NULL) {
      printk(KERN_ERR "kleak: Couldn't create proc entry\n");
      return -ENOMEM;
    }

    kleak_entry->write_proc = kleak_proc_write;
    kleak_entry->read_proc = kleak_proc_read;
    printk(KERN_INFO "kleak: Module loaded successfully\n");

    addr=NULL;
    size=100;

    return 0;
}

static void cleanup_kleak(void)
{
	remove_proc_entry("kleak", NULL);
	printk(KERN_INFO "kleak: Module unloaded.\n");
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("SynQ");
MODULE_DESCRIPTION("kernel memory viewer via /proc");

module_init(init_kleak);
module_exit(cleanup_kleak);
Makefile:
Код:
obj-m = kleak.o

M=$(shell pwd)

all:
	make -C /lib/modules/$(shell uname -r)/build/ M=$(M) modules
Также fmem - аналог /dev/mem (дамп физической памяти).

Последний раз редактировалось SynQ; 17.12.2011 в 12:12..
SynQ вне форума   Ответить с цитированием