[Forensics-changes] [yara] 171/407: Make not_before and not_after be integers.
Hilko Bengen
bengen at moszumanska.debian.org
Sat Jul 1 10:28:22 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 10d65548c01914cc337f45ab32dc78a70d229acd
Author: Wesley Shields <wxs at atarininja.org>
Date: Thu Oct 30 23:48:21 2014 -0400
Make not_before and not_after be integers.
I'm no longer storing the raw ASN1_TIME structures for later parsing, so
nuke everything related to that. This also means we can go back to returning
void for pe_parse_certificates.
ASN1_GetTimeT() is a cleaned up and slightly modified version from
http://stackoverflow.com/questions/10975542/asn1-time-conversion. It seems
to work well enough, but I suspect it will have some edge cases.
---
libyara/modules/pe.c | 266 +++++++++++----------------------------------------
1 file changed, 57 insertions(+), 209 deletions(-)
diff --git a/libyara/modules/pe.c b/libyara/modules/pe.c
index 94fd199..607b118 100644
--- a/libyara/modules/pe.c
+++ b/libyara/modules/pe.c
@@ -124,15 +124,6 @@ typedef struct _IMPORTED_FUNCTION
} IMPORTED_FUNCTION, *PIMPORTED_FUNCTION;
-typedef struct _X509_TIMESTAMPS
-{
- ASN1_TIME *not_before;
- ASN1_TIME *not_after;
- struct _X509_TIMESTAMPS *next;
-
-} X509_TIMESTAMPS, *PX509_TIMESTAMPS;
-
-
typedef struct _PE
{
uint8_t* data;
@@ -141,7 +132,6 @@ typedef struct _PE
PIMAGE_NT_HEADERS32 header;
YR_OBJECT* object;
IMPORTED_DLL* imported_dlls;
- PX509_TIMESTAMPS x509_timestamps;
} PE;
@@ -2362,13 +2352,54 @@ IMPORTED_DLL* pe_parse_imports(
}
#if defined(HAVE_LIBCRYPTO)
-PX509_TIMESTAMPS pe_parse_certificates(
+//
+// Taken from http://stackoverflow.com/questions/10975542/asn1-time-conversion
+// and cleaned up. Also uses timegm(3) instead of mktime(3).
+//
+static time_t ASN1_GetTimeT(
+ ASN1_TIME* time)
+{
+ struct tm t;
+ const char* str = (const char*) time->data;
+ size_t i = 0;
+
+ memset(&t, 0, sizeof(t));
+
+ if (time->type == V_ASN1_UTCTIME) /* two digit year */
+ {
+ t.tm_year = (str[i++] - '0') * 10;
+ t.tm_year += (str[i++] - '0');
+ if (t.tm_year < 70)
+ t.tm_year += 100;
+ }
+ else if (time->type == V_ASN1_GENERALIZEDTIME) /* four digit year */
+ {
+ t.tm_year = (str[i++] - '0') * 1000;
+ t.tm_year += (str[i++] - '0') * 100;
+ t.tm_year += (str[i++] - '0') * 10;
+ t.tm_year += (str[i++] - '0');
+ t.tm_year -= 1900;
+ }
+ t.tm_mon = (str[i++] - '0') * 10;
+ t.tm_mon += (str[i++] - '0') - 1; // -1 since January is 0 not 1.
+ t.tm_mday = (str[i++] - '0') * 10;
+ t.tm_mday += (str[i++] - '0');
+ t.tm_hour = (str[i++] - '0') * 10;
+ t.tm_hour += (str[i++] - '0');
+ t.tm_min = (str[i++] - '0') * 10;
+ t.tm_min += (str[i++] - '0');
+ t.tm_sec = (str[i++] - '0') * 10;
+ t.tm_sec += (str[i++] - '0');
+
+ /* Note: we did not adjust the time based on time zone information */
+ return timegm(&t);
+}
+
+void pe_parse_certificates(
PE* pe)
{
PIMAGE_DATA_DIRECTORY directory;
PWIN_CERTIFICATE win_cert;
- PX509_TIMESTAMPS head = NULL;
- PX509_TIMESTAMPS tail = NULL;
BIO *cert_bio = NULL;
PKCS7 *p7;
X509 *cert;
@@ -2378,7 +2409,7 @@ PX509_TIMESTAMPS pe_parse_certificates(
char *p;
const char *sig_alg;
ASN1_INTEGER *serial;
- ASN1_TIME *date_time;
+ time_t date_time;
STACK_OF(X509) *certs;
directory = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_SECURITY);
@@ -2386,7 +2417,7 @@ PX509_TIMESTAMPS pe_parse_certificates(
if (directory->VirtualAddress == 0 ||
directory->VirtualAddress + directory->Size > pe->data_size)
{
- return NULL;
+ return;
}
// Store the end of directory, making comparisons easier.
@@ -2471,21 +2502,10 @@ PX509_TIMESTAMPS pe_parse_certificates(
yr_free(p);
}
- // Store the ASN1_TIME structures in a list.
- PX509_TIMESTAMPS x509_timestamp = (PX509_TIMESTAMPS)
- yr_calloc(1, sizeof(X509_TIMESTAMPS));
- if (!x509_timestamp)
- break;
- if (head == NULL)
- head = x509_timestamp;
- if (tail != NULL)
- tail->next = x509_timestamp;
- tail = x509_timestamp;
-
- date_time = X509_get_notBefore(cert);
- x509_timestamp->not_before = date_time;
- date_time = X509_get_notAfter(cert);
- x509_timestamp->not_after = date_time;
+ date_time = ASN1_GetTimeT(X509_get_notBefore(cert));
+ set_integer(date_time, pe->object, "signatures[%i].not_before", counter);
+ date_time = ASN1_GetTimeT(X509_get_notAfter(cert));
+ set_integer(date_time, pe->object, "signatures[%i].not_after", counter);
counter++;
}
@@ -2502,13 +2522,7 @@ PX509_TIMESTAMPS pe_parse_certificates(
if (counter > 0)
counter--;
set_integer(counter, pe->object, "number_of_signatures");
- return head;
-}
-#else
-PX509_TIMESTAMPS pe_parse_certificates(
- PE* pe)
-{
- return NULL;
+ return;
}
#endif // defined(HAVE_LIBCRYPTO)
@@ -2630,159 +2644,6 @@ void pe_parse_header(
}
}
-#if defined(HAVE_LIBCRYPTO)
-// Given a string, see if any of the stored notBefore matches, exactly.
-define_function(not_before_string)
-{
- char *p;
- BIO* date_bio;
- X509_TIMESTAMPS* x509_timestamp;
- char* not_before = string_argument(1);
- YR_OBJECT* module = module();
- PE* pe = (PE*) module->data;
-
- x509_timestamp = pe->x509_timestamps;
- while (x509_timestamp)
- {
- date_bio = BIO_new(BIO_s_mem());
- if (!date_bio)
- break;
- ASN1_TIME_print(date_bio, x509_timestamp->not_before);
- // Use num_write to get the number of bytes available for reading.
- p = (char *) yr_malloc(date_bio->num_write + 1);
- if (!p)
- {
- BIO_set_close(date_bio, BIO_CLOSE);
- BIO_free(date_bio);
- break;
- }
- BIO_read(date_bio, p, date_bio->num_write);
- p[date_bio->num_write] = '\x0';
- BIO_set_close(date_bio, BIO_CLOSE);
- BIO_free(date_bio);
- if (strcasecmp(p, not_before) == 0)
- {
- yr_free(p);
- return_integer(1);
- }
- yr_free(p);
-
- x509_timestamp = x509_timestamp->next;
- }
-
- return_integer(0);
-}
-
-//
-// Given an integer argument return 1 if any of the stored notBefore values
-// come "after" it. For example, to find a binary with a notBefore in 2014
-// or later you can use 1388534400, which is Wed Jan 1 00:00:00 UTC 2014.
-//
-// Note that the comparison is inclusive. So if it is an exact match this
-// function will return 1. This is due to how X509_cmp_time() works. :(
-//
-// Looks like X509_cmp_time returns:
-// 0 on failure
-// 1 if the second argument is "before" the first.
-// A negative number if the second argument is "after" the first.
-// If the timestamps are identical -1 is returned.
-//
-define_function(not_before_integer)
-{
- X509_TIMESTAMPS* x509_timestamp;
- time_t time = (time_t) integer_argument(1);
- YR_OBJECT* module = module();
- PE* pe = (PE*) module->data;
- x509_timestamp = pe->x509_timestamps;
-
- while (x509_timestamp)
- {
- if (X509_cmp_time(x509_timestamp->not_before, &time) < 0)
- return_integer(1);
- x509_timestamp = x509_timestamp->next;
- }
-
- return_integer(0);
-}
-
-
-// Given a string, see if any of the stored notAfter matches, exactly.
-define_function(not_after_string)
-{
- char *p;
- BIO* date_bio;
- X509_TIMESTAMPS* x509_timestamp;
- char* not_after = string_argument(1);
- YR_OBJECT* module = module();
- PE* pe = (PE*) module->data;
-
- x509_timestamp = pe->x509_timestamps;
- while (x509_timestamp)
- {
- date_bio = BIO_new(BIO_s_mem());
- if (!date_bio)
- break;
- ASN1_TIME_print(date_bio, x509_timestamp->not_after);
- // Use num_write to get the number of bytes available for reading.
- p = (char *) yr_malloc(date_bio->num_write + 1);
- if (!p)
- {
- BIO_set_close(date_bio, BIO_CLOSE);
- BIO_free(date_bio);
- break;
- }
- BIO_read(date_bio, p, date_bio->num_write);
- p[date_bio->num_write] = '\x0';
- BIO_set_close(date_bio, BIO_CLOSE);
- BIO_free(date_bio);
- if (strcasecmp(p, not_after) == 0)
- {
- yr_free(p);
- return_integer(1);
- }
- yr_free(p);
-
- x509_timestamp = x509_timestamp->next;
- }
-
- return_integer(0);
-}
-
-
-//
-// Given an integer argument return 1 if any of the stored notAfter values
-// come "before" it. For example, to find a binary with a notAfter in 2014
-// or later you can use 1388534399, which is Tue, 31 Dec 2013 23:59:59 GMT.
-//
-// Note that the comparison is not inclusive. So if it is an exact match this
-// function will still return 0. This is due to how X509_cmp_time() works. :(
-//
-// Looks like X509_cmp_time returns:
-// 0 on failure
-// 1 if the second argument is "before" the first.
-// A negative number if the second argument is "after" the first.
-// If the timestamps are identical -1 is returned.
-//
-define_function(not_after_integer)
-{
- X509_TIMESTAMPS* x509_timestamp;
- time_t time = (time_t) integer_argument(1);
- YR_OBJECT* module = module();
- PE* pe = (PE*) module->data;
- x509_timestamp = pe->x509_timestamps;
-
- while (x509_timestamp)
- {
- if (X509_cmp_time(x509_timestamp->not_after, &time) == 1)
- return_integer(1);
- x509_timestamp = x509_timestamp->next;
- }
-
- return_integer(0);
-}
-
-#endif // defined(HAVE_LIBCRYPTO)
-
define_function(section_index)
{
YR_OBJECT* module = module();
@@ -3125,6 +2986,7 @@ define_function(language)
}
}
+
begin_declarations;
declare_integer("MACHINE_I386");
@@ -3222,10 +3084,8 @@ begin_declarations;
declare_integer("version");
declare_string("algorithm");
declare_string("serial");
- declare_function("not_before", "s", "i", not_before_string);
- declare_function("not_before", "i", "i", not_before_integer);
- declare_function("not_after", "s", "i", not_after_string);
- declare_function("not_after", "i", "i", not_after_integer);
+ declare_integer("not_before");
+ declare_integer("not_after");
end_struct_array("signatures");
declare_integer("number_of_signatures");
#endif
@@ -3355,7 +3215,9 @@ int module_load(
pe_parse_header(pe, block->base, context->flags);
pe_parse_rich_signature(pe);
- pe->x509_timestamps = pe_parse_certificates(pe);
+ #if defined(HAVE_LIBCRYPTO)
+ pe_parse_certificates(pe);
+ #endif
pe->imported_dlls = pe_parse_imports(pe);
@@ -3370,8 +3232,6 @@ int module_load(
int module_unload(YR_OBJECT* module_object)
{
- X509_TIMESTAMPS* x509_timestamp = NULL;
- X509_TIMESTAMPS* next_x509_timestamp = NULL;
IMPORTED_DLL* dll = NULL;
IMPORTED_DLL* next_dll = NULL;
IMPORTED_FUNCTION* func = NULL;
@@ -3400,18 +3260,6 @@ int module_unload(YR_OBJECT* module_object)
dll = next_dll;
}
- x509_timestamp = pe->x509_timestamps;
- while (x509_timestamp)
- {
- if (x509_timestamp->not_before)
- yr_free(x509_timestamp->not_before);
- if (x509_timestamp->not_after)
- yr_free(x509_timestamp->not_after);
- next_x509_timestamp = x509_timestamp->next;
- yr_free(x509_timestamp);
- x509_timestamp = next_x509_timestamp;
- }
-
yr_free(pe);
return ERROR_SUCCESS;
--
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