summaryrefslogtreecommitdiffstats
path: root/xml
diff options
context:
space:
mode:
authorAlex Nelson <ajnelson@cs.ucsc.edu>2011-08-12 23:03:37 -0700
committerRichard W.M. Jones <rjones@redhat.com>2011-08-13 09:42:27 +0100
commite0b21193257f9784b28e931525f2a382a74775c6 (patch)
tree970d790ff798a915d8ec8b24b421dce551c107f2 /xml
parent98d83de9444c893fded2e92a3c454ffbda4bd4ad (diff)
downloadhivex-e0b21193257f9784b28e931525f2a382a74775c6.tar.gz
hivex-e0b21193257f9784b28e931525f2a382a74775c6.tar.xz
hivex-e0b21193257f9784b28e931525f2a382a74775c6.zip
Report last-modified time of hive root and nodes
The infrastructure for modified-time reporting has been essentially unused. These changes report the registry time by treating the time fields as Windows filetime fields stored in little-Endian (which means they can be treated as a single 64-bit little-Endian integer). This patch adds to the hivex ABI: * int64_t hivex_last_modified (hive_h *) * int64_t hivex_node_timestamp (hive_h *, hive_node_h) These two functions return the hive's last-modified time and a particular node's last-modified time, respectively. Credit to Richard Jones for the ABI suggestion, and for the tip on Microsoft's filetime time span. hivexml employs these two functions to produce mtime elements for a hive and all of its nodes, producing ISO-8601 formatted time. Signed-off-by: Alex Nelson <ajnelson@cs.ucsc.edu> A lot of code cleanup by RWMJ.
Diffstat (limited to 'xml')
-rw-r--r--xml/hivexml.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/xml/hivexml.c b/xml/hivexml.c
index 90cb22b..2967ac9 100644
--- a/xml/hivexml.c
+++ b/xml/hivexml.c
@@ -25,6 +25,7 @@
#include <inttypes.h>
#include <unistd.h>
#include <errno.h>
+#include <time.h>
#include <libxml/xmlwriter.h>
@@ -39,6 +40,8 @@
//#define N_(str) str
#endif
+static char *filetime_to_8601 (int64_t windows_ticks);
+
/* Callback functions. */
static int node_start (hive_h *, void *, hive_node_h, const char *name);
static int node_end (hive_h *, void *, hive_node_h, const char *name);
@@ -124,6 +127,17 @@ main (int argc, char *argv[])
XML_CHECK (xmlTextWriterStartDocument, (writer, NULL, "utf-8", NULL));
XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "hive"));
+ int64_t hive_mtime = hivex_last_modified (h);
+ if (hive_mtime >= 0) {
+ char *timebuf = filetime_to_8601 (hive_mtime);
+ if (timebuf) {
+ XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "mtime"));
+ XML_CHECK (xmlTextWriterWriteString, (writer, BAD_CAST timebuf));
+ XML_CHECK (xmlTextWriterEndElement, (writer));
+ free (timebuf);
+ }
+ }
+
if (hivex_visit (h, &visitor, sizeof visitor, writer, visit_flags) == -1) {
perror (argv[optind]);
exit (EXIT_FAILURE);
@@ -141,12 +155,66 @@ main (int argc, char *argv[])
exit (EXIT_SUCCESS);
}
+/* Convert Windows filetime to ISO 8601 format.
+ * http://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux/6161842#6161842
+ *
+ * Source for time_t->char* conversion: Fiwalk version 0.6.14's
+ * fiwalk.cpp.
+ *
+ * The caller should free the returned buffer.
+ */
+
+#define WINDOWS_TICK 10000000LL
+#define SEC_TO_UNIX_EPOCH 11644473600LL
+#define TIMESTAMP_BUF_LEN 32
+
+static char *
+filetime_to_8601 (int64_t windows_ticks)
+{
+ char *ret;
+ time_t t;
+ struct tm *tm;
+
+ t = windows_ticks / WINDOWS_TICK - SEC_TO_UNIX_EPOCH;
+ tm = gmtime (&t);
+ if (tm == NULL)
+ return NULL;
+
+ ret = malloc (TIMESTAMP_BUF_LEN);
+ if (ret == NULL) {
+ perror ("malloc");
+ exit (EXIT_FAILURE);
+ }
+
+ if (strftime (ret, TIMESTAMP_BUF_LEN, "%FT%TZ", tm) == 0) {
+ perror ("strftime");
+ exit (EXIT_FAILURE);
+ }
+
+ return ret;
+}
+
static int
node_start (hive_h *h, void *writer_v, hive_node_h node, const char *name)
{
+ int64_t last_modified;
+ char *timebuf;
+
xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "node"));
XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "name", BAD_CAST name));
+
+ last_modified = hivex_node_timestamp (h, node);
+ if (last_modified >= 0) {
+ timebuf = filetime_to_8601 (last_modified);
+ if (timebuf) {
+ XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "mtime"));
+ XML_CHECK (xmlTextWriterWriteString, (writer, BAD_CAST timebuf));
+ XML_CHECK (xmlTextWriterEndElement, (writer));
+ free (timebuf);
+ }
+ }
+
return 0;
}