aboutsummaryrefslogblamecommitdiffstats
path: root/toj/center/src/judgk_syscall.c
blob: 370a3fe5396bc5527080b87792f82c096f044447 (plain) (tree)
1
2
3
4
5
6
7
8
9
                    
                      
                       





                       


                         
 
                         

























                                                                                  
                           












                                                                                  
                                                                     


                                                                         
                                   





















































































                                                                                  

                                                                                            






























                                                                                                   
                            




















                                                                

                                        



                 

                                 
 
                                                         





























                                                                                                
#include<linux/fs.h>
#include<linux/slab.h>
#include<linux/sched.h>
#include<linux/sort.h>
#include<asm/msr.h>
#include<asm/unistd.h>
#include<asm/uaccess.h>

#include"judge_def.h"
#include"judgk.h"
#include"judgk_com.h"
#include"judgk_syscall.h"

int judgk_syscall_hook(){
    int i;
    int j;

    unsigned int size;
    unsigned int restore;

    syscall_init_hook();
   
    syscall_addr_write((unsigned long)syscall_table,&size,&restore);
    for(i = 0,j = 0;i < syscall_max;i++){
        if(size == 0){
            syscall_addr_restore((unsigned long)(syscall_table + i - 1),restore);
            syscall_addr_write((unsigned long)(syscall_table + i),&size,&restore);
        }
        size -= sizeof(unsigned long);

        if(i == syscall_whitelist[j]){
            j++;
            continue;
        }
        syscall_table[i] = (unsigned long)hook_sys_block;
    }
    syscall_addr_restore((unsigned long)(&syscall_table[i - 1]),restore);

    return 0;
}
int judgk_syscall_unhook(){
    int i;

    unsigned int size;
    unsigned int restore;

    syscall_addr_write((unsigned long)syscall_table,&size,&restore);
    for(i = 0;i < syscall_max;i++){
        if(size == 0){
            syscall_addr_restore((unsigned long)(&syscall_table[i - 1]),restore);
            syscall_addr_write((unsigned long)(&syscall_table[i]),&size,&restore);
        }
        size -= sizeof(unsigned long);

        syscall_table[i] = (unsigned long)judgk_syscall_ori_table[i];
    }
    syscall_addr_restore((unsigned long)(&syscall_table[i - 1]),restore);

    kfree(judgk_syscall_ori_table);
    return 0;
}
static int syscall_init_hook(){
    ssize_t ret;
    int i;
    int j;

    struct file *f;
    char line[128];
    unsigned char code[3] = {0xff,0x14,0xc5};
    unsigned long addr;

    f = filp_open("/proc/kallsyms",O_RDONLY,0);
    set_fs(KERNEL_DS);

    i = 0;
    addr = 0;
    while(true){
        ret = f->f_op->read(f,&line[i],1,&f->f_pos);

        if(line[i] == '\n' || ret <= 0){
            line[i] = '\0';

            addr = 0;
            for(j = 0;j < i;j++){
                if(line[j] == ' '){
                    j++;
                    break;
                }

                addr *= 16UL;
                if(line[j] >= '0' && line[j] <= '9'){
                    addr += (unsigned long)(line[j] - '0');
                }else{
                    addr += (unsigned long)(line[j] - 'a' + 10);
                }
            }
            for(;j < i;j++){
                if(line[j] == ' '){
                    j++;
                    break;
                }
            }
            if(j < i){
                if(strcmp("system_call",line + j) == 0){
                    break;
                }
            }

            i = 0;
        }else{
            i++;
        }

        if(ret <= 0){
            break;
        }
    }

    set_fs(USER_DS);
    filp_close(f,NULL);

    while(true){
        for(i = 0;i < 3;i++){
            if(*(unsigned char*)addr != code[i]){
                addr++;
                break;
            }
            addr++;
        }
        if(i == 3){
            break;
        }
    }
    syscall_table = (unsigned long*)(0xffffffff00000000 + *((unsigned int*)addr));
    
    addr -= 4L;
    while(true){
        if(*(unsigned char*)addr == 0x3d){
            addr++;
            break;
        }
        addr--;
    }
    syscall_max = *(unsigned int*)addr;

    judgk_syscall_ori_table = kmalloc(sizeof(unsigned long) * (syscall_max + 1),GFP_KERNEL);
    memcpy(judgk_syscall_ori_table,syscall_table,sizeof(unsigned long) * syscall_max);

    sort(syscall_whitelist,SYSCALL_WHITELIST_SIZE,sizeof(unsigned int),syscall_whitelist_cmp,NULL);

    return 0;
}
static int syscall_whitelist_cmp(const void *a,const void *b){
    if(*(unsigned int*)a < *(unsigned int*)b){
        return -1;
    }else if(*(unsigned int*)a == *(unsigned int*)b){
        return 0;
    }else{
        return 1;
    }
}
static int syscall_addr_write(unsigned long addr,unsigned int *size,int *restore){
    unsigned int level;
    pte_t *pte;

    pte = lookup_address(addr,&level);
    if(pte->pte & _PAGE_RW){
        *restore = 0;
    }else{
        pte->pte |= _PAGE_RW;
        *restore = 1;
    }

    switch(level){
        case PG_LEVEL_4K:
            *size = 4096;
            break;
        case PG_LEVEL_2M:
            *size = 2097152;
            break;
        case PG_LEVEL_1G:
            *size = 1073741824;
            break;
    }
    *size -= (((unsigned int)addr) & (*size - 1));

    return 0;
}
static int syscall_addr_restore(unsigned long addr,int restore){
    unsigned int level;
    pte_t *pte;

    if(restore){
        pte = lookup_address(addr,&level);
        pte->pte ^= _PAGE_RW;
    }

    return 0;
}

int judgk_syscall_check(){
    if(judgk_proc_task_lookup(current)){
        return 1;
    }
    return 0;
}
int judgk_syscall_block(){
    struct judgk_proc_info *info;

    if((info = judgk_proc_task_lookup(current)) == NULL){
        return 0;
    }

    info->status = JUDGE_RF;
    send_sig(SIGKILL,current,0);
    return 0;
}

/*asmlinkage long hook_sys_nanosleep(struct timespec __user *rqtp,struct timespec __user *rmtp){
    long ret;

    struct judgm_proc_info *info;

    atomic64_inc(&syscall_pending);

    info = judgm_proc_task_lookup(current);
    if(info == NULL){
        ret = ori_sys_nanosleep(rqtp,rmtp);
        atomic64_dec(&syscall_pending);
        return ret;
    }

    pr_alert("judgm:PID %d  nanosleep\n",current->tgid);

    info->status = JUDGE_RF;
    send_sig(SIGKILL,current,0);

    atomic64_dec(&syscall_pending);
    return -EACCES;
}*/