[Forensics-changes] [yara] 32/407: Implement "locale" function in PE module and improve buffer bounds checking

Hilko Bengen bengen at moszumanska.debian.org
Sat Jul 1 10:28:05 UTC 2017


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

bengen pushed a commit to annotated tag v3.3.0
in repository yara.

commit f002d922b630b3ca7873397b10a8a4ea26802c2a
Author: Victor M. Alvarez <plusvic at gmail.com>
Date:   Mon Sep 15 14:27:10 2014 +0200

    Implement "locale" function in PE module and improve buffer bounds checking
---
 libyara/modules/pe.c | 129 ++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 92 insertions(+), 37 deletions(-)

diff --git a/libyara/modules/pe.c b/libyara/modules/pe.c
index ac8df6c..1be0ae7 100644
--- a/libyara/modules/pe.c
+++ b/libyara/modules/pe.c
@@ -60,6 +60,14 @@ limitations under the License.
     ((entry)->OffsetToData & 0x7FFFFFFF)
 
 
+#define fits_in_pe(pe, pointer, size) \
+    ((uint8_t*)(pointer) + size <= pe->data + pe->data_size)
+
+
+#define struct_fits_in_pe(pe, pointer, struct_type) \
+    fits_in_pe(pe, pointer, sizeof(struct_type))
+
+
 typedef int (*RESOURCE_CALLBACK_FUNC) ( \
      PIMAGE_RESOURCE_DATA_ENTRY rsrc_data, \
      int rsrc_type, \
@@ -198,6 +206,9 @@ int _pe_iterate_resources(
 
   for (int i = 0; i < total_entries; i++)
   {
+    if (!struct_fits_in_pe(pe, entry, IMAGE_RESOURCE_DIRECTORY_ENTRY))
+      break;
+
     switch(rsrc_tree_level)
     {
       case 0:
@@ -213,31 +224,40 @@ int _pe_iterate_resources(
 
     if (IS_RESOURCE_SUBDIRECTORY(entry))
     {
-      result = _pe_iterate_resources(
-          pe,
-          (PIMAGE_RESOURCE_DIRECTORY)(rsrc_data + RESOURCE_OFFSET(entry)),
-          rsrc_data,
-          rsrc_tree_level + 1,
-          type,
-          id,
-          language,
-          callback,
-          callback_data);
+      PIMAGE_RESOURCE_DIRECTORY directory = (PIMAGE_RESOURCE_DIRECTORY) \
+          (rsrc_data + RESOURCE_OFFSET(entry));
 
-      if (result == RESOURCE_ITERATOR_ABORTED)
-        return RESOURCE_ITERATOR_ABORTED;
+      if (struct_fits_in_pe(pe, directory, IMAGE_RESOURCE_DIRECTORY))
+      {
+        result = _pe_iterate_resources(
+            pe,
+            directory,
+            rsrc_data,
+            rsrc_tree_level + 1,
+            type,
+            id,
+            language,
+            callback,
+            callback_data);
+
+        if (result == RESOURCE_ITERATOR_ABORTED)
+          return RESOURCE_ITERATOR_ABORTED;
+      }
     }
     else
     {
       PIMAGE_RESOURCE_DATA_ENTRY data_entry = (PIMAGE_RESOURCE_DATA_ENTRY) \
           (rsrc_data + RESOURCE_OFFSET(entry));
 
-      result = callback(
-          data_entry,
-          *type,
-          *id,
-          *language,
-          callback_data);
+      if (struct_fits_in_pe(pe, data_entry, IMAGE_RESOURCE_DATA_ENTRY))
+      {
+        result = callback(
+            data_entry,
+            *type,
+            *id,
+            *language,
+            callback_data);
+      }
 
       if (result == RESOURCE_CALLBACK_ABORT)
         return RESOURCE_ITERATOR_ABORTED;
@@ -272,8 +292,7 @@ int pe_iterate_resources(
     offset = pe_rva_to_offset(pe, directory->VirtualAddress);
 
     if (offset != 0 &&
-        offset < pe->data_size &&
-        directory->Size < pe->data_size - offset)
+        offset < pe->data_size)
     {
       _pe_iterate_resources(
           pe,
@@ -318,11 +337,23 @@ int pe_find_version_info_cb(
 
     version_info = (PVERSION_INFO) (pe->data + version_info_offset);
 
+    if (!struct_fits_in_pe(pe, version_info, VERSION_INFO))
+      return RESOURCE_CALLBACK_CONTINUE;
+
+    if (!fits_in_pe(pe, version_info, sizeof("VS_VERSION_INFO")))
+      return RESOURCE_CALLBACK_CONTINUE;
+
     if (strcmp_w(version_info->Key, "VS_VERSION_INFO") != 0)
       return RESOURCE_CALLBACK_CONTINUE;
 
     string_file_info = ADD_OFFSET(version_info, sizeof(VERSION_INFO) + 86);
 
+    if (!struct_fits_in_pe(pe, string_file_info, VERSION_INFO))
+      return RESOURCE_CALLBACK_CONTINUE;
+
+    if (!fits_in_pe(pe, string_file_info, sizeof("StringFileInfo")))
+      return RESOURCE_CALLBACK_CONTINUE;
+
     while(strcmp_w(string_file_info->Key, "StringFileInfo") == 0)
     {
       PVERSION_INFO string_table = ADD_OFFSET(
@@ -575,9 +606,6 @@ define_function(exports)
 }
 
 
-#define check_bounds(pointer, struct_type, limit) \
-    ((uint8_t*)(pointer) + sizeof(struct_type) <= limit)
-
 define_function(imports)
 {
   char* dll_name = string_argument(1);
@@ -593,7 +621,6 @@ define_function(imports)
   PIMAGE_THUNK_DATA32 thunks32;
   PIMAGE_THUNK_DATA64 thunks64;
 
-  uint8_t* pe_end;
   uint64_t offset;
 
   // if not a PE file, return UNDEFINED
@@ -601,8 +628,6 @@ define_function(imports)
   if (pe == NULL)
     return_integer(UNDEFINED);
 
-  pe_end = pe->data + pe->data_size;
-
   directory = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_IMPORT);
 
   if (directory->VirtualAddress == 0)
@@ -616,7 +641,7 @@ define_function(imports)
 
   imports = (PIMAGE_IMPORT_DESCRIPTOR)(pe->data + offset);
 
-  while (check_bounds(imports, IMAGE_IMPORT_DESCRIPTOR, pe_end) &&
+  while (struct_fits_in_pe(pe, imports, IMAGE_IMPORT_DESCRIPTOR) &&
          imports->Name != 0)
   {
     offset = pe_rva_to_offset(pe, imports->Name);
@@ -636,7 +661,7 @@ define_function(imports)
         {
           thunks64 = (PIMAGE_THUNK_DATA64)(pe->data + offset);
 
-          while (check_bounds(thunks64, IMAGE_THUNK_DATA64, pe_end) &&
+          while (struct_fits_in_pe(pe, thunks64, IMAGE_THUNK_DATA64) &&
                  thunks64->u1.Ordinal != 0)
           {
             if (!(thunks64->u1.Ordinal & IMAGE_ORDINAL_FLAG64))
@@ -649,7 +674,7 @@ define_function(imports)
               {
                 import = (PIMAGE_IMPORT_BY_NAME)(pe->data + offset);
 
-                if (pe_end - import->Name >= function_name_len)
+                if (fits_in_pe(pe, import->Name, function_name_len))
                 {
                   if (strncmp((char*) import->Name,
                               function_name,
@@ -668,7 +693,7 @@ define_function(imports)
         {
           thunks32 = (PIMAGE_THUNK_DATA32)(pe->data + offset);
 
-          while (check_bounds(thunks32, IMAGE_THUNK_DATA32, pe_end) &&
+          while (struct_fits_in_pe(pe, thunks32, sizeof(IMAGE_THUNK_DATA32)) &&
                  thunks32->u1.Ordinal != 0)
           {
             if (!(thunks32->u1.Ordinal & IMAGE_ORDINAL_FLAG32))
@@ -681,7 +706,7 @@ define_function(imports)
               {
                 import = (PIMAGE_IMPORT_BY_NAME)(pe->data + offset);
 
-                if (pe_end - import->Name >= function_name_len)
+                if (fits_in_pe(pe, import->Name, function_name_len))
                 {
                   if (strncmp((char*) import->Name,
                               function_name,
@@ -708,7 +733,9 @@ define_function(imports)
 
 typedef struct _FIND_LANGUAGE_CB_DATA
 {
-  uint64_t language;
+  uint64_t locale;
+  uint64_t mask;
+
   int found;
 
 } FIND_LANGUAGE_CB_DATA;
@@ -719,12 +746,9 @@ int pe_find_language_cb(
     int rsrc_type,
     int rsrc_id,
     int rsrc_language,
-    PIMAGE_NT_HEADERS32 pe_header,
-    size_t pe_size,
-    size_t pe_offset,
     FIND_LANGUAGE_CB_DATA* cb_data)
 {
-  if (rsrc_language == cb_data->language)
+  if ((rsrc_language & cb_data->mask) == cb_data->locale)
   {
     cb_data->found = TRUE;
     return RESOURCE_CALLBACK_ABORT;
@@ -734,11 +758,41 @@ int pe_find_language_cb(
 }
 
 
+define_function(locale)
+{
+  FIND_LANGUAGE_CB_DATA cb_data;
+
+  cb_data.locale = integer_argument(1);
+  cb_data.mask = 0xFFFF;
+  cb_data.found = FALSE;
+
+  YR_OBJECT* module = module();
+  PE* pe = (PE*) module->data;
+
+  // if not a PE file, return UNDEFINED
+
+  if (pe == NULL)
+    return_integer(UNDEFINED);
+
+  if (pe_iterate_resources(pe,
+          (RESOURCE_CALLBACK_FUNC) pe_find_language_cb,
+          (void*) &cb_data))
+  {
+    return_integer(cb_data.found);
+  }
+  else
+  {
+    return_integer(UNDEFINED);
+  }
+}
+
+
 define_function(language)
 {
   FIND_LANGUAGE_CB_DATA cb_data;
 
-  cb_data.language = integer_argument(1);
+  cb_data.locale = integer_argument(1);
+  cb_data.mask = 0xFF;
   cb_data.found = FALSE;
 
   YR_OBJECT* module = module();
@@ -834,6 +888,7 @@ begin_declarations;
   declare_function("section_index", "s", "i", section_index);
   declare_function("exports", "s", "i", exports);
   declare_function("imports", "ss", "i", imports);
+  declare_function("locale", "i", "i", locale);
   declare_function("language", "i", "i", language);
 
 end_declarations;

-- 
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