[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