From d00dc913aad7111ffd1cc3692a7e40426141889c Mon Sep 17 00:00:00 2001 From: Matteo Cafasso Date: Tue, 25 Apr 2017 23:03:03 +0300 Subject: [PATCH] New API: internal_yara_scan 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 --- daemon/yara.c | 86 ++++++++++++++++++++++++ generator/actions_yara.ml | 8 +++ 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 +- po/POTFILES | 1 + 9 files changed, 110 insertions(+), 1 deletion(-) diff --git a/daemon/yara.c b/daemon/yara.c index 56eec74ad..0fd09815a 100644 --- a/daemon/yara.c +++ b/daemon/yara.c @@ -58,6 +58,8 @@ static bool initialized = false; static int compile_rules_file (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. @@ -125,6 +127,38 @@ do_yara_destroy (void) return 0; } +/* Has one FileOut parameter. */ +int +do_internal_yara_scan (const char *path) +{ + int r; + 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 == -1) { + reply_with_perror ("%s", path); + return -1; + } + + reply (NULL, NULL); /* Reply message. */ + + r = yr_rules_scan_fd (rules, fd, 0, yara_rules_callback, (void *) path, 0); + if (r == ERROR_SUCCESS) + r = 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. */ @@ -184,6 +218,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 r; + size_t len; + CLEANUP_FREE char *buf = NULL; + struct guestfs_int_yara_detection detection; + + detection.yara_name = (char *) name; + detection.yara_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); + + r = xdr_guestfs_int_yara_detection (&xdr, &detection); + if (r == 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/actions_yara.ml b/generator/actions_yara.ml index 388954f25..83896c5d3 100644 --- a/generator/actions_yara.ml +++ b/generator/actions_yara.ml @@ -53,4 +53,12 @@ Previously loaded rules will be destroyed." }; longdesc = "\ Destroy previously loaded Yara rules in order to free libguestfs resources." }; + { defaults with + name = "internal_yara_scan"; added = (1, 37, 13); + style = RErr, [Pathname "path"; FileOut "filename"], []; + visibility = VInternal; + optional = Some "libyara"; + shortdesc = "scan a file with the loaded yara rules"; + longdesc = "Internal function for yara_scan." }; + ] 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..834fa9c54 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 = [ + "yara_name", FString; + "yara_rule", FString; + ]; + s_camel_name = "YaraDetection" }; + ] (* end of structs *) let lookup_struct name = diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc index 8fa8599d3..a6dcba022 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 \ @@ -141,6 +142,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 diff --git a/po/POTFILES b/po/POTFILES index c8423bc64..d1542b272 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -313,6 +313,7 @@ gobject/src/struct-utsname.c gobject/src/struct-version.c gobject/src/struct-xattr.c gobject/src/struct-xfsinfo.c +gobject/src/struct-yara_detection.c gobject/src/tristate.c inspector/inspector.c java/actions-0.c