The internal_yara_scan runs the Yara engine with the previously loaded
rules against the given file.
For each rule matching against the scanned file, a struct containing
the file name and the rule identifier is returned.
The gathered list of yara_detection structs is serialised into XDR format
and written to a file.
Signed-off-by: Matteo Cafasso <noxdafox(a)gmail.com>
---
daemon/yara.c | 86 ++++++++++++++++++++++++++++++++
generator/proc_nr.ml | 1 +
generator/structs.ml | 9 ++++
gobject/Makefile.inc | 2 +
java/Makefile.inc | 1 +
java/com/redhat/et/libguestfs/.gitignore | 1 +
lib/MAX_PROC_NR | 2 +-
7 files changed, 101 insertions(+), 1 deletion(-)
diff --git a/daemon/yara.c b/daemon/yara.c
index cb49593c7..471547341 100644
--- a/daemon/yara.c
+++ b/daemon/yara.c
@@ -54,6 +54,8 @@ static bool initialized = false;
static int compile_rules_file (const char *, const char *);
static void compile_error_callback (int, const char *, int, const char *, void *);
static void cleanup_destroy_yara_compiler (void *ptr);
+static int yara_rules_callback (int , void *, void *);
+static int send_detection_info (const char *, YR_RULE *);
/* Has one FileIn parameter.
* Takes optional arguments, consult optargs_bitmask.
@@ -119,6 +121,38 @@ do_yara_destroy (void)
return 0;
}
+/* Has one FileOut parameter. */
+int
+do_internal_yara_scan (const char *path)
+{
+ int ret = 0;
+ CLEANUP_CLOSE int fd = -1;
+
+ if (rules == NULL) {
+ reply_with_error ("no yara rules loaded");
+ return -1;
+ }
+
+ CHROOT_IN;
+ fd = open (path, O_RDONLY|O_CLOEXEC);
+ CHROOT_OUT;
+
+ if (fd < 0) {
+ reply_with_perror ("%s", path);
+ return -1;
+ }
+
+ reply (NULL, NULL); /* Reply message. */
+
+ ret = yr_rules_scan_fd (rules, fd, 0, yara_rules_callback, (void *) path, 0);
+ if (ret == ERROR_SUCCESS)
+ ret = send_file_end (0); /* File transfer end. */
+ else
+ send_file_end (1); /* Cancel file transfer. */
+
+ return 0;
+}
+
/* Compile source code rules and load them.
* Return ERROR_SUCCESS on success, Yara error code type on error.
*/
@@ -170,6 +204,58 @@ compile_error_callback(int level, const char *name, int line,
fprintf (stderr, "Yara warning (line %d): %s\n", line, message);
}
+/* Yara scan callback, called by yr_rules_scan_file.
+ * Return 0 on success, -1 on error.
+ */
+static int
+yara_rules_callback (int code, void *message, void *data)
+{
+ int ret = 0;
+
+ if (code == CALLBACK_MSG_RULE_MATCHING)
+ ret = send_detection_info ((const char *)data, (YR_RULE *) message);
+
+ return (ret == 0) ? CALLBACK_CONTINUE : CALLBACK_ERROR;
+}
+
+/* Serialize file path and rule name and send it out.
+ * Return 0 on success, -1 on error.
+ */
+static int
+send_detection_info (const char *name, YR_RULE *rule)
+{
+ XDR xdr;
+ int ret = 0;
+ size_t len = 0;
+ CLEANUP_FREE char *buf = NULL;
+ struct guestfs_int_yara_detection detection;
+
+ detection.name = (char *) name;
+ detection.rule = (char *) rule->identifier;
+
+ /* Serialize detection struct. */
+ buf = malloc (GUESTFS_MAX_CHUNK_SIZE);
+ if (buf == NULL) {
+ perror ("malloc");
+ return -1;
+ }
+
+ xdrmem_create (&xdr, buf, GUESTFS_MAX_CHUNK_SIZE, XDR_ENCODE);
+
+ ret = xdr_guestfs_int_yara_detection (&xdr, &detection);
+ if (ret == 0) {
+ perror ("xdr_guestfs_int_yara_detection");
+ return -1;
+ }
+
+ len = xdr_getpos (&xdr);
+
+ xdr_destroy (&xdr);
+
+ /* Send serialised yara_detection out. */
+ return send_file_write (buf, len);
+}
+
/* Clean up yara handle on daemon exit. */
void yara_finalize (void) __attribute__((destructor));
diff --git a/generator/proc_nr.ml b/generator/proc_nr.ml
index d471b1a83..c7619638a 100644
--- a/generator/proc_nr.ml
+++ b/generator/proc_nr.ml
@@ -481,6 +481,7 @@ let proc_nr = [
471, "mksquashfs";
472, "yara_load";
473, "yara_destroy";
+474, "internal_yara_scan";
]
(* End of list. If adding a new entry, add it at the end of the list
diff --git a/generator/structs.ml b/generator/structs.ml
index c1c9b668e..01aa3d371 100644
--- a/generator/structs.ml
+++ b/generator/structs.ml
@@ -469,6 +469,15 @@ let structs = [
];
s_camel_name = "TSKDirent" };
+ (* Yara detection information. *)
+ { defaults with
+ s_name = "yara_detection";
+ s_cols = [
+ "name", FString;
+ "rule", FString;
+ ];
+ s_camel_name = "YaraDetection" };
+
] (* end of structs *)
let lookup_struct name =
diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc
index b0ebf15d9..4b067d9e0 100644
--- a/gobject/Makefile.inc
+++ b/gobject/Makefile.inc
@@ -49,6 +49,7 @@ guestfs_gobject_headers= \
include/guestfs-gobject/struct-version.h \
include/guestfs-gobject/struct-xattr.h \
include/guestfs-gobject/struct-xfsinfo.h \
+ include/guestfs-gobject/struct-yara_detection.h \
include/guestfs-gobject/optargs-add_domain.h \
include/guestfs-gobject/optargs-add_drive.h \
include/guestfs-gobject/optargs-add_drive_scratch.h \
@@ -142,6 +143,7 @@ guestfs_gobject_sources= \
src/struct-version.c \
src/struct-xattr.c \
src/struct-xfsinfo.c \
+ src/struct-yara_detection.c \
src/optargs-add_domain.c \
src/optargs-add_drive.c \
src/optargs-add_drive_scratch.c \
diff --git a/java/Makefile.inc b/java/Makefile.inc
index b0ddb5c3d..3a202cee0 100644
--- a/java/Makefile.inc
+++ b/java/Makefile.inc
@@ -46,4 +46,5 @@ java_built_sources = \
com/redhat/et/libguestfs/Version.java \
com/redhat/et/libguestfs/XAttr.java \
com/redhat/et/libguestfs/XFSInfo.java \
+ com/redhat/et/libguestfs/YaraDetection.java \
com/redhat/et/libguestfs/GuestFS.java
diff --git a/java/com/redhat/et/libguestfs/.gitignore
b/java/com/redhat/et/libguestfs/.gitignore
index 89d923949..bc03cb965 100644
--- a/java/com/redhat/et/libguestfs/.gitignore
+++ b/java/com/redhat/et/libguestfs/.gitignore
@@ -23,3 +23,4 @@ VG.java
Version.java
XAttr.java
XFSInfo.java
+YaraDetection.java
diff --git a/lib/MAX_PROC_NR b/lib/MAX_PROC_NR
index 8410b8b89..5f3bb9813 100644
--- a/lib/MAX_PROC_NR
+++ b/lib/MAX_PROC_NR
@@ -1 +1 @@
-473
+474
--
2.11.0