[Forensics-changes] [yara] 189/415: Allow to specify a timeout in scanning functions

Hilko Bengen bengen at moszumanska.debian.org
Thu Apr 3 05:43:04 UTC 2014


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to branch debian
in repository yara.

commit eb3bd52919c630162bdce39141af040a1ec54e15
Author: Victor M. Alvarez <plusvic at gmail.com>
Date:   Tue Jul 2 14:18:00 2013 +0000

    Allow to specify a timeout in scanning functions
---
 libyara/rules.c           | 45 ++++++++++++++++++++++++++++++++++++---------
 libyara/yara.h            | 10 +++++++---
 yara-python/yara-python.c | 27 +++++++++++++++++++++------
 yara.c                    | 36 ++++++++++++++++++++++++++++++------
 4 files changed, 94 insertions(+), 24 deletions(-)

diff --git a/libyara/rules.c b/libyara/rules.c
index 526fb0f..32e1760 100644
--- a/libyara/rules.c
+++ b/libyara/rules.c
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 #include <string.h>
+#include <time.h>
 
 #include "arena.h"
 #include "exec.h"
@@ -596,13 +597,18 @@ int yr_rules_scan_mem_block(
     YARA_RULES* rules,
     uint8_t* data,
     size_t data_size,
-    int fast_scan_mode)
+    int fast_scan_mode,
+    int timeout,
+    time_t start_time)
 {
 
   AC_STATE* next_state;
   AC_MATCH* ac_match;
   AC_STATE* current_state;
+
+  time_t current_time;
   size_t i;
+
   int result;
 
   current_state = rules->automaton->root;
@@ -646,6 +652,14 @@ int yr_rules_scan_mem_block(
       current_state = next_state;
 
     i++;
+
+    if (timeout > 0 && i % 256 == 0)
+    {
+      current_time = time(NULL);
+
+      if (difftime(current_time, start_time) > timeout)
+        return ERROR_TIMEOUT;
+    }
   }
 
   ac_match = current_state->matches;
@@ -674,11 +688,14 @@ int yr_rules_scan_mem_blocks(
     int scanning_process_memory,
     YARACALLBACK callback,
     void* user_data,
-    int fast_scan_mode)
+    int fast_scan_mode,
+    int timeout)
 {
   RULE* rule;
   EVALUATION_CONTEXT context;
 
+  time_t start_time;
+
   char message[512];
   int result;
 
@@ -688,6 +705,8 @@ int yr_rules_scan_mem_blocks(
 
   yr_rules_free_matches(rules);
 
+  start_time = time(NULL);
+
   while (block != NULL)
   {
     if (context.entry_point == UNDEFINED)
@@ -707,7 +726,9 @@ int yr_rules_scan_mem_blocks(
         rules,
         block->data,
         block->size,
-        fast_scan_mode);
+        fast_scan_mode,
+        timeout,
+        start_time);
 
     if (result != ERROR_SUCCESS)
       return result;
@@ -763,7 +784,8 @@ int yr_rules_scan_mem(
     size_t buffer_size,
     YARACALLBACK callback,
     void* user_data,
-    int fast_scan_mode)
+    int fast_scan_mode,
+    int timeout)
 {
   MEMORY_BLOCK block;
 
@@ -778,7 +800,8 @@ int yr_rules_scan_mem(
       FALSE,
       callback,
       user_data,
-      fast_scan_mode);
+      fast_scan_mode,
+      timeout);
 }
 
 
@@ -787,7 +810,8 @@ int yr_rules_scan_file(
     const char* filename,
     YARACALLBACK callback,
     void* user_data,
-    int fast_scan_mode)
+    int fast_scan_mode,
+    int timeout)
 {
   MAPPED_FILE mfile;
   int result;
@@ -802,7 +826,8 @@ int yr_rules_scan_file(
         mfile.size,
         callback,
         user_data,
-        fast_scan_mode);
+        fast_scan_mode,
+        timeout);
 
     yr_filemap_unmap(&mfile);
   }
@@ -816,7 +841,8 @@ int yr_rules_scan_proc(
     int pid,
     YARACALLBACK callback,
     void* user_data,
-    int fast_scan_mode)
+    int fast_scan_mode,
+    int timeout)
 {
   MEMORY_BLOCK* first_block;
   MEMORY_BLOCK* next_block;
@@ -833,7 +859,8 @@ int yr_rules_scan_proc(
         TRUE,
         callback,
         user_data,
-        fast_scan_mode);
+        fast_scan_mode,
+        timeout);
 
   block = first_block;
 
diff --git a/libyara/yara.h b/libyara/yara.h
index d0ed1a8..7fa2ff9 100644
--- a/libyara/yara.h
+++ b/libyara/yara.h
@@ -78,6 +78,7 @@ limitations under the License.
 #define ERROR_INCLUDE_DEPTH_EXCEEDED            32
 #define ERROR_INVALID_OR_CORRUPT_FILE           33
 #define ERROR_EXEC_STACK_OVERFLOW               34
+#define ERROR_TIMEOUT                           35
 
 #define MAX_INCLUDE_DEPTH 16
 #define LEX_BUF_SIZE  1024
@@ -563,7 +564,8 @@ int yr_rules_scan_mem(
     size_t buffer_size,
     YARACALLBACK callback,
     void* user_data,
-    int fast_scan_mode);
+    int fast_scan_mode,
+    int timeout);
 
 
 int yr_rules_scan_file(
@@ -571,7 +573,8 @@ int yr_rules_scan_file(
     const char* filename,
     YARACALLBACK callback,
     void* user_data,
-    int fast_scan_mode);
+    int fast_scan_mode,
+    int timeout);
 
 
 int yr_rules_scan_proc(
@@ -579,7 +582,8 @@ int yr_rules_scan_proc(
     int pid,
     YARACALLBACK callback,
     void* user_data,
-    int fast_scan_mode);
+    int fast_scan_mode,
+    int timeout);
 
 
 int yr_rules_save(
diff --git a/yara-python/yara-python.c b/yara-python/yara-python.c
index e43b5d7..a29611b 100644
--- a/yara-python/yara-python.c
+++ b/yara-python/yara-python.c
@@ -53,6 +53,7 @@ typedef int Py_ssize_t;
 
 static PyObject *YaraError = NULL;
 static PyObject *YaraSyntaxError = NULL;
+static PyObject *YaraTimeoutError = NULL;
 
 
 #define YARA_DOC "\
@@ -595,6 +596,10 @@ PyObject* handle_error(
           YaraError,
           "invalid or corrupt compiled rules file \"%s\"",
           extra);
+    case ERROR_TIMEOUT:
+      return PyErr_Format(
+          YaraTimeoutError,
+          "scanning timed out");
     default:
       return PyErr_Format(
           YaraError,
@@ -744,12 +749,15 @@ static PyObject * Rules_match(
     PyObject *keywords)
 {
   static char *kwlist[] = {
-      "filepath", "pid", "data", "externals", "callback", "fast", NULL};
+      "filepath", "pid", "data", "externals",
+      "callback", "fast", "timeout", NULL
+      };
 
   char* filepath = NULL;
   char* data = NULL;
 
   int pid = 0;
+  int timeout = 0;
   int length;
   int error;
   int fast_mode = FALSE;
@@ -766,7 +774,7 @@ static PyObject * Rules_match(
   if (PyArg_ParseTupleAndKeywords(
         args,
         keywords,
-        "|sis#OOO",
+        "|sis#OOOi",
         kwlist,
         &filepath,
         &pid,
@@ -774,7 +782,8 @@ static PyObject * Rules_match(
         &length,
         &externals,
         &callback_data.callback,
-        &fast))
+        &fast,
+        &timeout))
   {
     if (externals != NULL)
     {
@@ -821,7 +830,8 @@ static PyObject * Rules_match(
           filepath,
           yara_callback,
           &callback_data,
-          fast_mode);
+          fast_mode,
+          timeout);
 
       Py_END_ALLOW_THREADS
 
@@ -847,7 +857,8 @@ static PyObject * Rules_match(
           (unsigned int) length,
           yara_callback,
           &callback_data,
-          fast_mode);
+          fast_mode,
+          timeout);
 
       Py_END_ALLOW_THREADS
 
@@ -872,7 +883,8 @@ static PyObject * Rules_match(
           pid,
           yara_callback,
           &callback_data,
-          fast_mode);
+          fast_mode,
+          timeout);
 
       Py_END_ALLOW_THREADS
 
@@ -1291,9 +1303,11 @@ MOD_INIT(yara)
 #if PYTHON_API_VERSION >= 1007
   YaraError = PyErr_NewException("yara.Error", PyExc_Exception, NULL);
   YaraSyntaxError = PyErr_NewException("yara.SyntaxError", YaraError, NULL);
+  YaraTimeoutError = PyErr_NewException("yara.TimeoutError", YaraError, NULL);
 #else
   YaraError = Py_BuildValue("s", "yara.Error");
   YaraSyntaxError = Py_BuildValue("s", "yara.SyntaxError");
+  YaraTimeoutError = Py_BuildValue("s", "yara.TimeoutError");
 #endif
 
   if (PyType_Ready(&Rules_Type) < 0)
@@ -1304,6 +1318,7 @@ MOD_INIT(yara)
 
   PyModule_AddObject(m, "Error", YaraError);
   PyModule_AddObject(m, "SyntaxError", YaraSyntaxError);
+  PyModule_AddObject(m, "TimeoutError", YaraTimeoutError);
 
   yr_initialize();
 
diff --git a/yara.c b/yara.c
index 5394416..85eac30 100644
--- a/yara.c
+++ b/yara.c
@@ -55,6 +55,7 @@ int fast_scan = FALSE;
 int negate = FALSE;
 int count = 0;
 int limit = 0;
+int timeout = 0;
 
 
 typedef struct _TAG
@@ -104,7 +105,8 @@ EXTERNAL* externals_list = NULL;
 "  -g                       print tags.\n"\
 "  -m                       print metadata.\n"\
 "  -s                       print matching strings.\n"\
-"  -l <number>              abort scanning after matching <number> rules.\n"\
+"  -l <number>              abort scanning after matching a <number> rules.\n"\
+"  -a <seconds>             abort scanning after a number of seconds has elapsed.\n"\
 "  -d <identifier>=<value>  define external variable.\n"\
 "  -r                       recursively search directories.\n"\
 "  -v                       show version information.\n"
@@ -176,7 +178,8 @@ int scan_dir(
             full_path,
             callback,
             full_path,
-            TRUE);
+            fast_scan,
+            timeout);
       }
       else if (recursive && FindFileData.cFileName[0] != '.' )
       {
@@ -243,7 +246,8 @@ int scan_dir(
               full_path,
               callback,
               full_path,
-              fast_scan);
+              fast_scan,
+              timeout);
         }
         else if(recursive && S_ISDIR(st.st_mode) && de->d_name[0] != '.')
         {
@@ -484,7 +488,7 @@ int process_cmd_line(
 
   opterr = 0;
 
-  while ((c = getopt (argc, (char**) argv, "rnsvgml:t:i:d:f")) != -1)
+  while ((c = getopt (argc, (char**) argv, "rnsvgma:l:t:i:d:f")) != -1)
   {
     switch (c)
     {
@@ -593,6 +597,10 @@ int process_cmd_line(
         limit = atoi(optarg);
         break;
 
+      case 'a':
+        timeout = atoi(optarg);
+        break;
+
       case '?':
 
         if (optopt == 't')
@@ -682,6 +690,8 @@ int main(
   int errors;
   int result;
 
+  clock_t start, end;
+
   if (!process_cmd_line(argc, argv))
     return 0;
 
@@ -797,7 +807,8 @@ int main(
         pid,
         callback,
         (void*) argv[argc - 1],
-        fast_scan);
+        fast_scan,
+        timeout);
   }
   else if (is_directory(argv[argc - 1]))
   {
@@ -809,12 +820,19 @@ int main(
   }
   else
   {
+    start = clock();
+
     result = yr_rules_scan_file(
         rules,
         argv[argc - 1],
         callback,
         (void*) argv[argc - 1],
-        fast_scan);
+        fast_scan,
+        timeout);
+
+    end = clock();
+
+    printf( "Scanning time: %f s\n", (float)(end - start) / CLOCKS_PER_SEC);
   }
 
   switch (result)
@@ -827,6 +845,12 @@ int main(
     case ERROR_INSUFICIENT_MEMORY:
       fprintf(stderr, "not enough memory\n");
       break;
+    case ERROR_TIMEOUT:
+      fprintf(stderr, "scanning timed out\n");
+      break;
+    case ERROR_COULD_NOT_OPEN_FILE:
+      fprintf(stderr, "could not open file\n");
+      break;
     default:
       fprintf(stderr, "internal error: %d\n", result);
       break;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git



More information about the forensics-changes mailing list