commit 0d5c5f78b174c4965ec050494f9fc97718c56a84
parent ff2d786dab2ec2eba939b10c9f7ee1d750935bd7
Author: MTRNord <mtrnord1@gmail.com>
Date: Sat, 7 Oct 2023 23:33:18 +0200
Add json parsing support to the yara build
Diffstat:
12 files changed, 737 insertions(+), 2 deletions(-)
diff --git a/.cargo/config.toml b/.cargo/config.toml
@@ -1,3 +1,27 @@
[env]
YARA_LIBRARY_PATH = { value = "build/yara/lib", relative = true }
YARA_INCLUDE_DIR = { value = "build/yara/include", relative = true }
+
+[target.x86_64-unknown-linux-gnu]
+linker = "clang"
+rustflags = ["-Clink-arg=-fuse-ld=lld", "-Zshare-generics=y"]
+
+# NOTE: you must install [Mach-O LLD Port](https://lld.llvm.org/MachO/index.html) on mac. you can easily do this by installing llvm which includes lld with the "brew" package manager:
+# `brew install llvm`
+[target.x86_64-apple-darwin]
+rustflags = [
+ "-C",
+ "link-arg=-fuse-ld=/usr/local/opt/llvm/bin/ld64.lld",
+ "-Zshare-generics=y",
+]
+
+[target.aarch64-apple-darwin]
+rustflags = [
+ "-C",
+ "link-arg=-fuse-ld=/opt/homebrew/opt/llvm/bin/ld64.lld",
+ "-Zshare-generics=y",
+]
+
+[target.x86_64-pc-windows-msvc]
+linker = "rust-lld.exe"
+rustflags = ["-Zshare-generics=n"]
+\ No newline at end of file
diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
@@ -32,6 +32,8 @@ jobs:
brew install automake
brew install libtool
brew install pkg-config
+ brew install jansson
+ brew install llvm
make build
strip -x *.node
- host: windows-latest
@@ -41,7 +43,7 @@ jobs:
target: x86_64-unknown-linux-gnu
build: |-
set -e &&
- sudo apt-get install -y automake libtool make gcc pkg-config &&
+ sudo apt-get install -y automake libtool make gcc pkg-config libjansson-dev &&
make debug_results &&
make yara &&
yarn build --target x86_64-unknown-linux-gnu &&
@@ -53,6 +55,8 @@ jobs:
brew install automake
brew install libtool
brew install pkg-config
+ brew install jansson
+ brew install llvm
CFLAGS="-target arm64-apple-macos11" make yara
yarn build --target aarch64-apple-darwin
strip -x *.node
diff --git a/.gitignore b/.gitignore
@@ -197,4 +197,5 @@ Cargo.lock
*.node
deps/yara-*
+deps/jansson-*
build
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
@@ -0,0 +1,12 @@
+{
+ "files.associations": {
+ "*.rs": "rust",
+ "*.zonefile": "zone",
+ "system_error": "c",
+ "modules.h": "c",
+ "globals.h": "c",
+ "stdio.h": "c",
+ "jansson.h": "c",
+ "jansson_config.h": "c"
+ }
+}
+\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
@@ -2,6 +2,7 @@
edition = "2021"
name = "mtrnord_node-yara-rs"
version = "0.0.0"
+links = "jansson"
[lib]
crate-type = ["cdylib"]
diff --git a/Makefile b/Makefile
@@ -5,6 +5,7 @@ ifeq ($(OSNAME),Darwin)
CFLAGS += -I/usr/local/include/node
CFLAGS += -I/usr/local/include
LDFLAGS += -L/usr/local/lib
+JANSSON_LDFLAGS += $(LDFLAGS)
endif
ifeq ($(findstring arm64,$(CFLAGS)),arm64)
@@ -12,26 +13,65 @@ CFGOPTS += --host=aarch64-apple-darwin
endif
YARA?=4.3.2
+JANSSON?=2.13.1
libyara: yara
clean:
-rm -rf $(BASE)/build/yara
-rm -rf $(BASE)/deps/yara-$(YARA)
+ -rm -rf $(BASE)/build/jansson
+ -rm -rf $(BASE)/deps/jansson-$(JANSSON)
cargo clean
-yara: clean
+jansson: clean
+ echo $(CFLAGS)
+ echo $(LDFLAGS)
+ echo $(JANSSON_LDFLAGS)
+ echo $(CC)
+ test -f $(BASE)/deps/jansson-$(JANSSON).tar.gz || curl -L -k https://github.com/akheron/jansson/releases/download/v$(JANSSON)/jansson-$(JANSSON).tar.gz > $(BASE)/deps/jansson-$(JANSSON).tar.gz
+ cd $(BASE)/deps && tar -xzvf jansson-$(JANSSON).tar.gz
+ cd $(BASE)/deps/jansson-$(JANSSON) && \
+ CFLAGS="$(CFLAGS)" \
+ LDFLAGS="$(JANSSON_LDFLAGS)" \
+ ./configure \
+ $(CFGOPTS) \
+ --enable-static \
+ --disable-shared \
+ --with-pic \
+ --prefix=$(BASE)/build/jansson
+ cd $(BASE)/deps/jansson-$(JANSSON) && make
+ cd $(BASE)/deps/jansson-$(JANSSON) && make install
+
+yara: clean jansson
echo $(CFLAGS)
echo $(LDFLAGS)
echo $(CC)
test -f $(BASE)/deps/yara-$(YARA).tar.gz || curl -L -k https://github.com/VirusTotal/yara/archive/v$(YARA).tar.gz > $(BASE)/deps/yara-$(YARA).tar.gz
cd $(BASE)/deps && tar -xzvf yara-$(YARA).tar.gz
+
+ # Handle json.c
+ mkdir -p $(BASE)/deps/yara-$(YARA)/libyara/modules/json
+ echo "Copying json.c into libyara..."
+ cp $(BASE)/deps/json.c $(BASE)/deps/yara-$(YARA)/libyara/modules/json/json.c
+ @if grep -q "MODULE(json)" "$(BASE)/deps/yara-$(YARA)/libyara/modules/module_list"; then\
+ echo "Already added json module to module list...";\
+ else\
+ echo "MODULE(json)" >> "$(BASE)/deps/yara-$(YARA)/libyara/modules/module_list";\
+ fi
+ @if grep -q "MODULES += libyara/modules/json/json.c" "$(BASE)/deps/yara-$(YARA)/Makefile.am"; then\
+ echo "Already added json module link to Makefile.am...";\
+ else\
+ echo "MODULES += libyara/modules/json/json.c" >> "$(BASE)/deps/yara-$(YARA)/Makefile.am";\
+ fi
+
cd $(BASE)/deps/yara-$(YARA) && ./bootstrap.sh
cd $(BASE)/deps/yara-$(YARA) && \
CFLAGS="$(CFLAGS)" \
LDFLAGS="$(LDFLAGS)" \
./configure \
$(CFGOPTS) \
+ --enable-cuckoo \
--enable-static \
--disable-shared \
--with-pic \
@@ -45,6 +85,9 @@ build: yara
debug_results: build
cargo rustc --release -- --print link-args
ldd *.node
+ nm build/yara/bin/yara | grep json
+ nm build/yara/lib/libyara.a | grep json
+ nm *.node | grep json
test: build
yarn run test
\ No newline at end of file
diff --git a/__test__/index.spec.mjs b/__test__/index.spec.mjs
@@ -1,6 +1,7 @@
import test from 'ava'
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
+import * as fs from 'fs';
import { YaraCompiler } from '../index.js'
const TEST_RULE = "rule TestRule {\n condition:\n true\n}"
@@ -104,4 +105,58 @@ test('can match file based rules', (t) => {
}
])
});
+})
+
+
+test('can match file based json rules', (t) => {
+ const data = fs.readFileSync(join(__dirname, "./test.json"), 'utf8');
+ t.plan(2)
+ t.notThrows(() => {
+ const compiler = new YaraCompiler([{
+ filename: join(__dirname, "./json_test.yara")
+ }, {
+ filename: join(__dirname, "./test.yara")
+ }], []);
+ const scanner = compiler.newScanner();
+ const result = scanner.scanString(data);
+ t.deepEqual(result, [
+ {
+ identifier: "string_array_includes",
+ namespace: "default",
+ metadatas: [],
+ tags: [],
+ strings: []
+ }, {
+ identifier: "string_array_includes_nested",
+ namespace: "default",
+ metadatas: [],
+ tags: [],
+ strings: []
+ }, {
+ identifier: "integer_array_includes",
+ namespace: "default",
+ metadatas: [],
+ tags: [],
+ strings: []
+ }, {
+ identifier: "integer_array_includes_nested",
+ namespace: "default",
+ metadatas: [],
+ tags: [],
+ strings: []
+ }, {
+ identifier: "float_array_includes",
+ namespace: "default",
+ metadatas: [],
+ tags: [],
+ strings: []
+ }, {
+ identifier: "float_array_includes_nested",
+ namespace: "default",
+ metadatas: [],
+ tags: [],
+ strings: []
+ }
+ ])
+ });
})
\ No newline at end of file
diff --git a/__test__/json_test.yara b/__test__/json_test.yara
@@ -0,0 +1,43 @@
+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")
+}
+
+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")
+}
+
+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)
+}
+
+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)
+}
+
+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)
+}
+
+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)
+}
+\ No newline at end of file
diff --git a/__test__/test.json b/__test__/test.json
@@ -0,0 +1,50 @@
+{
+ "keykey": "valuevalue",
+ "foo": {
+ "bar": "valuevalue",
+ "baz": {
+ "boo": "value"
+ }
+ },
+ "numbers": {
+ "int": 1,
+ "float": 1.1
+ },
+ "regex": "e2c87f81a9bcb33d4f943a4072c137c2",
+ "strArray": [
+ "one",
+ "two",
+ "three"
+ ],
+ "string": {
+ "strArray": [
+ "one",
+ "two",
+ "three"
+ ]
+ },
+ "intArray": [
+ 1,
+ 2,
+ 3
+ ],
+ "integer": {
+ "intArray": [
+ 1,
+ 2,
+ 3
+ ]
+ },
+ "floatArray": [
+ 1,
+ 2,
+ 3
+ ],
+ "float": {
+ "floatArray": [
+ 1,
+ 2,
+ 3
+ ]
+ }
+}
+\ No newline at end of file
diff --git a/build.rs b/build.rs
@@ -1,7 +1,18 @@
+use std::path::PathBuf;
+
extern crate napi_build;
fn main() {
println!("cargo:rerun-if-changed=build");
println!("cargo:rerun-if-changed=deps");
+
+ // Workaround weird jansson linking
+
+ let base = env!("CARGO_MANIFEST_DIR");
+ let mut include_path = PathBuf::from(base);
+ include_path.push("build/jansson/lib");
+
+ println!("cargo:rustc-link-search=native={}", include_path.display());
+ println!("cargo:rustc-link-lib=static=jansson");
napi_build::setup();
}
diff --git a/changelog.d/+json.feature b/changelog.d/+json.feature
@@ -0,0 +1 @@
+Add a json module to the used yara version
+\ No newline at end of file
diff --git a/deps/json.c b/deps/json.c
@@ -0,0 +1,485 @@
+/*
+Copyright (c) 2014. The YARA Authors. All Rights Reserved.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+3. Neither the name of the copyright holder nor the names of its contributors
+may be used to endorse or promote products derived from this software without
+specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <jansson.h>
+#include <stdio.h>
+#include <yara/modules.h>
+#include <yara/globals.h>
+#include <string.h>
+
+#define MODULE_NAME json
+
+// Ensures Key exists in JSON
+define_function(key_exists)
+{
+ char *key = strdup(string_argument(1));
+
+ json_t *json = yr_module()->data;
+ if (json == NULL)
+ {
+ return_integer(0);
+ }
+
+ // Split key into possible subcomponents - separated by '.'
+ json_t *iter = json;
+ char *token = strtok(key, ".");
+ while (token != NULL)
+ {
+ iter = json_object_get(iter, token);
+ if (iter == NULL)
+ {
+ return_integer(0);
+ }
+ token = strtok(NULL, ".");
+ }
+
+ free(key);
+ free(token);
+
+ return_integer(1);
+}
+
+// Assert String value
+define_function(value_exists_string)
+{
+ char *key = strdup(string_argument(1));
+ char *value = strdup(string_argument(2));
+
+ json_t *json = yr_module()->data;
+ if (json == NULL)
+ {
+ return_integer(0);
+ }
+
+ // Split key into possible subcomponents - separated by '.'
+ json_t *iter = json;
+ char *token = strtok(key, ".");
+ char *prevToken = strdup(token);
+
+ while (token != NULL)
+ {
+ iter = json_object_get(iter, token);
+ if (iter == NULL)
+ {
+ return_integer(0);
+ }
+
+ strcpy(prevToken, token);
+ token = strtok(NULL, ".");
+ }
+
+ const char *found = json_string_value(iter);
+ if (found == NULL)
+ {
+ printf("no string value could be obtained from value at key\n");
+ return_integer(0);
+ }
+
+ if (strcmp(found, value) != 0)
+ {
+ return_integer(0);
+ }
+ free(key);
+ free(value);
+ free(prevToken);
+ free(token);
+
+ return_integer(1);
+}
+
+// Assert Integer value
+define_function(value_exists_integer)
+{
+ char *key = strdup(string_argument(1));
+ int value = integer_argument(2);
+
+ json_t *json = yr_module()->data;
+ if (json == NULL)
+ {
+ return_integer(0);
+ }
+
+ // Split key into possible subcomponents - separated by '.'
+ json_t *iter = json;
+ char *token = strtok(key, ".");
+ char *prevToken = strdup(token);
+
+ while (token != NULL)
+ {
+ iter = json_object_get(iter, token);
+ if (iter == NULL)
+ {
+ return_integer(0);
+ }
+
+ strcpy(prevToken, token);
+ token = strtok(NULL, ".");
+ }
+
+ double foundNumber = json_number_value(iter);
+ if (foundNumber == 0.0)
+ {
+ printf("no number value could be obtained from value at key\n");
+ return_integer(0);
+ }
+ int found = (int)foundNumber;
+
+ if (found != value)
+ {
+ return_integer(0);
+ }
+ free(key);
+ free(prevToken);
+ free(token);
+
+ return_integer(1);
+}
+
+// Assert Regex value
+define_function(value_exists_regex)
+{
+ YR_SCAN_CONTEXT *context = yr_scan_context();
+ char *key = strdup(string_argument(1));
+ RE *value = regexp_argument(2);
+
+ json_t *json = yr_module()->data;
+ if (json == NULL)
+ {
+ return_integer(0);
+ }
+
+ // Split key into possible subcomponents - separated by '.'
+ json_t *iter = json;
+ char *token = strtok(key, ".");
+ char *prevToken = strdup(token);
+
+ while (token != NULL)
+ {
+ iter = json_object_get(iter, token);
+ if (iter == NULL)
+ {
+ return_integer(0);
+ }
+
+ strcpy(prevToken, token);
+ token = strtok(NULL, ".");
+ }
+
+ const char *found = json_string_value(iter);
+ if (found == NULL)
+ {
+ printf("no string value could be obtained from value at key\n");
+ return_integer(0);
+ }
+ if (yr_re_match(context, value, found) <= 0)
+ {
+ return_integer(0);
+ }
+
+ free(key);
+ free(prevToken);
+ free(token);
+
+ return_integer(1);
+}
+
+// Assert Float value
+define_function(value_exists_float)
+{
+ char *key = strdup(string_argument(1));
+ double value = float_argument(2);
+
+ json_t *json = yr_module()->data;
+ if (json == NULL)
+ {
+ return_integer(0);
+ }
+
+ // Split key into possible subcomponents - separated by '.'
+ json_t *iter = json;
+ char *token = strtok(key, ".");
+ char *prevToken = strdup(token);
+
+ while (token != NULL)
+ {
+ iter = json_object_get(iter, token);
+ if (iter == NULL)
+ {
+ return_integer(0);
+ }
+
+ strcpy(prevToken, token);
+ token = strtok(NULL, ".");
+ }
+
+ double found = json_number_value(iter);
+ if (found == 0.0)
+ {
+ printf("no number value could be obtained from value at key\n");
+ return_integer(0);
+ }
+
+ if (found != value)
+ {
+ return_integer(0);
+ }
+ free(key);
+ free(prevToken);
+ free(token);
+
+ return_integer(1);
+}
+
+// String Array includes
+define_function(string_array_includes)
+{
+ char *key = strdup(string_argument(1));
+ char *value = strdup(string_argument(2));
+
+ json_t *json = yr_module()->data;
+ if (json == NULL)
+ {
+ return_integer(0);
+ }
+
+ // Split key into possible subcomponents - separated by '.'
+ json_t *iter = json;
+ char *token = strtok(key, ".");
+ char *prevToken = strdup(token);
+
+ while (token != NULL)
+ {
+ iter = json_object_get(iter, token);
+ if (iter == NULL)
+ {
+ return_integer(0);
+ }
+
+ strcpy(prevToken, token);
+ token = strtok(NULL, ".");
+ }
+
+ json_t *array = iter;
+ bool isArray = json_is_array(array);
+
+ size_t index;
+ json_t *val;
+
+ json_array_foreach(array, index, val)
+ {
+ json_t *element = json_array_get(array, index);
+ const char *found = json_string_value(element);
+ if (strcmp(found, value) == 0)
+ {
+ return_integer(1);
+ }
+ }
+
+ free(array);
+ free(key);
+ free(key);
+ free(value);
+ free(prevToken);
+ free(token);
+
+ return_integer(0);
+}
+// Integer Array includes
+define_function(integer_array_includes)
+{
+ char *key = strdup(string_argument(1));
+ int value = integer_argument(2);
+
+ json_t *json = yr_module()->data;
+ if (json == NULL)
+ {
+ return_integer(0);
+ }
+
+ // Split key into possible subcomponents - separated by '.'
+ json_t *iter = json;
+ char *token = strtok(key, ".");
+ char *prevToken = strdup(token);
+
+ while (token != NULL)
+ {
+ iter = json_object_get(iter, token);
+ if (iter == NULL)
+ {
+ return_integer(0);
+ }
+
+ strcpy(prevToken, token);
+ token = strtok(NULL, ".");
+ }
+
+ json_t *array = iter;
+ bool isArray = json_is_array(array);
+
+ size_t index;
+ json_t *val;
+
+ json_array_foreach(array, index, val)
+ {
+ json_t *element = json_array_get(array, index);
+ double foundNumber = json_number_value(element);
+ if (foundNumber == 0.0)
+ {
+ printf("no number value could be obtained from value at key\n");
+ return_integer(0);
+ }
+ int found = (int)foundNumber;
+
+ if (found == value)
+ {
+ return_integer(1);
+ }
+ }
+
+ free(array);
+ free(key);
+ free(key);
+ free(value);
+ free(prevToken);
+ free(token);
+
+ return_integer(0);
+}
+// Float Array includes
+define_function(float_array_includes)
+{
+ char *key = strdup(string_argument(1));
+ double value = float_argument(2);
+
+ json_t *json = yr_module()->data;
+ if (json == NULL)
+ {
+ return_integer(0);
+ }
+
+ // Split key into possible subcomponents - separated by '.'
+ json_t *iter = json;
+ char *token = strtok(key, ".");
+ char *prevToken = strdup(token);
+
+ while (token != NULL)
+ {
+ iter = json_object_get(iter, token);
+ if (iter == NULL)
+ {
+ return_integer(0);
+ }
+
+ strcpy(prevToken, token);
+ token = strtok(NULL, ".");
+ }
+
+ json_t *array = iter;
+ bool isArray = json_is_array(array);
+
+ size_t index;
+ json_t *val;
+
+ json_array_foreach(array, index, val)
+ {
+ json_t *element = json_array_get(array, index);
+ double found = json_number_value(element);
+ if (found == 0.0)
+ {
+ printf("no number value could be obtained from value at key\n");
+ return_integer(0);
+ }
+
+ if (found == value)
+ {
+ return_integer(1);
+ }
+ }
+
+ free(array);
+ free(key);
+ free(key);
+ free(prevToken);
+ free(token);
+
+ return_integer(0);
+}
+
+begin_declarations;
+
+declare_function("key_exists", "s", "i", key_exists);
+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);
+end_declarations;
+
+int module_initialize(YR_MODULE *module)
+{
+ return ERROR_SUCCESS;
+}
+
+int module_finalize(YR_MODULE *module)
+{
+ return ERROR_SUCCESS;
+}
+
+int module_load(
+ YR_SCAN_CONTEXT *context,
+ YR_OBJECT *module_object,
+ void *module_data,
+ size_t module_data_size)
+{
+ // Get first Memory Block
+ YR_MEMORY_BLOCK *block = first_memory_block(context);
+ const uint8_t *block_data = block->fetch_data(block);
+
+ // Parse and Save JSON to Module
+ json_error_t json_error;
+ int flags = JSON_DECODE_INT_AS_REAL | JSON_ALLOW_NUL;
+
+ json_t *json = json_loads((const char *)block_data, flags, &json_error);
+ if (!json)
+ {
+ // fprintf(stderr, "most likely not a json file. error on line %d: %s\n", json_error.line, json_error.text);
+ // NOT a JSON file or a VALID JSON FILE
+ // YR_DEBUG_FPRINTF(2, stderr, "most likely not a json file. error on line %d: %s\n", json_error.line, json_error.text);
+ module_object->data = NULL;
+ return ERROR_SUCCESS;
+ }
+
+ // JSON is valid
+ module_object->data = json;
+
+ return ERROR_SUCCESS;
+}
+
+int module_unload(YR_OBJECT *module_object)
+{
+ free(module_object->data);
+ return ERROR_SUCCESS;
+}