void test_ports(int proto, int *_errors, int *_total)
{
    int i;

    for(i = 0; i<= 65535; i++)
    {
        (*_total)++;
        if(conn_port(proto, i))
        {
            /* Checking if we can find it using netstat, if not,
             * check again to see if the port is still being used.
             */
            if(run_netstat(proto, i))
            {
                continue;

#ifdef OSSECHIDS
                sleep(2);
#endif
            }

            /* If we are being run by the ossec hids, sleep here (no rush) */
#ifdef OSSECHIDS
            sleep(2);
#endif

            if(!run_netstat(proto, i) && conn_port(proto, i))
            {
                char op_msg[OS_SIZE_1024 +1];

                (*_errors)++;

                snprintf(op_msg, OS_SIZE_1024, "Port '%d'(%s) hidden. "
                         "Kernel-level rootkit or trojaned "
                         "version of netstat.", i,
                         (proto == IPPROTO_UDP)? "udp" : "tcp");

                notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
            }
        }

        if((*_errors) > 20)
        {
            char op_msg[OS_SIZE_1024 +1];
            snprintf(op_msg, OS_SIZE_1024, "Excessive number of '%s' ports "
                     "hidden. It maybe a false-positive or "
                     "something really bad is going on.",
                     (proto == IPPROTO_UDP)? "udp" : "tcp" );
            notify_rk(ALERT_SYSTEM_CRIT, op_msg);
            return;
        }
    }

}
/*  check_rc_ports: v0.1
 *  Check all ports
 */
void check_rc_ports()
{
    int _errors = 0;
    int _total = 0;

    int i = 0;

    while(i<=65535)
    {
        total_ports_tcp[i] = 0;
        total_ports_udp[i] = 0;
        i++;
    }

    /* Trsting TCP ports */
    test_ports(IPPROTO_TCP, &_errors, &_total);

    /* Testing UDP ports */
    test_ports(IPPROTO_UDP, &_errors, &_total);

    if(_errors == 0)
    {
        char op_msg[OS_SIZE_1024 +1];
        snprintf(op_msg,OS_SIZE_1024,"No kernel-level rootkit hiding any port."
                 "\n      Netstat is acting correctly."
                 " Analyzed %d ports.", _total);
        notify_rk(ALERT_OK, op_msg);
    }

    return;
}
Exemple #3
0
int read_dev_file(char *file_name)
{
    struct stat statbuf;
    
    if(lstat(file_name, &statbuf) < 0)
    {
        return(-1);
    }
    
    if(S_ISDIR(statbuf.st_mode))
    {
        #ifdef DEBUG
        verbose("%s: Reading dir: %s\n",ARGV0, file_name);
        #endif

        return(read_dev_dir(file_name));
    }
        
    else if(S_ISREG(statbuf.st_mode))
    {
        char op_msg[OS_SIZE_1024 +1];

        snprintf(op_msg, OS_SIZE_1024, "File '%s' present on /dev."
                                    " Possible hidden file.", file_name);
        notify_rk(ALERT_SYSTEM_CRIT, op_msg);

        _dev_errors++;
    }

    return(0);
}
Exemple #4
0
/*  check_rc_sys: v0.1
 *  Scan the whole filesystem looking for possible issues
 */
void check_rc_pids()
{
    int _total = 0;
    int _errors = 0;

    char ps[OS_SIZE_1024 +1];

    char proc_0[] = "/proc";
    char proc_1[] = "/proc/1";

    pid_t max_pid = MAX_PID;

    noproc = 1;

    /* Checking where ps is */
    memset(ps, '\0', OS_SIZE_1024 +1);
    strncpy(ps, "/bin/ps", OS_SIZE_1024);
    if(!is_file(ps))
    {
        strncpy(ps, "/usr/bin/ps", OS_SIZE_1024);
        if(!is_file(ps))
            ps[0] = '\0';
    }


    /* Proc is mounted */
    if(is_file(proc_0) && is_file(proc_1))
    {
        noproc = 0;
    }

    loop_all_pids(ps, max_pid, &_errors, &_total);

    if(_errors == 0)
    {
        char op_msg[OS_SIZE_1024 +1];
        snprintf(op_msg, OS_SIZE_1024, "No hidden process by Kernel-level "
                                    "rootkits.\n      %s is not trojaned. "
                                    "Analyzed %d processes.", ps, _total);
        notify_rk(ALERT_OK, op_msg);
    }

    return;
}
void check_open_ports()
{
#ifndef OSSECHIDS
    memset(open_ports_str, '\0', OS_SIZE_1024 + 1);
    open_ports_size = OS_SIZE_1024 - 1;
    _ports_open = 0;

    snprintf(open_ports_str, OS_SIZE_1024, "The following ports are open:");
    open_ports_size -= strlen(open_ports_str) + 1;

    /* Testing All ports */
    try_to_access_ports();

    open_ports_str[strlen(open_ports_str) - 1] = '\0';

    notify_rk(ALERT_OK, open_ports_str);

#endif
    return;
}
Exemple #6
0
void check_rc_dev(const char *basedir)
{
    char file_path[OS_SIZE_1024 + 1];

    _dev_total = 0, _dev_errors = 0;
    debug1("%s: DEBUG: Starting on check_rc_dev", ARGV0);

    snprintf(file_path, OS_SIZE_1024, "%s/dev", basedir);

    read_dev_dir(file_path);
    if (_dev_errors == 0) {
        char op_msg[OS_SIZE_1024 + 1];
        snprintf(op_msg, OS_SIZE_1024, "No problem detected on the /dev "
                 "directory. Analyzed %d files",
                 _dev_total);
        notify_rk(ALERT_OK, op_msg);
    }

    return;
}
Exemple #7
0
/*  check_rc_if: v0.1
 *  Check all interfaces for promiscuous mode
 */
void check_rc_if()
{
    int _fd, _errors = 0, _total = 0;
    struct ifreq tmp_str[16];

    struct ifconf _if;
    struct ifreq *_ir;
    struct ifreq *_ifend;
    struct ifreq _ifr;

    _fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(_fd < 0)
    {
        merror("%s: Error checking interfaces (socket)", ARGV0);
        return;
    }


    memset(tmp_str, 0, sizeof(struct ifreq)*16);
    _if.ifc_len = sizeof(tmp_str);
    _if.ifc_buf = (caddr_t)(tmp_str);

    if (ioctl(_fd, SIOCGIFCONF, &_if) < 0)
    {
        close(_fd);
        merror("%s: Error checking interfaces (ioctl)", ARGV0);
        return;
    }

    _ifend = (struct ifreq*) (void *) ((char*)tmp_str + _if.ifc_len);
    _ir = tmp_str;

    /* Looping on all interfaces */
    for (; _ir < _ifend; _ir++)
    {
        strncpy(_ifr.ifr_name, _ir->ifr_name, sizeof(_ifr.ifr_name));

        /* Getting information from each interface */
        if (ioctl(_fd, SIOCGIFFLAGS, (char*)&_ifr) == -1)
        {
            continue;
        }

        _total++;


        if ((_ifr.ifr_flags & IFF_PROMISC) )
        {
            char op_msg[OS_SIZE_1024 +1];
            if(run_ifconfig(_ifr.ifr_name))
            {
                snprintf(op_msg, OS_SIZE_1024,"Interface '%s' in promiscuous"
                                            " mode.", _ifr.ifr_name);
                notify_rk(ALERT_SYSTEM_CRIT, op_msg);
            }
            else
            {
                snprintf(op_msg, OS_SIZE_1024,"Interface '%s' in promiscuous"
                                 " mode, but ifconfig is not showing it"
                                 "(probably trojaned).", _ifr.ifr_name);
                notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
            }
            _errors++;
        }
    }
    close(_fd);

    if(_errors == 0)
    {
        char op_msg[OS_SIZE_1024 +1];
        snprintf(op_msg, OS_SIZE_1024, "No problem detected on ifconfig/ifs."
                                    " Analyzed %d interfaces.", _total);
        notify_rk(ALERT_OK, op_msg);
    }

    return;
}
Exemple #8
0
/* Check if file has NTFS ADS */
int os_check_ads(const char *full_path)
{
    HANDLE file_h;
    WIN32_STREAM_ID sid;
    void *context = NULL;
    char stream_name[MAX_PATH + 1];
    char final_name[MAX_PATH + 1];
    DWORD dwRead, shs, dw1, dw2;

    /* Open file */
    file_h = CreateFile(full_path,
                        GENERIC_READ,
                        FILE_SHARE_READ,
                        NULL,
                        OPEN_EXISTING,
                        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS,
                        NULL);

    if (file_h == INVALID_HANDLE_VALUE) {
        return 0;
    }

    /* Zero memory */
    ZeroMemory(&sid, sizeof(WIN32_STREAM_ID));

    /* Get stream header size -- should be 20 bytes */
    shs = (LPBYTE)&sid.cStreamName - (LPBYTE)&sid + sid.dwStreamNameSize;

    while (1) {
        if (BackupRead(file_h, (LPBYTE) &sid, shs, &dwRead,
                       FALSE, FALSE, &context) == 0) {
            break;
        }
        if (dwRead == 0) {
            break;
        }

        stream_name[0] = '\0';
        stream_name[MAX_PATH] = '\0';
        if (BackupRead(file_h, (LPBYTE)stream_name,
                       sid.dwStreamNameSize,
                       &dwRead, FALSE, FALSE, &context)) {
            if (dwRead != 0) {
                DWORD i = 0;
                int max_path_size = 0;
                char *tmp_pt;
                char op_msg[OS_SIZE_1024 + 1];

                snprintf(final_name, MAX_PATH, "%s", full_path);
                max_path_size = strlen(final_name);

                /* Copy from wide char to char */
                while ((i < dwRead) && (max_path_size < MAX_PATH)) {
                    if (stream_name[i] != 0) {
                        final_name[max_path_size] = stream_name[i];
                        max_path_size++;
                        final_name[max_path_size] = '\0';
                    }
                    i++;
                }

                tmp_pt = strrchr(final_name, ':');
                if (tmp_pt) {
                    *tmp_pt = '\0';
                }

                snprintf(op_msg, OS_SIZE_1024, "NTFS Alternate data stream "
                         "found: '%s'. Possible hidden"
                         " content.",
                         final_name);
                notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
            }
        }

        /* Get next */
        if (!BackupSeek(file_h, sid.Size.LowPart, sid.Size.HighPart,
                        &dw1, &dw2, &context)) {
            break;
        }
    }

    CloseHandle(file_h);
    return (0);
}
Exemple #9
0
/*  check_rc_sys: v0.1
 *  Scan the whole filesystem looking for possible issues
 */
void check_rc_sys(char *basedir)
{
    char file_path[OS_SIZE_1024 +1];

    debug1("%s: DEBUG: Starting on check_rc_sys", ARGV0);

    _sys_errors = 0;
    _sys_total = 0;
    did = 0; /* device id */
    
    snprintf(file_path, OS_SIZE_1024, "%s", basedir);


    /* Opening output files */
    if(rootcheck.notify != QUEUE)
    {
        _wx = fopen("rootcheck-rw-rw-rw-.txt", "w");
        _ww = fopen("rootcheck-rwxrwxrwx.txt", "w");
        _suid=fopen("rootcheck-suid-files.txt", "w");
    }
    else
    {
        _wx = NULL;
        _ww = NULL;
        _suid = NULL;
    }


        
    /* Scan the whole file system -- may be slow */
    if(rootcheck.scanall)    
    {
        #ifndef WIN32
        snprintf(file_path, 3, "%s", "/");
        #endif

        read_sys_dir(file_path, rootcheck.readall);
    }

    
    /* Scan only specific directories */
    else
    {
        int _i = 0;
        
        #ifndef WIN32
        char *(dirs_to_scan[]) = {"/bin", "/sbin", "/usr/bin",
                                  "/usr/sbin", "/dev", "/lib",
                                  "/etc", "/root", "/var/log",
                                  "/var/mail", "/var/lib", "/var/www",
                                  "/usr/lib", "/usr/include",
                                  "/tmp", "/boot", "/usr/local", 
                                  "/var/tmp", "/sys", NULL};

        #else
        char *(dirs_to_scan[]) = {"C:\\WINDOWS", "C:\\Program Files", NULL};
        #endif
        
        for(_i = 0; _i <= 24; _i++)
        {
            if(dirs_to_scan[_i] == NULL)
                break;
                
            #ifndef WIN32    
            snprintf(file_path, OS_SIZE_1024, "%s%s", 
                                            basedir, 
                                            dirs_to_scan[_i]);
            read_sys_dir(file_path, rootcheck.readall);

            #else
            read_sys_dir(dirs_to_scan[_i], rootcheck.readall);
            #endif
            
        }
    }
    
    if(_sys_errors == 0)
    {
        char op_msg[OS_SIZE_1024 +1];
        snprintf(op_msg, OS_SIZE_1024, "No problem found on the system."
                                    " Analyzed %d files.", _sys_total);
        notify_rk(ALERT_OK, op_msg);
    }

    else if(_wx && _ww && _suid)
    {
        char op_msg[OS_SIZE_1024 +1];
        snprintf(op_msg, OS_SIZE_1024, "Check the following files for more "
            "information:\n%s%s%s",
            (ftell(_wx) == 0)?"":       
            "       rootcheck-rw-rw-rw-.txt (list of world writable files)\n",
            (ftell(_ww) == 0)?"":
            "       rootcheck-rwxrwxrwx.txt (list of world writtable/executable files)\n",
            (ftell(_suid) == 0)?"":        
            "       rootcheck-suid-files.txt (list of suid files)");
        
        notify_rk(ALERT_SYSTEM_ERROR, op_msg);
    }

    if(_wx)
    {
        if(ftell(_wx) == 0)
            unlink("rootcheck-rw-rw-rw-.txt");
        fclose(_wx);
    }
    
    if(_ww)
    {
        if(ftell(_ww) == 0)
            unlink("rootcheck-rwxrwxrwx.txt");
        fclose(_ww);
    }
    
    if(_suid)
    {
        if(ftell(_suid) == 0)
            unlink("rootcheck-suid-files.txt");
        fclose(_suid); 
    }
               
    return;
}
Exemple #10
0
int read_sys_file(char *file_name, int do_read)
{
    struct stat statbuf;
   
    _sys_total++;


    #ifdef WIN32
    /* Check for NTFS ADS on Windows */
    os_check_ads(file_name);
    #endif


    if(lstat(file_name, &statbuf) < 0)
    {
        #ifndef WIN32
        char op_msg[OS_SIZE_1024 +1];
        snprintf(op_msg, OS_SIZE_1024, "Anomaly detected in file '%s'. "
                "Hidden from stats, but showing up on readdir. "
                "Possible kernel level rootkit.",
                file_name);
        notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
        _sys_errors++;

        #endif
        return(-1);
    }
   
    /* If directory, read the directory */
    else if(S_ISDIR(statbuf.st_mode))
    {
        /* Making Darwin happy. for some reason,
         * when I read /dev/fd, it goes forever on
         * /dev/fd5, /dev/fd6, etc.. weird
         */
        if(strstr(file_name, "/dev/fd") != NULL)
            return(0);

        /* Ignoring /proc directory (it has the size 0). */
        if(statbuf.st_size == 0)
            return(0);

        return(read_sys_dir(file_name, do_read));
    }

    /* Check if the size from stats is the same as when we
     * read the file
     */
    if(S_ISREG(statbuf.st_mode) && do_read)
    {
        char buf[OS_SIZE_1024];
        int fd;
        int nr;
        unsigned long int total = 0;

        fd = open(file_name, O_RDONLY, 0);

        /* It may not necessarily open */
        if(fd >= 0)
        {
            while ((nr = read(fd, buf, sizeof(buf))) > 0)
            {
                total += nr;
            }
            close(fd);

            if(strcmp(file_name, "/dev/bus/usb/.usbfs/devices") == 0)
            {
                /* Ignore .usbfs/devices. */
            }

            else if(total != statbuf.st_size)
            {
                struct stat statbuf2;

                if((lstat(file_name, &statbuf2) == 0) &&
                   (total != statbuf2.st_size) &&
                   (statbuf.st_size == statbuf2.st_size))
                {
                    char op_msg[OS_SIZE_1024 +1];
                    snprintf(op_msg, OS_SIZE_1024, "Anomaly detected in file "
                            "'%s'. File size doesn't match what we found. "
                            "Possible kernel level rootkit.",
                            file_name);
                    notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
                    _sys_errors++;
                }
            }
        }
    }
     
    
    /* If has OTHER write and exec permission, alert */
    #ifndef WIN32
    if(((statbuf.st_mode & S_IWOTH) == S_IWOTH) && 
         (S_ISREG(statbuf.st_mode)))
    {
        if((statbuf.st_mode & S_IXUSR) == S_IXUSR)
        {
            if(_wx)
                fprintf(_wx, "%s\n",file_name);
                
            _sys_errors++;    
        }
        else
        {
            if(_ww)
                fprintf(_ww, "%s\n", file_name);
        }

        if(statbuf.st_uid == 0)
        {
            char op_msg[OS_SIZE_1024 +1];
            #ifdef OSSECHIDS
            snprintf(op_msg, OS_SIZE_1024, "File '%s' is owned by root "
                             "and has written permissions to anyone.",
                             file_name);
            #else
            snprintf(op_msg, OS_SIZE_1024, "File '%s' is: \n"
                             "          - owned by root,\n"
                             "          - has written permissions to anyone.",
                             file_name);
            #endif
            notify_rk(ALERT_SYSTEM_CRIT, op_msg);

        }
        _sys_errors++;
    }

    else if((statbuf.st_mode & S_ISUID) == S_ISUID)
    {
        if(_suid)
            fprintf(_suid,"%s\n", file_name);
    }
    #endif

    return(0);
}
Exemple #11
0
/* read_dir v0.1
 *
 */
int read_sys_dir(char *dir_name, int do_read)
{
    int i = 0;
    unsigned int entry_count = 0;
    int did_changed = 0;
    DIR *dp;
    
	struct dirent *entry;
    struct stat statbuf;	
   
    #ifndef WIN32
    char *(dirs_to_doread[]) = { "/bin", "/sbin", "/usr/bin",
                                 "/usr/sbin", "/dev", "/etc", 
                                 "/boot", NULL };
    #endif
    
    if((dir_name == NULL)||(strlen(dir_name) > PATH_MAX))
    {
        merror("%s: Invalid directory given.",ARGV0);
        return(-1);
    }


    /* Ignoring user-supplied list. */
    if(rootcheck.ignore)
    {
        while(rootcheck.ignore[i])
        {
            if(strcmp(dir_name, rootcheck.ignore[i]) == 0)
            {
                return(1);
            }
            i++;
        }
        i = 0;
    }

    
    
    /* Getting the number of nodes. The total number on opendir
     * must be the same
     */
    if(lstat(dir_name, &statbuf) < 0)
    {
        return(-1);
    }
    
    
    /* Currently device id */
    if(did != statbuf.st_dev)
    {
        if(did != 0)
            did_changed = 1;
        did = statbuf.st_dev;
    }
    
    
    if(!S_ISDIR(statbuf.st_mode))
    {
        return(-1);
    }
   

    #ifndef WIN32
    /* Check if the do_read is valid for this directory */
    while(dirs_to_doread[i])
    {
        if(strcmp(dir_name, dirs_to_doread[i]) == 0)
        {
            do_read = 1;
            break;
        }
        i++;
    }
    #else
    do_read = 0;
    #endif
     
     
    /* Opening the directory given */
    dp = opendir(dir_name);
	if(!dp)
    {
        if((strcmp(dir_name, "") == 0)&&
           (dp = opendir("/"))) 
        {
            /* ok */
        }
        else
        {
            return(-1);
        }
    }


    /* Reading every entry in the directory */
    while((entry = readdir(dp)) != NULL)
    {
        char f_name[PATH_MAX +2];
        struct stat statbuf_local;

        /* Just ignore . and ..  */
        if((strcmp(entry->d_name,".") == 0) ||
           (strcmp(entry->d_name,"..") == 0))  
        {
            entry_count++;
            continue;
        }

        /* Creating new file + path string */
        if(strcmp(dir_name, "/") == 0)
        {
            snprintf(f_name, PATH_MAX +1, "/%s", entry->d_name);
        }
        else
        {
            snprintf(f_name, PATH_MAX +1, "%s/%s",dir_name, entry->d_name);
        }

        /* Checking if file is a directory */
        if(lstat(f_name, &statbuf_local) == 0)
        {
            /* On all the systems, except darwin, the
             * link count is only increased on directories.
             */
	        #ifndef Darwin
            if(S_ISDIR(statbuf_local.st_mode))
	        #else
	        if(S_ISDIR(statbuf_local.st_mode) || 
 	           S_ISREG(statbuf_local.st_mode) ||
	           S_ISLNK(statbuf_local.st_mode))
	        #endif
            {
                entry_count++;
            }
        }

        
        /* Checking every file against the rootkit database */
        for(i = 0; i<= rk_sys_count; i++)
        {
            if(!rk_sys_file[i])
                break;

            if(strcmp(rk_sys_file[i], entry->d_name) == 0)
            {
                char op_msg[OS_SIZE_1024 +1];

                _sys_errors++;
                snprintf(op_msg, OS_SIZE_1024, "Rootkit '%s' detected "
                        "by the presence of file '%s/%s'.",
                        rk_sys_name[i], dir_name, rk_sys_file[i]);

                notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
            }
        }

        /* Ignoring /proc */
        if((strcmp(f_name, "/proc") == 0) || (strcmp(f_name, "/sys") == 0))
            continue;

        read_sys_file(f_name, do_read);
    }

    /* Entry count for directory different than the actual
     * link count from stats.
     */
    if((entry_count != statbuf.st_nlink) && 
       ((did_changed == 0) || ((entry_count + 1) != statbuf.st_nlink)))
    {
        #ifndef WIN32
        struct stat statbuf2;
        char op_msg[OS_SIZE_1024 +1];
        

        if((lstat(dir_name, &statbuf2) == 0) && 
            (statbuf2.st_nlink != entry_count))
        {
            snprintf(op_msg, OS_SIZE_1024, "Files hidden inside directory "
                    "'%s'. Link count does not match number of files "
                    "(%d,%d).",
                    dir_name, entry_count, (int)statbuf.st_nlink);

            /* Solaris /boot is terrible :) */
            #ifdef SOLARIS
            if(strncmp(dir_name, "/boot", strlen("/boot")) != 0)
            {
                notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
                _sys_errors++;
            }
            #elif Darwin
            if(strncmp(dir_name, "/dev", strlen("/dev")) != 0)
            {
                notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
                _sys_errors++;
            } 
            #else
            notify_rk(ALERT_ROOTKIT_FOUND, op_msg);

            _sys_errors++;
            #endif
        }

        #endif
    }
    
    closedir(dp);
    
    return(0);
}
Exemple #12
0
/* check_rc_files:
 * Read the file pointer specified (rootkit_files)
 * and check if the configured file is there
 */
void check_rc_files(char *basedir, FILE *fp)
{
    char buf[OS_SIZE_1024 +1];
    char file_path[OS_SIZE_1024 +1];

    char *file;
    char *name;
    char *link;

    int _errors = 0;
    int _total = 0;


    debug1("%s: DEBUG: Starting on check_rc_files", ARGV0);

    while(fgets(buf, OS_SIZE_1024, fp) != NULL)
    {
        char *nbuf;

        /* Removing end of line */
        nbuf = strchr(buf, '\n');
        if(nbuf)
        {
            *nbuf = '\0';
        }

        /* Assigning buf to be used */
        nbuf = buf;

        /* Excluding commented lines or blanked ones */
        while(*nbuf != '\0')
        {
            if(*nbuf == ' ' || *nbuf == '\t')
            {
                nbuf++;
                continue;
            }
            else if(*nbuf == '#')
                goto newline;
            else
                break;
        }

        if(*nbuf == '\0')
            goto newline;

        /* File now may be valid */
        file = nbuf;
        name = nbuf;


        /* Getting the file and the rootkit name */
        while(*nbuf != '\0')
        {
            if(*nbuf == ' ' || *nbuf == '\t')
            {
                /* Setting the limit for the file */
                *nbuf = '\0';
                nbuf++;
                break;
            }
            else
            {
                nbuf++;
            }
        }

        if(*nbuf == '\0')
            goto newline;


        /* Some ugly code to remove spaces and \t */
        while(*nbuf != '\0')
        {
           if(*nbuf == '!')
           {
               nbuf++;
               if(*nbuf == ' ' || *nbuf == '\t')
               {
                   nbuf++;
                   name = nbuf;

                   break;
               }
           }
           else if(*nbuf == ' ' || *nbuf == '\t')
           {
               nbuf++;
               continue;
           }
           else
           {
               goto newline;
           }
        }


        /* Getting the link (if present) */
        link = strchr(nbuf, ':');
        if(link)
        {
            *link = '\0';

            link++;
            if(*link == ':')
            {
                link++;
            }
        }


        /* Cleaning any space of \t at the end */
        nbuf = strchr(nbuf, ' ');
        if(nbuf)
        {
            *nbuf = '\0';
        }

        nbuf = strchr(nbuf, '\t');
        if(nbuf)
        {
            *nbuf = '\0';
        }

        _total++;


        /* Checking if it is a file to search everywhere */
        if(*file == '*')
        {
            if(rk_sys_count >= MAX_RK_SYS)
            {
                merror(MAX_RK_MSG, ARGV0, MAX_RK_SYS);
            }

            else
            {
                /* Removing * / from the file */
                file++;
                if(*file == '/')
                    file++;

                /* Memory assignment */
                rk_sys_file[rk_sys_count] = strdup(file);
                rk_sys_name[rk_sys_count] = strdup(name);

                if(!rk_sys_name[rk_sys_count] ||
                   !rk_sys_file[rk_sys_count] )
                {
                    merror(MEM_ERROR, ARGV0);

                    if(rk_sys_file[rk_sys_count])
                        free(rk_sys_file[rk_sys_count]);
                    if(rk_sys_name[rk_sys_count])
                        free(rk_sys_name[rk_sys_count]);

                    rk_sys_file[rk_sys_count] = NULL;
                    rk_sys_name[rk_sys_count] = NULL;
                }

                rk_sys_count++;

                /* Always assigning the last as NULL */
                rk_sys_file[rk_sys_count] = NULL;
                rk_sys_name[rk_sys_count] = NULL;
            }
            continue;
        }

        snprintf(file_path, OS_SIZE_1024, "%s/%s",basedir, file);

        /* Checking if file exists */
        if(is_file(file_path))
        {
            char op_msg[OS_SIZE_1024 +1];

            _errors = 1;
            snprintf(op_msg, OS_SIZE_1024, "Rootkit '%s' detected "
                     "by the presence of file '%s'.",name, file_path);

            notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
        }

        newline:
            continue;
    }

    if(_errors == 0)
    {
        char op_msg[OS_SIZE_1024 +1];
        snprintf(op_msg,OS_SIZE_1024,"No presence of public rootkits detected."
                                    " Analyzed %d files.", _total);
        notify_rk(ALERT_OK, op_msg);
    }
}
/* check_rc_trojans:
 * Read the file pointer specified (rootkit_trojans)
 * and check if the any trojan entry is on the configured files
 */
void check_rc_trojans(char *basedir, FILE *fp)
{
    int i = 0, _errors = 0, _total = 0;
    char buf[OS_SIZE_1024 +1];
    char file_path[OS_SIZE_1024 +1];

    char *file;
    char *string_to_look;

    #ifndef WIN32
    char *(all_paths[]) = {"bin","sbin","usr/bin","usr/sbin", NULL};
    #else
    char *(all_paths[]) = {"C:\\Windows\\", "D:\\Windows\\", NULL};
    #endif

    debug1("%s: DEBUG: Starting on check_rc_trojans", ARGV0);


    while(fgets(buf, OS_SIZE_1024, fp) != NULL)
    {
        char *nbuf;
        char *message = NULL;

        i = 0;

        /* Removing end of line */
        nbuf = strchr(buf, '\n');
        if(nbuf)
        {
            *nbuf = '\0';
        }


        /* Normalizing line */
        nbuf = normalize_string(buf);
        

        if(*nbuf == '\0' || *nbuf == '#')
        {
            continue;
        }


        /* File now may be valid */
        file = nbuf;

        string_to_look = strchr(file, '!');
        if(!string_to_look)
        {
            continue;
        }
        
        *string_to_look = '\0';
        string_to_look++;

        message = strchr(string_to_look, '!');
        if(!message)
        {
            continue;
        }
        *message = '\0';
        message++;
        
        string_to_look = normalize_string(string_to_look);
        file = normalize_string(file);
        message = normalize_string(message);
        
        
        if(*file == '\0' || *string_to_look == '\0')
        {
            continue;
        }
        
        _total++;
        
        
        /* Trying with all possible paths */
        while(all_paths[i] != NULL)
        {
            if(*file != '/')
            {
                snprintf(file_path, OS_SIZE_1024, "%s/%s/%s",basedir, 
                        all_paths[i],
                        file);
            }
            else
            {
                strncpy(file_path, file, OS_SIZE_1024);
                file_path[OS_SIZE_1024 -1] = '\0';
            }
            
            /* Checking if entry is found */
            if(is_file(file_path) && os_string(file_path, string_to_look))
            {
                char op_msg[OS_SIZE_1024 +1];
                _errors = 1;
            
                snprintf(op_msg, OS_SIZE_1024, "Trojaned version of file "
                        "'%s' detected. Signature used: '%s' (%s).", 
                                        file_path,
                                        string_to_look,
                                        *message == '\0'?
                                        "Generic":message);

                notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
            }

            if(*file == '/')
            {
                break;
            }
            i++;
        }
        continue;        
    }


    if(_errors == 0)
    {
        char op_msg[OS_SIZE_1024 +1];
        snprintf(op_msg,OS_SIZE_1024, "No binaries with any trojan detected. "
                                    "Analyzed %d files.", _total);
        notify_rk(ALERT_OK, op_msg);
    }
}
Exemple #14
0
/* run_rk_check: v0.1
 * Execute the rootkit checks
 */
void run_rk_check()
{
    time_t time1;
    time_t time2;

    FILE *fp;
    OSList *plist;

#ifndef WIN32
    /* Hard coding basedir */
    size_t i;
    char basedir[] = "/";

    /* Removing the last / from basedir */
    i = strlen(basedir);
    if(i > 0)
    {
        if(basedir[i-1] == '/')
        {
            basedir[i-1] = '\0';
        }
    }
#else

    /* Basedir for Windows */
    char basedir[] = "C:\\";

#endif


    /* Setting basedir */
    if(rootcheck.basedir == NULL)
    {
        rootcheck.basedir = basedir;
    }


    time1 = time(0);

    /*** Initial message ***/
    if(rootcheck.notify != QUEUE)
    {
        printf("\n");
        printf("** Starting Rootcheck v0.9 by Daniel B. Cid        **\n");
        printf("** http://www.ossec.net/en/about.html#dev-team     **\n");
        printf("** http://www.ossec.net/rootcheck/                 **\n\n");
        printf("Be patient, it may take a few minutes to complete...\n");
        printf("\n");
    }


    /* Cleaning the global variables */
    rk_sys_count = 0;
    rk_sys_file[rk_sys_count] = NULL;
    rk_sys_name[rk_sys_count] = NULL;



    /* Sending scan start message */
    notify_rk(ALERT_POLICY_VIOLATION, "Starting rootcheck scan.");
    if(rootcheck.notify == QUEUE)
    {
        merror("%s: INFO: Starting rootcheck scan.", ARGV0);
    }



    /***  First check, look for rootkits ***/
    /* Open rootkit_files and pass the pointer to check_rc_files */
    if (rootcheck.checks.rc_files)
    {
        if(!rootcheck.rootkit_files)
        {
#ifndef WIN32
            merror("%s: No rootcheck_files file configured.", ARGV0);
#endif
        }

        else
        {
            fp = fopen(rootcheck.rootkit_files, "r");
            if(!fp)
            {
                merror("%s: No rootcheck_files file: '%s'",ARGV0,
                       rootcheck.rootkit_files);
            }

            else
            {
                check_rc_files(rootcheck.basedir, fp);

                fclose(fp);
            }
        }
    }



    /*** Second check. look for trojan entries in common binaries ***/
    if (rootcheck.checks.rc_trojans)
    {
        if(!rootcheck.rootkit_trojans)
        {
#ifndef WIN32
            merror("%s: No rootcheck_trojans file configured.", ARGV0);
#endif
        }

        else
        {
            fp = fopen(rootcheck.rootkit_trojans, "r");
            if(!fp)
            {
                merror("%s: No rootcheck_trojans file: '%s'",ARGV0,
                       rootcheck.rootkit_trojans);
            }

            else
            {
#ifndef HPUX
                check_rc_trojans(rootcheck.basedir, fp);
#endif

                fclose(fp);
            }
        }
    }



#ifdef WIN32

    /*** Getting process list ***/
    plist = os_get_process_list();


    /*** Windows audit check ***/
    if (rootcheck.checks.rc_winaudit)
    {
        if(!rootcheck.winaudit)
        {
            merror("%s: No winaudit file configured.", ARGV0);
        }
        else
        {
            fp = fopen(rootcheck.winaudit, "r");
            if(!fp)
            {
                merror("%s: No winaudit file: '%s'",ARGV0,
                       rootcheck.winaudit);
            }
            else
            {
                check_rc_winaudit(fp, plist);
                fclose(fp);
            }
        }
    }

    /* Windows malware */
    if (rootcheck.checks.rc_winmalware)
    {
        if(!rootcheck.winmalware)
        {
            merror("%s: No winmalware file configured.", ARGV0);
        }
        else
        {
            fp = fopen(rootcheck.winmalware, "r");
            if(!fp)
            {
                merror("%s: No winmalware file: '%s'",ARGV0,
                       rootcheck.winmalware);
            }
            else
            {
                check_rc_winmalware(fp, plist);
                fclose(fp);
            }
        }
    }

    /* Windows Apps */
    if (rootcheck.checks.rc_winapps)
    {
        if(!rootcheck.winapps)
        {
            merror("%s: No winapps file configured.", ARGV0);
        }
        else
        {
            fp = fopen(rootcheck.winapps, "r");
            if(!fp)
            {
                merror("%s: No winapps file: '%s'",ARGV0,
                       rootcheck.winapps);
            }
            else
            {
                check_rc_winapps(fp, plist);
                fclose(fp);
            }
        }
    }


    /* Freeing process list */
    del_plist((void *)plist);



    /** Checks for other non Windows. **/
#else



    /*** Unix audit check ***/
    if (rootcheck.checks.rc_unixaudit)
    {
        if(rootcheck.unixaudit)
        {
            /* Getting process list. */
            plist = os_get_process_list();


            i = 0;
            while(rootcheck.unixaudit[i])
            {
                fp = fopen(rootcheck.unixaudit[i], "r");
                if(!fp)
                {
                    merror("%s: No unixaudit file: '%s'",ARGV0,
                           rootcheck.unixaudit[i]);
                }
                else
                {
                    /* Running unix audit. */
                    check_rc_unixaudit(fp, plist);

                    fclose(fp);
                }

                i++;
            }


            /* Freeing list */
            del_plist(plist);
        }
    }


#endif


    /*** Third check, looking for files on the /dev ***/
    if (rootcheck.checks.rc_dev)
    {
        debug1("%s: DEBUG: Going into check_rc_dev", ARGV0);
        check_rc_dev(rootcheck.basedir);
    }

    /*** Fourth check,  scan the whole system looking for additional issues */
    if (rootcheck.checks.rc_sys)
    {
        debug1("%s: DEBUG: Going into check_rc_sys", ARGV0);
        check_rc_sys(rootcheck.basedir);
    }

    /*** Process checking ***/
    if (rootcheck.checks.rc_pids)
    {
        debug1("%s: DEBUG: Going into check_rc_pids", ARGV0);
        check_rc_pids();
    }

    /*** Check all the ports ***/
    if (rootcheck.checks.rc_ports)
    {
        debug1("%s: DEBUG: Going into check_rc_ports", ARGV0);
        check_rc_ports();

        /*** Check open ports ***/
        debug1("%s: DEBUG: Going into check_open_ports", ARGV0);
        check_open_ports();
    }

    /*** Check interfaces ***/
    if (rootcheck.checks.rc_if)
    {
        debug1("%s: DEBUG: Going into check_rc_if", ARGV0);
        check_rc_if();
    }


    debug1("%s: DEBUG: Completed with all checks.", ARGV0);


    /* Cleaning the global memory */
    {
        int li;
        for(li = 0; li <= rk_sys_count; li++)
        {
            if(!rk_sys_file[li] ||
                    !rk_sys_name[li])
                break;

            free(rk_sys_file[li]);
            free(rk_sys_name[li]);
        }
    }

    /*** Final message ***/
    time2 = time(0);

    if(rootcheck.notify != QUEUE)
    {
        printf("\n");
        printf("- Scan completed in %d seconds.\n\n", (int)(time2 - time1));
    }
    else
    {
        sleep(5);
    }


    /* Sending scan ending message */
    notify_rk(ALERT_POLICY_VIOLATION, "Ending rootcheck scan.");
    if(rootcheck.notify == QUEUE)
    {
        merror("%s: INFO: Ending rootcheck scan.", ARGV0);
    }


    debug1("%s: DEBUG: Leaving run_rk_check",ARGV0);
    return;
}
Exemple #15
0
/** void loop_all_pids(char *ps, pid_t max_pid, int *_errors, int *_total)
 * Check all the available PIDs for hidden stuff.
 */
void loop_all_pids(char *ps, pid_t max_pid, int *_errors, int *_total)
{
    int _kill0 = 0;
    int _kill1 = 0;
    int _gsid0 = 0;
    int _gsid1 = 0;
    int _gpid0 = 0;
    int _gpid1 = 0;
    int _ps0 = -1;
    int _proc_stat  = 0;
    int _proc_read  = 0;
    int _proc_chdir = 0;

    pid_t i = 1;
    pid_t my_pid;

    char command[OS_SIZE_1024 +1];

    my_pid = getpid();

    for(;;i++)
    {
        if((i <= 0)||(i > max_pid))
            break;

        (*_total)++;

        _kill0 = 0;
        _kill1 = 0;
        _gsid0 = 0;
        _gsid1 = 0;
        _gpid0 = 0;
        _gpid1 = 0;
        _ps0 = -1;
        _proc_stat  = 0;
        _proc_read  = 0;
        _proc_chdir = 0;


        /* kill test */
        if(!((kill(i, 0) == -1)&&(errno == ESRCH)))
        {
            _kill0 = 1;
        }

        /* getsid to test */
        if(!((getsid(i) == -1)&&(errno == ESRCH)))
        {
            _gsid0 = 1;
        }

        /* getpgid test */
        if(!((getpgid(i) == -1)&&(errno == ESRCH)))
        {
            _gpid0 = 1;
        }


        /* proc stat */
        _proc_stat = proc_stat(i);

        /* proc readdir */
        _proc_read = proc_read(i);

        /* proc chdir */
        _proc_chdir = proc_chdir(i);


        /* IF PID does not exist, keep going */
        if(!_kill0 && !_gsid0 && !_gpid0 &&
           !_proc_stat && !_proc_read && !_proc_chdir)
        {
            continue;
        }

        /* We do not need to look at our own pid */
        else if(i == my_pid)
        {
            continue;
        }

        /* Checking the number of errors */
        if((*_errors) > 15)
        {
            char op_msg[OS_SIZE_1024 +1];
            snprintf(op_msg,OS_SIZE_1024,"Excessive number of hidden processes"
                    ". It maybe a false-positive or "
                    "something really bad is going on.");
            notify_rk(ALERT_SYSTEM_CRIT, op_msg);
            return;
        }


        /* checking if process appears on ps */
        if(*ps)
        {
            snprintf(command, OS_SIZE_1024, "%s -p %d > /dev/null 2>&1",
                                                        ps,
                                                        (int)i);

            /* Found PID on ps */
            _ps0 = 0;
            if(system(command) == 0)
                _ps0 = 1;
        }

        /* If we are being run by the ossec hids, sleep here (no rush) */
        #ifdef OSSECHIDS
        sleep(2);
        #endif

        /* Everyone returned ok */
        if(_ps0 && _kill0 && _gsid0 && _gpid0 && _proc_stat && _proc_read)
        {
            continue;
        }



        /* If our kill or getsid system call, got the
         * PID , but ps didn't, we need to find if it was a problem
         * with a PID being deleted (not used anymore)
         */
        {
            if(!((getsid(i) == -1)&&(errno == ESRCH)))
            {
                _gsid1 = 1;
            }

            if(!((kill(i, 0) == -1)&&(errno == ESRCH)))
            {
                _kill1 = 1;
            }

            if(!((getpgid(i) == -1)&&(errno == ESRCH)))
            {
                _gpid1 = 1;
            }


            _proc_stat = proc_stat(i);

            _proc_read = proc_read(i);

            _proc_chdir = proc_chdir(i);

            /* If it matches, process was terminated */
            if(!_gsid1 &&!_kill1 &&!_gpid1 &&!_proc_stat &&
               !_proc_read &&!_proc_chdir)
            {
                continue;
            }
        }

        #ifdef AIX
        /* Ignoring AIX wait and sched programs. */
        if((_gsid0 == _gsid1) &&
           (_kill0 == _kill1) &&
           (_gpid0 == _gpid1) &&
           (_ps0 == 1) &&
           (_gsid0 == 1) &&
           (_kill0 == 0))
        {
            /* The wait and sched programs do not respond to kill 0.
             * So, if everything else finds it, including ps, getpid, getsid,
             * but not
             * kill, we can safely ignore on AIX.
             * A malicious program would specially try to hide from ps..
             */
            continue;
        }
        #endif


        if((_gsid0 == _gsid1)&&
           (_kill0 == _kill1)&&
           (_gsid0 != _kill0))
        {
            /* If kill found, but getsid and getpgid didnt', it may
             * be a defunct process -- ignore.
             */
            if(!((_kill0 == 1)&&(_gsid0 == 0)&&(_gpid0 == 0)&&(_gsid1 == 0)))
            {
                char op_msg[OS_SIZE_1024 +1];

                snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
                        "kill (%d) or getsid (%d). Possible kernel-level"
                        " rootkit.", (int)i, _kill0, _gsid0);

                notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
                (*_errors)++;
            }
        }
        else if((_kill1 != _gsid1)||
                (_gpid1 != _kill1)||
                (_gpid1 != _gsid1))
        {
            /* See defunct process comment above. */
            if(!((_kill1 == 1)&&(_gsid1 == 0)&&(_gpid0 == 0)&&(_gsid1 == 0)))
            {
                char op_msg[OS_SIZE_1024 +1];
                snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
                        "kill (%d), getsid (%d) or getpgid. Possible "
                        "kernel-level rootkit.", (int)i, _kill1, _gsid1);

                notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
                (*_errors)++;
            }
        }
        else if((_proc_read != _proc_stat)||
                (_proc_read != _proc_chdir)||
                (_proc_stat != _kill1))
        {
            /* checking if the pid is a thread (not showing on proc */
            if(!noproc && !check_rc_readproc((int)i))
            {
                char op_msg[OS_SIZE_1024 +1];
                snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
                        "/proc. Possible kernel level rootkit.", (int)i);
                notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
                (*_errors)++;
            }
        }
        else if(_gsid1 && _kill1 && !_ps0)
        {
            /* checking if the pid is a thread (not showing on ps */
            if(!check_rc_readproc((int)i))
            {
                char op_msg[OS_SIZE_1024 +1];
                snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
                             "ps. Possible trojaned version installed.",
                             (int)i);

                notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
                (*_errors)++;
            }
        }
    }
}