[Forensics-changes] [yara] 108/368: Properly handle negative serial numbers.

Hilko Bengen bengen at moszumanska.debian.org
Sat Jul 1 10:30:17 UTC 2017


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

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

commit be4b068905aea3186d80cc40440b5c12e97fada6
Author: Wesley Shields <wxs at atarininja.org>
Date:   Tue Nov 3 07:18:20 2015 -0500

    Properly handle negative serial numbers.
    
    Negative serial numbers are stored in an ASN1_INTEGER using two's
    complement. This meant that negative serials were not properly handled
    prior to this commit.
    
    To fix this always use i2c_ASN1_INTEGER() to convert a serial number to
    it's "character" representation. You have to call i2c_ASN1_INTEGER()
    twice. The first call needs to be with a NULL second argument, which
    will return the number of bytes needed to store the serial, you can then
    allocate a buffer and call i2c_ASN1_INTEGER() a second time to get the
    properly formatted serial number.
    
    In the interest of making the code easier to read I chose to do this
    even for positive ASN1_INTEGER structures.
    
    Negative serial numbers are against the RFC but they do exist. For
    example 4bfe05f182aa273e113db6ed7dae4bb8.
---
 libyara/modules/pe.c | 87 ++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 61 insertions(+), 26 deletions(-)

diff --git a/libyara/modules/pe.c b/libyara/modules/pe.c
index 69b6684..28aa20a 100644
--- a/libyara/modules/pe.c
+++ b/libyara/modules/pe.c
@@ -1182,6 +1182,7 @@ void pe_parse_certificates(
     {
       const char* sig_alg;
       char buffer[256];
+      int bytes;
 
       ASN1_INTEGER* serial;
 
@@ -1207,37 +1208,71 @@ void pe_parse_certificates(
       set_string(sig_alg, pe->object, "signatures[%i].algorithm", counter);
 
       serial = X509_get_serialNumber(cert);
-
-      // According to X.509 specification the maximum length for the serial
-      // number is 20 octets.
-
-      if (serial->length > 0 && serial->length <= 20)
+      if (serial)
       {
-        // Convert serial number to "common" string format: 00:01:02:03:04...
-        // For each byte in the integer to convert to hexlified format we
-        // need three bytes, two for the byte itself and one for colon. The
-        // last one doesn't have the colon, but the extra byte is used for the
-        // NULL terminator.
-
-        char* serial_number = (char *) yr_malloc(serial->length * 3);
-
-        if (serial_number != NULL)
+        // ASN1_INTEGER can be negative (serial->type & V_ASN1_NEG_INTEGER),
+        // in which case the serial number will be stored in 2's complement.
+        //
+        // Handle negative serial numbers, which are technically not allowed
+        // by RFC5280, but do exist. An example binary which has a negative
+        // serial number is: 4bfe05f182aa273e113db6ed7dae4bb8.
+        //
+        // Negative serial numbers are handled by calling i2c_ASN1_INTEGER()
+        // with a NULL second parameter. This will return the size of the
+        // buffer necessary to store the proper serial number.
+        //
+        // Do this even for positive serial numbers because it makes the code
+        // cleaner and easier to read.
+
+        bytes = i2c_ASN1_INTEGER(serial, NULL);
+
+        // According to X.509 specification the maximum length for the serial
+        // number is 20 octets.
+
+        if (bytes > 0 && bytes <= 20)
         {
-          int j;
+          // Now that we know the size of the serial number allocate enough
+          // space to hold it, and use i2c_ASN1_INTEGER() one last time to
+          // hold it in the allocated buffer.
+          unsigned char* serial_bytes = (unsigned char*)  yr_malloc(bytes);
 
-          for (j = 0; j < serial->length; j++)
+          if (serial_bytes != NULL)
           {
-            // Don't put the colon on the last one.
-            if (j < serial->length - 1)
-              snprintf(serial_number + 3 * j, 4, "%02x:", serial->data[j]);
-            else
-              snprintf(serial_number + 3 * j, 3, "%02x", serial->data[j]);
-          }
-
-          set_string(
-              serial_number, pe->object, "signatures[%i].serial", counter);
 
-          yr_free(serial_number);
+            bytes = i2c_ASN1_INTEGER(serial, &serial_bytes);
+
+            // i2c_ASN1_INTEGER() moves the pointer as it writes into
+            // serial_bytes. Move it back.
+            serial_bytes -= bytes;
+
+            // Also allocate space to hold the "common" string format:
+            // 00:01:02:03:04...
+            //
+            // For each byte in the serial to convert to hexlified format we
+            // need three bytes, two for the byte itself and one for colon.
+            // The last one doesn't have the colon, but the extra byte is used
+            // for the NULL terminator.
+            char *serial_ascii = (char*) yr_malloc(bytes * 3);
+            if (serial_ascii)
+            {
+
+              int j;
+              for (j = 0; j < bytes; j++)
+              {
+                // Don't put the colon on the last one.
+                if (j < bytes - 1)
+                  snprintf((char*) serial_ascii + 3 * j, 4, "%02x:", serial_bytes[j]);
+                else
+                  snprintf((char*) serial_ascii + 3 * j, 3, "%02x", serial_bytes[j]);
+              }
+
+              set_string(
+                  (char*) serial_ascii, pe->object,"signatures[%i].serial", counter);
+
+              yr_free(serial_ascii);
+            }
+            yr_free(serial_bytes);
+          }
         }
       }
 

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