예제 #1
0
        /// <summary>
        /// Non referenced file scan
        /// </summary>
        /// <param name="filePath">File to scan.</param>
        /// <param name="Signatures">Signatures to scan with</param>
        /// <returns>Null or signature matching or found in file. </returns>
        //public static ScanResultArgs ScanFile(string filePath, SignatureController Signatures)
        //{
        //    return ScanFile(filePath, ref Signatures);
        //}

        /// <summary>
        /// Performs a scan on the provided file
        /// </summary>
        /// <param name="filePath">The file to scan.</param>
        /// <param name="Signatures">The signature controller</param>
        /// <param name="cached">The cache controller</param>
        /// <returns>Null or a signature</returns>
        public static ScanResultArgs ScanFile(string filePath, SignatureController Signatures)
        {
            //return ScanFileV2(filePath, Signatures);

            try
            {
                // Final args to return
                var args = new ScanResultArgs();

                // *** NEW ***
                // Create a new filestream to read the file with
                FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

                // Before performing any kind of scan, we need to make sure it's a executable file
                if (!isScannable(filePath))
                {
                    // If it's not, return null and theres no point of scanning it
                    //return null;
                    return(new ScanResultArgs()
                    {
                        Detection = null, Size = fs.Length
                    });
                }

                // Determine if the file is too large to scan based on settings
                if (fs.Length > Settings.MaxFileSize)
                {
                    // If so, just return null...
                    return(new ScanResultArgs()
                    {
                        Detection = null, Size = fs.Length
                    });
                }

                // ***********


                // Some local variables to store scan information in
                //byte[] hash = MD5.quickMD5(filePath);

                // If a cache database is supplied with the scan request
                //if (cached != null)
                //{
                //    // Try to obtain a md5 hash from the file (see exception below for possible issues)
                //    //hash = MD5.FromFile(ref fs);
                //    hash = MD5.quickMD5(filePath);

                //    // Check the file cache to see if the file has already been scanned
                //    var found = cached.GetById(hash);

                //    // If a cached item was found in the db
                //    if(found != null)
                //    {
                //        // Return the matching signature if any...
                //        //return Signatures.GetById(found.SignatureId);
                //        return new ScanResultArgs() { Detection = Signatures.GetById(found.SignatureId), Size = fs.Length, Cached = found };
                //    }
                //}

                // Either the file cache database is not being used or no entry was found
                // So we must perform a new scan on the file
                byte[] buffer = new byte[1024 * Settings.BufferSize]; // Scan in 32kb increments
                int    read   = -1;                                   // count how many bytes have been read on each read here

                // Make sure our buffer isn't bigger than the file
                if (buffer.Length > fs.Length)
                {
                    // If it is, resize the buffer accordinly
                    buffer = new byte[fs.Length];
                }

                // While there is data to read in the file stream
                while (read != 0)
                {
                    // Attempt to read the buffered amount..
                    read = fs.Read(buffer, 0, buffer.Length);

                    // If the buffered amount if greater than the amount read...
                    // Lets shrink buffer to speed up the pattern search
                    if (read < buffer.Length)
                    {
                        Array.Resize(ref buffer, read);
                    }



                    // Analyze the buffer with the pattern analyzer
                    var result = PatternAnalyzer.AnalyzeByteArray(buffer, Signatures);

                    // try version 2....
                    //var result = PatternAnalyzer.AnyalyzeByteArrayv2(buffer, Signatures);

                    // If the result is not null... a detection was found
                    if (result != null)
                    {
                        // Create args before closing
                        args = new ScanResultArgs()
                        {
                            Detection = result,
                            Size      = fs.Length,
                        };

                        // Detected upx packing...
                        if (args.Detection.Definition == "PACKED")
                        {
                            // UPX ISNT WORKING YET
                            //return new ScanResultArgs() { Detection = null, Size = 0 };

                            // unpack the file and store the unpacked path...
                            string unpacked = API.UPXHelper.UnpackFile(filePath);

                            // Perform another scan
                            args = ScanFile(unpacked, Signatures);

                            // this was an unpacked program...
                            //if(args.Detection != null)
                            //{
                            //    //args.Detection.Definition = args.Detection.Definition + "/UPX";
                            //}

                            // delete the unpacked file
                            File.DeleteFile(unpacked);

                            // Remove the unpacked file from white lsit
                            Settings.WhiteList.Remove(unpacked);
                        }

                        // We already detected the threat so we do not need to read any more..
                        fs.Dispose();

                        // return the threat
                        return(args);
                    }
                }

                // We finished reading the file and no threat was detected
                // Time to clean and and may be log to cache

                // Create clean args
                args = new ScanResultArgs()
                {
                    Detection = null,
                    Size      = fs.Length,
                };


                // Close up the file stream
                fs.Close();
                fs.Dispose();

                // clear buffer
                buffer = null;

                // Return a clean scan
                return(args);
            }
            catch (Exception ex) // for debugging purposes
            {
#if DEBUG
                Console.WriteLine(ex.Message);
#endif
                // Throw an exception with info about what may have caused the error.
                throw new Exception(String.Format("[2] Unable to scan file at location {0}. File may be use or additional rights may be required.", filePath));
                //return new ScanResultArgs() { Detection = null, Size = 0 };
            }
        }
예제 #2
0
        public static ScanResultArgs ScanFileV2(string filePath, SignatureController signatures)
        {
            try
            {
                // Create a new scan result to return with
                var args = new ScanResultArgs();

                // open new file stream
                FileStream fs = new System.IO.FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

                // set file size
                args.Size = fs.Length;

                // Check if scannable file type
                if (!isScannable(filePath))
                {
                    return(new ScanResultArgs()
                    {
                        Detection = null
                    });
                }

                // any other additional checks to perform here

                // Create variables to load file buffers into
                //byte[] buffer = new byte[1024 * Settings.BufferSize];
                int read = 1;

                // check if buffer is bigger than file
                //if(buffer.Length > fs.Length)
                //{
                // fix buffer
                //buffer = new byte[fs.Length];
                //}

                // Create list of tasks to perform scan on
                List <ThreadedAnalysis> scans = new List <ThreadedAnalysis>();

                int max = Environment.ProcessorCount;;
                if (Settings.ReducePriority)
                {
                    max = Environment.ProcessorCount / 2;
                }

                // Loop to read file while possible
                while (read > 0 && args.Detection == null)
                {
                    // read the file chunk
                    //read = fs.Read(buffer, 0, buffer.Length);

                    // create new threaded scan of the buffer read
                    ThreadedAnalysis t = new ThreadedAnalysis();
                    read = fs.Read(t.Buffer, 0, t.Buffer.Length);
                    scans.Add(t);
                    t.run(signatures);

                    // we now have to do a check
                    if (scans.Count > max)
                    {
                        // if we have max number of scans running we need to clear up some space
                        for (int i = 0; i < scans.Count; i++)
                        {
                            // check if a scan is done...
                            if (scans[i].Complete)
                            {
                                // if it is, check it's result
                                if (scans[i].Result != null)
                                {
                                    // copy detection over
                                    args.Detection = scans[i].Result;
                                    // Detected upx packing...
                                    if (args.Detection.Definition == "PACKED")
                                    {
                                        // unpack the file and store the unpacked path...
                                        string unpacked = API.UPXHelper.UnpackFile(filePath);

                                        // Perform another scan
                                        args = ScanFileV2(unpacked, signatures);

                                        // delete the unpacked file
                                        File.DeleteFile(unpacked);

                                        // Remove the unpacked file from white lsit
                                        Settings.WhiteList.Remove(unpacked);
                                    }
                                    return(args);
                                }
                                else
                                {
                                    // no detection so clear up the scan list
                                    scans.Remove(scans[i]);
                                }
                            }
                        }
                    }
                }

                while (scans.Count > 0)
                {
                    // if we have max number of scans running we need to clear up some space
                    for (int i = 0; i < scans.Count; i++)
                    {
                        // check if a scan is done...
                        if (scans[i].Complete)
                        {
                            // if it is, check it's result
                            if (scans[i].Result != null)
                            {
                                // copy detection over
                                args.Detection = scans[i].Result;
                                // Detected upx packing...
                                if (args.Detection.Definition == "PACKED")
                                {
                                    // unpack the file and store the unpacked path...
                                    string unpacked = API.UPXHelper.UnpackFile(filePath);

                                    // Perform another scan
                                    args = ScanFileV2(unpacked, signatures);

                                    // delete the unpacked file
                                    File.DeleteFile(unpacked);

                                    // Remove the unpacked file from white lsit
                                    Settings.WhiteList.Remove(unpacked);
                                }
                                return(args);
                            }
                            else
                            {
                                // no detection so clear up the scan list
                                scans.Remove(scans[i]);
                            }
                        }
                        else
                        {
                            scans[i].waiting();
                        }
                    }
                }

                fs.Dispose();
                //buffer = null;

                // return scan results
                return(args);
            }
            catch (Exception ex)
            {
#if DEBUG
                Console.WriteLine(ex.Message);
#endif

                throw new Exception("Unable to scan file at location: " + filePath);
            }
        }