[Forensics-changes] [yara] 26/407: Start to implement rich_signature.

Hilko Bengen bengen at moszumanska.debian.org
Sat Jul 1 10:28:00 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 4a73f8b8fc366d184735e83bc0799c593438e1ae
Author: Wesley Shields <wxs at atarininja.org>
Date:   Sat Sep 13 23:11:34 2014 -0400

    Start to implement rich_signature.
---
 libyara/exec.c                 |  15 +
 libyara/grammar.c              | 622 ++++++++++++++++++++++-------------------
 libyara/grammar.y              |  16 ++
 libyara/include/yara/exec.h    |   1 +
 libyara/include/yara/modules.h |   6 +-
 libyara/include/yara/object.h  |   3 +-
 libyara/include/yara/pe.h      |  20 ++
 libyara/include/yara/types.h   |   2 +-
 libyara/modules/demo.c         |   2 +-
 libyara/modules/elf.c          |   4 +-
 libyara/modules/pe.c           | 224 ++++++++++++++-
 libyara/modules/tests.c        |  12 +-
 libyara/object.c               |  12 +-
 13 files changed, 613 insertions(+), 326 deletions(-)

diff --git a/libyara/exec.c b/libyara/exec.c
index 7728580..8bfc1cc 100644
--- a/libyara/exec.c
+++ b/libyara/exec.c
@@ -717,6 +717,21 @@ int yr_execute_code(
         push(result >= 0);
         break;
 
+      case OP_CONTAINS_STR:
+        pop(r2);
+        pop(r1);
+        SIZED_STRING *big = UINT64_TO_PTR(SIZED_STRING*, r1);
+        YR_STRING *little = UINT64_TO_PTR(YR_STRING*, r2);
+
+        if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2))
+        {
+          push(UNDEFINED);
+          break;
+        }
+
+        push(memmem(big->c_string, big->length, little->string, little->length) != NULL);
+        break;
+
       default:
         // Unknown instruction, this shouldn't happen.
         assert(FALSE);
diff --git a/libyara/grammar.c b/libyara/grammar.c
index bde75d0..0428881 100644
--- a/libyara/grammar.c
+++ b/libyara/grammar.c
@@ -514,16 +514,16 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  2
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   433
+#define YYLAST   490
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  74
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  35
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  115
+#define YYNRULES  116
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  216
+#define YYNSTATES  217
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
@@ -578,13 +578,13 @@ static const yytype_uint16 yyprhs[] =
       57,    59,    62,    64,    67,    71,    75,    79,    83,    85,
       88,    93,    94,   100,   104,   105,   108,   110,   112,   114,
      116,   118,   122,   127,   132,   133,   135,   139,   141,   143,
-     145,   147,   151,   155,   157,   161,   165,   166,   167,   179,
-     180,   190,   194,   197,   201,   205,   209,   213,   217,   221,
-     225,   229,   233,   235,   239,   243,   245,   252,   254,   258,
-     259,   264,   266,   268,   272,   274,   276,   278,   280,   282,
-     286,   288,   290,   295,   300,   305,   310,   315,   320,   322,
-     324,   326,   331,   333,   335,   339,   343,   347,   351,   355,
-     359,   363,   367,   370,   374,   378
+     145,   147,   151,   155,   159,   161,   165,   169,   170,   171,
+     183,   184,   194,   198,   201,   205,   209,   213,   217,   221,
+     225,   229,   233,   237,   239,   243,   247,   249,   256,   258,
+     262,   263,   268,   270,   272,   276,   278,   280,   282,   284,
+     286,   290,   292,   294,   299,   304,   309,   314,   319,   324,
+     326,   328,   330,   335,   337,   339,   343,   347,   351,   355,
+     359,   363,   367,   371,   374,   378,   382
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
@@ -605,29 +605,30 @@ static const yytype_int8 yyrhs[] =
        9,    -1,    92,    69,   108,    70,    -1,    92,    71,    93,
       72,    -1,    -1,    96,    -1,    93,    73,    96,    -1,    17,
       -1,    96,    -1,    40,    -1,    41,    -1,   108,    37,    94,
-      -1,   108,    38,   108,    -1,    10,    -1,    10,    22,   108,
-      -1,    10,    27,   101,    -1,    -1,    -1,    29,   107,     9,
-      27,    97,   100,    66,    98,    71,    95,    72,    -1,    -1,
-      29,   107,    28,   103,    66,    99,    71,    95,    72,    -1,
-     107,    28,   103,    -1,    61,    95,    -1,    95,    43,    95,
-      -1,    95,    42,    95,    -1,   108,    53,   108,    -1,   108,
-      51,   108,    -1,   108,    52,   108,    -1,   108,    50,   108,
-      -1,   108,    49,   108,    -1,   108,    47,   108,    -1,   108,
-      48,   108,    -1,   108,    -1,    71,    96,    72,    -1,    71,
-     102,    72,    -1,   101,    -1,    71,   108,    68,    68,   108,
-      72,    -1,   108,    -1,   102,    73,   108,    -1,    -1,    71,
-     104,   105,    72,    -1,    30,    -1,   106,    -1,   105,    73,
-     106,    -1,    10,    -1,    13,    -1,   108,    -1,    25,    -1,
-      26,    -1,    71,   108,    72,    -1,    23,    -1,    24,    -1,
-      31,    71,   108,    72,    -1,    32,    71,   108,    72,    -1,
-      33,    71,   108,    72,    -1,    34,    71,   108,    72,    -1,
-      35,    71,   108,    72,    -1,    36,    71,   108,    72,    -1,
-      14,    -1,    15,    -1,    11,    -1,    12,    69,   108,    70,
-      -1,    12,    -1,    92,    -1,   108,    56,   108,    -1,   108,
-      57,   108,    -1,   108,    58,   108,    -1,   108,    59,   108,
-      -1,   108,    60,   108,    -1,   108,    46,   108,    -1,   108,
-      44,   108,    -1,   108,    45,   108,    -1,    62,   108,    -1,
-     108,    55,   108,    -1,   108,    54,   108,    -1,    94,    -1
+      -1,   108,    38,   108,    -1,   108,    38,    10,    -1,    10,
+      -1,    10,    22,   108,    -1,    10,    27,   101,    -1,    -1,
+      -1,    29,   107,     9,    27,    97,   100,    66,    98,    71,
+      95,    72,    -1,    -1,    29,   107,    28,   103,    66,    99,
+      71,    95,    72,    -1,   107,    28,   103,    -1,    61,    95,
+      -1,    95,    43,    95,    -1,    95,    42,    95,    -1,   108,
+      53,   108,    -1,   108,    51,   108,    -1,   108,    52,   108,
+      -1,   108,    50,   108,    -1,   108,    49,   108,    -1,   108,
+      47,   108,    -1,   108,    48,   108,    -1,   108,    -1,    71,
+      96,    72,    -1,    71,   102,    72,    -1,   101,    -1,    71,
+     108,    68,    68,   108,    72,    -1,   108,    -1,   102,    73,
+     108,    -1,    -1,    71,   104,   105,    72,    -1,    30,    -1,
+     106,    -1,   105,    73,   106,    -1,    10,    -1,    13,    -1,
+     108,    -1,    25,    -1,    26,    -1,    71,   108,    72,    -1,
+      23,    -1,    24,    -1,    31,    71,   108,    72,    -1,    32,
+      71,   108,    72,    -1,    33,    71,   108,    72,    -1,    34,
+      71,   108,    72,    -1,    35,    71,   108,    72,    -1,    36,
+      71,   108,    72,    -1,    14,    -1,    15,    -1,    11,    -1,
+      12,    69,   108,    70,    -1,    12,    -1,    92,    -1,   108,
+      56,   108,    -1,   108,    57,   108,    -1,   108,    58,   108,
+      -1,   108,    59,   108,    -1,   108,    60,   108,    -1,   108,
+      46,   108,    -1,   108,    44,   108,    -1,   108,    45,   108,
+      -1,    62,   108,    -1,   108,    55,   108,    -1,   108,    54,
+     108,    -1,    94,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
@@ -638,13 +639,13 @@ static const yytype_uint16 yyrline[] =
      343,   356,   393,   394,   399,   415,   428,   441,   458,   459,
      464,   478,   477,   494,   511,   512,   517,   518,   519,   520,
      525,   613,   662,   712,   752,   755,   777,   810,   855,   872,
-     881,   890,   905,   919,   933,   949,   964,   999,   963,  1110,
-    1109,  1186,  1192,  1198,  1204,  1212,  1221,  1230,  1239,  1248,
-    1275,  1302,  1329,  1333,  1341,  1342,  1347,  1369,  1381,  1397,
-    1396,  1402,  1411,  1412,  1417,  1422,  1431,  1432,  1436,  1444,
-    1448,  1458,  1471,  1483,  1495,  1507,  1519,  1531,  1543,  1553,
-    1576,  1591,  1606,  1628,  1665,  1675,  1685,  1695,  1705,  1715,
-    1725,  1735,  1745,  1755,  1765,  1775
+     881,   890,   905,   919,   935,   949,   965,   980,  1015,   979,
+    1126,  1125,  1202,  1208,  1214,  1220,  1228,  1237,  1246,  1255,
+    1264,  1291,  1318,  1345,  1349,  1357,  1358,  1363,  1385,  1397,
+    1413,  1412,  1418,  1427,  1428,  1433,  1438,  1447,  1448,  1452,
+    1460,  1464,  1474,  1487,  1499,  1511,  1523,  1535,  1547,  1559,
+    1569,  1592,  1607,  1622,  1644,  1681,  1691,  1701,  1711,  1721,
+    1731,  1741,  1751,  1761,  1771,  1781,  1791
 };
 #endif
 
@@ -700,13 +701,13 @@ static const yytype_uint8 yyr1[] =
       84,    84,    85,    85,    86,    86,    86,    86,    87,    87,
       88,    89,    88,    88,    90,    90,    91,    91,    91,    91,
       92,    92,    92,    92,    93,    93,    93,    94,    95,    96,
-      96,    96,    96,    96,    96,    96,    97,    98,    96,    99,
-      96,    96,    96,    96,    96,    96,    96,    96,    96,    96,
-      96,    96,    96,    96,   100,   100,   101,   102,   102,   104,
-     103,   103,   105,   105,   106,   106,   107,   107,   107,   108,
+      96,    96,    96,    96,    96,    96,    96,    97,    98,    96,
+      99,    96,    96,    96,    96,    96,    96,    96,    96,    96,
+      96,    96,    96,    96,    96,   100,   100,   101,   102,   102,
+     104,   103,   103,   105,   105,   106,   106,   107,   107,   107,
      108,   108,   108,   108,   108,   108,   108,   108,   108,   108,
      108,   108,   108,   108,   108,   108,   108,   108,   108,   108,
-     108,   108,   108,   108,   108,   108
+     108,   108,   108,   108,   108,   108,   108
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -717,13 +718,13 @@ static const yytype_uint8 yyr2[] =
        1,     2,     1,     2,     3,     3,     3,     3,     1,     2,
        4,     0,     5,     3,     0,     2,     1,     1,     1,     1,
        1,     3,     4,     4,     0,     1,     3,     1,     1,     1,
-       1,     3,     3,     1,     3,     3,     0,     0,    11,     0,
-       9,     3,     2,     3,     3,     3,     3,     3,     3,     3,
-       3,     3,     1,     3,     3,     1,     6,     1,     3,     0,
-       4,     1,     1,     3,     1,     1,     1,     1,     1,     3,
-       1,     1,     4,     4,     4,     4,     4,     4,     1,     1,
-       1,     4,     1,     1,     3,     3,     3,     3,     3,     3,
-       3,     3,     2,     3,     3,     1
+       1,     3,     3,     3,     1,     3,     3,     0,     0,    11,
+       0,     9,     3,     2,     3,     3,     3,     3,     3,     3,
+       3,     3,     3,     1,     3,     3,     1,     6,     1,     3,
+       0,     4,     1,     1,     3,     1,     1,     1,     1,     1,
+       3,     1,     1,     4,     4,     4,     4,     4,     4,     1,
+       1,     1,     4,     1,     1,     3,     3,     3,     3,     3,
+       3,     3,     3,     2,     3,     3,     1
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -735,33 +736,33 @@ static const yytype_uint8 yydefact[] =
        7,     0,    16,    17,    15,    18,     0,     0,    20,    19,
        9,    21,     0,    11,     0,     0,     0,     0,    10,    22,
        0,     0,     0,     0,    23,     0,    12,    28,     0,     8,
-      25,    24,    26,    27,    31,    29,    40,    53,   100,   102,
-      98,    99,    47,    90,    91,    87,    88,     0,     0,     0,
-       0,     0,     0,     0,    49,    50,     0,     0,     0,   103,
-     115,    13,    48,     0,    72,    34,    33,     0,     0,     0,
-       0,     0,     0,    86,     0,     0,     0,     0,     0,     0,
-      62,   112,     0,    48,    72,     0,     0,    44,     0,     0,
+      25,    24,    26,    27,    31,    29,    40,    54,   101,   103,
+      99,   100,    47,    91,    92,    88,    89,     0,     0,     0,
+       0,     0,     0,     0,    49,    50,     0,     0,     0,   104,
+     116,    13,    48,     0,    73,    34,    33,     0,     0,     0,
+       0,     0,     0,    87,     0,     0,     0,     0,     0,     0,
+      63,   113,     0,    48,    73,     0,     0,    44,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-      30,    34,    54,     0,    55,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,    73,    89,    41,     0,     0,
-      45,    64,    63,    81,    79,    61,    51,    52,   110,   111,
-     109,    70,    71,    69,    68,    66,    67,    65,   114,   113,
-     104,   105,   106,   107,   108,    37,    36,    38,    39,    35,
-      32,     0,   101,    56,     0,    92,    93,    94,    95,    96,
-      97,    42,    43,     0,     0,     0,     0,    59,    46,    84,
-      85,     0,    82,     0,     0,     0,    75,     0,    80,     0,
-       0,     0,    77,    57,     0,    83,    76,    74,     0,     0,
-       0,    78,     0,    60,     0,    58
+      30,    34,    55,     0,    56,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    74,    90,    41,     0,     0,
+      45,    65,    64,    82,    80,    62,    51,    53,    52,   111,
+     112,   110,    71,    72,    70,    69,    67,    68,    66,   115,
+     114,   105,   106,   107,   108,   109,    37,    36,    38,    39,
+      35,    32,     0,   102,    57,     0,    93,    94,    95,    96,
+      97,    98,    42,    43,     0,     0,     0,     0,    60,    46,
+      85,    86,     0,    83,     0,     0,     0,    76,     0,    81,
+       0,     0,     0,    78,    58,     0,    84,    77,    75,     0,
+       0,     0,    79,     0,    61,     0,    59
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
       -1,     1,     5,     6,    23,    26,    32,     7,    14,    17,
-      19,    28,    29,    36,    37,    77,   120,   169,    69,   139,
-      70,    92,    72,   186,   209,   197,   195,   124,   201,   145,
-     184,   191,   192,    73,    74
+      19,    28,    29,    36,    37,    77,   120,   170,    69,   139,
+      70,    92,    72,   187,   210,   198,   196,   124,   202,   145,
+     185,   192,   193,    73,    74
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
@@ -771,88 +772,94 @@ static const yytype_int16 yypact[] =
 {
      -66,     6,   -66,   -59,     0,   -66,   -66,    59,   -66,   -66,
      -66,     9,   -66,   -66,   -66,   -44,    16,   -24,   -66,    49,
-      81,   -66,    26,    88,    92,    43,   115,    54,    92,   -66,
-     116,    63,    66,    -2,   -66,    75,   116,   -66,    79,   -66,
-     -66,   -66,   -66,   -66,    82,   -66,   -66,    -8,   -66,    83,
-     -66,   -66,   -66,   -66,   -66,   -66,   -66,   113,    72,    80,
-      84,    94,    96,    97,   -66,   -66,    79,   168,    79,   -42,
-     -66,    57,   -66,   125,   205,   -66,   -66,   137,   168,    98,
-     168,   168,    -7,   372,   168,   168,   168,   168,   168,   168,
-     -66,   -66,    57,   100,   169,   161,   168,    79,    79,    79,
-     -29,   156,   168,   168,   168,   168,   168,   168,   168,   168,
-     168,   168,   168,   168,   168,   168,   168,   168,   168,   168,
-      36,   -66,   372,   168,   -66,   338,   222,   149,   -29,   229,
-     251,   258,   280,   287,   309,   -66,   -66,   -66,   345,    34,
-      74,   135,   -66,   -66,   -66,   -66,   -66,   372,   104,   104,
-     104,   372,   372,   372,   372,   372,   372,   372,   -23,   -23,
-      25,    25,   -66,   -66,   -66,   -66,   -66,   -66,   -66,   -66,
-      36,   365,   -66,   -66,   120,   -66,   -66,   -66,   -66,   -66,
-     -66,   -66,   -66,    79,    -5,   119,   110,   -66,    74,   -66,
-     -66,    60,   -66,   168,   168,   122,   -66,   118,   -66,    -5,
-     316,    62,   365,   -66,    79,   -66,   -66,   -66,   168,   123,
-     -26,   372,    79,   -66,   -19,   -66
+      87,   -66,    30,    95,   101,    58,   119,    55,   101,   -66,
+     120,    68,    70,    -2,   -66,    69,   120,   -66,    80,   -66,
+     -66,   -66,   -66,   -66,    72,   -66,   -66,    -8,   -66,    74,
+     -66,   -66,   -66,   -66,   -66,   -66,   -66,   114,    73,    81,
+      82,    83,    84,    85,   -66,   -66,    80,   201,    80,   -42,
+     -66,    56,   -66,   138,   262,   -66,   -66,   151,   201,    98,
+     201,   201,    -7,   429,   201,   201,   201,   201,   201,   201,
+     -66,   -66,    56,    99,   229,   161,   201,    80,    80,    80,
+     -29,   156,   169,   201,   201,   201,   201,   201,   201,   201,
+     201,   201,   201,   201,   201,   201,   201,   201,   201,   201,
+      36,   -66,   429,   201,   -66,   395,   279,   147,   -29,   286,
+     308,   315,   337,   344,   366,   -66,   -66,   -66,   402,    28,
+      65,   134,   -66,   -66,   -66,   -66,   -66,   -66,   429,   105,
+     105,   105,   429,   429,   429,   429,   429,   429,   429,   -23,
+     -23,    25,    25,   -66,   -66,   -66,   -66,   -66,   -66,   -66,
+     -66,    36,   422,   -66,   -66,   116,   -66,   -66,   -66,   -66,
+     -66,   -66,   -66,   -66,    80,    -5,   121,   117,   -66,    65,
+     -66,   -66,    45,   -66,   201,   201,   124,   -66,   123,   -66,
+      -5,   373,    60,   422,   -66,    80,   -66,   -66,   -66,   201,
+     125,   -26,   429,    80,   -66,   -19,   -66
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-     -66,   -66,   -66,   187,   -66,   -66,   -66,   -66,   -66,   -66,
-     -66,   -66,   165,   -66,   159,   -66,    77,   -66,   -66,   -66,
-      95,   -38,   -65,   -66,   -66,   -66,   -66,    19,   -66,   103,
-     -66,   -66,    10,   151,   -37
+     -66,   -66,   -66,   184,   -66,   -66,   -66,   -66,   -66,   -66,
+     -66,   -66,   163,   -66,   159,   -66,    76,   -66,   -66,   -66,
+      97,   -38,   -65,   -66,   -66,   -66,   -66,    12,   -66,    78,
+     -66,   -66,     7,   152,   -37
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
    If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -87
+#define YYTABLE_NINF -88
 static const yytype_int16 yytable[] =
 {
-      71,   143,   127,    93,     8,   189,     2,     3,   190,   -14,
+      71,   143,   127,    93,     8,   190,     2,     3,   191,   -14,
      -14,   -14,    40,    41,    78,    10,    98,    99,    15,    79,
       83,   128,    16,    98,    99,    18,    95,    96,    90,    97,
       91,    94,   140,   115,   116,   117,   118,   119,    42,    43,
-      20,   122,   144,   125,   126,     4,   213,   129,   130,   131,
-     132,   133,   134,   215,   165,   166,   167,   168,    21,   138,
-     141,   142,    11,    12,    13,   147,   148,   149,   150,   151,
-     152,   153,   154,   155,   156,   157,   158,   159,   160,   161,
-     162,   163,   164,   117,   118,   119,   171,    22,    46,    47,
-      48,    49,    24,    50,    51,    25,    52,    75,    76,    98,
-      99,    27,    53,    54,    55,    56,   182,   183,    57,    30,
-      58,    59,    60,    61,    62,    63,   -48,   -48,   188,    64,
-      65,    33,    46,    31,    48,    49,    35,    50,    51,    38,
-      52,    39,   198,   199,   207,   208,    53,    54,    55,    56,
-      66,    67,    44,    84,    58,    59,    60,    61,    62,    63,
-      68,    85,    80,   100,   121,    86,   200,   202,   113,   114,
-     115,   116,   117,   118,   119,    87,   210,    88,    89,   123,
-     137,   211,   135,    52,   214,    67,   173,    46,    99,    48,
-      49,   194,    50,    51,    81,    52,   187,   193,   203,   204,
-       9,    53,    54,    34,   212,    45,   146,   -86,   170,    58,
-      59,    60,    61,    62,    63,   196,   101,   102,    82,   205,
-       0,     0,     0,   103,   104,   105,   106,   107,   108,   109,
+      20,   122,   144,   125,   126,     4,   214,   129,   130,   131,
+     132,   133,   134,   216,   166,   167,   168,   169,    21,   138,
+     141,   142,    11,    12,    13,   148,   149,   150,   151,   152,
+     153,   154,   155,   156,   157,   158,   159,   160,   161,   162,
+     163,   164,   165,   117,   118,   119,   172,    75,    76,    46,
+      47,    48,    49,    22,    50,    51,    24,    52,    98,    99,
+     183,   184,    25,    53,    54,    55,    56,   -48,   -48,    57,
+      27,    58,    59,    60,    61,    62,    63,   199,   200,   189,
+      64,    65,    33,    46,    30,    48,    49,    31,    50,    51,
+      35,    52,   208,   209,    38,    39,    44,    53,    54,    55,
+      56,    66,    67,    80,    84,    58,    59,    60,    61,    62,
+      63,    68,    85,    86,    87,    88,    89,   201,   203,   113,
+     114,   115,   116,   117,   118,   119,   100,   211,   121,   123,
+     137,   135,   212,    52,   174,   215,    67,    99,    46,   147,
+      48,    49,   188,    50,    51,    81,    52,     9,   195,   194,
+     204,    34,    53,    54,   205,    45,   213,   171,   146,   197,
+      58,    59,    60,    61,    62,    63,   175,   206,     0,    82,
+      46,     0,    48,    49,     0,    50,    51,     0,    52,     0,
+       0,     0,     0,     0,    53,    54,     0,     0,     0,     0,
+       0,    67,    58,    59,    60,    61,    62,    63,     0,     0,
+      81,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   -87,     0,     0,
+       0,     0,     0,    67,     0,     0,   101,   102,     0,     0,
+       0,     0,    81,   103,   104,   105,   106,   107,   108,   109,
      110,   111,   112,   113,   114,   115,   116,   117,   118,   119,
-      67,   174,     0,   -86,     0,     0,     0,     0,     0,    81,
-       0,   136,   101,   102,     0,     0,     0,     0,     0,   103,
-     104,   105,   106,   107,   108,   109,   110,   111,   112,   113,
-     114,   115,   116,   117,   118,   119,   103,   104,   105,     0,
-       0,     0,     0,   103,   104,   105,   113,   114,   115,   116,
-     117,   118,   119,   113,   114,   115,   116,   117,   118,   119,
-       0,     0,     0,     0,   136,   103,   104,   105,     0,     0,
-       0,   175,   103,   104,   105,   113,   114,   115,   116,   117,
-     118,   119,   113,   114,   115,   116,   117,   118,   119,     0,
-       0,     0,     0,   176,   103,   104,   105,     0,     0,     0,
-     177,   103,   104,   105,   113,   114,   115,   116,   117,   118,
-     119,   113,   114,   115,   116,   117,   118,   119,     0,     0,
-       0,     0,   178,   103,   104,   105,     0,     0,     0,   179,
+     -87,     0,     0,     0,     0,     0,     0,     0,     0,   101,
+     102,   136,     0,     0,     0,     0,   103,   104,   105,   106,
+     107,   108,   109,   110,   111,   112,   113,   114,   115,   116,
+     117,   118,   119,   103,   104,   105,     0,     0,     0,     0,
      103,   104,   105,   113,   114,   115,   116,   117,   118,   119,
      113,   114,   115,   116,   117,   118,   119,     0,     0,     0,
-       0,   180,   103,   104,   105,     0,     0,     0,   206,   103,
+       0,   136,   103,   104,   105,     0,     0,     0,   176,   103,
      104,   105,   113,   114,   115,   116,   117,   118,   119,   113,
-     114,   115,   116,   117,   118,   119,     0,     0,   172,   103,
-     104,   105,     0,     0,     0,   181,   103,   104,   105,   113,
+     114,   115,   116,   117,   118,   119,     0,     0,     0,     0,
+     177,   103,   104,   105,     0,     0,     0,   178,   103,   104,
+     105,   113,   114,   115,   116,   117,   118,   119,   113,   114,
+     115,   116,   117,   118,   119,     0,     0,     0,     0,   179,
+     103,   104,   105,     0,     0,     0,   180,   103,   104,   105,
+     113,   114,   115,   116,   117,   118,   119,   113,   114,   115,
+     116,   117,   118,   119,     0,     0,     0,     0,   181,   103,
+     104,   105,     0,     0,     0,   207,   103,   104,   105,   113,
      114,   115,   116,   117,   118,   119,   113,   114,   115,   116,
-     117,   118,   119,   185
+     117,   118,   119,     0,     0,   173,   103,   104,   105,     0,
+       0,     0,   182,   103,   104,   105,   113,   114,   115,   116,
+     117,   118,   119,   113,   114,   115,   116,   117,   118,   119,
+     186
 };
 
 static const yytype_int16 yycheck[] =
@@ -865,42 +872,48 @@ static const yytype_int16 yycheck[] =
       87,    88,    89,    72,    18,    19,    20,    21,     9,    96,
       98,    99,     3,     4,     5,   102,   103,   104,   105,   106,
      107,   108,   109,   110,   111,   112,   113,   114,   115,   116,
-     117,   118,   119,    58,    59,    60,   123,     6,     9,    10,
-      11,    12,    66,    14,    15,     7,    17,    15,    16,    42,
-      43,     9,    23,    24,    25,    26,    72,    73,    29,    66,
-      31,    32,    33,    34,    35,    36,    42,    43,   183,    40,
-      41,    67,     9,     8,    11,    12,    10,    14,    15,    66,
-      17,    65,    72,    73,    72,    73,    23,    24,    25,    26,
-      61,    62,    67,    71,    31,    32,    33,    34,    35,    36,
-      71,    71,    69,    28,    17,    71,   193,   194,    54,    55,
-      56,    57,    58,    59,    60,    71,   204,    71,    71,    71,
-       9,   208,    72,    17,   212,    62,    27,     9,    43,    11,
-      12,    71,    14,    15,    71,    17,    66,    68,    66,    71,
-       3,    23,    24,    28,    71,    36,   101,    28,   121,    31,
-      32,    33,    34,    35,    36,   186,    37,    38,    57,   199,
-      -1,    -1,    -1,    44,    45,    46,    47,    48,    49,    50,
+     117,   118,   119,    58,    59,    60,   123,    15,    16,     9,
+      10,    11,    12,     6,    14,    15,    66,    17,    42,    43,
+      72,    73,     7,    23,    24,    25,    26,    42,    43,    29,
+       9,    31,    32,    33,    34,    35,    36,    72,    73,   184,
+      40,    41,    67,     9,    66,    11,    12,     8,    14,    15,
+      10,    17,    72,    73,    66,    65,    67,    23,    24,    25,
+      26,    61,    62,    69,    71,    31,    32,    33,    34,    35,
+      36,    71,    71,    71,    71,    71,    71,   194,   195,    54,
+      55,    56,    57,    58,    59,    60,    28,   205,    17,    71,
+       9,    72,   209,    17,    27,   213,    62,    43,     9,    10,
+      11,    12,    66,    14,    15,    71,    17,     3,    71,    68,
+      66,    28,    23,    24,    71,    36,    71,   121,   101,   187,
+      31,    32,    33,    34,    35,    36,   128,   200,    -1,    57,
+       9,    -1,    11,    12,    -1,    14,    15,    -1,    17,    -1,
+      -1,    -1,    -1,    -1,    23,    24,    -1,    -1,    -1,    -1,
+      -1,    62,    31,    32,    33,    34,    35,    36,    -1,    -1,
+      71,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    28,    -1,    -1,
+      -1,    -1,    -1,    62,    -1,    -1,    37,    38,    -1,    -1,
+      -1,    -1,    71,    44,    45,    46,    47,    48,    49,    50,
       51,    52,    53,    54,    55,    56,    57,    58,    59,    60,
-      62,   128,    -1,    28,    -1,    -1,    -1,    -1,    -1,    71,
-      -1,    72,    37,    38,    -1,    -1,    -1,    -1,    -1,    44,
-      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    57,    58,    59,    60,    44,    45,    46,    -1,
-      -1,    -1,    -1,    44,    45,    46,    54,    55,    56,    57,
-      58,    59,    60,    54,    55,    56,    57,    58,    59,    60,
-      -1,    -1,    -1,    -1,    72,    44,    45,    46,    -1,    -1,
-      -1,    72,    44,    45,    46,    54,    55,    56,    57,    58,
-      59,    60,    54,    55,    56,    57,    58,    59,    60,    -1,
-      -1,    -1,    -1,    72,    44,    45,    46,    -1,    -1,    -1,
-      72,    44,    45,    46,    54,    55,    56,    57,    58,    59,
-      60,    54,    55,    56,    57,    58,    59,    60,    -1,    -1,
-      -1,    -1,    72,    44,    45,    46,    -1,    -1,    -1,    72,
+      28,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    37,
+      38,    72,    -1,    -1,    -1,    -1,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    44,    45,    46,    -1,    -1,    -1,    -1,
       44,    45,    46,    54,    55,    56,    57,    58,    59,    60,
       54,    55,    56,    57,    58,    59,    60,    -1,    -1,    -1,
       -1,    72,    44,    45,    46,    -1,    -1,    -1,    72,    44,
       45,    46,    54,    55,    56,    57,    58,    59,    60,    54,
-      55,    56,    57,    58,    59,    60,    -1,    -1,    70,    44,
-      45,    46,    -1,    -1,    -1,    70,    44,    45,    46,    54,
+      55,    56,    57,    58,    59,    60,    -1,    -1,    -1,    -1,
+      72,    44,    45,    46,    -1,    -1,    -1,    72,    44,    45,
+      46,    54,    55,    56,    57,    58,    59,    60,    54,    55,
+      56,    57,    58,    59,    60,    -1,    -1,    -1,    -1,    72,
+      44,    45,    46,    -1,    -1,    -1,    72,    44,    45,    46,
+      54,    55,    56,    57,    58,    59,    60,    54,    55,    56,
+      57,    58,    59,    60,    -1,    -1,    -1,    -1,    72,    44,
+      45,    46,    -1,    -1,    -1,    72,    44,    45,    46,    54,
       55,    56,    57,    58,    59,    60,    54,    55,    56,    57,
-      58,    59,    60,    68
+      58,    59,    60,    -1,    -1,    70,    44,    45,    46,    -1,
+      -1,    -1,    70,    44,    45,    46,    54,    55,    56,    57,
+      58,    59,    60,    54,    55,    56,    57,    58,    59,    60,
+      68
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -921,14 +934,14 @@ static const yytype_uint8 yystos[] =
       51,    52,    53,    54,    55,    56,    57,    58,    59,    60,
       90,    17,   108,    71,   101,   108,   108,     9,    28,   108,
      108,   108,   108,   108,   108,    72,    72,     9,   108,    93,
-      96,    95,    95,    30,    71,   103,    94,   108,   108,   108,
+      96,    95,    95,    30,    71,   103,    94,    10,   108,   108,
      108,   108,   108,   108,   108,   108,   108,   108,   108,   108,
-     108,   108,   108,   108,   108,    18,    19,    20,    21,    91,
-      90,   108,    70,    27,   103,    72,    72,    72,    72,    72,
-      72,    70,    72,    73,   104,    68,    97,    66,    96,    10,
-      13,   105,   106,    68,    71,   100,   101,    99,    72,    73,
-     108,   102,   108,    66,    71,   106,    72,    72,    73,    98,
-      95,   108,    71,    72,    95,    72
+     108,   108,   108,   108,   108,   108,    18,    19,    20,    21,
+      91,    90,   108,    70,    27,   103,    72,    72,    72,    72,
+      72,    72,    70,    72,    73,   104,    68,    97,    66,    96,
+      10,    13,   105,   106,    68,    71,   100,   101,    99,    72,
+      73,   108,   102,   108,    66,    71,   106,    72,    72,    73,
+      98,    95,   108,    71,    72,    95,    72
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -1451,42 +1464,42 @@ yydestruct (yymsg, yytype, yyvaluep, yyscanner, compiler)
       case 9: /* "_IDENTIFIER_" */
 #line 178 "grammar.y"
 	{ yr_free((yyvaluep->c_string)); };
-#line 1455 "grammar.c"
+#line 1468 "grammar.c"
 	break;
       case 10: /* "_STRING_IDENTIFIER_" */
 #line 179 "grammar.y"
 	{ yr_free((yyvaluep->c_string)); };
-#line 1460 "grammar.c"
+#line 1473 "grammar.c"
 	break;
       case 11: /* "_STRING_COUNT_" */
 #line 180 "grammar.y"
 	{ yr_free((yyvaluep->c_string)); };
-#line 1465 "grammar.c"
+#line 1478 "grammar.c"
 	break;
       case 12: /* "_STRING_OFFSET_" */
 #line 181 "grammar.y"
 	{ yr_free((yyvaluep->c_string)); };
-#line 1470 "grammar.c"
+#line 1483 "grammar.c"
 	break;
       case 13: /* "_STRING_IDENTIFIER_WITH_WILDCARD_" */
 #line 182 "grammar.y"
 	{ yr_free((yyvaluep->c_string)); };
-#line 1475 "grammar.c"
+#line 1488 "grammar.c"
 	break;
       case 15: /* "_TEXT_STRING_" */
 #line 183 "grammar.y"
 	{ yr_free((yyvaluep->sized_string)); };
-#line 1480 "grammar.c"
+#line 1493 "grammar.c"
 	break;
       case 16: /* "_HEX_STRING_" */
 #line 184 "grammar.y"
 	{ yr_free((yyvaluep->sized_string)); };
-#line 1485 "grammar.c"
+#line 1498 "grammar.c"
 	break;
       case 17: /* "_REGEXP_" */
 #line 185 "grammar.y"
 	{ yr_free((yyvaluep->sized_string)); };
-#line 1490 "grammar.c"
+#line 1503 "grammar.c"
 	break;
 
       default:
@@ -2578,6 +2591,25 @@ yyreduce:
   case 53:
 #line 920 "grammar.y"
     {
+        CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_STRING, "contains");
+
+        int result = yr_parser_reduce_string_identifier(
+            yyscanner,
+            (yyvsp[(3) - (3)].c_string),
+            OP_CONTAINS_STR,
+            UNDEFINED); // XXX: UNDEFINED?
+
+        yr_free((yyvsp[(3) - (3)].c_string));
+
+        ERROR_IF(result != ERROR_SUCCESS);
+
+        (yyval.expression).type = EXPRESSION_TYPE_BOOLEAN;
+      }
+    break;
+
+  case 54:
+#line 936 "grammar.y"
+    {
         int result = yr_parser_reduce_string_identifier(
             yyscanner,
             (yyvsp[(1) - (1)].c_string),
@@ -2592,8 +2624,8 @@ yyreduce:
       }
     break;
 
-  case 54:
-#line 934 "grammar.y"
+  case 55:
+#line 950 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "at");
 
@@ -2611,8 +2643,8 @@ yyreduce:
       }
     break;
 
-  case 55:
-#line 950 "grammar.y"
+  case 56:
+#line 966 "grammar.y"
     {
         compiler->last_result = yr_parser_reduce_string_identifier(
             yyscanner,
@@ -2628,8 +2660,8 @@ yyreduce:
       }
     break;
 
-  case 56:
-#line 964 "grammar.y"
+  case 57:
+#line 980 "grammar.y"
     {
         int var_index;
 
@@ -2666,8 +2698,8 @@ yyreduce:
       }
     break;
 
-  case 57:
-#line 999 "grammar.y"
+  case 58:
+#line 1015 "grammar.y"
     {
         int mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
         int8_t* addr;
@@ -2704,8 +2736,8 @@ yyreduce:
       }
     break;
 
-  case 58:
-#line 1034 "grammar.y"
+  case 59:
+#line 1050 "grammar.y"
     {
         int mem_offset;
 
@@ -2783,8 +2815,8 @@ yyreduce:
       }
     break;
 
-  case 59:
-#line 1110 "grammar.y"
+  case 60:
+#line 1126 "grammar.y"
     {
         int mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
         int8_t* addr;
@@ -2816,8 +2848,8 @@ yyreduce:
       }
     break;
 
-  case 60:
-#line 1140 "grammar.y"
+  case 61:
+#line 1156 "grammar.y"
     {
         int mem_offset;
 
@@ -2866,8 +2898,8 @@ yyreduce:
       }
     break;
 
-  case 61:
-#line 1187 "grammar.y"
+  case 62:
+#line 1203 "grammar.y"
     {
         yr_parser_emit(yyscanner, OP_OF, NULL);
 
@@ -2875,8 +2907,8 @@ yyreduce:
       }
     break;
 
-  case 62:
-#line 1193 "grammar.y"
+  case 63:
+#line 1209 "grammar.y"
     {
         yr_parser_emit(yyscanner, OP_NOT, NULL);
 
@@ -2884,8 +2916,8 @@ yyreduce:
       }
     break;
 
-  case 63:
-#line 1199 "grammar.y"
+  case 64:
+#line 1215 "grammar.y"
     {
         yr_parser_emit(yyscanner, OP_AND, NULL);
 
@@ -2893,8 +2925,8 @@ yyreduce:
       }
     break;
 
-  case 64:
-#line 1205 "grammar.y"
+  case 65:
+#line 1221 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_BOOLEAN, "or");
 
@@ -2904,8 +2936,8 @@ yyreduce:
       }
     break;
 
-  case 65:
-#line 1213 "grammar.y"
+  case 66:
+#line 1229 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "<");
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "<");
@@ -2916,8 +2948,8 @@ yyreduce:
       }
     break;
 
-  case 66:
-#line 1222 "grammar.y"
+  case 67:
+#line 1238 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, ">");
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, ">");
@@ -2928,8 +2960,8 @@ yyreduce:
       }
     break;
 
-  case 67:
-#line 1231 "grammar.y"
+  case 68:
+#line 1247 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "<=");
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "<=");
@@ -2940,8 +2972,8 @@ yyreduce:
       }
     break;
 
-  case 68:
-#line 1240 "grammar.y"
+  case 69:
+#line 1256 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, ">=");
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, ">=");
@@ -2952,8 +2984,8 @@ yyreduce:
       }
     break;
 
-  case 69:
-#line 1249 "grammar.y"
+  case 70:
+#line 1265 "grammar.y"
     {
         if ((yyvsp[(1) - (3)].expression).type != (yyvsp[(3) - (3)].expression).type)
         {
@@ -2982,8 +3014,8 @@ yyreduce:
       }
     break;
 
-  case 70:
-#line 1276 "grammar.y"
+  case 71:
+#line 1292 "grammar.y"
     {
         if ((yyvsp[(1) - (3)].expression).type != (yyvsp[(3) - (3)].expression).type)
         {
@@ -3012,8 +3044,8 @@ yyreduce:
       }
     break;
 
-  case 71:
-#line 1303 "grammar.y"
+  case 72:
+#line 1319 "grammar.y"
     {
         if ((yyvsp[(1) - (3)].expression).type != (yyvsp[(3) - (3)].expression).type)
         {
@@ -3042,32 +3074,32 @@ yyreduce:
       }
     break;
 
-  case 72:
-#line 1330 "grammar.y"
+  case 73:
+#line 1346 "grammar.y"
     {
         (yyval.expression) = (yyvsp[(1) - (1)].expression);
       }
     break;
 
-  case 73:
-#line 1334 "grammar.y"
+  case 74:
+#line 1350 "grammar.y"
     {
         (yyval.expression) = (yyvsp[(2) - (3)].expression);
       }
     break;
 
-  case 74:
-#line 1341 "grammar.y"
+  case 75:
+#line 1357 "grammar.y"
     { (yyval.integer) = INTEGER_SET_ENUMERATION; }
     break;
 
-  case 75:
-#line 1342 "grammar.y"
+  case 76:
+#line 1358 "grammar.y"
     { (yyval.integer) = INTEGER_SET_RANGE; }
     break;
 
-  case 76:
-#line 1348 "grammar.y"
+  case 77:
+#line 1364 "grammar.y"
     {
         if ((yyvsp[(2) - (6)].expression).type != EXPRESSION_TYPE_INTEGER)
         {
@@ -3087,8 +3119,8 @@ yyreduce:
       }
     break;
 
-  case 77:
-#line 1370 "grammar.y"
+  case 78:
+#line 1386 "grammar.y"
     {
         if ((yyvsp[(1) - (1)].expression).type != EXPRESSION_TYPE_INTEGER)
         {
@@ -3102,8 +3134,8 @@ yyreduce:
       }
     break;
 
-  case 78:
-#line 1382 "grammar.y"
+  case 79:
+#line 1398 "grammar.y"
     {
         if ((yyvsp[(3) - (3)].expression).type != EXPRESSION_TYPE_INTEGER)
         {
@@ -3116,61 +3148,61 @@ yyreduce:
       }
     break;
 
-  case 79:
-#line 1397 "grammar.y"
+  case 80:
+#line 1413 "grammar.y"
     {
         // Push end-of-list marker
         yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
       }
     break;
 
-  case 81:
-#line 1403 "grammar.y"
+  case 82:
+#line 1419 "grammar.y"
     {
         yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
         yr_parser_emit_pushes_for_strings(yyscanner, "$*");
       }
     break;
 
-  case 84:
-#line 1418 "grammar.y"
+  case 85:
+#line 1434 "grammar.y"
     {
         yr_parser_emit_pushes_for_strings(yyscanner, (yyvsp[(1) - (1)].c_string));
         yr_free((yyvsp[(1) - (1)].c_string));
       }
     break;
 
-  case 85:
-#line 1423 "grammar.y"
+  case 86:
+#line 1439 "grammar.y"
     {
         yr_parser_emit_pushes_for_strings(yyscanner, (yyvsp[(1) - (1)].c_string));
         yr_free((yyvsp[(1) - (1)].c_string));
       }
     break;
 
-  case 87:
-#line 1433 "grammar.y"
+  case 88:
+#line 1449 "grammar.y"
     {
         yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
       }
     break;
 
-  case 88:
-#line 1437 "grammar.y"
+  case 89:
+#line 1453 "grammar.y"
     {
         yr_parser_emit_with_arg(yyscanner, OP_PUSH, 1, NULL);
       }
     break;
 
-  case 89:
-#line 1445 "grammar.y"
+  case 90:
+#line 1461 "grammar.y"
     {
         (yyval.expression) = (yyvsp[(2) - (3)].expression);
       }
     break;
 
-  case 90:
-#line 1449 "grammar.y"
+  case 91:
+#line 1465 "grammar.y"
     {
         compiler->last_result = yr_parser_emit(
             yyscanner, OP_FILESIZE, NULL);
@@ -3182,8 +3214,8 @@ yyreduce:
       }
     break;
 
-  case 91:
-#line 1459 "grammar.y"
+  case 92:
+#line 1475 "grammar.y"
     {
         yywarning(yyscanner,
             "Using deprecated \"entrypoint\" keyword. Use the \"entry_point\" " "function from PE module instead.");
@@ -3198,8 +3230,8 @@ yyreduce:
       }
     break;
 
-  case 92:
-#line 1472 "grammar.y"
+  case 93:
+#line 1488 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(3) - (4)].expression), EXPRESSION_TYPE_INTEGER, "int8");
 
@@ -3213,8 +3245,8 @@ yyreduce:
       }
     break;
 
-  case 93:
-#line 1484 "grammar.y"
+  case 94:
+#line 1500 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(3) - (4)].expression), EXPRESSION_TYPE_INTEGER, "int16");
 
@@ -3228,8 +3260,8 @@ yyreduce:
       }
     break;
 
-  case 94:
-#line 1496 "grammar.y"
+  case 95:
+#line 1512 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(3) - (4)].expression), EXPRESSION_TYPE_INTEGER, "int32");
 
@@ -3243,8 +3275,8 @@ yyreduce:
       }
     break;
 
-  case 95:
-#line 1508 "grammar.y"
+  case 96:
+#line 1524 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(3) - (4)].expression), EXPRESSION_TYPE_INTEGER, "uint8");
 
@@ -3258,8 +3290,8 @@ yyreduce:
       }
     break;
 
-  case 96:
-#line 1520 "grammar.y"
+  case 97:
+#line 1536 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(3) - (4)].expression), EXPRESSION_TYPE_INTEGER, "uint16");
 
@@ -3273,8 +3305,8 @@ yyreduce:
       }
     break;
 
-  case 97:
-#line 1532 "grammar.y"
+  case 98:
+#line 1548 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(3) - (4)].expression), EXPRESSION_TYPE_INTEGER, "uint32");
 
@@ -3288,8 +3320,8 @@ yyreduce:
       }
     break;
 
-  case 98:
-#line 1544 "grammar.y"
+  case 99:
+#line 1560 "grammar.y"
     {
         compiler->last_result = yr_parser_emit_with_arg(
             yyscanner, OP_PUSH, (yyvsp[(1) - (1)].integer), NULL);
@@ -3301,8 +3333,8 @@ yyreduce:
       }
     break;
 
-  case 99:
-#line 1554 "grammar.y"
+  case 100:
+#line 1570 "grammar.y"
     {
         SIZED_STRING* sized_string = (yyvsp[(1) - (1)].sized_string);
         char* string;
@@ -3327,8 +3359,8 @@ yyreduce:
       }
     break;
 
-  case 100:
-#line 1577 "grammar.y"
+  case 101:
+#line 1593 "grammar.y"
     {
         compiler->last_result = yr_parser_reduce_string_identifier(
             yyscanner,
@@ -3345,8 +3377,8 @@ yyreduce:
       }
     break;
 
-  case 101:
-#line 1592 "grammar.y"
+  case 102:
+#line 1608 "grammar.y"
     {
         compiler->last_result = yr_parser_reduce_string_identifier(
             yyscanner,
@@ -3363,8 +3395,8 @@ yyreduce:
       }
     break;
 
-  case 102:
-#line 1607 "grammar.y"
+  case 103:
+#line 1623 "grammar.y"
     {
         compiler->last_result = yr_parser_emit_with_arg(
             yyscanner,
@@ -3388,8 +3420,8 @@ yyreduce:
       }
     break;
 
-  case 103:
-#line 1629 "grammar.y"
+  case 104:
+#line 1645 "grammar.y"
     {
         if ((yyvsp[(1) - (1)].object) == (YR_OBJECT*) -1)  // loop identifier
         {
@@ -3428,8 +3460,8 @@ yyreduce:
       }
     break;
 
-  case 104:
-#line 1666 "grammar.y"
+  case 105:
+#line 1682 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "+");
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "+");
@@ -3441,8 +3473,8 @@ yyreduce:
       }
     break;
 
-  case 105:
-#line 1676 "grammar.y"
+  case 106:
+#line 1692 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "-");
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "-");
@@ -3454,8 +3486,8 @@ yyreduce:
       }
     break;
 
-  case 106:
-#line 1686 "grammar.y"
+  case 107:
+#line 1702 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "*");
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "*");
@@ -3467,8 +3499,8 @@ yyreduce:
       }
     break;
 
-  case 107:
-#line 1696 "grammar.y"
+  case 108:
+#line 1712 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "\\");
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "\\");
@@ -3480,8 +3512,8 @@ yyreduce:
       }
     break;
 
-  case 108:
-#line 1706 "grammar.y"
+  case 109:
+#line 1722 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "%");
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "%");
@@ -3493,8 +3525,8 @@ yyreduce:
       }
     break;
 
-  case 109:
-#line 1716 "grammar.y"
+  case 110:
+#line 1732 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "^");
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "^");
@@ -3506,8 +3538,8 @@ yyreduce:
       }
     break;
 
-  case 110:
-#line 1726 "grammar.y"
+  case 111:
+#line 1742 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "^");
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "^");
@@ -3519,8 +3551,8 @@ yyreduce:
       }
     break;
 
-  case 111:
-#line 1736 "grammar.y"
+  case 112:
+#line 1752 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "|");
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "|");
@@ -3532,8 +3564,8 @@ yyreduce:
       }
     break;
 
-  case 112:
-#line 1746 "grammar.y"
+  case 113:
+#line 1762 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(2) - (2)].expression), EXPRESSION_TYPE_INTEGER, "~");
 
@@ -3545,8 +3577,8 @@ yyreduce:
       }
     break;
 
-  case 113:
-#line 1756 "grammar.y"
+  case 114:
+#line 1772 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, "<<");
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, "<<");
@@ -3558,8 +3590,8 @@ yyreduce:
       }
     break;
 
-  case 114:
-#line 1766 "grammar.y"
+  case 115:
+#line 1782 "grammar.y"
     {
         CHECK_TYPE((yyvsp[(1) - (3)].expression), EXPRESSION_TYPE_INTEGER, ">>");
         CHECK_TYPE((yyvsp[(3) - (3)].expression), EXPRESSION_TYPE_INTEGER, ">>");
@@ -3571,8 +3603,8 @@ yyreduce:
       }
     break;
 
-  case 115:
-#line 1776 "grammar.y"
+  case 116:
+#line 1792 "grammar.y"
     {
         (yyval.expression) = (yyvsp[(1) - (1)].expression);
       }
@@ -3580,7 +3612,7 @@ yyreduce:
 
 
 /* Line 1267 of yacc.c.  */
-#line 3584 "grammar.c"
+#line 3616 "grammar.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -3794,6 +3826,6 @@ yyreturn:
 }
 
 
-#line 1781 "grammar.y"
+#line 1797 "grammar.y"
 
 
diff --git a/libyara/grammar.y b/libyara/grammar.y
index aabeb41..6b613bd 100644
--- a/libyara/grammar.y
+++ b/libyara/grammar.y
@@ -916,6 +916,22 @@ expression
 
         $$.type = EXPRESSION_TYPE_BOOLEAN;
       }
+    | primary_expression _CONTAINS_ _STRING_IDENTIFIER_
+      {
+        CHECK_TYPE($1, EXPRESSION_TYPE_STRING, "contains");
+
+        int result = yr_parser_reduce_string_identifier(
+            yyscanner,
+            $3,
+            OP_CONTAINS_STR,
+            UNDEFINED); // XXX: UNDEFINED?
+
+        yr_free($3);
+
+        ERROR_IF(result != ERROR_SUCCESS);
+
+        $$.type = EXPRESSION_TYPE_BOOLEAN;
+      }
     | _STRING_IDENTIFIER_
       {
         int result = yr_parser_reduce_string_identifier(
diff --git a/libyara/include/yara/exec.h b/libyara/include/yara/exec.h
index 5254425..2d9cef4 100644
--- a/libyara/include/yara/exec.h
+++ b/libyara/include/yara/exec.h
@@ -84,6 +84,7 @@ limitations under the License.
 #define OP_MATCHES        54
 #define OP_IMPORT         55
 #define OP_LOOKUP_DICT    56
+#define OP_CONTAINS_STR   57
 
 
 #define OPERATION(operator, op1, op2) \
diff --git a/libyara/include/yara/modules.h b/libyara/include/yara/modules.h
index fde28e0..3c7bf32 100644
--- a/libyara/include/yara/modules.h
+++ b/libyara/include/yara/modules.h
@@ -196,7 +196,7 @@ limitations under the License.
 
 
 #define integer_argument(n)  (((int64_t*) __args)[n-1])
-#define string_argument(n)   ((char*)((int64_t*) __args)[n-1])
+#define string_argument(n)   ((SIZED_STRING*)((int64_t*) __args)[n-1])
 #define regexp_argument(n)   ((RE_CODE)((int64_t*) __args)[n-1])
 
 
@@ -231,8 +231,8 @@ limitations under the License.
     yr_object_set_integer(value, object, __VA_ARGS__)
 
 
-#define set_string(value, object, ...) \
-    yr_object_set_string(value, object, __VA_ARGS__)
+#define set_string(value, len, object, ...) \
+    yr_object_set_string(value, len, object, __VA_ARGS__)
 
 
 #define return_integer(integer) { \
diff --git a/libyara/include/yara/object.h b/libyara/include/yara/object.h
index 508babf..ba56934 100644
--- a/libyara/include/yara/object.h
+++ b/libyara/include/yara/object.h
@@ -74,7 +74,7 @@ int64_t yr_object_get_integer(
     ...);
 
 
-char* yr_object_get_string(
+SIZED_STRING* yr_object_get_string(
     YR_OBJECT* object,
     char* field,
     ...);
@@ -89,6 +89,7 @@ void yr_object_set_integer(
 
 void yr_object_set_string(
     char* value,
+    size_t len,
     YR_OBJECT* object,
     char* field,
     ...);
diff --git a/libyara/include/yara/pe.h b/libyara/include/yara/pe.h
index 7914088..cc6c2b2 100644
--- a/libyara/include/yara/pe.h
+++ b/libyara/include/yara/pe.h
@@ -84,6 +84,26 @@ typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
 #endif
 
 //
+// Rich signature.
+// http://www.ntcore.com/files/richsign.htm
+//
+typedef struct _RICH_SIGNATURE {
+    DWORD dans;
+    DWORD key1;
+    DWORD key2;
+    DWORD key3;
+  } RICH_SIGNATURE, *PRICH_SIGNATURE;
+
+#define RICH_DANS 0x536e6144 // "DanS"
+#define RICH_RICH 0x68636952 // "Rich"
+
+typedef struct _RICH_DATA {
+    size_t len;
+    BYTE* raw_data;
+    BYTE* clear_data;
+  } RICH_DATA, *PRICH_DATA;
+
+//
 // File header format.
 //
 
diff --git a/libyara/include/yara/types.h b/libyara/include/yara/types.h
index ff25080..dd5ed4e 100644
--- a/libyara/include/yara/types.h
+++ b/libyara/include/yara/types.h
@@ -410,7 +410,7 @@ typedef struct _YR_OBJECT_INTEGER
 typedef struct _YR_OBJECT_STRING
 {
   OBJECT_COMMON_FIELDS
-  char* value;
+  SIZED_STRING* value;
 
 } YR_OBJECT_STRING;
 
diff --git a/libyara/modules/demo.c b/libyara/modules/demo.c
index 1906a2f..2579f45 100644
--- a/libyara/modules/demo.c
+++ b/libyara/modules/demo.c
@@ -45,7 +45,7 @@ int module_load(
     void* module_data,
     size_t module_data_size)
 {
-  set_string("Hello World!", module_object, "greeting");
+  set_string("Hello World!", 12, module_object, "greeting");
 
   return ERROR_SUCCESS;
 }
diff --git a/libyara/modules/elf.c b/libyara/modules/elf.c
index 35e6a4d..fe9dba6 100644
--- a/libyara/modules/elf.c
+++ b/libyara/modules/elf.c
@@ -108,6 +108,7 @@ void parse_elf_header_##bits(                                                 \
   YR_OBJECT* elf_obj)                                                         \
 {                                                                             \
   char* str_table;                                                            \
+  size_t name_len;                                                            \
   elf##bits##_section_header_t* section;                                      \
                                                                               \
   set_integer(elf->type, elf_obj, "type");                                    \
@@ -138,7 +139,8 @@ void parse_elf_header_##bits(                                                 \
       set_integer(section->flags, elf_obj, "sections[%i].flags", i);          \
       set_integer(section->size, elf_obj, "sections[%i].size", i);            \
       set_integer(section->offset, elf_obj, "sections[%i].offset", i);        \
-      set_string(str_table + section->name, elf_obj, "sections[%i].name", i); \
+      name_len = strlen(str_table + section->name);                           \
+      set_string(str_table + section->name, name_len, elf_obj, "sections[%i].name", i); \
                                                                               \
       section++;                                                              \
     }                                                                         \
diff --git a/libyara/modules/pe.c b/libyara/modules/pe.c
index ac8df6c..2857de0 100644
--- a/libyara/modules/pe.c
+++ b/libyara/modules/pe.c
@@ -75,6 +75,7 @@ typedef struct _PE
 
   PIMAGE_NT_HEADERS32 header;
   YR_OBJECT* object;
+  PRICH_DATA rich_data;
 
 } PE;
 
@@ -124,6 +125,101 @@ PIMAGE_NT_HEADERS32 pe_get_header(
 }
 
 
+/* This is basically a straight copy/paste of pe_get_header(). :( */
+PRICH_DATA pe_get_rich_signature(
+    uint8_t* buffer,
+    size_t buffer_length,
+    YR_OBJECT* pe_obj)
+{
+  PIMAGE_DOS_HEADER mz_header;
+  PIMAGE_NT_HEADERS32 pe_header;
+  PRICH_SIGNATURE rich_signature;
+  DWORD* rich_ptr;
+  PRICH_DATA rich_data;
+
+  BYTE* raw_data = NULL;
+  BYTE* clear_data = NULL;
+  size_t headers_size = 0;
+  size_t rich_len = 0;
+
+  if (buffer_length < sizeof(IMAGE_DOS_HEADER))
+    return NULL;
+
+  mz_header = (PIMAGE_DOS_HEADER) buffer;
+
+  if (mz_header->e_magic != IMAGE_DOS_SIGNATURE)
+    return NULL;
+
+  if (mz_header->e_lfanew < 0)
+    return NULL;
+
+  headers_size = mz_header->e_lfanew + \
+                 sizeof(pe_header->Signature) + \
+                 sizeof(IMAGE_FILE_HEADER);
+
+  if (buffer_length < headers_size)
+    return NULL;
+
+  /*
+   * From offset 0x80 until the start of the PE header should be the Rich
+   * signature. The three key values must all be equal and the first dword
+   * XORs to "DanS". Then walk the buffer looking for "Rich" which marks the
+   * end. Technically the XOR key should be right after "Rich" but it's not
+   * important.
+   */
+  rich_signature = (PRICH_SIGNATURE) (buffer + 0x80);
+  if (rich_signature->key1 != rich_signature->key2 ||
+      rich_signature->key2 != rich_signature->key3 ||
+      (rich_signature->dans ^ rich_signature->key1) != RICH_DANS)
+    return NULL;
+
+  for (rich_ptr = (DWORD *) rich_signature; rich_ptr <= (DWORD *) (buffer + headers_size); rich_ptr++) {
+    if (*rich_ptr == RICH_RICH) {
+      // Multiple by 4 because we are counting in DWORDs.
+      rich_len = (rich_ptr - (DWORD *) rich_signature) * 4;
+      raw_data = (BYTE *) yr_malloc(rich_len);
+      if (!raw_data)
+        return NULL;
+
+      memcpy(raw_data, rich_signature, rich_len);
+      set_integer(htonl(rich_signature->dans), pe_obj, "rich_signature.start");
+      set_integer(htonl(rich_signature->key1), pe_obj, "rich_signature.key");
+      break;
+    }
+  }
+
+  /* Walk the entire block and apply the XOR key. */
+  if (raw_data) {
+    clear_data = (BYTE *) yr_malloc(rich_len);
+    if (!clear_data) {
+      yr_free(raw_data);
+      return NULL;
+    }
+
+    /* Copy the entire block here to be XORed */
+    memcpy(clear_data, raw_data, rich_len);
+    for (rich_ptr = (DWORD *) clear_data; rich_ptr < (DWORD *) (clear_data + rich_len); rich_ptr++) {
+      *rich_ptr ^= rich_signature->key1;
+    }
+
+    rich_data = (PRICH_DATA) yr_malloc(sizeof(RICH_DATA));
+    if (!rich_data) {
+      yr_free(raw_data);
+      yr_free(clear_data);
+    }
+
+    set_string((char *) raw_data, rich_len, pe_obj, "rich_signature.raw_data");
+    set_string((char *) clear_data, rich_len, pe_obj, "rich_signature.clear_data");
+    rich_data->len = rich_len;
+    rich_data->raw_data = raw_data;
+    rich_data->clear_data = clear_data;
+    return rich_data;
+  }
+
+  return NULL;
+}
+
+
 PIMAGE_DATA_DIRECTORY pe_get_directory_entry(
     PE* pe,
     int entry)
@@ -358,7 +454,7 @@ int pe_find_version_info_cb(
           strlcpy_w(key, string->Key, sizeof(key));
           strlcpy_w(value, string_value, sizeof(value));
 
-          set_string(value, pe->object, "version_info[%s]", key);
+          set_string(value, sizeof(value), pe->object, "version_info[%s]", key);
 
           string = ADD_OFFSET(string, string->Length);
           string = ALIGN_NEXT_DWORD(string);
@@ -381,6 +477,7 @@ void pe_parse(
   PIMAGE_SECTION_HEADER section;
 
   char section_name[IMAGE_SIZEOF_SHORT_NAME + 1];
+  size_t str_size;
 
 #define OptionalHeader(field) \
   (pe->header->FileHeader.Machine == 0x8664 ? \
@@ -466,10 +563,10 @@ void pe_parse(
       break;
     }
 
-    strlcpy(section_name, (char*) section->Name, IMAGE_SIZEOF_SHORT_NAME + 1);
+    str_size = strlcpy(section_name, (char*) section->Name, IMAGE_SIZEOF_SHORT_NAME + 1);
 
     set_string(
-        section_name,
+        section_name, str_size,
         pe->object, "sections[%i].name", i);
 
     set_integer(
@@ -497,7 +594,8 @@ void pe_parse(
 define_function(section_index)
 {
   YR_OBJECT* module = module();
-  char* name = string_argument(1);
+  SIZED_STRING* sect;
+  SIZED_STRING* name = string_argument(1);
 
   int64_t n = get_integer(module, "number_of_sections");
   int64_t i;
@@ -507,7 +605,10 @@ define_function(section_index)
 
   for (i = 0; i < n; i++)
   {
-    if (strcmp(name, get_string(module, "sections[%i].name", i)) == 0)
+    sect = get_string(module, "sections[%i].name", i);
+    if (sect->length != name->length)
+      continue;
+    if (memcmp(name->c_string, sect->c_string, name->length) == 0)
       return_integer(i);
   }
 
@@ -517,7 +618,7 @@ define_function(section_index)
 
 define_function(exports)
 {
-  char* function_name = string_argument(1);
+  SIZED_STRING* function_name = string_argument(1);
 
   YR_OBJECT* module = module();
   PE* pe = (PE*) module->data;
@@ -567,7 +668,10 @@ define_function(exports)
 
     name = (char*)(pe->data + offset);
 
-    if (strncmp(name, function_name, pe->data_size - offset) == 0)
+    if (function_name->length != pe->data_size - offset)
+        continue;
+
+    if (memcmp(name, function_name->c_string, pe->data_size - offset) == 0)
       return_integer(1);
   }
 
@@ -580,9 +684,9 @@ define_function(exports)
 
 define_function(imports)
 {
-  char* dll_name = string_argument(1);
-  char* function_name = string_argument(2);
-  int function_name_len = strlen(function_name);
+  SIZED_STRING* dll_name = string_argument(1);
+  SIZED_STRING* function_name = string_argument(2);
+  int function_name_len = function_name->length;
 
   YR_OBJECT* module = module();
   PE* pe = (PE*) module->data;
@@ -624,7 +728,7 @@ define_function(imports)
     if (offset > 0 &&
         offset <= pe->data_size &&
         strncasecmp(
-            dll_name,
+            dll_name->c_string, // XXX
             (char*)(pe->data + offset),
             pe->data_size - offset) == 0)
     {
@@ -652,7 +756,7 @@ define_function(imports)
                 if (pe_end - import->Name >= function_name_len)
                 {
                   if (strncmp((char*) import->Name,
-                              function_name,
+                              function_name->c_string,
                               function_name_len) == 0)
                   {
                     return_integer(1);
@@ -684,7 +788,7 @@ define_function(imports)
                 if (pe_end - import->Name >= function_name_len)
                 {
                   if (strncmp((char*) import->Name,
-                              function_name,
+                              function_name->c_string,
                               function_name_len) == 0)
                   {
                     return_integer(1);
@@ -761,6 +865,67 @@ define_function(language)
   }
 }
 
+/*
+define_function(matches)
+{
+  void *cmp_data;
+  uint64_t cmp_len;
+
+  YR_OBJECT* parent = parent();
+  YR_OBJECT* module = module();
+  DATA* data = (DATA*) module->data;
+  char *str = string_argument(1);
+  uint64_t len = integer_argument(2);
+
+  if (data == NULL || data->rich_data == NULL)
+    return_integer(UNDEFINED);
+
+  if (strcmp(parent->identifier, "raw_data") == 0)
+    cmp_data = data->rich_data->raw_data;
+  else if (strcmp(parent->identifier, "clear_data") == 0)
+    cmp_data = data->rich_data->clear_data;
+  else
+    return_integer(UNDEFINED);
+
+  // Compare the smaller of the two.
+  if (data->rich_data->len < len)
+    cmp_len = data->rich_data->len;
+  else
+    cmp_len = len;
+
+  if (memcmp(cmp_data, str, cmp_len) == 0)
+    return_integer(1);
+
+  return_integer(0);
+}
+
+define_function(contains)
+{
+  void *cmp_data;
+
+  YR_OBJECT* parent = parent();
+  YR_OBJECT* module = module();
+  DATA* data = (DATA*) module->data;
+  char *str = string_argument(1);
+  uint64_t len = integer_argument(2);
+
+  if (data == NULL || data->rich_data == NULL)
+    return_integer(UNDEFINED);
+
+  if (strcmp(parent->identifier, "raw_data") == 0)
+    cmp_data = data->rich_data->raw_data;
+  else if (strcmp(parent->identifier, "clear_data") == 0)
+    cmp_data = data->rich_data->clear_data;
+  else
+    return_integer(UNDEFINED);
+
+  if (memmem(cmp_data, data->rich_data->len, str, len) != NULL)
+    return_integer(1);
+
+  return_integer(0);
+}
+*/
+
 begin_declarations;
 
   declare_integer("MACHINE_I386");
@@ -831,6 +996,23 @@ begin_declarations;
     declare_integer("raw_data_size");
   end_struct_array("sections");
 
+  begin_struct("rich_signature");
+    declare_integer("start");
+    declare_integer("key");
+    declare_string("raw_data");
+    declare_string("clear_data");
+/*
+    begin_struct("raw_data");
+      declare_function("is", "si", "i", matches);
+      declare_function("has", "si", "i", contains);
+    end_struct("raw_data")
+    begin_struct("clear_data");
+      declare_function("is", "si", "i", matches);
+      declare_function("has", "si", "i", contains);
+    end_struct("clear_data")
+*/
+  end_struct("rich_signature");
+
   declare_function("section_index", "s", "i", section_index);
   declare_function("exports", "s", "i", exports);
   declare_function("imports", "ss", "i", imports);
@@ -859,6 +1041,7 @@ int module_load(
     void* module_data,
     size_t module_data_size)
 {
+
   set_integer(
       IMAGE_FILE_MACHINE_I386, module_object,
       "MACHINE_I386");
@@ -952,10 +1135,14 @@ int module_load(
         if (pe == NULL)
           return ERROR_INSUFICIENT_MEMORY;
 
+        // Get the rich signature.
+        PRICH_DATA rich_data = pe_get_rich_signature(block->data, block->size, module_object);
+
         pe->data = block->data;
         pe->data_size = block->size;
         pe->header = pe_header;
         pe->object = module_object;
+        pe->rich_data = rich_data;
 
         module_object->data = pe;
 
@@ -975,8 +1162,17 @@ int module_load(
 
 int module_unload(YR_OBJECT* module_object)
 {
-  if (module_object->data != NULL)
+  PE* pe = (PE *) module_object->data;
+  if (pe != NULL) {
+    if (pe->rich_data) {
+      if (pe->rich_data->raw_data)
+        yr_free(pe->rich_data->raw_data);
+      if (pe->rich_data->clear_data)
+        yr_free(pe->rich_data->clear_data);
+      yr_free(pe->rich_data);
+    }
     yr_free(module_object->data);
+  }
 
   return ERROR_SUCCESS;
 }
diff --git a/libyara/modules/tests.c b/libyara/modules/tests.c
index d839a5f..70e4988 100644
--- a/libyara/modules/tests.c
+++ b/libyara/modules/tests.c
@@ -75,7 +75,7 @@ int module_load(
 {
   set_integer(1, module_object, "constants.one");
   set_integer(2, module_object, "constants.two");
-  set_string("foo", module_object, "constants.foo");
+  set_string("foo", 3, module_object, "constants.foo");
 
   set_integer(1, module_object, "struct_array[1].i");
 
@@ -83,12 +83,12 @@ int module_load(
   set_integer(1, module_object, "integer_array[%i]", 1);
   set_integer(2, module_object, "integer_array[%i]", 2);
 
-  set_string("foo", module_object, "string_array[%i]", 0);
-  set_string("bar", module_object, "string_array[%i]", 1);
-  set_string("baz", module_object, "string_array[%i]", 2);
+  set_string("foo", 3, module_object, "string_array[%i]", 0);
+  set_string("bar", 3, module_object, "string_array[%i]", 1);
+  set_string("baz", 3, module_object, "string_array[%i]", 2);
 
-  set_string("foo", module_object, "string_dict[%s]", "foo");
-  set_string("bar", module_object, "string_dict[\"bar\"]");
+  set_string("foo", 3, module_object, "string_dict[%s]", "foo");
+  set_string("bar", 3, module_object, "string_dict[\"bar\"]");
 
   return ERROR_SUCCESS;
 }
diff --git a/libyara/object.c b/libyara/object.c
index 877330d..60fbe54 100644
--- a/libyara/object.c
+++ b/libyara/object.c
@@ -228,7 +228,7 @@ int yr_object_from_external_variable(
 
       case EXTERNAL_VARIABLE_TYPE_STRING:
       case EXTERNAL_VARIABLE_TYPE_MALLOC_STRING:
-        yr_object_set_string(external->string, obj, NULL);
+        yr_object_set_string(external->string, 0, obj, NULL); // XXX
         break;
     }
 
@@ -249,7 +249,7 @@ void yr_object_destroy(
 
   RE* re;
   int i;
-  char* str;
+  SIZED_STRING* str;
 
   switch(object->type)
   {
@@ -776,7 +776,7 @@ int64_t yr_object_get_integer(
 }
 
 
-char* yr_object_get_string(
+SIZED_STRING* yr_object_get_string(
     YR_OBJECT* object,
     char* field,
     ...)
@@ -831,6 +831,7 @@ void yr_object_set_integer(
 
 void yr_object_set_string(
     char* value,
+    size_t len,
     YR_OBJECT* object,
     char* field,
     ...)
@@ -854,7 +855,10 @@ void yr_object_set_string(
   if (string_obj->value != NULL)
     yr_free(string_obj->value);
 
-  string_obj->value = yr_strdup(value);
+  string_obj->value = (SIZED_STRING*) yr_malloc(len + sizeof(SIZED_STRING));
+  string_obj->value->length = len;
+  string_obj->value->flags = 0;
+  memcpy(string_obj->value->c_string, value, len);
 }
 
 

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