[Forensics-changes] [yara] 396/407: Merge pull request #228 with some improvements

Hilko Bengen bengen at moszumanska.debian.org
Sat Jul 1 10:28:48 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 b0d0494dc635e34ea7ad06530f0d156801cf3b50
Author: Victor M. Alvarez <plusvic at gmail.com>
Date:   Mon Feb 9 11:25:55 2015 +0100

    Merge pull request #228 with some improvements
---
 libyara/modules/pe.c | 312 ++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 257 insertions(+), 55 deletions(-)

diff --git a/libyara/modules/pe.c b/libyara/modules/pe.c
index f823715..385ec54 100644
--- a/libyara/modules/pe.c
+++ b/libyara/modules/pe.c
@@ -40,19 +40,28 @@ limitations under the License.
 
 #define MODULE_NAME pe
 
-#define RESOURCE_TYPE_CURSOR         1
-#define RESOURCE_TYPE_BITMAP         2
-#define RESOURCE_TYPE_ICON           3
-#define RESOURCE_TYPE_MENU           4
-#define RESOURCE_TYPE_DIALOG         5
-#define RESOURCE_TYPE_STRING         6
-#define RESOURCE_TYPE_FONTDIR        7
-#define RESOURCE_TYPE_FONT           8
-#define RESOURCE_TYPE_ACCELERATOR    9
-#define RESOURCE_TYPE_RCDATA         10
-#define RESOURCE_TYPE_MESSAGETABLE   11
-#define RESOURCE_TYPE_VERSION        16
-#define RESOURCE_TYPE_MANIFEST       24
+// http://msdn.microsoft.com/en-us/library/ms648009(v=vs.85).aspx
+#define RESOURCE_TYPE_CURSOR       1
+#define RESOURCE_TYPE_BITMAP       2
+#define RESOURCE_TYPE_ICON         3
+#define RESOURCE_TYPE_MENU         4
+#define RESOURCE_TYPE_DIALOG       5
+#define RESOURCE_TYPE_STRING       6
+#define RESOURCE_TYPE_FONTDIR      7
+#define RESOURCE_TYPE_FONT         8
+#define RESOURCE_TYPE_ACCELERATOR  9
+#define RESOURCE_TYPE_RCDATA       10
+#define RESOURCE_TYPE_MESSAGETABLE 11
+#define RESOURCE_TYPE_GROUP_CURSOR 12 // MAKEINTRESOURCE((ULONG_PTR)(RT_CURSOR) + 11)
+#define RESOURCE_TYPE_GROUP_ICON   14 // MAKEINTRESOURCE((ULONG_PTR)(RT_ICON) + 11)
+#define RESOURCE_TYPE_VERSION      16
+#define RESOURCE_TYPE_DLGINCLUDE   17
+#define RESOURCE_TYPE_PLUGPLAY     19
+#define RESOURCE_TYPE_VXD          20
+#define RESOURCE_TYPE_ANICURSOR    21
+#define RESOURCE_TYPE_ANIICON      22
+#define RESOURCE_TYPE_HTML         23
+#define RESOURCE_TYPE_MANIFEST     24
 
 
 #define RESOURCE_CALLBACK_CONTINUE   0
@@ -74,6 +83,10 @@ limitations under the License.
     ((entry)->OffsetToData & 0x7FFFFFFF)
 
 
+#define IS_64BITS_PE(pe) \
+    (pe->header64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+
+
 #define available_space(pe, pointer) \
     (pe->data + pe->data_size - (uint8_t*)(pointer))
 
@@ -91,6 +104,9 @@ typedef int (*RESOURCE_CALLBACK_FUNC) ( \
      int rsrc_type, \
      int rsrc_id, \
      int rsrc_language, \
+     uint8_t* type_string, \
+     uint8_t* name_string, \
+     uint8_t* lang_string, \
      void* cb_data);
 
 
@@ -123,7 +139,11 @@ typedef struct _PE
   uint8_t* data;
   size_t data_size;
 
-  PIMAGE_NT_HEADERS32 header;
+  union {
+    PIMAGE_NT_HEADERS32 header;
+    PIMAGE_NT_HEADERS64 header64;
+  };
+
   YR_OBJECT* object;
   IMPORTED_DLL* imported_dlls;
   uint32_t resources;
@@ -307,19 +327,15 @@ void pe_parse_rich_signature(
   return;
 }
 
+
 PIMAGE_DATA_DIRECTORY pe_get_directory_entry(
     PE* pe,
     int entry)
 {
   PIMAGE_DATA_DIRECTORY result;
 
-  // The first WORD in the OptionalHeader (32 or 64 bit) is a Magic value
-  // which determines the appropriate structure to use (PIMAGE_NT_HEADERS64
-  // or PIMAGE_NT_HEADERS32). As such, just cast pe->header to
-  // PIMAGE_NT_HEADERS64 and check the magic value, then cast accordingly.
-  if (((PIMAGE_NT_HEADERS64) pe->header)->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
-    result = &((PIMAGE_NT_HEADERS64) pe->header)->
-        OptionalHeader.DataDirectory[entry];
+  if (IS_64BITS_PE(pe))
+    result = &pe->header64->OptionalHeader.DataDirectory[entry];
   else
     result = &pe->header->OptionalHeader.DataDirectory[entry];
 
@@ -366,6 +382,42 @@ uint64_t pe_rva_to_offset(
 }
 
 
+// Return a pointer to the resource directory string or NULL.
+// The callback function will parse this and call set_sized_string().
+// The pointer is guranteed to have enough space to contain the entire string.
+
+uint8_t* parse_resource_name(
+    PE* pe,
+    uint8_t* rsrc_data,
+    PIMAGE_RESOURCE_DIRECTORY_ENTRY entry)
+{
+
+  // If high bit is set it is an offset relative to rsrc_data, which contains
+  // a resource directory string.
+
+  if (entry->Name & 0x80000000)
+  {
+    uint8_t* rsrc_str_ptr = rsrc_data + (entry->Name & 0x7FFFFFFF);
+
+    // A resource directory string is 2 bytes for a string and then a variable
+    // length Unicode string. Make sure we at least have two bytes.
+
+    if (!fits_in_pe(pe, rsrc_str_ptr, 2))
+      return NULL;
+
+    DWORD length = *rsrc_str_ptr;
+
+    // Move past the length and make sure we have enough bytes for the string.
+    if (!fits_in_pe(pe, rsrc_str_ptr + 2, length))
+      return NULL;
+
+    return rsrc_str_ptr;
+  }
+
+  return NULL;
+}
+
+
 int _pe_iterate_resources(
     PE* pe,
     PIMAGE_RESOURCE_DIRECTORY resource_dir,
@@ -374,6 +426,9 @@ int _pe_iterate_resources(
     int* type,
     int* id,
     int* language,
+    uint8_t* type_string,
+    uint8_t* name_string,
+    uint8_t* lang_string,
     RESOURCE_CALLBACK_FUNC callback,
     void* callback_data)
 {
@@ -408,12 +463,15 @@ int _pe_iterate_resources(
     {
       case 0:
         *type = entry->Name;
+        type_string = parse_resource_name(pe, rsrc_data, entry);
         break;
       case 1:
         *id = entry->Name;
+        name_string = parse_resource_name(pe, rsrc_data, entry);
         break;
       case 2:
         *language = entry->Name;
+        lang_string = parse_resource_name(pe, rsrc_data, entry);
         break;
     }
 
@@ -432,6 +490,9 @@ int _pe_iterate_resources(
             type,
             id,
             language,
+            type_string,
+            name_string,
+            lang_string,
             callback,
             callback_data);
 
@@ -451,6 +512,9 @@ int _pe_iterate_resources(
             *type,
             *id,
             *language,
+            type_string,
+            name_string,
+            lang_string,
             callback_data);
       }
 
@@ -478,6 +542,9 @@ int pe_iterate_resources(
   int type = -1;
   int id = -1;
   int language = -1;
+  uint8_t* type_string = NULL;
+  uint8_t* name_string = NULL;
+  uint8_t* lang_string = NULL;
 
   PIMAGE_DATA_DIRECTORY directory = pe_get_directory_entry(
       pe, IMAGE_DIRECTORY_ENTRY_RESOURCE);
@@ -494,16 +561,13 @@ int pe_iterate_resources(
 
       set_integer(rsrc_dir->TimeDateStamp,
                   pe->object,
-                  "resource_timestamp",
-                  pe->resources);
+                  "resource_timestamp");
       set_integer(rsrc_dir->MajorVersion,
                   pe->object,
-                  "resource_major_version",
-                  pe->resources);
+                  "resource_version.major");
       set_integer(rsrc_dir->MinorVersion,
                   pe->object,
-                  "resource_minor_version",
-                  pe->resources);
+                  "resource_version.minor");
       _pe_iterate_resources(
           pe,
           rsrc_dir,
@@ -512,6 +576,9 @@ int pe_iterate_resources(
           &type,
           &id,
           &language,
+          type_string,
+          name_string,
+          lang_string,
           callback,
           callback_data);
 
@@ -522,6 +589,7 @@ int pe_iterate_resources(
   return 0;
 }
 
+
 #ifdef __cplusplus
 #define typeof decltype
 #endif
@@ -619,8 +687,12 @@ int pe_collect_resources(
     int rsrc_type,
     int rsrc_id,
     int rsrc_language,
+    uint8_t* type_string,
+    uint8_t* name_string,
+    uint8_t* lang_string,
     PE* pe)
 {
+  DWORD length;
   size_t offset = pe_rva_to_offset(pe, rsrc_data->OffsetToData);
 
   if (offset == 0 || !fits_in_pe(pe, offset, rsrc_data->Size))
@@ -633,28 +705,64 @@ int pe_collect_resources(
         pe->resources);
 
   set_integer(
-        rsrc_type,
+        rsrc_data->Size,
         pe->object,
-        "resources[%i].type",
+        "resources[%i].length",
         pe->resources);
 
-  set_integer(
-        rsrc_id,
-        pe->object,
-        "resources[%i].id",
-        pe->resources);
+  if (type_string)
+  {
+    // Multiply by 2 because it is a Unicode string.
+    length = ((DWORD) *type_string) * 2;
+    type_string += 2;
+    set_sized_string(
+        (char*) type_string, length, pe->object,
+        "resources[%i].type_string", pe->resources);
+  }
+  else
+  {
+    set_integer(
+          rsrc_type,
+          pe->object,
+          "resources[%i].type",
+          pe->resources);
+  }
 
-  set_integer(
-        rsrc_language,
-        pe->object,
-        "resources[%i].language",
-        pe->resources);
+  if (name_string)
+  {
+    // Multiply by 2 because it is a Unicode string.
+    length = ((DWORD) *name_string) * 2;
+    name_string += 2;
+    set_sized_string(
+        (char*) name_string, length, pe->object,
+        "resources[%i].name_string", pe->resources);
+  }
+  else
+  {
+    set_integer(
+          rsrc_id,
+          pe->object,
+          "resources[%i].id",
+          pe->resources);
+  }
 
-  set_integer(
-        rsrc_data->Size,
-        pe->object,
-        "resources[%i].length",
-        pe->resources);
+  if (lang_string)
+  {
+    // Multiply by 2 because it is a Unicode string.
+    length = ((DWORD) *lang_string) * 2;
+    lang_string += 2;
+    set_sized_string(
+        (char*) lang_string, length, pe->object,
+        "resources[%i].language_string", pe->resources);
+  }
+  else
+  {
+    set_integer(
+          rsrc_language,
+          pe->object,
+          "resources[%i].language",
+          pe->resources);
+  }
 
   // Resources we do extra parsing on
   if (rsrc_type == RESOURCE_TYPE_VERSION)
@@ -678,13 +786,14 @@ IMPORTED_FUNCTION* pe_parse_import_descriptor(
 
   // I've seen binaries where OriginalFirstThunk is zero. In this case
   // use FirstThunk.
+
   if (offset == 0)
     offset = pe_rva_to_offset(pe, import_descriptor->FirstThunk);
 
   if (offset == 0)
     return NULL;
 
-  if (((PIMAGE_NT_HEADERS64) pe->header)->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+  if (IS_64BITS_PE(pe))
   {
     PIMAGE_THUNK_DATA64 thunks64 = (PIMAGE_THUNK_DATA64)(pe->data + offset);
 
@@ -820,6 +929,7 @@ int pe_valid_dll_name(
   return (l > 0 && l < n);
 }
 
+
 //
 // Walk the imports and collect relevant information. It is used in the
 // "imports" function for comparison and in the "imphash" function for
@@ -889,6 +999,7 @@ IMPORTED_DLL* pe_parse_imports(
   return head;
 }
 
+
 #if defined(HAVE_LIBCRYPTO)
 
 void pe_parse_certificates(
@@ -1052,9 +1163,9 @@ void pe_parse_header(
   char section_name[IMAGE_SIZEOF_SHORT_NAME + 1];
 
 #define OptionalHeader(field) \
-  (((PIMAGE_NT_HEADERS64) pe->header)->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC ? \
-   ((PIMAGE_NT_HEADERS64) pe->header)->OptionalHeader.field : \
-     pe->header->OptionalHeader.field)
+    (IS_64BITS_PE(pe) ? \
+        pe->header64->OptionalHeader.field : \
+        pe->header->OptionalHeader.field)
 
   set_integer(
       pe->header->FileHeader.Machine,
@@ -1565,6 +1676,28 @@ begin_declarations;
   declare_integer("SECTION_MEM_READ");
   declare_integer("SECTION_MEM_WRITE");
 
+  declare_integer("RESOURCE_TYPE_CURSOR");
+  declare_integer("RESOURCE_TYPE_BITMAP");
+  declare_integer("RESOURCE_TYPE_ICON");
+  declare_integer("RESOURCE_TYPE_MENU");
+  declare_integer("RESOURCE_TYPE_DIALOG");
+  declare_integer("RESOURCE_TYPE_STRING");
+  declare_integer("RESOURCE_TYPE_FONTDIR");
+  declare_integer("RESOURCE_TYPE_FONT");
+  declare_integer("RESOURCE_TYPE_ACCELERATOR");
+  declare_integer("RESOURCE_TYPE_RCDATA");
+  declare_integer("RESOURCE_TYPE_MESSAGETABLE");
+  declare_integer("RESOURCE_TYPE_GROUP_CURSOR");
+  declare_integer("RESOURCE_TYPE_GROUP_ICON");
+  declare_integer("RESOURCE_TYPE_VERSION");
+  declare_integer("RESOURCE_TYPE_DLGINCLUDE");
+  declare_integer("RESOURCE_TYPE_PLUGPLAY");
+  declare_integer("RESOURCE_TYPE_VXD");
+  declare_integer("RESOURCE_TYPE_ANICURSOR");
+  declare_integer("RESOURCE_TYPE_ANIICON");
+  declare_integer("RESOURCE_TYPE_HTML");
+  declare_integer("RESOURCE_TYPE_MANIFEST");
+
   declare_integer("machine");
   declare_integer("number_of_sections");
   declare_integer("timestamp");
@@ -1626,14 +1759,19 @@ begin_declarations;
   declare_function("language", "i", "i", language);
 
   declare_integer("resource_timestamp")
-  declare_integer("resource_major_version")
-  declare_integer("resource_minor_version")
+  begin_struct("resource_version");
+    declare_integer("major");
+    declare_integer("minor");
+  end_struct("resource_version");
   begin_struct_array("resources");
-    declare_integer("offset")
-    declare_integer("type")
-    declare_integer("id")
-    declare_integer("language")
-    declare_integer("length")
+    declare_integer("offset");
+    declare_integer("length");
+    declare_integer("type");
+    declare_integer("id");
+    declare_integer("language");
+    declare_string("type_string");
+    declare_string("name_string");
+    declare_string("language_string");
   end_struct_array("resources");
   declare_integer("number_of_resources");
 
@@ -1849,6 +1987,70 @@ int module_load(
       SECTION_MEM_WRITE, module_object,
       "SECTION_MEM_WRITE");
 
+  set_integer(
+      RESOURCE_TYPE_CURSOR, module_object,
+      "RESOURCE_TYPE_CURSOR");
+  set_integer(
+      RESOURCE_TYPE_BITMAP, module_object,
+      "RESOURCE_TYPE_BITMAP");
+  set_integer(
+      RESOURCE_TYPE_ICON, module_object,
+      "RESOURCE_TYPE_ICON");
+  set_integer(
+      RESOURCE_TYPE_MENU, module_object,
+      "RESOURCE_TYPE_MENU");
+  set_integer(
+      RESOURCE_TYPE_DIALOG, module_object,
+      "RESOURCE_TYPE_DIALOG");
+  set_integer(
+      RESOURCE_TYPE_STRING, module_object,
+      "RESOURCE_TYPE_STRING");
+  set_integer(
+      RESOURCE_TYPE_FONTDIR, module_object,
+      "RESOURCE_TYPE_FONTDIR");
+  set_integer(
+      RESOURCE_TYPE_FONT, module_object,
+      "RESOURCE_TYPE_FONT");
+  set_integer(
+      RESOURCE_TYPE_ACCELERATOR, module_object,
+      "RESOURCE_TYPE_ACCELERATOR");
+  set_integer(
+      RESOURCE_TYPE_RCDATA, module_object,
+      "RESOURCE_TYPE_RCDATA");
+  set_integer(
+      RESOURCE_TYPE_MESSAGETABLE, module_object,
+      "RESOURCE_TYPE_MESSAGETABLE");
+  set_integer(
+      RESOURCE_TYPE_GROUP_CURSOR, module_object,
+      "RESOURCE_TYPE_GROUP_CURSOR");
+  set_integer(
+      RESOURCE_TYPE_GROUP_ICON, module_object,
+      "RESOURCE_TYPE_GROUP_ICON");
+  set_integer(
+      RESOURCE_TYPE_VERSION, module_object,
+      "RESOURCE_TYPE_VERSION");
+  set_integer(
+      RESOURCE_TYPE_DLGINCLUDE, module_object,
+      "RESOURCE_TYPE_DLGINCLUDE");
+  set_integer(
+      RESOURCE_TYPE_PLUGPLAY, module_object,
+      "RESOURCE_TYPE_PLUGPLAY");
+  set_integer(
+      RESOURCE_TYPE_VXD, module_object,
+      "RESOURCE_TYPE_VXD");
+  set_integer(
+      RESOURCE_TYPE_ANICURSOR, module_object,
+      "RESOURCE_TYPE_ANICURSOR");
+  set_integer(
+      RESOURCE_TYPE_ANIICON, module_object,
+      "RESOURCE_TYPE_ANIICON");
+  set_integer(
+      RESOURCE_TYPE_HTML, module_object,
+      "RESOURCE_TYPE_HTML");
+  set_integer(
+      RESOURCE_TYPE_MANIFEST, module_object,
+      "RESOURCE_TYPE_MANIFEST");
+
   YR_MEMORY_BLOCK* block;
 
   foreach_memory_block(context, block)

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