Implement xor modifier. (#830)

This commit is contained in:
Wesley Shields
2018-02-18 19:46:08 +01:00
committed by Victor M. Alvarez
parent 16c5bad214
commit 2e664c566f
13 changed files with 1521 additions and 1567 deletions
+67
View File
@@ -578,6 +578,48 @@ static int _yr_atoms_case_insensitive(
}
//
// _yr_atoms_xor
//
// For a given list of atoms returns another list after a single byte xor
// has been applied to it.
//
static int _yr_atoms_xor(
YR_ATOM_LIST_ITEM* atoms,
YR_ATOM_LIST_ITEM** xor_atoms)
{
YR_ATOM_LIST_ITEM* atom;
YR_ATOM_LIST_ITEM* new_atom;
int i, j;
*xor_atoms = NULL;
atom = atoms;
while (atom != NULL)
{
for (j = 1; j <= 255; j++)
{
new_atom = (YR_ATOM_LIST_ITEM*) yr_malloc(sizeof(YR_ATOM_LIST_ITEM));
if (new_atom == NULL)
return ERROR_INSUFFICIENT_MEMORY;
for (i = 0; i < atom->atom_length; i++)
new_atom->atom[i] = atom->atom[i] ^ j;
new_atom->atom_length = yr_min(atom->atom_length, MAX_ATOM_LENGTH);
new_atom->forward_code = atom->forward_code;
new_atom->backward_code = atom->backward_code;
new_atom->backtrack = atom->backtrack;
new_atom->next = *xor_atoms;
*xor_atoms = new_atom;
}
atom = atom->next;
}
return ERROR_SUCCESS;
}
//
// _yr_atoms_wide
//
@@ -1185,6 +1227,7 @@ int yr_atoms_extract_from_string(
{
YR_ATOM_LIST_ITEM* item;
YR_ATOM_LIST_ITEM* case_insensitive_atoms;
YR_ATOM_LIST_ITEM* xor_atoms;
YR_ATOM_LIST_ITEM* wide_atoms;
int max_quality;
@@ -1260,6 +1303,30 @@ int yr_atoms_extract_from_string(
*atoms = _yr_atoms_list_concat(*atoms, case_insensitive_atoms);
}
if (flags & STRING_GFLAGS_XOR)
{
FAIL_ON_ERROR_WITH_CLEANUP(
_yr_atoms_xor(*atoms, &xor_atoms),
{
yr_atoms_list_destroy(*atoms);
yr_atoms_list_destroy(xor_atoms);
*atoms = NULL;
});
if (flags & STRING_GFLAGS_ASCII ||
flags & STRING_GFLAGS_WIDE ||
flags & STRING_GFLAGS_NO_CASE)
{
*atoms = _yr_atoms_list_concat(*atoms, xor_atoms);
}
else
{
yr_atoms_list_destroy(*atoms);
*atoms = xor_atoms;
}
}
return ERROR_SUCCESS;
}
+622 -613
View File
File diff suppressed because it is too large Load Diff
+60 -58
View File
@@ -66,34 +66,35 @@ extern int yara_yydebug;
_REGEXP_ = 276,
_ASCII_ = 277,
_WIDE_ = 278,
_NOCASE_ = 279,
_FULLWORD_ = 280,
_AT_ = 281,
_FILESIZE_ = 282,
_ENTRYPOINT_ = 283,
_ALL_ = 284,
_ANY_ = 285,
_IN_ = 286,
_OF_ = 287,
_FOR_ = 288,
_THEM_ = 289,
_MATCHES_ = 290,
_CONTAINS_ = 291,
_IMPORT_ = 292,
_TRUE_ = 293,
_FALSE_ = 294,
_OR_ = 295,
_AND_ = 296,
_EQ_ = 297,
_NEQ_ = 298,
_LT_ = 299,
_LE_ = 300,
_GT_ = 301,
_GE_ = 302,
_SHIFT_LEFT_ = 303,
_SHIFT_RIGHT_ = 304,
_NOT_ = 305,
UNARY_MINUS = 306
_XOR_ = 279,
_NOCASE_ = 280,
_FULLWORD_ = 281,
_AT_ = 282,
_FILESIZE_ = 283,
_ENTRYPOINT_ = 284,
_ALL_ = 285,
_ANY_ = 286,
_IN_ = 287,
_OF_ = 288,
_FOR_ = 289,
_THEM_ = 290,
_MATCHES_ = 291,
_CONTAINS_ = 292,
_IMPORT_ = 293,
_TRUE_ = 294,
_FALSE_ = 295,
_OR_ = 296,
_AND_ = 297,
_EQ_ = 298,
_NEQ_ = 299,
_LT_ = 300,
_LE_ = 301,
_GT_ = 302,
_GE_ = 303,
_SHIFT_LEFT_ = 304,
_SHIFT_RIGHT_ = 305,
_NOT_ = 306,
UNARY_MINUS = 307
};
#endif
/* Tokens. */
@@ -118,41 +119,42 @@ extern int yara_yydebug;
#define _REGEXP_ 276
#define _ASCII_ 277
#define _WIDE_ 278
#define _NOCASE_ 279
#define _FULLWORD_ 280
#define _AT_ 281
#define _FILESIZE_ 282
#define _ENTRYPOINT_ 283
#define _ALL_ 284
#define _ANY_ 285
#define _IN_ 286
#define _OF_ 287
#define _FOR_ 288
#define _THEM_ 289
#define _MATCHES_ 290
#define _CONTAINS_ 291
#define _IMPORT_ 292
#define _TRUE_ 293
#define _FALSE_ 294
#define _OR_ 295
#define _AND_ 296
#define _EQ_ 297
#define _NEQ_ 298
#define _LT_ 299
#define _LE_ 300
#define _GT_ 301
#define _GE_ 302
#define _SHIFT_LEFT_ 303
#define _SHIFT_RIGHT_ 304
#define _NOT_ 305
#define UNARY_MINUS 306
#define _XOR_ 279
#define _NOCASE_ 280
#define _FULLWORD_ 281
#define _AT_ 282
#define _FILESIZE_ 283
#define _ENTRYPOINT_ 284
#define _ALL_ 285
#define _ANY_ 286
#define _IN_ 287
#define _OF_ 288
#define _FOR_ 289
#define _THEM_ 290
#define _MATCHES_ 291
#define _CONTAINS_ 292
#define _IMPORT_ 293
#define _TRUE_ 294
#define _FALSE_ 295
#define _OR_ 296
#define _AND_ 297
#define _EQ_ 298
#define _NEQ_ 299
#define _LT_ 300
#define _LE_ 301
#define _GT_ 302
#define _GE_ 303
#define _SHIFT_LEFT_ 304
#define _SHIFT_RIGHT_ 305
#define _NOT_ 306
#define UNARY_MINUS 307
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE
{
#line 215 "grammar.y" /* yacc.c:1915 */
#line 216 "grammar.y" /* yacc.c:1915 */
EXPRESSION expression;
SIZED_STRING* sized_string;
@@ -163,7 +165,7 @@ union YYSTYPE
YR_META* meta;
YR_RULE* rule;
#line 167 "grammar.h" /* yacc.c:1915 */
#line 169 "grammar.h" /* yacc.c:1915 */
};
typedef union YYSTYPE YYSTYPE;
+2
View File
@@ -139,6 +139,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
%token <sized_string> _REGEXP_
%token _ASCII_
%token _WIDE_
%token _XOR_
%token _NOCASE_
%token _FULLWORD_
%token _AT_
@@ -571,6 +572,7 @@ string_modifier
| _ASCII_ { $$ = STRING_GFLAGS_ASCII; }
| _NOCASE_ { $$ = STRING_GFLAGS_NO_CASE; }
| _FULLWORD_ { $$ = STRING_GFLAGS_FULL_WORD; }
| _XOR_ { $$ = STRING_GFLAGS_XOR; }
;
+4
View File
@@ -67,6 +67,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define STRING_GFLAGS_GREEDY_REGEXP 0x10000
#define STRING_GFLAGS_DOT_ALL 0x20000
#define STRING_GFLAGS_DISABLED 0x40000
#define STRING_GFLAGS_XOR 0x80000
#define STRING_IS_HEX(x) \
(((x)->g_flags) & STRING_GFLAGS_HEXADECIMAL)
@@ -125,6 +126,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define STRING_IS_DISABLED(x) \
(((x)->g_flags) & STRING_GFLAGS_DISABLED)
#define STRING_IS_XOR(x) \
(((x)->g_flags) & STRING_GFLAGS_XOR)
#define STRING_FOUND(x) \
((x)->matches[yr_get_tidx()].tail != NULL)
+652 -894
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -173,6 +173,7 @@ octdigit [0-7]
"strings" { return _STRINGS_; }
"ascii" { return _ASCII_; }
"wide" { return _WIDE_; }
"xor" { return _XOR_; }
"fullword" { return _FULLWORD_; }
"nocase" { return _NOCASE_; }
"condition" { return _CONDITION_; }
@@ -943,4 +944,3 @@ int yr_lex_parse_rules_fd(
return compiler->errors;
}
+2 -1
View File
@@ -497,7 +497,8 @@ YR_STRING* yr_parser_reduce_string_declaration(
if (strcmp(identifier,"$") == 0)
string_flags |= STRING_GFLAGS_ANONYMOUS;
if (!(string_flags & STRING_GFLAGS_WIDE))
if (!(string_flags & STRING_GFLAGS_WIDE) &&
!(string_flags & STRING_GFLAGS_XOR))
string_flags |= STRING_GFLAGS_ASCII;
// Hex strings are always handled as DOT_ALL regexps.
+79
View File
@@ -58,6 +58,63 @@ typedef struct _CALLBACK_ARGS
} CALLBACK_ARGS;
static int _yr_scan_xor_compare(
const uint8_t* data,
size_t data_size,
uint8_t* string,
size_t string_length)
{
const uint8_t* s1 = data;
const uint8_t* s2 = string;
uint8_t k = 0;
size_t i = 0;
if (data_size < string_length)
return 0;
// Calculate the xor key to compare with. *s1 is the start of the string we
// matched on and *s2 is the "plaintext" string, so *s1 ^ *s2 is the key to
// every *s2 as we compare.
k = *s1 ^ *s2;
while (i < string_length && *s1++ == ((*s2++) ^ k))
i++;
return (int) ((i == string_length) ? i : 0);
}
static int _yr_scan_xor_wcompare(
const uint8_t* data,
size_t data_size,
uint8_t* string,
size_t string_length)
{
const uint8_t* s1 = data;
const uint8_t* s2 = string;
uint8_t k = 0;
size_t i = 0;
if (data_size < string_length * 2)
return 0;
// Calculate the xor key to compare with. *s1 is the start of the string we
// matched on and *s2 is the "plaintext" string, so *s1 ^ *s2 is the key to
// every *s2 as we compare.
k = *s1 ^ *s2;
while (i < string_length && *s1 == ((*s2) ^ k) && ((*(s1 + 1)) ^ k) == 0x00)
{
s1+=2;
s2++;
i++;
}
return (int) ((i == string_length) ? i * 2 : 0);
}
static int _yr_scan_compare(
const uint8_t* data,
size_t data_size,
@@ -720,6 +777,28 @@ static int _yr_scan_verify_literal_match(
string->string,
string->length);
}
if (STRING_IS_XOR(string) && forward_matches == 0)
{
if (STRING_IS_WIDE(string))
{
forward_matches = _yr_scan_xor_wcompare(
data + offset,
data_size - offset,
string->string,
string->length);
}
if (forward_matches == 0)
{
forward_matches = _yr_scan_xor_compare(
data + offset,
data_size - offset,
string->string,
string->length);
}
}
}
if (forward_matches == 0)
Binary file not shown.
Binary file not shown.
Binary file not shown.
+32
View File
@@ -477,6 +477,38 @@ static void test_strings()
condition:\n\
all of them\n\
}", "abcdef");
assert_true_rule_file(
"rule test {\n\
strings:\n\
$a = \"This program cannot\" xor\n\
condition:\n\
#a == 255\n\
}", "tests/data/xor.out");
assert_true_rule_file(
"rule test {\n\
strings:\n\
$a = \"This program cannot\" xor ascii\n\
condition:\n\
#a == 256\n\
}", "tests/data/xor.out");
assert_true_rule_file(
"rule test {\n\
strings:\n\
$a = \"This program cannot\" xor wide\n\
condition:\n\
#a == 256\n\
}", "tests/data/xorwide.out");
assert_true_rule_file(
"rule test {\n\
strings:\n\
$a = \"ab\" xor nocase\n\
condition:\n\
#a == 1084\n\
}", "tests/data/xornocase.out");
}