commit 3bbf253741a20a6cc2878a8856c1058c6db95144
parent 4677e0a1a67badcf0904f1b20231679917b70f8d
Author: MTRNord <mtrnord1@gmail.com>
Date: Fri, 13 Oct 2023 18:10:16 +0200
Extend function of the yara json module
Diffstat:
8 files changed, 243 insertions(+), 24 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
@@ -17,7 +17,13 @@ napi-derive = "2.12.2"
yara = { version = "0.21.0", features = ["yara-static"] }
[target.x86_64-pc-windows-msvc.dependencies]
-yara = { version = "0.21.0", features = ["yara-static", "vendored"] }
+yara = { version = "0.21.0", features = [
+ "yara-static",
+ "vendored",
+ "module-cuckoo",
+ "module-macho",
+ "module-hash",
+] }
[build-dependencies]
napi-build = "2.0.1"
diff --git a/__test__/index.spec.mjs b/__test__/index.spec.mjs
@@ -174,6 +174,24 @@ if (process.platform !== "win32") {
metadatas: [],
tags: [],
strings: []
+ }, {
+ identifier: "get_string",
+ namespace: "default",
+ metadatas: [],
+ tags: [],
+ strings: []
+ }, {
+ identifier: "get_integer",
+ namespace: "default",
+ metadatas: [],
+ tags: [],
+ strings: []
+ }, {
+ identifier: "get_float",
+ namespace: "default",
+ metadatas: [],
+ tags: [],
+ strings: []
}
])
});
diff --git a/__test__/json_test.yara b/__test__/json_test.yara
@@ -2,44 +2,44 @@ import "json"
rule string_array_includes {
condition:
- json.string_array_includes("strArray", "one") and
- json.string_array_includes("strArray", "two") and
- json.string_array_includes("strArray", "three")
+ json.array_includes("strArray", "one") and
+ json.array_includes("strArray", "two") and
+ json.array_includes("strArray", "three")
}
rule string_array_includes_nested {
condition:
- json.string_array_includes("string.strArray", "one") and
- json.string_array_includes("string.strArray", "two") and
- json.string_array_includes("string.strArray", "three")
+ json.array_includes("string.strArray", "one") and
+ json.array_includes("string.strArray", "two") and
+ json.array_includes("string.strArray", "three")
}
rule integer_array_includes {
condition:
- json.integer_array_includes("intArray", 1) and
- json.integer_array_includes("intArray", 2) and
- json.integer_array_includes("intArray", 3)
+ json.array_includes("intArray", 1) and
+ json.array_includes("intArray", 2) and
+ json.array_includes("intArray", 3)
}
rule integer_array_includes_nested {
condition:
- json.integer_array_includes("integer.intArray", 1) and
- json.integer_array_includes("integer.intArray", 2) and
- json.integer_array_includes("integer.intArray", 3)
+ json.array_includes("integer.intArray", 1) and
+ json.array_includes("integer.intArray", 2) and
+ json.array_includes("integer.intArray", 3)
}
rule float_array_includes {
condition:
- json.float_array_includes("floatArray", 1.0) and
- json.float_array_includes("floatArray", 2.0) and
- json.float_array_includes("floatArray", 3.0)
+ json.array_includes("floatArray", 1.0) and
+ json.array_includes("floatArray", 2.0) and
+ json.array_includes("floatArray", 3.0)
}
rule float_array_includes_nested {
condition:
- json.float_array_includes("float.floatArray", 1.0) and
- json.float_array_includes("float.floatArray", 2.0) and
- json.float_array_includes("float.floatArray", 3.0)
+ json.array_includes("float.floatArray", 1.0) and
+ json.array_includes("float.floatArray", 2.0) and
+ json.array_includes("float.floatArray", 3.0)
}
rule dotted_key {
@@ -55,4 +55,19 @@ rule dotted_key_sub {
rule has_key_normal {
condition:
json.key_exists("normal_key")
+}
+
+rule get_string {
+ condition:
+ json.get_string_value("keykey") == "valuevalue"
+}
+
+rule get_integer {
+ condition:
+ json.get_integer_value("integer_number") == 42
+}
+
+rule get_float {
+ condition:
+ json.get_float_value("float_number") == 42.42
}
\ No newline at end of file
diff --git a/__test__/test.json b/__test__/test.json
@@ -50,5 +50,7 @@
"dot.key": {
"subkey": {}
},
- "normal_key": {}
+ "normal_key": {},
+ "integer_number": 42,
+ "float_number": 42.42
}
\ No newline at end of file
diff --git a/changelog.d/+dotted_keys.misc b/changelog.d/+dotted_keys.feat
diff --git a/changelog.d/+get_values.misc b/changelog.d/+get_values.misc
@@ -0,0 +1 @@
+Add get_X_value methods to json module to get the value of a key
+\ No newline at end of file
diff --git a/changelog.d/+overloaded_value_exists.feat b/changelog.d/+overloaded_value_exists.feat
@@ -0,0 +1 @@
+Overload the value_exists function to have less function duplication on the frontend of the json module
+\ No newline at end of file
diff --git a/deps/json.c b/deps/json.c
@@ -359,6 +359,10 @@ define_function(string_array_includes)
json_t *array = iter;
bool isArray = json_is_array(array);
+ if (!isArray)
+ {
+ return_integer(0);
+ }
size_t index;
json_t *val;
@@ -382,6 +386,7 @@ define_function(string_array_includes)
return_integer(0);
}
+
// Integer Array includes
define_function(integer_array_includes)
{
@@ -448,13 +453,13 @@ define_function(integer_array_includes)
free(array);
free(key);
- free(value);
free(prevToken);
free(token);
free(realToken);
return_integer(0);
}
+
// Float Array includes
define_function(float_array_includes)
{
@@ -527,6 +532,172 @@ define_function(float_array_includes)
return_integer(0);
}
+// Get String value
+define_function(string_get_value)
+{
+ char *key = strdup(string_argument(1));
+
+ json_t *json = yr_module()->data;
+ if (json == NULL)
+ {
+ return_string(YR_UNDEFINED);
+ }
+
+ // Split key into possible subcomponents - separated by '.'
+ json_t *iter = json;
+ char *token = strtok(key, ".");
+ char *prevToken = strdup(token);
+ char previousChar = '\0';
+ char *realToken = strdup(token);
+
+ while (token != NULL)
+ {
+ previousChar = token[strlen(token)-1];
+ if (previousChar == '\\') {
+ realToken[strlen(realToken)-1] = '.';
+ token = strtok(NULL, ".");
+ strcat(realToken, token);
+ }
+
+ iter = json_object_get(iter, realToken);
+ if (iter == NULL)
+ {
+ return_string(YR_UNDEFINED);
+ }
+
+ strcpy(prevToken, token);
+ token = strtok(NULL, ".");
+ if (token != NULL) {
+ strcpy(realToken, token);
+ }
+ }
+
+ const char *found = json_string_value(iter);
+ if (found == NULL)
+ {
+ printf("no string value could be obtained from value at key\n");
+ return_string(YR_UNDEFINED);
+ }
+
+ free(key);
+ free(prevToken);
+ free(token);
+ free(realToken);
+
+ return_string(found);
+}
+
+// Get integer value
+define_function(integer_get_value)
+{
+ char *key = strdup(string_argument(1));
+
+ json_t *json = yr_module()->data;
+ if (json == NULL)
+ {
+ return_integer(YR_UNDEFINED);
+ }
+
+ // Split key into possible subcomponents - separated by '.'
+ json_t *iter = json;
+ char *token = strtok(key, ".");
+ char *prevToken = strdup(token);
+ char previousChar = '\0';
+ char *realToken = strdup(token);
+
+ while (token != NULL)
+ {
+ previousChar = token[strlen(token)-1];
+ if (previousChar == '\\') {
+ realToken[strlen(realToken)-1] = '.';
+ token = strtok(NULL, ".");
+ strcat(realToken, token);
+ }
+
+ iter = json_object_get(iter, realToken);
+ if (iter == NULL)
+ {
+ return_integer(YR_UNDEFINED);
+ }
+
+ strcpy(prevToken, token);
+ token = strtok(NULL, ".");
+ if (token != NULL) {
+ strcpy(realToken, token);
+ }
+ }
+
+ double foundNumber = json_number_value(iter);
+ if (foundNumber == 0.0)
+ {
+ printf("no integer value could be obtained from value at key\n");
+ return_integer(YR_UNDEFINED);
+ }
+ int found = (int)foundNumber;
+
+ free(key);
+ free(prevToken);
+ free(token);
+ free(realToken);
+
+ return_integer(found);
+}
+
+// Get float value
+define_function(float_get_value)
+{
+ char *key = strdup(string_argument(1));
+
+ json_t *json = yr_module()->data;
+ if (json == NULL)
+ {
+ return_float(YR_UNDEFINED);
+ }
+
+ // Split key into possible subcomponents - separated by '.'
+ json_t *iter = json;
+ char *token = strtok(key, ".");
+ char *prevToken = strdup(token);
+ char previousChar = '\0';
+ char *realToken = strdup(token);
+
+ while (token != NULL)
+ {
+ previousChar = token[strlen(token)-1];
+ if (previousChar == '\\') {
+ realToken[strlen(realToken)-1] = '.';
+ token = strtok(NULL, ".");
+ strcat(realToken, token);
+ }
+
+ iter = json_object_get(iter, realToken);
+ if (iter == NULL)
+ {
+ return_float(YR_UNDEFINED);
+ }
+
+ strcpy(prevToken, token);
+ token = strtok(NULL, ".");
+ if (token != NULL) {
+ strcpy(realToken, token);
+ }
+ }
+
+ double foundNumber = json_number_value(iter);
+ if (foundNumber == 0.0)
+ {
+ printf("no float value could be obtained from value at key\n");
+ return_float(YR_UNDEFINED);
+ }
+
+ free(key);
+ free(prevToken);
+ free(token);
+ free(realToken);
+
+ return_float(foundNumber);
+}
+
begin_declarations;
declare_function("key_exists", "s", "i", key_exists);
@@ -534,9 +705,12 @@ declare_function("value_exists", "ss", "i", value_exists_string);
declare_function("value_exists", "si", "i", value_exists_integer);
declare_function("value_exists", "sr", "i", value_exists_regex);
declare_function("value_exists", "sf", "i", value_exists_float);
-declare_function("string_array_includes", "ss", "i", string_array_includes);
-declare_function("integer_array_includes", "si", "i", integer_array_includes);
-declare_function("float_array_includes", "sf", "i", float_array_includes);
+declare_function("array_includes", "ss", "i", string_array_includes);
+declare_function("array_includes", "si", "i", integer_array_includes);
+declare_function("array_includes", "sf", "i", float_array_includes);
+declare_function("get_string_value", "s", "s", string_get_value);
+declare_function("get_integer_value", "s", "i", integer_get_value);
+declare_function("get_float_value", "s", "f", float_get_value);
end_declarations;
int module_initialize(YR_MODULE *module)