diff --git a/DataModel/nbproject/genfiles.properties b/DataModel/nbproject/genfiles.properties
index 80fe34e47bb67c19086fab933ca86c6da82deb4b..1051d9cbb36192e81a7d747a80118d88ffe63d35 100644
--- a/DataModel/nbproject/genfiles.properties
+++ b/DataModel/nbproject/genfiles.properties
@@ -3,6 +3,6 @@ build.xml.script.CRC32=3bd58878
 build.xml.stylesheet.CRC32=a56c6a5b@1.42.2
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=d5d42932
+nbproject/build-impl.xml.data.CRC32=68292042
 nbproject/build-impl.xml.script.CRC32=b0a13adb
-nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.46.1
diff --git a/DataModel/nbproject/project.properties b/DataModel/nbproject/project.properties
index 106624d8e802392cd91bcf3279f7f0fd1b120c1d..9c6bd6be1d62077c714df2f6c63df469632728fb 100644
--- a/DataModel/nbproject/project.properties
+++ b/DataModel/nbproject/project.properties
@@ -1,4 +1,3 @@
-file.reference.sqlite-jdbc-3.6.20.jar=release/modules/ext/sqlite-jdbc-3.6.20.jar
 file.reference.Tsk_DataModel.jar=release/modules/ext/Tsk_DataModel.jar
 javac.source=1.6
 javac.compilerargs=-Xlint -Xlint:-serial
diff --git a/DataModel/nbproject/project.xml b/DataModel/nbproject/project.xml
index 873a58d40b111f97cb16b55431a24b91f2353b25..16adc431b1c6bfb919ea33964109fc22d93a1885 100644
--- a/DataModel/nbproject/project.xml
+++ b/DataModel/nbproject/project.xml
@@ -59,16 +59,15 @@
             <public-packages>
                 <package>org.sleuthkit.autopsy.datamodel</package>
                 <package>org.sleuthkit.datamodel</package>
-                <package>org.sqlite</package>
             </public-packages>
-            <class-path-extension>
-                <runtime-relative-path>ext/sqlite-jdbc-3.6.20.jar</runtime-relative-path>
-                <binary-origin>release/modules/ext/sqlite-jdbc-3.6.20.jar</binary-origin>
-            </class-path-extension>
             <class-path-extension>
                 <runtime-relative-path>ext/Tsk_DataModel.jar</runtime-relative-path>
                 <binary-origin>release/modules/ext/Tsk_DataModel.jar</binary-origin>
             </class-path-extension>
+            <class-path-extension>
+                <runtime-relative-path>ext/sqlite-jdbc-3.7.2.jar</runtime-relative-path>
+                <binary-origin>release/modules/ext/sqlite-jdbc-3.7.2.jar</binary-origin>
+            </class-path-extension>
         </data>
     </configuration>
 </project>
diff --git a/DataModel/release/modules/ext/sqlite-jdbc-3.7.6.3-20110609.081603-3.jar b/DataModel/release/modules/ext/sqlite-jdbc-3.7.6.3-20110609.081603-3.jar
new file mode 100644
index 0000000000000000000000000000000000000000..187bccb2ef290487fa587d8fd55ecd5293a74acd
Binary files /dev/null and b/DataModel/release/modules/ext/sqlite-jdbc-3.7.6.3-20110609.081603-3.jar differ
diff --git a/DataModel/src/org/sleuthkit/autopsy/datamodel/KeyValueThing.java b/DataModel/src/org/sleuthkit/autopsy/datamodel/KeyValueThing.java
index 3441bcb9ec492c219c2bb6bccb7a332ef132e9bc..ddf5870bc9fea22787506bb64ab6ad862653f837 100755
--- a/DataModel/src/org/sleuthkit/autopsy/datamodel/KeyValueThing.java
+++ b/DataModel/src/org/sleuthkit/autopsy/datamodel/KeyValueThing.java
@@ -1,22 +1,3 @@
-/*
- * Autopsy Forensic Browser
- *
- * Copyright 2011 Basis Technology Corp.
- * Contact: carrier <at> sleuthkit <dot> org
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
 package org.sleuthkit.autopsy.datamodel;
 
 import java.util.Map;
@@ -27,7 +8,7 @@ public class KeyValueThing {
     String name;
 
     /**
-     * 
+     *
      * @param map must iterate it keys and values in a consistent order
      * (use of LinkedHashMap is recommended)
      * @param id an arbitrary id representing the type of the thing
@@ -38,6 +19,12 @@ public KeyValueThing(String name, Map<String, Object> map, int id) {
         this.id = id;
     }
 
+    public KeyValueThing(String name,  int id) {
+        this.name = name;
+        this.map = null;
+        this.id = id;
+    }
+
     public int getId() {
         return id;
     }
@@ -49,4 +36,9 @@ public Map<String, Object> getMap() {
     public String getName() {
         return name;
     }
+
+    public void addMap(Map<String,Object> inMap)
+    {
+       this.map = inMap;
+    }
 }
\ No newline at end of file
diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/Bundle.properties b/Ingest/src/org/sleuthkit/autopsy/ingest/Bundle.properties
index 0e6f76bb3ef1665a5cdd601ef0ba597a3d2931f0..9aef703e9e9b035c48ef68adb969ef194fcc9d55 100644
--- a/Ingest/src/org/sleuthkit/autopsy/ingest/Bundle.properties
+++ b/Ingest/src/org/sleuthkit/autopsy/ingest/Bundle.properties
@@ -4,7 +4,4 @@ HINT_IngestTopComponent=Ingest window
 OpenIDE-Module-Name=Ingest
 IngestTopComponent.topLable.text=Image ingest services
 IngestTopComponent.startButton.text=Start
-IngestTopComponent.messageFrame.title=Ingest Messages
 IngestTopComponent.refreshFreqLabel.text=Refresh frequency
-IngestTopComponent.refreshFrequencyLabel.text=Refresh Frequency
-IngestTopComponent.ingestProgressLabel.text=File Ingest Progress
diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManager.java
index 2f3417721d5b60a4a26411b819868e0ceaa1eff9..249ef5cdc690eb95986ea409a729808a4a6a3cc5 100644
--- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManager.java
+++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManager.java
@@ -39,7 +39,6 @@
 import org.netbeans.api.progress.ProgressHandleFactory;
 import org.openide.util.Cancellable;
 import org.openide.util.Lookup;
-import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
 import org.sleuthkit.datamodel.FsContent;
 import org.sleuthkit.datamodel.Image;
 
@@ -86,19 +85,25 @@ public class IngestManager {
      * Notifies services when work is complete or should be interrupted using complete() and stop() calls.
      * Does not block and can be called multiple times to enqueue more work to already running background process.
      */
-    void execute(final Collection<IngestServiceAbstract> services, final Collection<Image> images) {
-
-        //queuing start
-        tc.enableStartButton(false);
-        SwingWorker queueWorker = new EnqueueWorker(services, images);
-        queueWorker.execute();
+    void execute(Collection<IngestServiceAbstract> services, final Collection<Image> images) {
+
+        for (Image image : images) {
+            for (IngestServiceAbstract service : services) {
+                switch (service.getType()) {
+                    case Image:
+                        addImage((IngestServiceImage) service, image);
+                        break;
+                    case FsContent:
+                        addFsContent((IngestServiceFsContent) service, image);
+                        break;
+                    default:
+                        logger.log(Level.SEVERE, "Unexpected service type: " + service.getType().name());
+                }
+            }
+        }
 
         logger.log(Level.INFO, "Queues: " + imageQueue.toString() + " " + fsContentQueue.toString());
 
-
-    }
-
-    private void startAll() {
         boolean start = false;
         if (ingester == null) {
             start = true;
@@ -118,7 +123,6 @@ else if (ingester.isDone()
             stats = new IngestManagerStats();
             ingester.execute();
         }
-
     }
 
     /**
@@ -154,13 +158,6 @@ String getReport() {
      */
     public synchronized void postMessage(final IngestMessage message) {
 
-        if (stats != null) {
-            //record the error for stats, if stats are running
-            if (message.getMessageType() == MessageType.ERROR) {
-                stats.addError(message.getSource());
-            }
-        }
-
         SwingUtilities.invokeLater(new Runnable() {
 
             @Override
@@ -275,27 +272,6 @@ private int getNumImages() {
         }
         return ret;
     }
-    
-    private void initMainProgress(final int maximum) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                tc.initProgress(maximum);
-            }
-        });
-         
-        
-    }
-    
-    private void updateMainProgress(final int progress) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                tc.updateProgress(progress);
-            }
-        });
-        
-    }
 
     //manages queue of pending FsContent and IngestServiceFsContent to use on that content
     //TODO in future content sort will be maintained based on priorities
@@ -505,28 +481,6 @@ public String toString() {
             return sb.toString();
         }
 
-        public String toHtmlString() {
-            StringBuilder sb = new StringBuilder();
-            sb.append("<html>");
-            if (startTime != null) {
-                sb.append("Start time: ").append(dateFormatter.format(startTime)).append("<br />");
-            }
-            if (endTime != null) {
-                sb.append("End time: ").append(dateFormatter.format(endTime)).append("<br />");
-            }
-            sb.append("Total ingest time: ").append(getTotalTimeString()).append("<br />");
-            sb.append("Total errors: ").append(errorsTotal).append("<br />");
-            if (errorsTotal > 0) {
-                sb.append("Errors per service:");
-                for (IngestServiceAbstract service : errors.keySet()) {
-                    final int errorsService = errors.get(service);
-                    sb.append("\t").append(service.getName()).append(": ").append(errorsService).append("<br />");
-                }
-            }
-            sb.append("</html>");
-            return sb.toString();
-        }
-
         void start() {
             startTime = new Date();
         }
@@ -542,14 +496,6 @@ long getTotalTime() {
             return endTime.getTime() - startTime.getTime();
         }
 
-        String getStartTimeString() {
-            return dateFormatter.format(startTime);
-        }
-
-        String getEndTimeString() {
-            return dateFormatter.format(endTime);
-        }
-
         String getTotalTimeString() {
             long ms = getTotalTime();
             long hours = TimeUnit.MILLISECONDS.toHours(ms);
@@ -562,7 +508,7 @@ String getTotalTimeString() {
             return sb.toString();
         }
 
-        synchronized void addError(IngestServiceAbstract source) {
+        void addError(IngestServiceAbstract source) {
             ++errorsTotal;
             int curServiceError = errors.get(source);
             errors.put(source, curServiceError + 1);
@@ -606,20 +552,20 @@ public boolean cancel() {
 
                     try {
                         service.process(unit.content);
+                        //check if new files enqueued
+                        int newImages = getNumImages();
+                        if (newImages > numImages) {
+                            numImages = newImages + processedImages + 1;
+                            progress.switchToIndeterminate();
+                            progress.switchToDeterminate(numImages);
+
+                        }
+                        progress.progress("Images (" + service.getName() + ")", ++processedImages);
+                        --numImages;
                     } catch (Exception e) {
                         logger.log(Level.INFO, "Exception from service: " + service.getName(), e);
                         stats.addError(service);
                     }
-                    //check if new files enqueued
-                    int newImages = getNumImages();
-                    if (newImages > numImages) {
-                        numImages = newImages + processedImages + 1;
-                        progress.switchToIndeterminate();
-                        progress.switchToDeterminate(numImages);
-
-                    }
-                    progress.progress("Images (" + service.getName() + ")", ++processedImages);
-                    --numImages;
                 }
             }
 
@@ -627,8 +573,8 @@ public boolean cancel() {
             int numFsContents = getNumFsContents();
             progress.switchToDeterminate(numFsContents);
             int processedFiles = 0;
-            initMainProgress(numFsContents);
             //process fscontents queue
+            progress.progress("Running file ingest services.");
             while (hasNextFsContent()) {
                 QueueUnit<FsContent, IngestServiceFsContent> unit = getNextFsContent();
                 for (IngestServiceFsContent service : unit.services) {
@@ -637,23 +583,21 @@ public boolean cancel() {
                     }
                     try {
                         service.process(unit.content);
+                        int newFsContents = getNumFsContents();
+                        if (newFsContents > numFsContents) {
+                            //update progress bar if new enqueued
+                            numFsContents = newFsContents + processedFiles + 1;
+                            progress.switchToIndeterminate();
+                            progress.switchToDeterminate(numFsContents);
+
+                        }
+                        progress.progress("Files (" + service.getName() + ")", ++processedFiles);
+                        --numFsContents;
                     } catch (Exception e) {
                         logger.log(Level.INFO, "Exception from service: " + service.getName(), e);
                         stats.addError(service);
                     }
                 }
-                int newFsContents = getNumFsContents();
-                if (newFsContents > numFsContents) {
-                    //update progress bar if new enqueued
-                    numFsContents = newFsContents + processedFiles + 1;
-                    progress.switchToIndeterminate();
-                    progress.switchToDeterminate(numFsContents);
-                    initMainProgress(numFsContents);
-
-                }
-                progress.progress("Files", ++processedFiles);
-                updateMainProgress(processedFiles);
-                --numFsContents;
             }
             logger.log(Level.INFO, "Done background processing");
             return null;
@@ -691,10 +635,8 @@ protected void done() {
                 stats.end();
                 progress.finish();
 
-                if (! this.isCancelled()) {
-                    logger.log(Level.INFO, "Summary Report: " + stats.toString());
-                    tc.displayReport(stats.toHtmlString());
-                }
+                //TODO display report
+                logger.log(Level.INFO, "STATS: " + stats.toString());
             }
 
         }
@@ -715,100 +657,6 @@ private void handleInterruption() {
             //empty queues
             emptyFsContents();
             emptyImages();
-            
-            //reset main progress bar
-            initMainProgress(0);
-        }
-    }
-
-    private class EnqueueWorker extends SwingWorker {
-
-        Collection<IngestServiceAbstract> services;
-        final Collection<Image> images;
-        int total;
-
-        EnqueueWorker(final Collection<IngestServiceAbstract> services, final Collection<Image> images) {
-            this.services = services;
-            this.images = images;
-        }
-        private ProgressHandle progress;
-
-        @Override
-        protected Object doInBackground() throws Exception {
-            progress = ProgressHandleFactory.createHandle("Queueing Ingest", new Cancellable() {
-
-                @Override
-                public boolean cancel() {
-                    return EnqueueWorker.this.cancel(true);
-                }
-            });
-
-            total = services.size() * images.size();
-            progress.start(total);
-            //progress.switchToIndeterminate();
-            queueAll(services, images);
-            return null;
-        }
-
-        @Override
-        protected void done() {
-            try {
-                super.get(); //block and get all exceptions thrown while doInBackground()      
-            } catch (CancellationException e) {
-                //task was cancelled
-                handleInterruption();
-
-            } catch (InterruptedException ex) {
-                handleInterruption();
-            } catch (ExecutionException ex) {
-                handleInterruption();
-
-
-            } catch (Exception ex) {
-                handleInterruption();
-
-            } finally {
-                //queing end
-                if (this.isCancelled()) {
-                    //empty queues
-                    emptyFsContents();
-                    emptyImages();
-                } else {
-                    //start ingest workers
-                    startAll();
-                }
-
-                progress.finish();
-                tc.enableStartButton(true);
-            }
-        }
-
-        private void queueAll(Collection<IngestServiceAbstract> services, final Collection<Image> images) {
-            int processed = 0;
-            for (Image image : images) {
-                final String imageName = image.getName();
-                for (IngestServiceAbstract service : services) {
-                    final String serviceName = service.getName();
-                    progress.progress(serviceName + " " + imageName, processed);
-                    switch (service.getType()) {
-                        case Image:
-                            addImage((IngestServiceImage) service, image);
-                            break;
-                        case FsContent:
-                            addFsContent((IngestServiceFsContent) service, image);
-                            break;
-                        default:
-                            logger.log(Level.SEVERE, "Unexpected service type: " + service.getType().name());
-                    }
-                    progress.progress(serviceName + " " + imageName, ++processed);
-                }
-            }
-        }
-
-        private void handleInterruption() {
-            //empty queues
-            emptyFsContents();
-            emptyImages();
         }
     }
 }
diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessage.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessage.java
index abce9b0fbf64daaba3610063b02579a662fa87cf..23c29277ab4f39720651198e6e4f0d446363f4a3 100644
--- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessage.java
+++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessage.java
@@ -18,8 +18,6 @@
  */
 package org.sleuthkit.autopsy.ingest;
 
-import java.text.SimpleDateFormat;
-import java.util.Date;
 import org.sleuthkit.autopsy.datamodel.KeyValueThing;
 
 /**
@@ -40,15 +38,12 @@ public enum MessageType {
     private IngestServiceAbstract source;
     private String text;
     private KeyValueThing data;
-    private Date datePosted;
-    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 
     private IngestMessage(long ID, MessageType messageType, IngestServiceAbstract source, String text) {
         this.ID = ID;
         this.source = source;
         this.messageType = messageType;
         this.text = text;
-        datePosted = new Date();
     }
 
     //getters
@@ -72,24 +67,17 @@ public MessageType getMessageType() {
         return messageType;
     }
     
-    public Date getDatePosted() {
-        return datePosted;
-    }
-    
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
         sb.append(Long.toString(ID)).append(": ");
         sb.append("type: ").append(messageType.name());
-        if (source != null) //can be null for manager messages
-            sb.append(" source: ").append(source.getName());
-        sb.append(" date: ").append(dateFormat.format(datePosted));
+        sb.append(" source: ").append(source.getName());
         sb.append(" text: ").append(text);
         if (data != null)
             sb.append(" data: ").append(data.toString()).append(' ');
         return sb.toString();
     }
-    
 
     @Override
     public boolean equals(Object obj) {
@@ -109,23 +97,21 @@ public boolean equals(Object obj) {
         if (this.source != other.source && (this.source == null || !this.source.equals(other.source))) {
             return false;
         }
-        if (this.datePosted != other.datePosted && (this.datePosted == null || !this.datePosted.equals(other.datePosted))) {
-            return false;
-        }
         return true;
     }
 
     @Override
     public int hashCode() {
         int hash = 7;
-        hash = 29 * hash + (int) (this.ID ^ (this.ID >>> 32));
-        hash = 29 * hash + (this.messageType != null ? this.messageType.hashCode() : 0);
-        hash = 29 * hash + (this.source != null ? this.source.hashCode() : 0);
-        hash = 29 * hash + (this.text != null ? this.text.hashCode() : 0);
-        hash = 29 * hash + (this.datePosted != null ? this.datePosted.hashCode() : 0);
+        hash = 83 * hash + (int) (this.ID ^ (this.ID >>> 32));
+        hash = 83 * hash + (this.messageType != null ? this.messageType.hashCode() : 0);
+        hash = 83 * hash + (this.source != null ? this.source.hashCode() : 0);
+        hash = 83 * hash + (this.text != null ? this.text.hashCode() : 0);
         return hash;
     }
 
+   
+    
 
     //factory methods
     public static IngestMessage createMessage(long ID, MessageType messageType, IngestServiceAbstract source, String message) {
@@ -153,9 +139,4 @@ public static IngestMessage createDataMessage(long ID, IngestServiceAbstract sou
         return im;
     }
     
-    static IngestMessage createManagerMessage(String message) {
-        IngestMessage im = new IngestMessage(0, MessageType.INFO, null, message);
-        return im;
-    }
-    
 }
diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestTopComponent.form b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestTopComponent.form
index f09fc077f32c7ceaff2aa184ecadaa3cae995b7a..c1255b424d34587fe0c49786d7c8e3af4f47ef26 100644
--- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestTopComponent.form
+++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestTopComponent.form
@@ -16,12 +16,12 @@
   <Layout>
     <DimensionLayout dim="0">
       <Group type="103" groupAlignment="0" attributes="0">
-          <Component id="mainScrollPane" alignment="0" pref="340" max="32767" attributes="0"/>
+          <Component id="mainScrollPane" pref="289" max="32767" attributes="0"/>
       </Group>
     </DimensionLayout>
     <DimensionLayout dim="1">
       <Group type="103" groupAlignment="0" attributes="0">
-          <Component id="mainScrollPane" alignment="0" pref="771" max="32767" attributes="0"/>
+          <Component id="mainScrollPane" pref="509" max="32767" attributes="0"/>
       </Group>
     </DimensionLayout>
   </Layout>
@@ -29,245 +29,129 @@
     <Container class="javax.swing.JScrollPane" name="mainScrollPane">
       <Properties>
         <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-          <Dimension value="[322, 749]"/>
+          <Dimension value="[289, 509]"/>
         </Property>
       </Properties>
 
       <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
       <SubComponents>
         <Container class="javax.swing.JPanel" name="mainPanel">
-          <Properties>
-            <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-              <Dimension value="[322, 749]"/>
-            </Property>
-          </Properties>
 
           <Layout>
             <DimensionLayout dim="0">
               <Group type="103" groupAlignment="0" attributes="0">
                   <Group type="102" attributes="0">
-                      <EmptySpace max="-2" attributes="0"/>
                       <Group type="103" groupAlignment="0" attributes="0">
-                          <Group type="102" alignment="1" attributes="0">
-                              <Component id="controlPanel" max="32767" attributes="1"/>
-                              <EmptySpace min="-2" pref="71" max="-2" attributes="0"/>
+                          <Group type="102" alignment="0" attributes="0">
+                              <EmptySpace max="-2" attributes="0"/>
+                              <Group type="103" groupAlignment="1" attributes="0">
+                                  <Component id="topLable" alignment="0" min="-2" max="-2" attributes="1"/>
+                                  <Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
+                                      <Component id="servicesPanel" alignment="0" max="32767" attributes="1"/>
+                                      <Component id="freqSlider" alignment="0" max="32767" attributes="1"/>
+                                  </Group>
+                              </Group>
                           </Group>
                           <Group type="102" alignment="0" attributes="0">
-                              <Component id="messageFrame" min="-2" max="-2" attributes="1"/>
-                              <EmptySpace min="-2" pref="48" max="-2" attributes="0"/>
+                              <EmptySpace max="-2" attributes="0"/>
+                              <Component id="startButton" min="-2" max="-2" attributes="0"/>
+                          </Group>
+                          <Group type="102" alignment="0" attributes="0">
+                              <EmptySpace min="-2" pref="74" max="-2" attributes="0"/>
+                              <Component id="refreshFreqLabel" min="-2" max="-2" attributes="0"/>
                           </Group>
                       </Group>
+                      <EmptySpace pref="173" max="32767" attributes="0"/>
                   </Group>
               </Group>
             </DimensionLayout>
             <DimensionLayout dim="1">
               <Group type="103" groupAlignment="0" attributes="0">
                   <Group type="102" alignment="0" attributes="0">
+                      <EmptySpace min="-2" pref="24" max="-2" attributes="0"/>
+                      <Component id="topLable" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace type="unrelated" max="-2" attributes="0"/>
+                      <Component id="servicesPanel" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="startButton" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
+                      <Component id="freqSlider" min="-2" max="-2" attributes="0"/>
                       <EmptySpace max="-2" attributes="0"/>
-                      <Component id="controlPanel" min="-2" pref="357" max="-2" attributes="0"/>
-                      <EmptySpace min="-2" pref="30" max="-2" attributes="0"/>
-                      <Component id="messageFrame" min="-2" max="-2" attributes="0"/>
-                      <EmptySpace min="-2" pref="127" max="-2" attributes="0"/>
+                      <Component id="refreshFreqLabel" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace pref="198" max="32767" attributes="0"/>
                   </Group>
               </Group>
             </DimensionLayout>
           </Layout>
           <SubComponents>
-            <Container class="javax.swing.JInternalFrame" name="messageFrame">
+            <Component class="javax.swing.JLabel" name="topLable">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Tahoma" size="12" style="0"/>
+                </Property>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestTopComponent.topLable.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
+            <Container class="javax.swing.JPanel" name="servicesPanel">
               <Properties>
                 <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
                   <Border info="org.netbeans.modules.form.compat2.border.LineBorderInfo">
-                    <LineBorder roundedCorners="true" thickness="3">
-                      <Color PropertyName="color" blue="db" green="cd" id="InternalFrame.inactiveTitleBackground" palette="3" red="bf" type="palette"/>
-                    </LineBorder>
+                    <LineBorder/>
                   </Border>
                 </Property>
-                <Property name="maximizable" type="boolean" value="true"/>
-                <Property name="resizable" type="boolean" value="true"/>
-                <Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                  <ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestTopComponent.messageFrame.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-                </Property>
-                <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
-                  <Color id="Hand Cursor"/>
+                <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+                  <Dimension value="[200, 150]"/>
                 </Property>
-                <Property name="frameIcon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
-                  <Image iconType="0" name="null"/>
-                </Property>
-                <Property name="opaque" type="boolean" value="true"/>
                 <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-                  <Dimension value="[280, 260]"/>
+                  <Dimension value="[200, 150]"/>
                 </Property>
-                <Property name="visible" type="boolean" value="true"/>
               </Properties>
 
               <Layout>
                 <DimensionLayout dim="0">
                   <Group type="103" groupAlignment="0" attributes="0">
-                      <EmptySpace min="0" pref="274" max="32767" attributes="0"/>
-                  </Group>
-                </DimensionLayout>
-                <DimensionLayout dim="1">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <EmptySpace min="0" pref="231" max="32767" attributes="0"/>
-                  </Group>
-                </DimensionLayout>
-              </Layout>
-            </Container>
-            <Container class="javax.swing.JPanel" name="controlPanel">
-
-              <Layout>
-                <DimensionLayout dim="0">
-                  <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" attributes="0">
-                          <Group type="103" groupAlignment="0" attributes="0">
-                              <Group type="102" attributes="0">
-                                  <EmptySpace max="-2" attributes="0"/>
-                                  <Group type="103" groupAlignment="0" attributes="0">
-                                      <Component id="topLable" alignment="0" min="-2" max="-2" attributes="1"/>
-                                      <Component id="servicesPanel" alignment="0" min="-2" max="-2" attributes="1"/>
-                                      <Component id="startButton" alignment="0" min="-2" max="-2" attributes="0"/>
-                                      <Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
-                                          <Component id="mainProgressBar" alignment="0" max="32767" attributes="1"/>
-                                          <Component id="freqSlider" alignment="0" max="32767" attributes="1"/>
-                                      </Group>
-                                  </Group>
-                              </Group>
-                              <Group type="102" alignment="0" attributes="0">
-                                  <EmptySpace min="-2" pref="59" max="-2" attributes="0"/>
-                                  <Component id="refreshFrequencyLabel" min="-2" max="-2" attributes="0"/>
-                              </Group>
-                              <Group type="102" alignment="0" attributes="0">
-                                  <EmptySpace min="-2" pref="59" max="-2" attributes="0"/>
-                                  <Component id="ingestProgressLabel" min="-2" max="-2" attributes="0"/>
-                              </Group>
-                          </Group>
-                          <EmptySpace pref="115" max="32767" attributes="0"/>
-                      </Group>
-                      <Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
-                          <Group type="102" alignment="0" attributes="0">
-                              <EmptySpace min="-2" pref="74" max="-2" attributes="0"/>
-                              <Component id="refreshFreqLabel" min="-2" max="-2" attributes="0"/>
-                              <EmptySpace pref="161" max="32767" attributes="0"/>
-                          </Group>
-                      </Group>
+                      <EmptySpace min="0" pref="198" max="32767" attributes="0"/>
                   </Group>
                 </DimensionLayout>
                 <DimensionLayout dim="1">
                   <Group type="103" groupAlignment="0" attributes="0">
-                      <Group type="102" alignment="0" attributes="0">
-                          <EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
-                          <Component id="topLable" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
-                          <Component id="servicesPanel" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Component id="startButton" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace type="unrelated" max="-2" attributes="0"/>
-                          <Component id="freqSlider" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Component id="refreshFrequencyLabel" min="-2" pref="14" max="-2" attributes="0"/>
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Component id="mainProgressBar" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace max="-2" attributes="0"/>
-                          <Component id="ingestProgressLabel" min="-2" max="-2" attributes="0"/>
-                          <EmptySpace pref="228" max="32767" attributes="0"/>
-                      </Group>
-                      <Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
-                          <Group type="102" alignment="0" attributes="0">
-                              <EmptySpace min="-2" pref="555" max="-2" attributes="0"/>
-                              <Component id="refreshFreqLabel" min="-2" max="-2" attributes="0"/>
-                              <EmptySpace max="32767" attributes="0"/>
-                          </Group>
-                      </Group>
+                      <EmptySpace min="0" pref="148" max="32767" attributes="0"/>
                   </Group>
                 </DimensionLayout>
               </Layout>
-              <SubComponents>
-                <Component class="javax.swing.JLabel" name="topLable">
-                  <Properties>
-                    <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-                      <Font name="Tahoma" size="12" style="0"/>
-                    </Property>
-                    <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                      <ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestTopComponent.topLable.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-                    </Property>
-                  </Properties>
-                </Component>
-                <Container class="javax.swing.JPanel" name="servicesPanel">
-                  <Properties>
-                    <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
-                      <Border info="org.netbeans.modules.form.compat2.border.LineBorderInfo">
-                        <LineBorder/>
-                      </Border>
-                    </Property>
-                    <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-                      <Dimension value="[200, 150]"/>
-                    </Property>
-                    <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
-                      <Dimension value="[200, 150]"/>
-                    </Property>
-                  </Properties>
-
-                  <Layout>
-                    <DimensionLayout dim="0">
-                      <Group type="103" groupAlignment="0" attributes="0">
-                          <EmptySpace min="0" pref="198" max="32767" attributes="0"/>
-                      </Group>
-                    </DimensionLayout>
-                    <DimensionLayout dim="1">
-                      <Group type="103" groupAlignment="0" attributes="0">
-                          <EmptySpace min="0" pref="148" max="32767" attributes="0"/>
-                      </Group>
-                    </DimensionLayout>
-                  </Layout>
-                </Container>
-                <Component class="javax.swing.JSlider" name="freqSlider">
-                  <Properties>
-                    <Property name="majorTickSpacing" type="int" value="1"/>
-                    <Property name="maximum" type="int" value="10"/>
-                    <Property name="minimum" type="int" value="1"/>
-                    <Property name="paintLabels" type="boolean" value="true"/>
-                    <Property name="paintTicks" type="boolean" value="true"/>
-                    <Property name="snapToTicks" type="boolean" value="true"/>
-                  </Properties>
-                  <Events>
-                    <EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="freqSliderStateChanged"/>
-                  </Events>
-                </Component>
-                <Component class="javax.swing.JLabel" name="refreshFreqLabel">
-                  <Properties>
-                    <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                      <ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestTopComponent.refreshFreqLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-                    </Property>
-                  </Properties>
-                </Component>
-                <Component class="javax.swing.JButton" name="startButton">
-                  <Properties>
-                    <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                      <ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestTopComponent.startButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-                    </Property>
-                  </Properties>
-                  <Events>
-                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="startButtonActionPerformed"/>
-                  </Events>
-                </Component>
-                <Component class="javax.swing.JLabel" name="refreshFrequencyLabel">
-                  <Properties>
-                    <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                      <ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestTopComponent.refreshFrequencyLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-                    </Property>
-                  </Properties>
-                </Component>
-                <Component class="javax.swing.JProgressBar" name="mainProgressBar">
-                </Component>
-                <Component class="javax.swing.JLabel" name="ingestProgressLabel">
-                  <Properties>
-                    <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-                      <ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestTopComponent.ingestProgressLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-                    </Property>
-                  </Properties>
-                </Component>
-              </SubComponents>
             </Container>
+            <Component class="javax.swing.JSlider" name="freqSlider">
+              <Properties>
+                <Property name="majorTickSpacing" type="int" value="1"/>
+                <Property name="maximum" type="int" value="10"/>
+                <Property name="minimum" type="int" value="1"/>
+                <Property name="paintLabels" type="boolean" value="true"/>
+                <Property name="paintTicks" type="boolean" value="true"/>
+                <Property name="snapToTicks" type="boolean" value="true"/>
+              </Properties>
+              <Events>
+                <EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="freqSliderStateChanged"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JButton" name="startButton">
+              <Properties>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestTopComponent.startButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="startButtonActionPerformed"/>
+              </Events>
+            </Component>
+            <Component class="javax.swing.JLabel" name="refreshFreqLabel">
+              <Properties>
+                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                  <ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestTopComponent.refreshFreqLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+            </Component>
           </SubComponents>
         </Container>
       </SubComponents>
diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestTopComponent.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestTopComponent.java
index 0711b33bca82991d873bc797f062757507f88365..74b9665604c632a2de5eb00a2c5669ff740e9de5 100644
--- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestTopComponent.java
+++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestTopComponent.java
@@ -21,8 +21,6 @@
 import java.awt.BorderLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
 import java.beans.PropertyChangeEvent;
 import java.sql.SQLException;
 import java.util.ArrayList;
@@ -34,7 +32,6 @@
 import java.util.logging.Logger;
 import javax.swing.BoxLayout;
 import javax.swing.JCheckBox;
-import javax.swing.JOptionPane;
 import javax.swing.JScrollPane;
 import javax.swing.JSlider;
 import org.openide.util.NbBundle;
@@ -49,22 +46,21 @@
  * Top component explorer for the Ingest module.
  */
 public final class IngestTopComponent extends TopComponent implements DataExplorer {
-    
+
     private static IngestTopComponent instance;
     private static final Logger logger = Logger.getLogger(IngestTopComponent.class.getName());
     private IngestManager manager = null;
     private Collection<IngestServiceAbstract> services;
     private Map<String, Boolean> serviceStates;
-    private IngestMessagePanel messagePanel;
     private ActionListener serviceSelListener = new ActionListener() {
-        
+
         @Override
         public void actionPerformed(ActionEvent ev) {
             JCheckBox box = (JCheckBox) ev.getSource();
             serviceStates.put(box.getName(), box.isSelected());
         }
     };
-    
+
     private IngestTopComponent() {
         services = new ArrayList<IngestServiceAbstract>();
         serviceStates = new HashMap<String, Boolean>();
@@ -74,66 +70,41 @@ private IngestTopComponent() {
         setToolTipText(NbBundle.getMessage(IngestTopComponent.class, "HINT_IngestTopComponent"));
         //putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE);
         putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
-        
+
     }
-    
+
     public static synchronized IngestTopComponent getDefault() {
         if (instance == null) {
             instance = new IngestTopComponent();
         }
         return instance;
     }
-    
+
     @Override
     public TopComponent getTopComponent() {
         return this;
     }
-    
+
     @Override
     public void propertyChange(PropertyChangeEvent evt) {
         logger.log(Level.INFO, "Unhandled property change: " + evt.getPropertyName());
     }
-    
+
     @Override
     public int getPersistenceType() {
         return TopComponent.PERSISTENCE_NEVER;
     }
-    
+
     private void customizeComponents() {
         //custom GUI setup not done by builder
         freqSlider.setToolTipText("Lower update frequency can optimize performance of certain ingest services, but also reduce real time status feedback");
-        
+
         JScrollPane scrollPane = new JScrollPane(servicesPanel);
         scrollPane.setPreferredSize(this.getSize());
         this.add(scrollPane, BorderLayout.CENTER);
-        
+
         servicesPanel.setLayout(new BoxLayout(servicesPanel, BoxLayout.Y_AXIS));
-        
-        
-        freqSlider.setEnabled(false);
-        
-        messagePanel = new IngestMessagePanel();
-        
-        messagePanel.setOpaque(false);
-        messageFrame.setOpaque(false);
-        messageFrame.addComponentListener(new ComponentAdapter() {
-            
-            @Override
-            public void componentResized(ComponentEvent e) {
-                
-                super.componentResized(e);
-                messageFrame.setPreferredSize(messageFrame.getSize());
-            }
-        });
 
-        //make messageframe on top
-        this.setComponentZOrder(controlPanel, 2);
-        messageFrame.setContentPane(messagePanel);
-        messageFrame.pack();
-        messageFrame.setVisible(true);
-        
-        
-        
         Collection<IngestServiceImage> imageServices = IngestManager.enumerateImageServices();
         for (IngestServiceImage service : imageServices) {
             final String serviceName = service.getName();
@@ -144,7 +115,7 @@ public void componentResized(ComponentEvent e) {
             servicesPanel.add(checkbox);
             serviceStates.put(serviceName, true);
         }
-        
+
         Collection<IngestServiceFsContent> fsServices = IngestManager.enumerateFsContentServices();
         for (IngestServiceFsContent service : fsServices) {
             final String serviceName = service.getName();
@@ -155,7 +126,6 @@ public void componentResized(ComponentEvent e) {
             servicesPanel.add(checkbox);
             serviceStates.put(serviceName, true);
         }
-        
     }
 
     /** This method is called from within the constructor to
@@ -168,41 +138,13 @@ private void initComponents() {
 
         mainScrollPane = new javax.swing.JScrollPane();
         mainPanel = new javax.swing.JPanel();
-        messageFrame = new javax.swing.JInternalFrame();
-        controlPanel = new javax.swing.JPanel();
         topLable = new javax.swing.JLabel();
         servicesPanel = new javax.swing.JPanel();
         freqSlider = new javax.swing.JSlider();
-        refreshFreqLabel = new javax.swing.JLabel();
         startButton = new javax.swing.JButton();
-        refreshFrequencyLabel = new javax.swing.JLabel();
-        mainProgressBar = new javax.swing.JProgressBar();
-        ingestProgressLabel = new javax.swing.JLabel();
-
-        mainScrollPane.setPreferredSize(new java.awt.Dimension(322, 749));
-
-        mainPanel.setPreferredSize(new java.awt.Dimension(322, 749));
-
-        messageFrame.setBorder(new javax.swing.border.LineBorder(javax.swing.UIManager.getDefaults().getColor("InternalFrame.inactiveTitleBackground"), 3, true));
-        messageFrame.setMaximizable(true);
-        messageFrame.setResizable(true);
-        messageFrame.setTitle(org.openide.util.NbBundle.getMessage(IngestTopComponent.class, "IngestTopComponent.messageFrame.title")); // NOI18N
-        messageFrame.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
-        messageFrame.setFrameIcon(null);
-        messageFrame.setOpaque(true);
-        messageFrame.setPreferredSize(new java.awt.Dimension(280, 260));
-        messageFrame.setVisible(true);
-
-        javax.swing.GroupLayout messageFrameLayout = new javax.swing.GroupLayout(messageFrame.getContentPane());
-        messageFrame.getContentPane().setLayout(messageFrameLayout);
-        messageFrameLayout.setHorizontalGroup(
-            messageFrameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 274, Short.MAX_VALUE)
-        );
-        messageFrameLayout.setVerticalGroup(
-            messageFrameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 231, Short.MAX_VALUE)
-        );
+        refreshFreqLabel = new javax.swing.JLabel();
+
+        mainScrollPane.setPreferredSize(new java.awt.Dimension(289, 509));
 
         topLable.setFont(new java.awt.Font("Tahoma", 0, 12));
         org.openide.awt.Mnemonics.setLocalizedText(topLable, org.openide.util.NbBundle.getMessage(IngestTopComponent.class, "IngestTopComponent.topLable.text")); // NOI18N
@@ -234,8 +176,6 @@ public void stateChanged(javax.swing.event.ChangeEvent evt) {
             }
         });
 
-        org.openide.awt.Mnemonics.setLocalizedText(refreshFreqLabel, org.openide.util.NbBundle.getMessage(IngestTopComponent.class, "IngestTopComponent.refreshFreqLabel.text")); // NOI18N
-
         org.openide.awt.Mnemonics.setLocalizedText(startButton, org.openide.util.NbBundle.getMessage(IngestTopComponent.class, "IngestTopComponent.startButton.text")); // NOI18N
         startButton.addActionListener(new java.awt.event.ActionListener() {
             public void actionPerformed(java.awt.event.ActionEvent evt) {
@@ -243,92 +183,43 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
             }
         });
 
-        org.openide.awt.Mnemonics.setLocalizedText(refreshFrequencyLabel, org.openide.util.NbBundle.getMessage(IngestTopComponent.class, "IngestTopComponent.refreshFrequencyLabel.text")); // NOI18N
-
-        org.openide.awt.Mnemonics.setLocalizedText(ingestProgressLabel, org.openide.util.NbBundle.getMessage(IngestTopComponent.class, "IngestTopComponent.ingestProgressLabel.text")); // NOI18N
-
-        javax.swing.GroupLayout controlPanelLayout = new javax.swing.GroupLayout(controlPanel);
-        controlPanel.setLayout(controlPanelLayout);
-        controlPanelLayout.setHorizontalGroup(
-            controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(controlPanelLayout.createSequentialGroup()
-                .addContainerGap()
-                .addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addGroup(controlPanelLayout.createSequentialGroup()
-                        .addComponent(topLable)
-                        .addContainerGap(198, Short.MAX_VALUE))
-                    .addGroup(controlPanelLayout.createSequentialGroup()
-                        .addComponent(servicesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                        .addGap(115, 115, 115))
-                    .addGroup(controlPanelLayout.createSequentialGroup()
-                        .addComponent(startButton)
-                        .addContainerGap(258, Short.MAX_VALUE))
-                    .addGroup(controlPanelLayout.createSequentialGroup()
-                        .addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
-                            .addComponent(mainProgressBar, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                            .addComponent(freqSlider, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-                        .addContainerGap(115, Short.MAX_VALUE))))
-            .addGroup(controlPanelLayout.createSequentialGroup()
-                .addGap(59, 59, 59)
-                .addComponent(refreshFrequencyLabel)
-                .addContainerGap(174, Short.MAX_VALUE))
-            .addGroup(controlPanelLayout.createSequentialGroup()
-                .addGap(59, 59, 59)
-                .addComponent(ingestProgressLabel)
-                .addContainerGap(171, Short.MAX_VALUE))
-            .addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                .addGroup(controlPanelLayout.createSequentialGroup()
-                    .addGap(74, 74, 74)
-                    .addComponent(refreshFreqLabel)
-                    .addContainerGap(161, Short.MAX_VALUE)))
-        );
-        controlPanelLayout.setVerticalGroup(
-            controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(controlPanelLayout.createSequentialGroup()
-                .addGap(20, 20, 20)
-                .addComponent(topLable)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                .addComponent(servicesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addComponent(startButton)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
-                .addComponent(freqSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addComponent(refreshFrequencyLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addComponent(mainProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addComponent(ingestProgressLabel)
-                .addContainerGap(228, Short.MAX_VALUE))
-            .addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                .addGroup(controlPanelLayout.createSequentialGroup()
-                    .addGap(555, 555, 555)
-                    .addComponent(refreshFreqLabel)
-                    .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
-        );
+        org.openide.awt.Mnemonics.setLocalizedText(refreshFreqLabel, org.openide.util.NbBundle.getMessage(IngestTopComponent.class, "IngestTopComponent.refreshFreqLabel.text")); // NOI18N
 
         javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
         mainPanel.setLayout(mainPanelLayout);
         mainPanelLayout.setHorizontalGroup(
             mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
             .addGroup(mainPanelLayout.createSequentialGroup()
-                .addContainerGap()
                 .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup()
-                        .addComponent(controlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                        .addGap(71, 71, 71))
                     .addGroup(mainPanelLayout.createSequentialGroup()
-                        .addComponent(messageFrame, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                        .addGap(48, 48, 48))))
+                        .addContainerGap()
+                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                            .addComponent(topLable, javax.swing.GroupLayout.Alignment.LEADING)
+                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
+                                .addComponent(servicesPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                                .addComponent(freqSlider, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
+                    .addGroup(mainPanelLayout.createSequentialGroup()
+                        .addContainerGap()
+                        .addComponent(startButton))
+                    .addGroup(mainPanelLayout.createSequentialGroup()
+                        .addGap(74, 74, 74)
+                        .addComponent(refreshFreqLabel)))
+                .addContainerGap(173, Short.MAX_VALUE))
         );
         mainPanelLayout.setVerticalGroup(
             mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
             .addGroup(mainPanelLayout.createSequentialGroup()
-                .addContainerGap()
-                .addComponent(controlPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 357, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addGap(30, 30, 30)
-                .addComponent(messageFrame, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addGap(127, 127, 127))
+                .addGap(24, 24, 24)
+                .addComponent(topLable)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                .addComponent(servicesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(startButton)
+                .addGap(18, 18, 18)
+                .addComponent(freqSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(refreshFreqLabel)
+                .addContainerGap(198, Short.MAX_VALUE))
         );
 
         mainScrollPane.setViewportView(mainPanel);
@@ -337,20 +228,19 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
         this.setLayout(layout);
         layout.setHorizontalGroup(
             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 340, Short.MAX_VALUE)
+            .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 289, Short.MAX_VALUE)
         );
         layout.setVerticalGroup(
             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 771, Short.MAX_VALUE)
+            .addComponent(mainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 509, Short.MAX_VALUE)
         );
     }// </editor-fold>//GEN-END:initComponents
 
     private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startButtonActionPerformed
         
-        if (manager == null) {
+        if (manager == null)
             return;
-        }
-
+        
         //pick the services
         List<IngestServiceAbstract> servicesToStart = new ArrayList<IngestServiceAbstract>();
         for (IngestServiceAbstract service : services) {
@@ -373,7 +263,7 @@ private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-F
                 images.add(image);
             } catch (TskException e) {
                 logger.log(Level.SEVERE, "Error ingesting image, can't retrieve image id: " + Integer.toString(imageId), e);
-                
+
             } catch (SQLException e) {
                 logger.log(Level.SEVERE, "Error ingesting image, can't retrieve image id: " + Integer.toString(imageId), e);
             }
@@ -381,25 +271,20 @@ private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-F
         
         manager.execute(servicesToStart, images);
     }//GEN-LAST:event_startButtonActionPerformed
-    
+
     private void freqSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_freqSliderStateChanged
         JSlider source = (JSlider) evt.getSource();
         if (!source.getValueIsAdjusting()) {
             final int refresh = (int) source.getValue();
             manager.setUpdateFrequency(refresh);
-            
+
         }
     }//GEN-LAST:event_freqSliderStateChanged
     // Variables declaration - do not modify//GEN-BEGIN:variables
-    private javax.swing.JPanel controlPanel;
     private javax.swing.JSlider freqSlider;
-    private javax.swing.JLabel ingestProgressLabel;
     private javax.swing.JPanel mainPanel;
-    private javax.swing.JProgressBar mainProgressBar;
     private javax.swing.JScrollPane mainScrollPane;
-    private javax.swing.JInternalFrame messageFrame;
     private javax.swing.JLabel refreshFreqLabel;
-    private javax.swing.JLabel refreshFrequencyLabel;
     private javax.swing.JPanel servicesPanel;
     private javax.swing.JButton startButton;
     private javax.swing.JLabel topLable;
@@ -410,51 +295,37 @@ public void componentOpened() {
         logger.log(Level.INFO, "IngestTopComponent opened()");
         manager = new IngestManager(this);
     }
-    
+
     @Override
     public void componentClosed() {
         logger.log(Level.INFO, "IngestTopComponent closed()");
     }
-    
-    void enableStartButton(boolean enable) {
-        startButton.setEnabled(enable);
-    }
-    
+
     void writeProperties(java.util.Properties p) {
         // better to version settings since initial version as advocated at
         // http://wiki.apidesign.org/wiki/PropertyFiles
         p.setProperty("version", "1.0");
-        
+
     }
-    
+
     void readProperties(java.util.Properties p) {
         String version = p.getProperty("version");
-        
+
     }
 
     /**
      * Display ingest summary report in some dialog
      */
     void displayReport(String ingestReport) {
-        JOptionPane.showMessageDialog(
-                        null,
-                        ingestReport,
-                        "Ingest Summary",
-                        JOptionPane.INFORMATION_MESSAGE);
+        //TODO widget
+        logger.log(Level.INFO, "INGEST REPORT: " + ingestReport);
     }
 
     /**
      * Display IngestMessage from service (forwarded by IngestManager)
      */
     void displayMessage(IngestMessage ingestMessage) {
-        messagePanel.addMessage(ingestMessage);
-    }
-    
-    void initProgress(int maximum) {
-        this.mainProgressBar.setMaximum(maximum);
-    }
-
-    void updateProgress(int progress) {
-        this.mainProgressBar.setValue(progress);
+        //TODO widget
+        logger.log(Level.INFO, "INGEST MESSAGE: " + ingestMessage.toString());
     }
 }
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java
index a152a75f068c778109ba7cb15b88970e2ec0dd0f..2497254bf1183ba2ab2b7c69c29c2cea24aa881f 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java
@@ -69,7 +69,7 @@ public void init(IngestManager manager) {
         logger.log(Level.INFO, "init()");
         this.manager = manager;
         
-        manager.postMessage(IngestMessage.createMessage(1, MessageType.WARNING, this, "INIT"));
+        manager.postMessage(IngestMessage.createMessage(1, MessageType.INFO, this, "INIT"));
     }
 
     @Override
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java
index 7e85fbf0d980b20aebac3e6b8297763eaf2307e3..a3637b82ff7644f8595d8445d35cd69379f3ba32 100755
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java
@@ -44,7 +44,6 @@
 import org.apache.solr.client.solrj.response.TermsResponse;
 import org.apache.commons.httpclient.NoHttpResponseException;
 import org.apache.solr.client.solrj.SolrRequest;
-import org.apache.solr.client.solrj.SolrRequest.METHOD;
 import org.openide.modules.InstalledFileLocator;
 import org.openide.util.Exceptions;
 import org.sleuthkit.autopsy.casemodule.Case;
diff --git a/RecentActivity/build.xml b/RecentActivity/build.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5c34a68973c58ec52d1bc46197b60f8fe1ad093a
--- /dev/null
+++ b/RecentActivity/build.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="org.sleuthkit.autopsy.recentactivity" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project org.sleuthkit.autopsy.recentactivity.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
diff --git a/RecentActivity/manifest.mf b/RecentActivity/manifest.mf
new file mode 100644
index 0000000000000000000000000000000000000000..b8bdf7aa3bb150ee20b510b7d514d1134f43750e
--- /dev/null
+++ b/RecentActivity/manifest.mf
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0
+OpenIDE-Module: org.sleuthkit.autopsy.recentactivity
+OpenIDE-Module-Layer: org/sleuthkit/autopsy/recentactivity/layer.xml
+OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/recentactivity/Bundle.properties
+OpenIDE-Module-Requires: 
+  org.openide.modules.InstalledFileLocator,
+  org.openide.windows.TopComponent$Registry,
+  org.openide.windows.WindowManager
+OpenIDE-Module-Specification-Version: 1.0
+
diff --git a/RecentActivity/nbproject/build-impl.xml b/RecentActivity/nbproject/build-impl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..276cc6a4d14342e7d9166f134484cec2378daf90
--- /dev/null
+++ b/RecentActivity/nbproject/build-impl.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="org.sleuthkit.autopsy.recentactivity-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
diff --git a/RecentActivity/nbproject/genfiles.properties b/RecentActivity/nbproject/genfiles.properties
new file mode 100644
index 0000000000000000000000000000000000000000..fca57470c60c753c45a3231e7ae3c8cb23cdaae4
--- /dev/null
+++ b/RecentActivity/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=c008ddb2
+build.xml.script.CRC32=d323407a
+build.xml.stylesheet.CRC32=a56c6a5b@1.46.1
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=c008ddb2
+nbproject/build-impl.xml.script.CRC32=aef16a21
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.46.1
diff --git a/RecentActivity/nbproject/platform.properties b/RecentActivity/nbproject/platform.properties
new file mode 100644
index 0000000000000000000000000000000000000000..38ecd5a92ebea2c14710d0595bdd2d6df0bafcf4
--- /dev/null
+++ b/RecentActivity/nbproject/platform.properties
@@ -0,0 +1,99 @@
+cluster.path=\
+    ${nbplatform.active.dir}/java:\
+    ${nbplatform.active.dir}/platform
+disabled.modules=\
+    org.apache.tools.ant.module,\
+    org.netbeans.api.debugger.jpda,\
+    org.netbeans.api.java,\
+    org.netbeans.libs.cglib,\
+    org.netbeans.libs.javacapi,\
+    org.netbeans.libs.javacimpl,\
+    org.netbeans.libs.jsr223,\
+    org.netbeans.libs.springframework,\
+    org.netbeans.modules.ant.browsetask,\
+    org.netbeans.modules.ant.debugger,\
+    org.netbeans.modules.ant.freeform,\
+    org.netbeans.modules.ant.grammar,\
+    org.netbeans.modules.ant.kit,\
+    org.netbeans.modules.beans,\
+    org.netbeans.modules.classfile,\
+    org.netbeans.modules.dbschema,\
+    org.netbeans.modules.debugger.jpda,\
+    org.netbeans.modules.debugger.jpda.ant,\
+    org.netbeans.modules.debugger.jpda.projects,\
+    org.netbeans.modules.debugger.jpda.ui,\
+    org.netbeans.modules.form,\
+    org.netbeans.modules.form.j2ee,\
+    org.netbeans.modules.form.kit,\
+    org.netbeans.modules.hibernate,\
+    org.netbeans.modules.hibernatelib,\
+    org.netbeans.modules.hudson.ant,\
+    org.netbeans.modules.hudson.maven,\
+    org.netbeans.modules.i18n,\
+    org.netbeans.modules.i18n.form,\
+    org.netbeans.modules.j2ee.core.utilities,\
+    org.netbeans.modules.j2ee.eclipselink,\
+    org.netbeans.modules.j2ee.eclipselinkmodelgen,\
+    org.netbeans.modules.j2ee.jpa.refactoring,\
+    org.netbeans.modules.j2ee.jpa.verification,\
+    org.netbeans.modules.j2ee.metadata,\
+    org.netbeans.modules.j2ee.metadata.model.support,\
+    org.netbeans.modules.j2ee.persistence,\
+    org.netbeans.modules.j2ee.persistence.kit,\
+    org.netbeans.modules.j2ee.persistenceapi,\
+    org.netbeans.modules.j2ee.toplinklib,\
+    org.netbeans.modules.java.api.common,\
+    org.netbeans.modules.java.debug,\
+    org.netbeans.modules.java.editor,\
+    org.netbeans.modules.java.editor.lib,\
+    org.netbeans.modules.java.examples,\
+    org.netbeans.modules.java.freeform,\
+    org.netbeans.modules.java.guards,\
+    org.netbeans.modules.java.helpset,\
+    org.netbeans.modules.java.hints,\
+    org.netbeans.modules.java.hints.processor,\
+    org.netbeans.modules.java.j2seplatform,\
+    org.netbeans.modules.java.j2seproject,\
+    org.netbeans.modules.java.kit,\
+    org.netbeans.modules.java.lexer,\
+    org.netbeans.modules.java.navigation,\
+    org.netbeans.modules.java.platform,\
+    org.netbeans.modules.java.preprocessorbridge,\
+    org.netbeans.modules.java.project,\
+    org.netbeans.modules.java.source,\
+    org.netbeans.modules.java.source.ant,\
+    org.netbeans.modules.java.sourceui,\
+    org.netbeans.modules.javadoc,\
+    org.netbeans.modules.javawebstart,\
+    org.netbeans.modules.jellytools,\
+    org.netbeans.modules.jellytools.java,\
+    org.netbeans.modules.junit,\
+    org.netbeans.modules.maven,\
+    org.netbeans.modules.maven.coverage,\
+    org.netbeans.modules.maven.embedder,\
+    org.netbeans.modules.maven.grammar,\
+    org.netbeans.modules.maven.graph,\
+    org.netbeans.modules.maven.hints,\
+    org.netbeans.modules.maven.indexer,\
+    org.netbeans.modules.maven.junit,\
+    org.netbeans.modules.maven.kit,\
+    org.netbeans.modules.maven.model,\
+    org.netbeans.modules.maven.osgi,\
+    org.netbeans.modules.maven.persistence,\
+    org.netbeans.modules.maven.repository,\
+    org.netbeans.modules.maven.search,\
+    org.netbeans.modules.maven.spring,\
+    org.netbeans.modules.projectimport.eclipse.core,\
+    org.netbeans.modules.projectimport.eclipse.j2se,\
+    org.netbeans.modules.refactoring.java,\
+    org.netbeans.modules.spellchecker.bindings.java,\
+    org.netbeans.modules.spring.beans,\
+    org.netbeans.modules.swingapp,\
+    org.netbeans.modules.websvc.jaxws21,\
+    org.netbeans.modules.websvc.jaxws21api,\
+    org.netbeans.modules.websvc.saas.codegen.java,\
+    org.netbeans.modules.xml.jaxb,\
+    org.netbeans.modules.xml.tools.java,\
+    org.openide.compat,\
+    org.openide.util.enumerations
+nbplatform.active=default
diff --git a/RecentActivity/nbproject/project.properties b/RecentActivity/nbproject/project.properties
new file mode 100644
index 0000000000000000000000000000000000000000..0feca1f89d641f9877fa49bbb35cbe3428e4a66f
--- /dev/null
+++ b/RecentActivity/nbproject/project.properties
@@ -0,0 +1,3 @@
+file.reference.jcalendarbutton-1.4.5.jar=release/modules/ext/jcalendarbutton-1.4.5.jar
+javac.source=1.6
+javac.compilerargs=-Xlint -Xlint:-serial
diff --git a/RecentActivity/nbproject/project.xml b/RecentActivity/nbproject/project.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cfff641740ef56a4bcb6d76376e2b83c8227a44f
--- /dev/null
+++ b/RecentActivity/nbproject/project.xml
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>org.sleuthkit.autopsy.recentactivity</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.options.api</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.22.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.settings</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.31.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.31.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.dialogs</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.20.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.explorer</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.35.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.modules</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.23.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.nodes</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.21.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.15.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.8.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.windows</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.40.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.sleuthkit.autopsy.casemodule</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.sleuthkit.autopsy.corecomponentinterfaces</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.sleuthkit.autopsy.corecomponents</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.sleuthkit.autopsy.coreutils</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>0-1</release-version>
+                        <specification-version>0.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.sleuthkit.autopsy.datamodel</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.sleuthkit.autopsy.directorytree</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.sleuthkit.autopsy.filesearch</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.sleuthkit.autopsy.ingest</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>0-1</release-version>
+                        <specification-version>1.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.sleuthkit.autopsy.keywordsearch</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>0-1</release-version>
+                        <specification-version>0.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.sleuthkit.autopsy.menuactions</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>0-1</release-version>
+                        <specification-version>0.0</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+            <class-path-extension>
+                <runtime-relative-path>ext/sqlite-jdbc-3.7.6.3-20110609.081603-3.jar</runtime-relative-path>
+                <binary-origin>release/modules/ext/sqlite-jdbc-3.7.6.3-20110609.081603-3.jar</binary-origin>
+            </class-path-extension>
+            <class-path-extension>
+                <runtime-relative-path>ext/jcalendarbutton-1.4.5.jar</runtime-relative-path>
+                <binary-origin>release/modules/ext/jcalendarbutton-1.4.5.jar</binary-origin>
+            </class-path-extension>
+        </data>
+    </configuration>
+</project>
diff --git a/RecentActivity/nbproject/suite.properties b/RecentActivity/nbproject/suite.properties
new file mode 100644
index 0000000000000000000000000000000000000000..29d7cc9bd6fdd81453543cdf1bcf1dab301e3a92
--- /dev/null
+++ b/RecentActivity/nbproject/suite.properties
@@ -0,0 +1 @@
+suite.dir=${basedir}/..
diff --git a/RecentActivity/release/modules/ext/jcalendarbutton-1.4.5.jar b/RecentActivity/release/modules/ext/jcalendarbutton-1.4.5.jar
new file mode 100644
index 0000000000000000000000000000000000000000..4128ca1e05a3e57d1b1a98cf56643daca8e102f2
Binary files /dev/null and b/RecentActivity/release/modules/ext/jcalendarbutton-1.4.5.jar differ
diff --git a/RecentActivity/release/modules/ext/sqlite-jdbc-3.6.20.jar b/RecentActivity/release/modules/ext/sqlite-jdbc-3.6.20.jar
new file mode 100644
index 0000000000000000000000000000000000000000..2009143653bdc88b5ebbbeb4f588eead97c3784c
Binary files /dev/null and b/RecentActivity/release/modules/ext/sqlite-jdbc-3.6.20.jar differ
diff --git a/RecentActivity/release/modules/ext/sqlite-jdbc-3.7.2.jar b/RecentActivity/release/modules/ext/sqlite-jdbc-3.7.2.jar
new file mode 100644
index 0000000000000000000000000000000000000000..b0bec7b000d369a8f3dcaa9c6cd0b3ce87aed454
Binary files /dev/null and b/RecentActivity/release/modules/ext/sqlite-jdbc-3.7.2.jar differ
diff --git a/RecentActivity/release/modules/ext/sqlite-jdbc-3.7.6.3-20110609.081603-3.jar b/RecentActivity/release/modules/ext/sqlite-jdbc-3.7.6.3-20110609.081603-3.jar
new file mode 100644
index 0000000000000000000000000000000000000000..187bccb2ef290487fa587d8fd55ecd5293a74acd
Binary files /dev/null and b/RecentActivity/release/modules/ext/sqlite-jdbc-3.7.6.3-20110609.081603-3.jar differ
diff --git a/RecentActivity/release/modules/ext/sqlite-jdbc-3.7.7.1-20110713.014305-1.jar b/RecentActivity/release/modules/ext/sqlite-jdbc-3.7.7.1-20110713.014305-1.jar
new file mode 100644
index 0000000000000000000000000000000000000000..4dbeb15cf4306ac9f949847e71b68f65946f02e3
Binary files /dev/null and b/RecentActivity/release/modules/ext/sqlite-jdbc-3.7.7.1-20110713.014305-1.jar differ
diff --git a/RecentActivity/release/modules/ext/sqlite-jdbc-3.7.8-20111025.014814-1.jar b/RecentActivity/release/modules/ext/sqlite-jdbc-3.7.8-20111025.014814-1.jar
new file mode 100644
index 0000000000000000000000000000000000000000..bcea83745ab32246e315dd0c53209dc6a0cd39b9
Binary files /dev/null and b/RecentActivity/release/modules/ext/sqlite-jdbc-3.7.8-20111025.014814-1.jar differ
diff --git a/RecentActivity/release/modules/ext/sqlite4java.jar b/RecentActivity/release/modules/ext/sqlite4java.jar
new file mode 100644
index 0000000000000000000000000000000000000000..6622f51c65f70592b7ffbb9debeb21c4c23f637d
Binary files /dev/null and b/RecentActivity/release/modules/ext/sqlite4java.jar differ
diff --git a/RecentActivity/release/modules/ext/sqlitejdbc-v056.jar b/RecentActivity/release/modules/ext/sqlitejdbc-v056.jar
new file mode 100644
index 0000000000000000000000000000000000000000..f95d90eb07094f8646118332f50cb2cd4597d80f
Binary files /dev/null and b/RecentActivity/release/modules/ext/sqlitejdbc-v056.jar differ
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserActivity.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..ce72e7ef54d69df02daa2c70cfe9cbb4dea3fc74
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserActivity.java
@@ -0,0 +1,46 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.recentactivity;
+
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ * @author arivera
+ */
+public enum BrowserActivity {
+   IE(0),
+   FF(1),
+   CH(2);
+    private static final Map<Integer,BrowserActivity> lookup
+            = new HashMap<Integer,BrowserActivity>();
+
+    static {
+        for(BrowserActivity bat : values())
+            lookup.put(bat.type, bat);
+    }
+
+
+   private int type;
+
+   private BrowserActivity(int type)
+   {
+      this.type = type;
+   }
+
+    public int getType() { return type; }
+
+    public static BrowserActivity get(int type) {
+        switch(type) {
+            case 0: return IE;
+            case 1: return FF;
+            case 2: return CH;
+        }
+        return null;
+    }
+
+}
\ No newline at end of file
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserActivityModel.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserActivityModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..247bd1b25ce3a4101f8e9dfb0588ebc5deb4bc0f
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserActivityModel.java
@@ -0,0 +1,28 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.recentactivity;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+/**
+ *
+ * @author Alex
+ */
+public class BrowserActivityModel {
+ 
+ int count = 0;
+ private ArrayList<Map<BrowserActivity,Map>> BAM = new ArrayList<Map<BrowserActivity,Map>>();
+  public BrowserActivityModel(){
+      init();
+  }
+  
+  public void init()
+  {
+      
+  }
+
+}
+
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserActivityType.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserActivityType.java
new file mode 100644
index 0000000000000000000000000000000000000000..b22a80975f59acf97041974c4e6af84a3c8ed8a6
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserActivityType.java
@@ -0,0 +1,46 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.recentactivity;
+
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ * @author arivera
+ */
+public enum BrowserActivityType {
+   Cookies(0),
+   Url(1),
+   Bookmarks(2);
+    private static final Map<Integer,BrowserActivityType> lookup
+            = new HashMap<Integer,BrowserActivityType>();
+
+    static {
+        for(BrowserActivityType bat : values())
+            lookup.put(bat.type, bat);
+    }
+
+
+   private int type;
+
+   private BrowserActivityType(int type)
+   {
+      this.type = type;
+   }
+
+    public int getType() { return type; }
+
+    public static BrowserActivityType get(int type) {
+        switch(type) {
+            case 0: return Cookies;
+            case 1: return Url;
+            case 2: return Bookmarks;
+        }
+        return null;
+    }
+
+}
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserModel.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca887a7872bda0251592cb507d3fffd567a81e1e
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserModel.java
@@ -0,0 +1,47 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.recentactivity;
+
+import java.util.ArrayList;
+import javax.swing.AbstractListModel;
+import javax.swing.ListModel;
+
+/**
+ *
+ * @author Alex
+ */
+public abstract class BrowserModel extends AbstractListModel implements ListModel {
+    
+  private  int id;
+  private  int visit_count;
+  private  String last_accessed;
+  private  String from_visit;
+  private  String url;
+  private  String title;
+  private  String type;  
+  private String browser;
+  
+  public BrowserModel(){
+       
+    }
+    
+   public BrowserModel(int ID, String browser, int count, String accessed, String reference, String path, String name) {
+        this.id = ID;
+        this.type = type;
+        this.browser = browser;
+        this.visit_count = count;
+        this.last_accessed = accessed;
+        this.from_visit = reference;
+        this.url = path;
+        this.title = name;
+        
+    }
+    
+   public ArrayList<BrowserModel> getresults()
+   {
+       return null;
+   }
+    
+}
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserType.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserType.java
new file mode 100644
index 0000000000000000000000000000000000000000..494a10ba1088b2951c3e7936b2e915d41af30b42
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/BrowserType.java
@@ -0,0 +1,45 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.recentactivity;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ * @author arivera
+ */
+public enum BrowserType {
+   IE(0), //Internet Explorer
+   FF(1), //Firefox
+   CH(2); //Chrome
+    private static final Map<Integer,BrowserType> lookup
+            = new HashMap<Integer,BrowserType>();
+
+    static {
+        for(BrowserType bt : values())
+            lookup.put(bt.type, bt);
+    }
+
+
+   private int type;
+
+   private BrowserType(int type)
+   {
+      this.type = type;
+   }
+
+    public int getType() { return type; }
+
+    public static BrowserType get(int type) {
+        switch(type) {
+            case 0: return IE;
+            case 1: return FF;
+            case 2: return CH;
+        }
+        return null;
+    }
+
+}
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties
new file mode 100644
index 0000000000000000000000000000000000000000..fc21672edd5c40e82e657d6e46dc2d9d8dc19e50
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties
@@ -0,0 +1,24 @@
+OpenIDE-Module-Name=RecentActivity
+RecentActivityTopComponent.makeNodesButton.text=Get Recent Activity
+RecentActivityTopComponent.jLabel1.text=Filter Options
+RecentActivityTopComponent.jLabel2.text=Browser Activity
+RecentActivityTopComponent.jLabel3.text=jLabel3
+RecentActivityTopComponent.jLabel4.text=Registry Information
+RecentActivityTopComponent.jLabel5.text=Date/Time
+RecentActivityTopComponent.jLabel6.text=Recent Activity Keyword Filter
+RecentActivityTopComponent.jTextField1.text=
+RecentActivityTopComponent.jLabel5.toolTipText=
+RecentActivityTopComponent.jLabel6.toolTipText=
+RecentActivityTopComponent.jLabel7.text=to
+RecentActivityTopComponent.dateFromTextField.text=
+RecentActivityTopComponent.dateToTextField.text=
+RecentActivityTopComponent.dateToButtonCalendar.text=
+RecentActivityTopComponent.dateFromButtonCalendar.text=
+RecentActivityTopComponent.jTextField1.toolTipText=Enter a word or words you'd like to pattern match against
+RecentActivityTopComponent.jCheckBox1.AccessibleContext.accessibleName=IEhistory
+RecentActivityTopComponent.jCheckBox1.label=
+RecentActivityTopComponent.IEhistory.text=
+RecentActivityTopComponent.FFhistory.text=jCheckBox3
+RecentActivityTopComponent.CHhistory.text=jCheckBox2
+RecentActivityTopComponent.Cookies.text=jCheckBox4
+RecentActivityTopComponent.Bookmarks.text=jCheckBox5
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java
new file mode 100644
index 0000000000000000000000000000000000000000..6cf37cc2953e15ebc9dd8d1c17dd98929523792c
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java
@@ -0,0 +1,207 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.recentactivity;
+import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.datamodel.FsContent;
+import org.sleuthkit.datamodel.SleuthkitCase;
+import org.sleuthkit.autopsy.datamodel.ContentUtils;
+import java.sql.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.lang.*;
+import java.util.*;
+import java.io.File;
+import java.io.IOException;
+/**
+ *
+ * @author Alex
+ */
+
+
+public class Chrome {
+
+   
+   public static final String chquery = "SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, "
+           + "urls.last_visit_time, urls.hidden, visits.visit_time, visits.from_visit, visits.transition FROM urls, visits WHERE urls.id = visits.url";
+   public static final String chcookiequery = "select name, value, host, expires_utc, last_access_utc, creation_utc from cookies";
+   public static final String chbookmarkquery = "SELECT starred.title, urls.url, starred.date_added, starred.date_modified, urls.typed_count, urls._last_visit_time FROM starred INNER JOIN urls ON urls.id = starred.url_id";
+   public List<Map> als = new ArrayList();
+   public ArrayList<HashMap> cookies = new ArrayList<HashMap>();
+    public ArrayList<HashMap> bookmarks = new ArrayList<HashMap>();
+   private final Logger logger = Logger.getLogger(this.getClass().getName());
+    
+    public Chrome(){
+ 
+   }
+  
+     public void getchdb(){
+         
+        try 
+        {   
+            Case currentCase = Case.getCurrentCase(); // get the most updated case
+            SleuthkitCase tempDb = currentCase.getSleuthkitCase();
+            List<FsContent> FFSqlitedb;  
+            Map<String, Object> kvs = new LinkedHashMap<String, Object>();
+            
+            ResultSet rs = tempDb.runQuery("select * from tsk_files where name LIKE 'History' AND parent_path LIKE '%Chrome%'");
+            FFSqlitedb = tempDb.resultSetToFsContents(rs);
+            
+            int j = 0;
+     
+            while (j < FFSqlitedb.size())
+            {
+                String temps = currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db";
+                String connectionString = "jdbc:sqlite:" + temps;
+                 ContentUtils.writeToFile(FFSqlitedb.get(j), new File(currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db"));
+                
+                try
+                {
+                   dbconnect tempdbconnect = new dbconnect("org.sqlite.JDBC",connectionString);
+                   ResultSet temprs = tempdbconnect.executeQry(chquery);
+                   
+                   
+                   
+                   while(temprs.next()) 
+                   {
+                      kvs.clear();       
+                      kvs.put("Url", temprs.getString("url"));
+                      kvs.put("Title", ((temprs.getString("title") != null) ? temprs.getString("title") : "No Title"));
+                      kvs.put("Count", temprs.getString("visit_count"));
+                      kvs.put("Last Accessed", temprs.getString("visit_date"));
+                      kvs.put("Reference", temprs.getString("from_visit"));
+                      als.add(kvs);
+                     
+                   } 
+                   tempdbconnect.closeConnection();
+                   temprs.close();
+             
+                 }
+                 catch (Exception ex)
+                 {
+                    logger.log(Level.WARNING, "Error while trying to read into a sqlite db." + connectionString, ex);      
+                 }
+		 
+                j++;
+            }
+        }
+        catch (SQLException ex) 
+        {
+           logger.log(Level.WARNING, "Error while trying to get Firefox SQLite db.", ex);
+        }
+        catch(IOException ioex)
+        {   
+            logger.log(Level.WARNING, "Error while trying to write to the file system.", ioex);
+        }
+        
+        //COOKIES section
+          // This gets the cookie info
+         try 
+        {   
+            Case currentCase = Case.getCurrentCase(); // get the most updated case
+            SleuthkitCase tempDb = currentCase.getSleuthkitCase();
+            List<FsContent> FFSqlitedb;  
+            ResultSet rs = tempDb.runQuery("select * from tsk_files where name LIKE 'Cookies' and parent_path LIKE '%Chrome%'");
+            FFSqlitedb = tempDb.resultSetToFsContents(rs);
+            
+            int j = 0;
+     
+            while (j < FFSqlitedb.size())
+            {
+                String temps = currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db";
+                String connectionString = "jdbc:sqlite:" + temps;
+                ContentUtils.writeToFile(FFSqlitedb.get(j), new File(currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db"));
+                File dbFile = new File(temps);
+                 try
+                {
+                   dbconnect tempdbconnect = new dbconnect("org.sqlite.JDBC",connectionString);
+                   ResultSet temprs = tempdbconnect.executeQry(chcookiequery);  
+                   while(temprs.next()) 
+                   {
+                      HashMap<String, Object> kvs = new HashMap<String, Object>();
+                      kvs.put("Url", temprs.getString("host"));
+                      kvs.put("Title", ((temprs.getString("name") != null) ? temprs.getString("name") : "No name"));
+                      kvs.put("Count", temprs.getString("value"));
+                      kvs.put("Last Accessed", temprs.getString("access_utc"));
+                      kvs.put("Reference", temprs.getString("creation_utc"));
+                      cookies.add(kvs);
+                      
+                   } 
+                   tempdbconnect.closeConnection();
+                   temprs.close();
+                    
+                 }
+                 catch (Exception ex)
+                 {
+                    logger.log(Level.WARNING, "Error while trying to read into a sqlite db." + connectionString, ex);      
+                 }
+                j++;
+                dbFile.delete();
+            }
+        }
+        catch (SQLException ex) 
+        {
+           logger.log(Level.WARNING, "Error while trying to get Firefox SQLite db.", ex);
+        }
+        catch(IOException ioex)
+        {   
+            logger.log(Level.WARNING, "Error while trying to write to the file system.", ioex);
+        }
+        
+        //COOKIES section
+          // This gets the cookie info
+         try 
+        {   
+            Case currentCase = Case.getCurrentCase(); // get the most updated case
+            SleuthkitCase tempDb = currentCase.getSleuthkitCase();
+            List<FsContent> FFSqlitedb;  
+            ResultSet rs = tempDb.runQuery("select * from tsk_files where name LIKE 'Bookmarks' and parent_path LIKE '%Chrome%'");
+            FFSqlitedb = tempDb.resultSetToFsContents(rs);
+            
+            int j = 0;
+     
+            while (j < FFSqlitedb.size())
+            {
+                String temps = currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db";
+                String connectionString = "jdbc:sqlite:" + temps;
+                ContentUtils.writeToFile(FFSqlitedb.get(j), new File(currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db"));
+                File dbFile = new File(temps);
+                 try
+                {
+                   dbconnect tempdbconnect = new dbconnect("org.sqlite.JDBC",connectionString);
+                   ResultSet temprs = tempdbconnect.executeQry(chbookmarkquery);  
+                   while(temprs.next()) 
+                   {
+                      HashMap<String, Object> kvs = new HashMap<String, Object>();
+                      kvs.put("Url", temprs.getString("urls.url"));
+                      kvs.put("Title", ((temprs.getString("starred.title") != null) ? temprs.getString("starred.title") : "No name"));
+                      kvs.put("Count", temprs.getString("urls.typed_count"));
+                      kvs.put("Last Accessed", temprs.getString("urls._last_visit_time"));
+                      kvs.put("Reference", temprs.getString("starred.date_added"));
+                      bookmarks.add(kvs);
+                      
+                   } 
+                   tempdbconnect.closeConnection();
+                   temprs.close();
+                    
+                 }
+                 catch (Exception ex)
+                 {
+                    logger.log(Level.WARNING, "Error while trying to read into a sqlite db." + connectionString, ex);      
+                 }
+                j++;
+                dbFile.delete();
+            }
+        }
+        catch (SQLException ex) 
+        {
+           logger.log(Level.WARNING, "Error while trying to get Firefox SQLite db.", ex);
+        }
+        catch(IOException ioex)
+        {   
+            logger.log(Level.WARNING, "Error while trying to write to the file system.", ioex);
+        } 
+         
+    }
+}
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java
new file mode 100644
index 0000000000000000000000000000000000000000..e1f97ba74cfda7317e78d3753fb048c5f06c815f
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java
@@ -0,0 +1,213 @@
+package org.sleuthkit.autopsy.recentactivity;
+
+//IO imports
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+// SQL imports
+import java.sql.ResultSet;
+
+//Util Imports
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Scanner;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+// TSK Imports
+import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.autopsy.datamodel.ContentUtils;
+import org.sleuthkit.autopsy.datamodel.KeyValueThing;
+import org.sleuthkit.datamodel.FsContent;
+import org.sleuthkit.datamodel.SleuthkitCase;
+
+
+public class ExtractIE { // implements BrowserActivity {
+
+   //Constants region
+   private final String indexDatQueryStr = "select * from tsk_files where name LIKE '%index.dat%'";
+
+   private final String PASCO_HOME = System.getenv("PASCO_HOME");
+   private final String PASCO_RESULTS_PATH =  PASCO_HOME + "\\results";
+   private final String PASCO_LIB_PATH = PASCO_HOME + "\\pasco2.jar;"
+                                                  +  PASCO_HOME + "\\lib\\*";
+
+   //Results List to be referenced/used outside the class
+   public ArrayList<HashMap<String,Object>> PASCO_RESULTS_LIST = new ArrayList<HashMap<String,Object>>();
+   //Look Up Table  that holds Pasco2 results
+   private  HashMap<String, Object> PASCO_RESULTS_LUT ;
+
+   private KeyValueThing IE_PASCO_LUT = new KeyValueThing(BrowserType.IE.name(), BrowserType.IE.getType());
+
+   public LinkedHashMap<String, Object> IE_OBJ;
+
+   //Get this case
+   private Case currentCase = Case.getCurrentCase();
+   private SleuthkitCase tempDb = currentCase.getSleuthkitCase();
+
+   //Singleton logger object.
+   private final Logger logger = Logger.getLogger(this.getClass().getName());
+
+   public ExtractIE(){
+      init();
+   }
+
+   //@Override
+   public KeyValueThing getRecentActivity()
+   {
+      return IE_PASCO_LUT;
+   }
+
+   void init()
+   {
+      try
+      {
+         Collection<FsContent> FsContentCollection;
+         ResultSet rs = tempDb.runQuery(indexDatQueryStr);
+         FsContentCollection = tempDb.resultSetToFsContents(rs);
+
+         String temps;
+         String indexFileName;
+         int index = 0;
+
+         for(FsContent fsc : FsContentCollection)
+         {
+             // Since each result represent an index.dat file,
+             // just create these files with the following notation:
+             // index<Number>.dat (i.e. index0.dat, index1.dat,..., indexN.dat)
+             // Write each index.dat file to a temp directory.
+             indexFileName = "index" + Integer.toString(index) + ".dat";
+             temps = currentCase.getTempDirectory() + "\\" + indexFileName;
+             File datFile = new File(temps);
+             ContentUtils.writeToFile(fsc, datFile);
+             boolean bPascProcSuccess = executePasco(temps, index);
+
+             //At this point pasco2 proccessed the index files.
+             //Now fetch the results, parse them and the delete the files.
+             if(bPascProcSuccess)
+             {
+                //Delete index<n>.dat file since it was succcessfully by Pasco
+                datFile.delete();
+             }
+             ++index;
+         }
+      }
+      catch(Exception ioex)
+      {
+         logger.log(Level.SEVERE, "Error while trying to write index.dat files.", ioex);
+      }
+   }
+
+
+    //Simple wrapper to JavaSystemCaller.Exec() to execute pasco2 jar
+    // TODO: Hardcoded command args/path needs to be removed. Maybe set some constants and set env variables for classpath
+    // I'm not happy with this code. Can't stand making a system call, is not an acceptable solution but is a hack for now.
+	private  boolean executePasco(String indexFilePath, int fileIndex)
+    {
+       boolean success = true;
+
+       try
+       {
+			List<String> command = new ArrayList<String>();
+
+            command.add("-cp");
+		    command.add(PASCO_LIB_PATH);
+            command.add(" isi.pasco2.Main");
+            command.add(" -T history");
+            command.add(indexFilePath);
+            command.add(" > " + PASCO_RESULTS_PATH + "\\pasco2Result" + Integer.toString(fileIndex) + ".txt");
+
+            String[] cmd = command.toArray(new String[0]);
+
+            JavaSystemCaller.Exec.execute("java", cmd);
+
+       }
+       catch(Exception e)
+       {
+          success = false;
+          logger.log(Level.SEVERE, "ExtractIE::executePasco() -> " ,e.getMessage() );
+       }
+
+       return success;
+    }
+
+    public void parsePascoResults()
+    {
+       // First thing we want to do is check to make sure the results directory
+       // is not empty.
+       File rFile = new File(PASCO_RESULTS_PATH);
+
+       //Let's make sure our list and lut are empty.
+       //PASCO_RESULTS_LIST.clear();
+
+       if(rFile.exists())
+       {
+          //Give me a list of pasco results in that directory
+          File[] pascoFiles = rFile.listFiles();
+
+          if(pascoFiles.length > 0)
+          {
+             try
+             {
+                for (File file : pascoFiles)
+                {
+
+                   // Make sure the file the is not empty or the Scanner will
+                   // throw a "No Line found" Exception
+                   if (file != null && file.length() > 0 )
+                   {
+                      Scanner fileScanner = new Scanner(new FileInputStream(file.toString()));
+                      //Skip the first three lines
+                      fileScanner.nextLine();
+                      fileScanner.nextLine();
+                      fileScanner.nextLine();
+
+                      while (fileScanner.hasNext())
+                      {
+                         String line = fileScanner.nextLine();
+                         //Need to change this pattern a bit because there might
+                         //be instances were "V" might not apply.
+                         String pattern = "(?)URL(\\s)(V|\\:)";
+                         Pattern p = Pattern.compile(pattern);
+                         Matcher m  = p.matcher(line);
+                         if(m.find())
+                         {
+                            String[] lineBuff = line.split("\\t");
+                            PASCO_RESULTS_LUT = new HashMap<String,Object>();
+                            PASCO_RESULTS_LUT.put(BrowserActivityType.Url.name(), lineBuff[1]);
+                            PASCO_RESULTS_LUT.put("Title", lineBuff[2]);
+                            PASCO_RESULTS_LUT.put("Count", lineBuff[0]);
+                            PASCO_RESULTS_LUT.put("Last Accessed", lineBuff[3]);
+                           
+                            PASCO_RESULTS_LUT.put("Reference", "None");
+                            //KeyValueThing
+                            //This will be redundant in terms IE.name() because of
+                            //the way they implemented KeyValueThing
+                            IE_OBJ = new LinkedHashMap<String,Object>();
+                            IE_OBJ.put(BrowserType.IE.name(), PASCO_RESULTS_LUT);
+                            IE_PASCO_LUT.addMap(IE_OBJ);
+
+                            PASCO_RESULTS_LIST.add(PASCO_RESULTS_LUT);
+                         }
+                      }
+                   }
+                   //TODO: Fix Delete issue
+                   boolean bDelete = file.delete();
+                }
+             }
+             catch(IOException ioex)
+             {
+                logger.log(Level.SEVERE, "ExtractIE::parsePascosResults() -> " ,ioex.getMessage() );
+             }
+
+          }
+       }
+    }
+
+}
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java
new file mode 100644
index 0000000000000000000000000000000000000000..b2e81c3eb0e4a18ac97df4a4e55464bbf7d3d165
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java
@@ -0,0 +1,128 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.recentactivity;
+
+import com.sun.corba.se.spi.activation.Server;
+import java.io.File;
+import java.io.IOException;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.openide.modules.InstalledFileLocator;
+import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.autopsy.datamodel.ContentUtils;
+import org.sleuthkit.datamodel.FsContent;
+import org.sleuthkit.datamodel.SleuthkitCase;
+
+/**
+ *
+ * @author Alex \System32\Config
+ */
+public class ExtractRegistry {
+
+      public Logger logger = Logger.getLogger(this.getClass().getName());
+    
+    ExtractRegistry(){
+    }
+    
+    
+    
+public void getregistryfiles(){
+ try 
+        {   
+            Case currentCase = Case.getCurrentCase(); // get the most updated case
+            SleuthkitCase tempDb = currentCase.getSleuthkitCase();
+            List<FsContent> Regfiles;  
+            ResultSet rs = tempDb.runQuery("select * from tsk_files where lower(name) = 'ntuser.dat' OR lower(parent_path) LIKE '%/system32/config%' and (name = 'system' OR name = 'software' OR name = 'SECURITY' OR name = 'SAM' OR name = 'default')");
+            Regfiles = tempDb.resultSetToFsContents(rs);
+            
+            int j = 0;
+     
+            while (j < Regfiles.size())
+            {
+               
+                String temps = currentCase.getTempDirectory() + "\\" + Regfiles.get(j).getName().toString();
+                ContentUtils.writeToFile(Regfiles.get(j), new File(currentCase.getTempDirectory() + "\\" + Regfiles.get(j).getName()));
+                File regFile = new File(temps);
+               
+                 boolean regSuccess = executeRegRip(temps, j);
+
+             //At this point pasco2 proccessed the index files.
+             //Now fetch the results, parse them and the delete the files.
+             if(regSuccess)
+             {
+                //Delete index<n>.dat file since it was succcessfully by Pasco
+                regFile.delete();
+             }
+                j++;
+                
+                
+             
+            }
+        }
+        catch (SQLException ex) 
+        {
+           logger.log(Level.WARNING, "Error while trying to get Registry files", ex);
+        }
+        catch(IOException ioex)
+        {   
+            logger.log(Level.WARNING, "Error while trying to write to the file system.", ioex);
+        }
+}
+
+//Simple wrapper to JavaSystemCaller.Exec() to execute pasco2 jar
+    // TODO: Hardcoded command args/path needs to be removed. Maybe set some constants and set env variables for classpath
+    // I'm not happy with this code. Can't stand making a system call, is not an acceptable solution but is a hack for now.
+	private  boolean executeRegRip(String regFilePath, int fileIndex)
+    {
+       boolean success = true;
+       String type = "";
+       File rrFolder = InstalledFileLocator.getDefault().locate("rr", Server.class.getPackage().getName(), false);
+      // String instanceDir = rrFolder.getAbsolutePath() + File.separator + "rr";
+
+       try
+       {
+            if(regFilePath.toLowerCase().contains("system"))
+                {
+                    type = "system";
+                }
+                if(regFilePath.toLowerCase().contains("software"))
+                {
+                    type = "software";
+                }
+                if(regFilePath.toLowerCase().contains("ntuser"))
+                {
+                    type = "ntuser";
+                }
+                if(regFilePath.toLowerCase().contains("default"))
+                {
+                    type = "default";
+                }
+                if(regFilePath.toLowerCase().contains("sam"))
+                {
+                    type = "sam";
+                }
+                if(regFilePath.toLowerCase().contains("security"))
+                {
+                    type = "security";
+                }
+           String command = "rip -r " + regFilePath +" -f " + type + " >> " + regFilePath + type + Integer.toString(fileIndex) + ".txt";
+
+            JavaSystemCaller.Exec.execute(command);
+
+       }
+       catch(Exception e)
+       {
+          success = false;
+          logger.log(Level.SEVERE, "ExtractRegistry::executeRegRip() -> " ,e.getMessage() );
+       }
+
+       return success;
+    }
+
+
+}
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7bbdc33e4d65d71c1c77d32533f5700d1c06df6
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java
@@ -0,0 +1,177 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.recentactivity;
+import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.datamodel.FsContent;
+import org.sleuthkit.datamodel.SleuthkitCase;
+import org.sleuthkit.autopsy.datamodel.ContentUtils;
+import java.sql.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+//<editor-fold defaultstate="collapsed" desc="comment">
+import java.lang.*;
+//</editor-fold>
+import java.util.*;
+import java.io.File;
+import java.io.IOException;
+/**
+ *
+ * @author Alex
+ */
+public class Firefox {
+
+    private static final String ffquery = "SELECT moz_historyvisits.id,url,title,visit_count,visit_date,from_visit FROM moz_places, moz_historyvisits WHERE moz_places.id = moz_historyvisits.place_id AND hidden = 0";
+    private static final String ffcookiequery = "SELECT name,value,host,expiry,lastAccessed,creationTime FROM moz_cookies";
+    private static final String ffbookmarkquery = "SELECT fk, moz_bookmarks.title, url FROM moz_bookmarks INNER JOIN moz_places ON moz_bookmarks.fk=moz_places.id";
+    
+    public ArrayList<HashMap> als = new ArrayList<HashMap>();
+    public Logger logger = Logger.getLogger(this.getClass().getName());
+    public ArrayList<HashMap> cookies = new ArrayList<HashMap>();
+    public ArrayList<HashMap> bookmarks = new ArrayList<HashMap>();
+   public Firefox(){
+       
+   }
+
+       public void getffdb(){
+         //Make these seperate, this is for history
+        try 
+        {   
+            Case currentCase = Case.getCurrentCase(); // get the most updated case
+            SleuthkitCase tempDb = currentCase.getSleuthkitCase();
+            List<FsContent> FFSqlitedb;  
+            ResultSet rs = tempDb.runQuery("select * from tsk_files where name LIKE '%places.sqlite%' and parent_path LIKE '%Firefox%'");
+            FFSqlitedb = tempDb.resultSetToFsContents(rs);
+            
+            int j = 0;
+     
+            while (j < FFSqlitedb.size())
+            {
+                String temps = currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db";
+                String connectionString = "jdbc:sqlite:" + temps;
+                ContentUtils.writeToFile(FFSqlitedb.get(j), new File(currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db"));
+                File dbFile = new File(temps);
+                
+                
+                try
+                {
+                   dbconnect tempdbconnect = new dbconnect("org.sqlite.JDBC",connectionString);
+                   ResultSet temprs = tempdbconnect.executeQry(ffquery);  
+                   while(temprs.next()) 
+                   {
+                      
+                      HashMap<String, Object> kvs = new HashMap<String, Object>();
+                      kvs.put("Url", temprs.getString("url"));
+                      kvs.put("Title", ((temprs.getString("title") != null) ? temprs.getString("title") : "No Title"));
+                      kvs.put("Count", temprs.getString("visit_count"));
+                      kvs.put("Last Accessed", temprs.getString("visit_date"));
+                      kvs.put("Reference", temprs.getString("from_visit"));
+                      als.add(kvs);
+                      
+                   }
+                   temprs.close(); 
+                   ResultSet tempbm = tempdbconnect.executeQry(ffbookmarkquery);  
+                   while(tempbm.next()) 
+                   {
+                      
+                      HashMap<String, Object> kvs = new HashMap<String, Object>();
+                      kvs.put("Url", temprs.getString("url"));
+                      kvs.put("Title", ((temprs.getString("title") != null) ? temprs.getString("title") : "No Title"));
+                      kvs.put("Count", "");
+                      kvs.put("Last Accessed", "");
+                      kvs.put("Reference", "");
+                      bookmarks.add(kvs);
+                      
+                   } 
+                   tempbm.close();
+                   tempdbconnect.closeConnection();
+                   
+ 
+                 }
+                 catch (Exception ex)
+                 {
+                    logger.log(Level.WARNING, "Error while trying to read into a sqlite db." + connectionString, ex);      
+                 }
+                j++;
+                dbFile.delete();
+            }
+        }
+        catch (SQLException ex) 
+        {
+           logger.log(Level.WARNING, "Error while trying to get Firefox SQLite db.", ex);
+        }
+        catch(IOException ioex)
+        {   
+            logger.log(Level.WARNING, "Error while trying to write to the file system.", ioex);
+        }
+        
+        
+        //COOKIES section
+          // This gets the cookie info
+         try 
+        {   
+            Case currentCase = Case.getCurrentCase(); // get the most updated case
+            SleuthkitCase tempDb = currentCase.getSleuthkitCase();
+            List<FsContent> FFSqlitedb;  
+            ResultSet rs = tempDb.runQuery("select * from tsk_files where name LIKE '%cookies.sqlite%' and parent_path LIKE '%Firefox%'");
+            FFSqlitedb = tempDb.resultSetToFsContents(rs);
+            
+            int j = 0;
+     
+            while (j < FFSqlitedb.size())
+            {
+                String temps = currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db";
+                String connectionString = "jdbc:sqlite:" + temps;
+                ContentUtils.writeToFile(FFSqlitedb.get(j), new File(currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db"));
+                File dbFile = new File(temps);
+                 try
+                {
+                   dbconnect tempdbconnect = new dbconnect("org.sqlite.JDBC",connectionString);
+                   ResultSet temprs = tempdbconnect.executeQry(ffcookiequery);  
+                   while(temprs.next()) 
+                   {
+                      
+                      HashMap<String, Object> kvs = new HashMap<String, Object>();
+                      kvs.put("Url", temprs.getString("host"));
+                      kvs.put("Title", ((temprs.getString("name") != null) ? temprs.getString("name") : "No name"));
+                      kvs.put("Count", temprs.getString("value"));
+                      kvs.put("Last Accessed", temprs.getString("lastAccessed"));
+                      kvs.put("Reference", temprs.getString("creationTime"));
+                      cookies.add(kvs);
+                      
+                   } 
+                   tempdbconnect.closeConnection();
+                   temprs.close();
+                    
+                 }
+                 catch (Exception ex)
+                 {
+                    logger.log(Level.WARNING, "Error while trying to read into a sqlite db." + connectionString, ex);      
+                 }
+                j++;
+                dbFile.delete();
+            }
+        }
+        catch (SQLException ex) 
+        {
+           logger.log(Level.WARNING, "Error while trying to get Firefox SQLite db.", ex);
+        }
+        catch(IOException ioex)
+        {   
+            logger.log(Level.WARNING, "Error while trying to write to the file system.", ioex);
+        }
+   } 
+}
+   //@Override
+//   public HashMap<String,String> ExtractActivity() {
+//     return ExtractActivity;
+//       
+//    }
+    
+                
+    
+   
+   
+    
+        
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/JavaSystemCaller.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/JavaSystemCaller.java
new file mode 100644
index 0000000000000000000000000000000000000000..3fc7947130b592330e427d87069e094c9a9e4202
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/JavaSystemCaller.java
@@ -0,0 +1,342 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.recentactivity;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+
+/**
+ * Make a system call through a system shell in a platform-independent manner in Java. <br />
+ * This class only demonstrate a 'dir' or 'ls' within current (execution) path, if no parameters are used.
+ * If parameters are used, the first one is the system command to execute, the others are its system command parameters. <br />
+ * To be system independent, an <b><a href="http://www.allapplabs.com/java_design_patterns/abstract_factory_pattern.htm">
+ * Abstract Factory Pattern</a></b> will be used to build the right underlying system shell in which the system command will be executed.
+ * @author <a href="http://stackoverflow.com/users/6309/vonc">VonC</a>
+ * @see <a href="http://stackoverflow.com/questions/236737#236873">
+   How to make a system call that returns the stdout output as a string in various languages?</a>
+ */
+public final class JavaSystemCaller 
+{
+	
+	/**
+	 * Execute a system command. <br />
+	 * Default is 'ls' in current directory if no parameters, or a system command (if Windows, it is automatically translated to 'dir')
+	 * @param args first element is the system command, the others are its parameters (NOT NULL)
+	 * @throws IllegalArgumentException if one parameters is null or empty. 
+	 * 'args' can be empty (default 'ls' performed then)
+	 */
+	public static void main(final String[] args)
+	{
+		String anOutput = "";
+		if(args.length == 0)
+		{
+			anOutput = Exec.execute("ls");
+		}
+		else
+		{
+			String[] someParameters = null;
+			anOutput = Exec.execute(args[0],someParameters);
+		}
+		System.out.println("Final output: " + anOutput);   
+	}
+	/**
+	 * Asynchronously read the output of a given input stream. <br />
+	 * Any exception during execution of the command in managed in this thread.
+	 * @author <a href="http://stackoverflow.com/users/6309/vonc">VonC</a>
+	 */
+	public static class StreamGobbler extends Thread
+	{
+		private InputStream is;
+		private String type;
+		private StringBuffer output = new StringBuffer();
+
+		StreamGobbler(final InputStream anIs, final String aType)
+		{
+			this.is = anIs;
+			this.type = aType;
+		}
+
+		/**
+		 * Asynchronous read of the input stream. <br />
+		 * Will report output as its its displayed.
+		 * @see java.lang.Thread#run()
+		 */
+		@Override
+		public final void run()
+		{
+			try
+			{
+				final InputStreamReader isr = new InputStreamReader(this.is);
+				final BufferedReader br = new BufferedReader(isr);
+				String line=null;
+				while ( (line = br.readLine()) != null)
+				{
+					System.out.println(this.type + ">" + line);
+					this.output.append(line+System.getProperty("line.separator"));
+				}
+			} catch (final IOException ioe)
+			{
+				ioe.printStackTrace();  
+			}
+		}
+		/**
+		 * Get output filled asynchronously. <br />
+		 * Should be called after execution
+		 * @return final output
+		 */
+		public final String getOutput()
+		{
+			return this.output.toString();
+		}
+	}
+	/**
+	 * Execute a system command in the appropriate shell. <br />
+	 * Read asynchronously stdout and stderr to report any result.
+	 * @author <a href="http://stackoverflow.com/users/6309/vonc">VonC</a>
+	 */
+	public static final class Exec
+	{
+	   
+		/**
+		 * Execute a system command. <br />
+		 * Listen asynchronously to stdout and stderr
+		 * @param aCommand system command to be executed (must not be null or empty)
+		 * @param someParameters parameters of the command (must not be null or empty)
+		 * @return final output (stdout only)
+		 */
+		public static String execute(final String aCommand, final String... someParameters)
+		{
+			String output = "";
+			try
+			{			
+				ExecEnvironmentFactory anExecEnvFactory = getExecEnvironmentFactory(aCommand, someParameters);
+				final IShell aShell = anExecEnvFactory.createShell();
+				final String aCommandLine = anExecEnvFactory.createCommandLine();
+
+				final Runtime rt = Runtime.getRuntime();
+				System.out.println("Executing " + aShell.getShellCommand() + " " + aCommandLine);
+
+				final Process proc = rt.exec(aShell.getShellCommand() + " " + aCommandLine);
+				// any error message?
+				final StreamGobbler errorGobbler = new 
+					StreamGobbler(proc.getErrorStream(), "ERROR");			
+
+				// any output?
+				final StreamGobbler outputGobbler = new 
+					StreamGobbler(proc.getInputStream(), "OUTPUT");
+
+				// kick them off
+				errorGobbler.start();
+				outputGobbler.start();
+
+				// any error???
+				final int exitVal = proc.waitFor();
+				System.out.println("ExitValue: " + exitVal);   
+
+				output = outputGobbler.getOutput();
+
+			} catch (final Throwable t)
+			{
+				t.printStackTrace();
+			}
+			return output;
+		}
+		
+		private static ExecEnvironmentFactory getExecEnvironmentFactory(final String aCommand, final String... someParameters)
+		{
+			final String anOSName = System.getProperty("os.name" );
+			if(anOSName.toLowerCase().startsWith("windows"))
+			{
+				return new WindowsExecEnvFactory(aCommand, someParameters);
+			}
+			return new UnixExecEnvFactory(aCommand, someParameters);
+			// TODO be more specific for other OS.
+		}
+		
+		private Exec() { /**/ }
+	}
+	private JavaSystemCaller() { /**/ }
+	
+	/*
+	 * ABSTRACT FACTORY PATTERN
+	 */
+	/**
+	 * Environment needed to be build for the Exec class to be able to execute the system command. <br />
+	 * Must have the right shell and the right command line. <br />
+	 * @author <a href="http://stackoverflow.com/users/6309/vonc">VonC</a>
+	 */
+	public abstract static class ExecEnvironmentFactory
+	{
+		private String command = null;
+		private ArrayList<String> parameters = new ArrayList<String>();
+		final String getCommand() { return this.command; }
+		final ArrayList<String> getParameters() { return this.parameters; }
+		/**
+		 * Builds an execution environment for a system command to be played. <br />
+		 * Independent from the OS.
+		 * @param aCommand system command to be executed (must not be null or empty)
+		 * @param someParameters parameters of the command (must not be null or empty)
+		 */
+		public ExecEnvironmentFactory(final String aCommand, final String... someParameters)
+		{
+			if(aCommand == null || aCommand.length() == 0) { throw new IllegalArgumentException("Command must not be empty"); }
+			this.command = aCommand;
+			for (int i = 0; i < someParameters.length; i++) {
+				final String aParameter = someParameters[i];
+				if(aParameter == null || aParameter.length() == 0) { throw new IllegalArgumentException("Parameter n° '"+i+"' must not be empty"); }
+				this.parameters.add(aParameter);
+			}
+		}
+		/**
+		 * Builds the right Shell for the current OS. <br />
+		 * Allow for independent platform execution.
+		 * @return right shell, NEVER NULL
+		 */
+		public abstract IShell createShell();
+		/**
+		 * Builds the right command line for the current OS. <br />
+		 * Means that a command might be translated, if it does not fit the right OS ('dir' => 'ls' on unix)
+		 * @return  right complete command line, with parameters added (NEVER NULL)
+		 */
+		public abstract String createCommandLine();
+		
+		protected final String buildCommandLine(final String aCommand, final ArrayList<String> someParameters)
+		{
+			final StringBuilder aCommandLine = new StringBuilder();
+			aCommandLine.append(aCommand);
+			for (String aParameter : someParameters) {
+				aCommandLine.append(" ");
+				aCommandLine.append(aParameter);
+			}
+			return aCommandLine.toString();
+		}
+	}
+	
+	/**
+	 * Builds a Execution Environment for Windows. <br />
+	 * Cmd with windows commands
+	 * @author <a href="http://stackoverflow.com/users/6309/vonc">VonC</a>
+	 */
+	public static final class WindowsExecEnvFactory extends ExecEnvironmentFactory
+	{
+
+		/**
+		 * Builds an execution environment for a Windows system command to be played. <br />
+		 * Any command not from windows will be translated in its windows equivalent if possible.
+		 * @param aCommand system command to be executed (must not be null or empty)
+		 * @param someParameters parameters of the command (must not be null or empty)
+		 */
+		public WindowsExecEnvFactory(final String aCommand, final String... someParameters)
+		{
+			super(aCommand, someParameters);
+		}
+		/**
+		 * @see test.JavaSystemCaller.ExecEnvironmentFactory#createShell()
+		 */
+		@Override
+		public IShell createShell() {
+			return new WindowsShell();
+		}
+
+		/**
+		 * @see test.JavaSystemCaller.ExecEnvironmentFactory#createCommandLine()
+		 */
+		@Override
+		public String createCommandLine() {
+			String aCommand = getCommand();
+			if(aCommand.toLowerCase().trim().equals("ls")) { aCommand = "dir"; }
+			// TODO translates other Unix commands
+			return buildCommandLine(aCommand, getParameters());
+		}	
+	}
+	
+	/**
+	 * Builds a Execution Environment for Unix. <br />
+	 * Sh with Unix commands
+	 * @author <a href="http://stackoverflow.com/users/6309/vonc">VonC</a>
+	 */
+	public static final class UnixExecEnvFactory extends ExecEnvironmentFactory
+	{
+
+		/**
+		 * Builds an execution environment for a Unix system command to be played. <br />
+		 * Any command not from Unix will be translated in its Unix equivalent if possible.
+		 * @param aCommand system command to be executed (must not be null or empty)
+		 * @param someParameters parameters of the command (must not be null or empty)
+		 */
+		public UnixExecEnvFactory(final String aCommand, final String... someParameters)
+		{
+			super(aCommand, someParameters);
+		}
+		/**
+		 * @see test.JavaSystemCaller.ExecEnvironmentFactory#createShell()
+		 */
+		@Override
+		public IShell createShell() {
+			return new UnixShell();
+		}
+
+		/**
+		 * @see test.JavaSystemCaller.ExecEnvironmentFactory#createCommandLine()
+		 */
+		@Override
+		public String createCommandLine() {
+			String aCommand = getCommand();
+			if(aCommand.toLowerCase().trim().equals("dir")) { aCommand = "ls"; }
+			// TODO translates other Windows commands
+			return buildCommandLine(aCommand, getParameters());
+		}	
+	}
+	
+	/**
+	 * System Shell with its right OS command. <br />
+	 * 'cmd' for Windows or 'sh' for Unix, ...
+	 * @author <a href="http://stackoverflow.com/users/6309/vonc">VonC</a>
+	 */
+	public interface IShell
+	{
+		/**
+		 * Get the right shell command. <br />
+		 * Used to launch a new shell
+		 * @return command used to launch a Shell (NEVEL NULL)
+		 */
+		String getShellCommand();
+	}
+	/**
+	 * Windows shell (cmd). <br />
+	 * More accurately 'cmd /C'
+	 * @author <a href="http://stackoverflow.com/users/6309/vonc">VonC</a>
+	 */
+	public static class WindowsShell implements IShell
+	{
+		/**
+		 * @see test.JavaSystemCaller.IShell#getShellCommand()
+		 */
+		@Override
+		public final String getShellCommand() {
+			final String osName = System.getProperty("os.name" );
+			if( osName.equals( "Windows 95" ) ) { return "command.com /C"; }
+			return "cmd.exe /C";
+		}
+	}
+	/**
+	 * Unix shell (sh). <br />
+	 * More accurately 'sh -C'
+	 * @author <a href="http://stackoverflow.com/users/6309/vonc">VonC</a>
+	 */
+	public static class UnixShell implements IShell
+	{
+		/**
+		 * @see test.JavaSystemCaller.IShell#getShellCommand()
+		 */
+		@Override
+		public final String getShellCommand() {
+			return "/bin/sh -c";
+		}
+	}
+}
\ No newline at end of file
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityDataExplorer.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityDataExplorer.java
new file mode 100644
index 0000000000000000000000000000000000000000..61691364d8eaddc8cb979877b445cfb388d92515
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityDataExplorer.java
@@ -0,0 +1,119 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.recentactivity;
+
+import java.beans.PropertyChangeEvent;
+import java.lang.reflect.Array;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node;
+import org.openide.util.lookup.ServiceProvider;
+import org.openide.windows.TopComponent;
+import org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer;
+import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
+import org.sleuthkit.autopsy.datamodel.KeyValueThing;
+import java.util.Random.*;
+import java.util.*;
+import java.util.logging.Logger;
+
+
+@ServiceProvider(service = DataExplorer.class)
+public class RecentActivityDataExplorer implements DataExplorer {
+    
+    RecentActivityTopComponent tc;
+    
+    static final int NUMBER_THING_ID = 41234;
+   private final Logger logger = Logger.getLogger(this.getClass().getName());
+    private Collection<KeyValueThing> things = new ArrayList<KeyValueThing>();
+    
+    //Empty Constructor
+    public RecentActivityDataExplorer() {
+        tc = new RecentActivityTopComponent(this);
+        tc.setName("Recent Activity");
+        tc.edx.tc.setbrowsercheckboxes(0,0,0,0,0);
+    }
+
+    @Override
+    public org.openide.windows.TopComponent getTopComponent() {
+        return tc;
+    }
+
+    @Override
+    public void propertyChange(PropertyChangeEvent evt) {
+        // nothing to do in simple example
+    }
+    
+  
+    
+    public void getallactivity()
+    {
+      Firefox ffre = new Firefox();
+      ffre.getffdb();
+      Chrome chre = new Chrome();
+      chre.getchdb();
+    }
+    
+void makeNodes() 
+    {
+        things.clear();
+        ExtractRegistry eree = new ExtractRegistry();
+        eree.getregistryfiles();
+        Firefox ffre = new Firefox();
+        ffre.getffdb();    
+        Chrome chre = new Chrome();
+        chre.getchdb();
+        ExtractIE eere = new ExtractIE();
+        eere.parsePascoResults();
+        
+        
+        
+        ArrayList<HashMap<String,Object>> IEresults = eere.PASCO_RESULTS_LIST;
+        int cookiescount = 0;
+        int bookmarkscount = 0;
+        int iecount = IEresults.size();
+        bookmarkscount = ffre.bookmarks.size() + chre.bookmarks.size();
+        cookiescount = ffre.cookies.size() + chre.cookies.size();
+        int ffcount = ffre.als.size();
+        int chcount = chre.als.size();
+        ExtractRegistry regob = new ExtractRegistry();
+        regob.getregistryfiles();
+        
+          
+        for(Map<String,Object> FFmap : ffre.als){
+           things.add(new KeyValueThing("FireFox", FFmap, NUMBER_THING_ID));  
+        }
+        
+         for(HashMap<String,Object> IEmap : IEresults){
+           things.add(new KeyValueThing("Internet Explorer", IEmap, NUMBER_THING_ID));  
+        }
+        for(Map<String,Object> CHmap : chre.als){
+           things.add(new KeyValueThing("Chrome", CHmap, NUMBER_THING_ID));  
+        }
+        
+        for(Map<String,Object> FFCookies : ffre.cookies){
+             things.add(new KeyValueThing("Cookie", FFCookies, NUMBER_THING_ID)); 
+        }
+        for(Map<String,Object> FFBookmark : ffre.bookmarks){
+             things.add(new KeyValueThing("Bookmark", FFBookmark, NUMBER_THING_ID)); 
+        }
+        
+        for(Map<String,Object> CHCookies : chre.cookies){
+             things.add(new KeyValueThing("Cookie", CHCookies, NUMBER_THING_ID)); 
+        }
+        
+        for(Map<String,Object> CHBookmark : chre.bookmarks){
+             things.add(new KeyValueThing("Bookmark", CHBookmark, NUMBER_THING_ID)); 
+        }
+      
+        Children childThingNodes = Children.create(new RecentActivityKeyValueChildFactory(things), true);
+        tc.setbrowsercheckboxes(iecount,ffcount,chcount,cookiescount,bookmarkscount);
+        Node rootNode = new AbstractNode(childThingNodes);
+        String pathText = "Recent User Activity";
+        TopComponent searchResultWin = DataResultTopComponent.createInstance("Recent Activity", pathText, rootNode, things.size()); 
+         
+        searchResultWin.requestActive(); // make it the active top component
+       
+    }
+}
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityKeyValueChildFactory.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityKeyValueChildFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..48e9a3c3466f0616af2ec4f6f7836bbf8698e6ac
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityKeyValueChildFactory.java
@@ -0,0 +1,28 @@
+package org.sleuthkit.autopsy.recentactivity;
+
+import java.util.Collection;
+import java.util.List;
+import org.openide.nodes.ChildFactory;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node;
+import org.sleuthkit.autopsy.datamodel.KeyValueNode;
+import org.sleuthkit.autopsy.datamodel.KeyValueThing;
+
+public class RecentActivityKeyValueChildFactory extends ChildFactory<KeyValueThing> {
+
+    private Collection<KeyValueThing> things;
+
+    public RecentActivityKeyValueChildFactory(Collection<KeyValueThing> things) {
+        this.things = things;
+    }
+
+    @Override
+    protected boolean createKeys(List<KeyValueThing> toPopulate) {
+        return toPopulate.addAll(things);
+    }
+
+    @Override
+    protected Node createNodeForKey(KeyValueThing thing) {
+        return new KeyValueNode(thing, Children.LEAF);
+    }
+}
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityModel.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..60224828d1073b142ac271d2022a0e3fe3178a22
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityModel.java
@@ -0,0 +1,26 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.recentactivity;
+import java.util.ArrayList;
+import javax.swing.AbstractListModel;
+import javax.swing.ListModel;
+
+
+public class RecentActivityModel {
+    
+  private String name;
+  private ArrayList<BrowserModel> data;
+        
+    public RecentActivityModel (){
+    
+    }
+    
+    public RecentActivityModel(String name, ArrayList<BrowserModel> data) {
+        this.name = name;
+        this.data = data;
+    }
+    
+}
+
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityTopComponent.form b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityTopComponent.form
new file mode 100644
index 0000000000000000000000000000000000000000..abe16fa0d9eb1c5fc387eca73bcdadf29574a2db
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityTopComponent.form
@@ -0,0 +1,327 @@
+<?xml version="1.1" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" attributes="0">
+                      <Component id="makeNodesButton" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace type="separate" max="-2" attributes="0"/>
+                      <Component id="activityProgressBar" min="-2" pref="190" max="-2" attributes="0"/>
+                  </Group>
+                  <Component id="jLabel1" alignment="0" min="-2" pref="84" max="-2" attributes="0"/>
+                  <Component id="jSeparator1" alignment="1" pref="414" max="32767" attributes="0"/>
+                  <Component id="jLabel6" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Component id="jTextField1" alignment="0" min="-2" pref="146" max="-2" attributes="0"/>
+                  <Component id="Bookmarks" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Group type="102" alignment="0" attributes="0">
+                      <Component id="CHhistory" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace type="separate" max="-2" attributes="0"/>
+                      <Component id="Cookies" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <Group type="102" alignment="0" attributes="0">
+                      <Component id="IEhistory" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace type="separate" max="-2" attributes="0"/>
+                      <Component id="FFhistory" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Component id="jLabel4" alignment="0" min="-2" pref="179" max="-2" attributes="0"/>
+                  <Component id="jLabel5" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Group type="102" alignment="0" attributes="0">
+                      <Component id="dateFromTextField" min="-2" pref="92" max="-2" attributes="0"/>
+                      <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
+                      <Component id="dateFromButtonCalendar" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
+                      <Component id="jLabel7" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace type="unrelated" max="-2" attributes="0"/>
+                      <Component id="dateToTextField" min="-2" pref="92" max="-2" attributes="0"/>
+                      <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
+                      <Component id="dateToButtonCalendar" min="-2" max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" max="-2" attributes="0">
+                  <Component id="activityProgressBar" max="32767" attributes="1"/>
+                  <Component id="makeNodesButton" alignment="0" max="32767" attributes="1"/>
+              </Group>
+              <EmptySpace type="unrelated" max="-2" attributes="0"/>
+              <Component id="jLabel1" min="-2" pref="14" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jSeparator1" min="-2" pref="7" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jLabel6" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jTextField1" min="-2" max="-2" attributes="0"/>
+              <EmptySpace type="separate" max="-2" attributes="0"/>
+              <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
+              <EmptySpace type="unrelated" max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="IEhistory" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="FFhistory" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace type="unrelated" max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="CHhistory" alignment="3" min="-2" max="-2" attributes="0"/>
+                  <Component id="Cookies" alignment="3" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace type="unrelated" max="-2" attributes="0"/>
+              <Component id="Bookmarks" min="-2" max="-2" attributes="0"/>
+              <EmptySpace type="separate" max="-2" attributes="0"/>
+              <Component id="jLabel4" min="-2" max="-2" attributes="0"/>
+              <EmptySpace min="-2" pref="97" max="-2" attributes="0"/>
+              <Component id="jLabel5" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="dateFromTextField" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Group type="103" alignment="0" groupAlignment="1" attributes="0">
+                      <Group type="103" alignment="1" groupAlignment="3" attributes="0">
+                          <Component id="dateToTextField" alignment="3" min="-2" max="-2" attributes="0"/>
+                          <Component id="jLabel7" alignment="3" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                      <Group type="102" alignment="1" attributes="0">
+                          <Component id="dateToButtonCalendar" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
+                      </Group>
+                      <Component id="dateFromButtonCalendar" alignment="1" min="-2" max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+              <EmptySpace pref="102" max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Component class="javax.swing.JButton" name="makeNodesButton">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.makeNodesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="makeNodesButtonActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JLabel" name="jLabel1">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="jLabel2">
+      <Properties>
+        <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+          <Font name="Tahoma" size="11" style="1"/>
+        </Property>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JSeparator" name="jSeparator1">
+    </Component>
+    <Component class="javax.swing.JLabel" name="jLabel3">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.jLabel3.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="jLabel4">
+      <Properties>
+        <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+          <Font name="Tahoma" size="11" style="1"/>
+        </Property>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.jLabel4.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Container class="javax.swing.JScrollPane" name="jScrollPane2">
+      <AuxValues>
+        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+      </AuxValues>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JList" name="jList2">
+          <Properties>
+            <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
+              <StringArray count="5">
+                <StringItem index="0" value="Item 1"/>
+                <StringItem index="1" value="Item 2"/>
+                <StringItem index="2" value="Item 3"/>
+                <StringItem index="3" value="Item 4"/>
+                <StringItem index="4" value="Item 5"/>
+              </StringArray>
+            </Property>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Component class="javax.swing.JCheckBox" name="IEhistory">
+      <Properties>
+        <Property name="selected" type="boolean" value="true"/>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.IEhistory.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <AccessibilityProperties>
+        <Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.jCheckBox1.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </AccessibilityProperties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="IEhistoryActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JCheckBox" name="CHhistory">
+      <Properties>
+        <Property name="selected" type="boolean" value="true"/>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.CHhistory.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JCheckBox" name="FFhistory">
+      <Properties>
+        <Property name="selected" type="boolean" value="true"/>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.FFhistory.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JCheckBox" name="Cookies">
+      <Properties>
+        <Property name="selected" type="boolean" value="true"/>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.Cookies.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JCheckBox" name="Bookmarks">
+      <Properties>
+        <Property name="selected" type="boolean" value="true"/>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.Bookmarks.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="jLabel5">
+      <Properties>
+        <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+          <Font name="Tahoma" size="11" style="1"/>
+        </Property>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.jLabel5.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+        <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.jLabel5.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="jLabel6">
+      <Properties>
+        <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+          <Font name="Tahoma" size="11" style="1"/>
+        </Property>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.jLabel6.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+        <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.jLabel6.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JTextField" name="jTextField1">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.jTextField1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+        <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.jTextField1.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="jLabel7">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.jLabel7.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JFormattedTextField" name="dateFromTextField">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.dateFromTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="focusLost" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="dateFromTextFieldFocusLost"/>
+      </Events>
+      <AuxValues>
+        <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new JFormattedTextField(this.dateFormat);"/>
+      </AuxValues>
+    </Component>
+    <Component class="org.sourceforge.jcalendarbutton.JCalendarButton" name="dateFromButtonCalendar">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.dateFromButtonCalendar.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="propertyChange" listener="java.beans.PropertyChangeListener" parameters="java.beans.PropertyChangeEvent" handler="dateFromPopupChanged"/>
+      </Events>
+    </Component>
+    <Component class="org.sourceforge.jcalendarbutton.JCalendarButton" name="dateToButtonCalendar">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.dateToButtonCalendar.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="propertyChange" listener="java.beans.PropertyChangeListener" parameters="java.beans.PropertyChangeEvent" handler="dateToPopupChanged"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JFormattedTextField" name="dateToTextField">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/sleuthkit/autopsy/recentactivity/Bundle.properties" key="RecentActivityTopComponent.dateToTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="focusLost" listener="java.awt.event.FocusListener" parameters="java.awt.event.FocusEvent" handler="dateToTextFieldFocusLost"/>
+      </Events>
+      <AuxValues>
+        <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new JFormattedTextField(this.dateFormat);"/>
+      </AuxValues>
+    </Component>
+    <Component class="javax.swing.JProgressBar" name="activityProgressBar">
+      <AuxValues>
+        <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new javax.swing.JProgressBar(0, 100)"/>
+      </AuxValues>
+    </Component>
+  </SubComponents>
+</Form>
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityTopComponent.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityTopComponent.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea644c93db9154b24ae082c4e1f36659b64d893f
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentActivityTopComponent.java
@@ -0,0 +1,364 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/*
+ * RecentActivityTopComponent.java
+ *
+ * Created on Dec 12, 2011, 1:55:46 PM
+ */
+package org.sleuthkit.autopsy.recentactivity;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import org.openide.windows.TopComponent;
+import javax.swing.JFormattedTextField;
+/**
+ *
+ * @author pmartel
+ */
+public class RecentActivityTopComponent extends TopComponent {
+
+    RecentActivityDataExplorer edx;
+    DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
+    
+    /** Creates new form RecentActivityTopComponent */
+    public RecentActivityTopComponent(RecentActivityDataExplorer edx) {
+        this.edx = edx;
+        initComponents();
+    }
+    
+    JFormattedTextField getDateFromTextField() {
+        return dateFromTextField;
+    }
+
+    JFormattedTextField getDateToTextField() {
+        return dateToTextField;
+    }
+    
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        makeNodesButton = new javax.swing.JButton();
+        jLabel1 = new javax.swing.JLabel();
+        jLabel2 = new javax.swing.JLabel();
+        jSeparator1 = new javax.swing.JSeparator();
+        jLabel3 = new javax.swing.JLabel();
+        jLabel4 = new javax.swing.JLabel();
+        jScrollPane2 = new javax.swing.JScrollPane();
+        jList2 = new javax.swing.JList();
+        IEhistory = new javax.swing.JCheckBox();
+        CHhistory = new javax.swing.JCheckBox();
+        FFhistory = new javax.swing.JCheckBox();
+        Cookies = new javax.swing.JCheckBox();
+        Bookmarks = new javax.swing.JCheckBox();
+        jLabel5 = new javax.swing.JLabel();
+        jLabel6 = new javax.swing.JLabel();
+        jTextField1 = new javax.swing.JTextField();
+        jLabel7 = new javax.swing.JLabel();
+        dateFromTextField = new JFormattedTextField(this.dateFormat);
+        dateFromButtonCalendar = new org.sourceforge.jcalendarbutton.JCalendarButton();
+        dateToButtonCalendar = new org.sourceforge.jcalendarbutton.JCalendarButton();
+        dateToTextField = new JFormattedTextField(this.dateFormat);
+        activityProgressBar = new javax.swing.JProgressBar(0, 100);
+
+        makeNodesButton.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.makeNodesButton.text")); // NOI18N
+        makeNodesButton.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                makeNodesButtonActionPerformed(evt);
+            }
+        });
+
+        jLabel1.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.jLabel1.text")); // NOI18N
+
+        jLabel2.setFont(new java.awt.Font("Tahoma", 1, 11));
+        jLabel2.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.jLabel2.text")); // NOI18N
+
+        jLabel3.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.jLabel3.text")); // NOI18N
+
+        jLabel4.setFont(new java.awt.Font("Tahoma", 1, 11));
+        jLabel4.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.jLabel4.text")); // NOI18N
+
+        jList2.setModel(new javax.swing.AbstractListModel() {
+            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
+            public int getSize() { return strings.length; }
+            public Object getElementAt(int i) { return strings[i]; }
+        });
+        jScrollPane2.setViewportView(jList2);
+
+        IEhistory.setSelected(true);
+        IEhistory.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.IEhistory.text")); // NOI18N
+        IEhistory.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                IEhistoryActionPerformed(evt);
+            }
+        });
+
+        CHhistory.setSelected(true);
+        CHhistory.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.CHhistory.text")); // NOI18N
+
+        FFhistory.setSelected(true);
+        FFhistory.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.FFhistory.text")); // NOI18N
+
+        Cookies.setSelected(true);
+        Cookies.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.Cookies.text")); // NOI18N
+
+        Bookmarks.setSelected(true);
+        Bookmarks.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.Bookmarks.text")); // NOI18N
+
+        jLabel5.setFont(new java.awt.Font("Tahoma", 1, 11));
+        jLabel5.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.jLabel5.text")); // NOI18N
+        jLabel5.setToolTipText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.jLabel5.toolTipText")); // NOI18N
+
+        jLabel6.setFont(new java.awt.Font("Tahoma", 1, 11));
+        jLabel6.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.jLabel6.text")); // NOI18N
+        jLabel6.setToolTipText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.jLabel6.toolTipText")); // NOI18N
+
+        jTextField1.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.jTextField1.text")); // NOI18N
+        jTextField1.setToolTipText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.jTextField1.toolTipText")); // NOI18N
+
+        jLabel7.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.jLabel7.text")); // NOI18N
+
+        dateFromTextField.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.dateFromTextField.text")); // NOI18N
+        dateFromTextField.addFocusListener(new java.awt.event.FocusAdapter() {
+            public void focusLost(java.awt.event.FocusEvent evt) {
+                dateFromTextFieldFocusLost(evt);
+            }
+        });
+
+        dateFromButtonCalendar.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.dateFromButtonCalendar.text")); // NOI18N
+        dateFromButtonCalendar.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+            public void propertyChange(java.beans.PropertyChangeEvent evt) {
+                dateFromPopupChanged(evt);
+            }
+        });
+
+        dateToButtonCalendar.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.dateToButtonCalendar.text")); // NOI18N
+        dateToButtonCalendar.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+            public void propertyChange(java.beans.PropertyChangeEvent evt) {
+                dateToPopupChanged(evt);
+            }
+        });
+
+        dateToTextField.setText(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.dateToTextField.text")); // NOI18N
+        dateToTextField.addFocusListener(new java.awt.event.FocusAdapter() {
+            public void focusLost(java.awt.event.FocusEvent evt) {
+                dateToTextFieldFocusLost(evt);
+            }
+        });
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(layout.createSequentialGroup()
+                        .addComponent(makeNodesButton)
+                        .addGap(18, 18, 18)
+                        .addComponent(activityProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE, 190, javax.swing.GroupLayout.PREFERRED_SIZE))
+                    .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 84, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(jSeparator1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 414, Short.MAX_VALUE)
+                    .addComponent(jLabel6)
+                    .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 146, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(Bookmarks)
+                    .addGroup(layout.createSequentialGroup()
+                        .addComponent(CHhistory)
+                        .addGap(18, 18, 18)
+                        .addComponent(Cookies))
+                    .addGroup(layout.createSequentialGroup()
+                        .addComponent(IEhistory)
+                        .addGap(18, 18, 18)
+                        .addComponent(FFhistory))
+                    .addComponent(jLabel2)
+                    .addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(jLabel5)
+                    .addGroup(layout.createSequentialGroup()
+                        .addComponent(dateFromTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addGap(0, 0, 0)
+                        .addComponent(dateFromButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addGap(6, 6, 6)
+                        .addComponent(jLabel7)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                        .addComponent(dateToTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addGap(0, 0, 0)
+                        .addComponent(dateToButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addContainerGap())
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+                    .addComponent(activityProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                    .addComponent(makeNodesButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 7, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jLabel6)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addGap(18, 18, 18)
+                .addComponent(jLabel2)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(IEhistory)
+                    .addComponent(FFhistory))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(CHhistory)
+                    .addComponent(Cookies))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                .addComponent(Bookmarks)
+                .addGap(18, 18, 18)
+                .addComponent(jLabel4)
+                .addGap(97, 97, 97)
+                .addComponent(jLabel5)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(dateFromTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                            .addComponent(dateToTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                            .addComponent(jLabel7))
+                        .addGroup(layout.createSequentialGroup()
+                            .addComponent(dateToButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                            .addGap(1, 1, 1))
+                        .addComponent(dateFromButtonCalendar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addContainerGap(102, Short.MAX_VALUE))
+        );
+
+        IEhistory.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(RecentActivityTopComponent.class, "RecentActivityTopComponent.jCheckBox1.AccessibleContext.accessibleName")); // NOI18N
+    }// </editor-fold>//GEN-END:initComponents
+
+    private void makeNodesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_makeNodesButtonActionPerformed
+        activityProgressBar.setIndeterminate(true);
+        edx.makeNodes();
+        activityProgressBar.setIndeterminate(false);
+        
+    }//GEN-LAST:event_makeNodesButtonActionPerformed
+
+public void setProgress(int percent){
+    activityProgressBar.setValue(percent);
+}
+    
+private void IEhistoryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_IEhistoryActionPerformed
+// TODO add your handling code here:
+}//GEN-LAST:event_IEhistoryActionPerformed
+
+private void dateFromTextFieldFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_dateFromTextFieldFocusLost
+        // set the "from" calendar button to listen to change in the text field
+        String fromDateString = this.dateFromTextField.getText();
+        if (!fromDateString.equals("")) {
+            try {
+                Date fromDate = dateFormat.parse(fromDateString);
+                dateFromButtonCalendar.setTargetDate(fromDate);
+            } catch (ParseException ex) {
+                // for now, no need to show the error message to the user her
+            }
+        }
+}//GEN-LAST:event_dateFromTextFieldFocusLost
+
+private void dateFromPopupChanged(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_dateFromPopupChanged
+        if (evt.getNewValue() instanceof Date) {
+            setFromDate((Date) evt.getNewValue());
+        }
+}//GEN-LAST:event_dateFromPopupChanged
+
+private void dateToPopupChanged(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_dateToPopupChanged
+        if (evt.getNewValue() instanceof Date) {
+            setToDate((Date) evt.getNewValue());
+        }
+}//GEN-LAST:event_dateToPopupChanged
+
+private void dateToTextFieldFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_dateToTextFieldFocusLost
+        // set the "to" calendar button to listen to change in the text field
+        String toDateString = this.dateToTextField.getText();
+        if (!toDateString.equals("")) {
+            try {
+                Date toDate = dateFormat.parse(toDateString);
+                dateToButtonCalendar.setTargetDate(toDate);
+            } catch (ParseException ex) {
+                // for now, no need to show the error message to the user here
+            }
+        }
+}//GEN-LAST:event_dateToTextFieldFocusLost
+ /**
+     * Validate and set the datetime field on the screen given a datetime string.
+     * @param date The date object
+     */
+    private void setFromDate(Date date) {
+        String dateStringResult = "";
+        if (date != null) {
+            dateStringResult = dateFormat.format(date);
+        }
+        dateFromTextField.setText(dateStringResult);
+        dateFromButtonCalendar.setTargetDate(date);
+    }
+
+    /**
+     * Validate and set the datetime field on the screen given a date.
+     * @param date The date object
+     */
+    private void setToDate(Date date) {
+        String dateStringResult = "";
+        if (date != null) {
+            dateStringResult = dateFormat.format(date);
+        }
+        dateToTextField.setText(dateStringResult);
+        dateToButtonCalendar.setTargetDate(date);
+    }
+    
+    /**
+     * Set the counts and populate the browser checkboxes which will be used to filter 
+     */
+    private int FFcount = 0;
+    private int IEcount = 0;
+    private int CHcount = 0;
+    private int Cookiescount = 0;
+    private int Bookmarkcount = 0;
+    public void setbrowsercheckboxes(int IEcount, int FFcount, int CHcount, int Cookiescount, int Bookmarkcount) {
+        IEhistory.setText("IE History (" + IEcount +")");
+        FFhistory.setText("Firefox History (" + FFcount +")");
+        CHhistory.setText("Chrome History (" + CHcount +")");
+        Cookies.setText("All Cookies (" + Cookiescount +")");
+        Bookmarks.setText("All Bookmarks (" + Bookmarkcount +")");
+        
+    }
+    
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JCheckBox Bookmarks;
+    private javax.swing.JCheckBox CHhistory;
+    private javax.swing.JCheckBox Cookies;
+    private javax.swing.JCheckBox FFhistory;
+    private javax.swing.JCheckBox IEhistory;
+    private javax.swing.JProgressBar activityProgressBar;
+    private org.sourceforge.jcalendarbutton.JCalendarButton dateFromButtonCalendar;
+    private javax.swing.JFormattedTextField dateFromTextField;
+    private org.sourceforge.jcalendarbutton.JCalendarButton dateToButtonCalendar;
+    private javax.swing.JFormattedTextField dateToTextField;
+    private javax.swing.JLabel jLabel1;
+    private javax.swing.JLabel jLabel2;
+    private javax.swing.JLabel jLabel3;
+    private javax.swing.JLabel jLabel4;
+    private javax.swing.JLabel jLabel5;
+    private javax.swing.JLabel jLabel6;
+    private javax.swing.JLabel jLabel7;
+    private javax.swing.JList jList2;
+    private javax.swing.JScrollPane jScrollPane2;
+    private javax.swing.JSeparator jSeparator1;
+    private javax.swing.JTextField jTextField1;
+    private javax.swing.JButton makeNodesButton;
+    // End of variables declaration//GEN-END:variables
+}
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java
new file mode 100644
index 0000000000000000000000000000000000000000..2b8070b11080e464a6a1df6c503afbe9962d6170
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java
@@ -0,0 +1,60 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.recentactivity;
+import java.io.File;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.datamodel.FsContent;
+import org.sleuthkit.datamodel.SleuthkitCase;
+/**
+ *
+ * @author Alex
+ */
+public class Util {
+public Logger logger = Logger.getLogger(this.getClass().getName());    
+    
+  private Util(){
+      
+  }
+
+public static boolean pathexists(String path){
+    File file=new File(path);
+    boolean exists = file.exists();
+    return exists;
+}
+
+public static boolean imgpathexists(String path){
+    Case currentCase = Case.getCurrentCase(); // get the most updated case
+    SleuthkitCase tempDb = currentCase.getSleuthkitCase();
+    
+    int count = 0;
+    try { 
+     List<FsContent> FFSqlitedb;
+     ResultSet rs = tempDb.runQuery("select * from tsk_files where parent_path LIKE '%"+ path + "%'");
+     FFSqlitedb = tempDb.resultSetToFsContents(rs);
+     count = FFSqlitedb.size();
+    }
+    catch (SQLException ex) 
+        {
+           //logger.log(Level.WARNING, "Error while trying to contact SQLite db.", ex);
+        }
+    finally {
+        
+        if(count > 0)
+            {
+            return true;
+            }
+        else
+            {
+             return false;
+            }
+        }    
+
+    }
+}
\ No newline at end of file
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/dbconnect.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/dbconnect.java
new file mode 100644
index 0000000000000000000000000000000000000000..b3f127e900fb314eed37c3da11338e59130f6a2d
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/dbconnect.java
@@ -0,0 +1,25 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.recentactivity;
+
+import java.sql.*;
+/**
+ *
+ * @author Alex
+ */
+ public class dbconnect extends sqlitedbconnect{
+        
+        private String sDriverForclass = "org.sqlite.JDBC";
+        public dbconnect(String sDriverForClass, String sUrlKey) throws Exception
+        { 
+            init(sDriverForClass, sUrlKey); 
+            Statement stmt = conn.createStatement();
+            //String selecthistory = "SELECT moz_historyvisits.id,url,title,visit_count,visit_date,from_visit,rev_host FROM moz_places, moz_historyvisits WHERE moz_places.id = moz_historyvisits.place_id AND hidden = 0";
+           // ResultSet rs = stmt.executeQuery(selecthistory); 
+           
+        }
+        
+        
+    }
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/layer.xml b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/layer.xml
new file mode 100644
index 0000000000000000000000000000000000000000..40f6e5e00b945a031f5d6ba2afa590e0f35a5728
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/layer.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
+<filesystem/>
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/sqlitedbconnect.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/sqlitedbconnect.java
new file mode 100644
index 0000000000000000000000000000000000000000..59e1f1c557dcba2923d6bd85cbefde8148d33b89
--- /dev/null
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/sqlitedbconnect.java
@@ -0,0 +1,102 @@
+/*
+ * General C&P class that we need to figure out a better way to integrate, replace after demo
+ */
+package org.sleuthkit.autopsy.recentactivity;
+
+/**
+ *
+ * @author Alex
+ */
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+ 
+ 
+/** Database connection class & utilities **/
+ 
+abstract class sqlitedbconnect {
+ 
+public  String sDriver = ""; 
+public  String sUrl = null;
+public  int iTimeout = 30;
+public  Connection conn = null;
+public  Statement statement = null;
+ 
+ 
+/* Stub constructor for quick instantiation o/t fly for using some of the ancillary stuff */
+ 
+public  sqlitedbconnect()
+{}
+ 
+/* quick and dirty constructor to test the database passing the DriverManager name and the fully loaded url to handle */
+/* NB this will typically be available if you make this class concrete and not abstract */
+public sqlitedbconnect(String sDriverToLoad, String sUrlToLoad) throws Exception
+{
+init(sDriverToLoad, sUrlToLoad);
+}
+ 
+public void init(String sDriverVar, String sUrlVar) throws Exception
+{
+setDriver(sDriverVar);
+setUrl(sUrlVar);
+setConnection();
+setStatement();
+}
+ 
+private void setDriver(String sDriverVar)
+{
+sDriver = sDriverVar;
+}
+ 
+private void setUrl(String sUrlVar)
+{
+sUrl = sUrlVar;
+}
+ 
+public  void setConnection() throws Exception {
+Class.forName(sDriver);
+conn = DriverManager.getConnection(sUrl);
+}
+ 
+ 
+public  Connection getConnection() {
+return conn;
+}
+ 
+public  void setStatement() throws Exception {
+if (conn == null) {
+setConnection();
+}
+statement = conn.createStatement();
+statement.setQueryTimeout(iTimeout);  // set timeout to 30 sec.
+}
+ 
+public  Statement getStatement() {
+return statement;
+}
+ 
+public  void executeStmt(String instruction) throws SQLException {
+statement.executeUpdate(instruction);
+}
+ 
+// processes an array of instructions e.g. a set of SQL command strings passed from a file
+//NB you should ensure you either handle empty lines in files by either removing them or parsing them out 
+// since they will generate spurious SQLExceptions when they are encountered during the iteration....
+public void executeStmt(String[] instructionSet) throws SQLException {
+for (int i = 0; i < instructionSet.length; i++) {
+executeStmt(instructionSet[i]);
+}
+}
+ 
+public ResultSet executeQry(String instruction) throws SQLException {
+return statement.executeQuery(instruction);
+} 
+ 
+public void closeConnection() {
+try { conn.close(); } catch (Exception ignore) {}
+}
+ 
+}
\ No newline at end of file
diff --git a/nbproject/project.properties b/nbproject/project.properties
index 4acb2e5e05bca9380be26edfe6add618e6bbaca2..392e98bff729cef7b06a2a562dbdf9d4884e3929 100644
--- a/nbproject/project.properties
+++ b/nbproject/project.properties
@@ -20,7 +20,10 @@ modules=\
     ${project.org.sleuthkit.autopsy.keywordsearch}:\
     ${project.org.sleuthkit.autopsy.coreutils}:\
     ${project.org.sleuthkit.autopsy.ingest}:\
-    ${project.org.sleuthkit.autopsy.hashdatabase}
+    ${project.org.sleuthkit.autopsy.hashdatabase}:\
+    ${project.org.gnu.trove}:\
+    ${project.org.sleuthkit.autopsy.recentactivity}
+project.org.gnu.trove=trove
 project.org.sleuthkit.autopsy.casemodule=Case
 project.org.sleuthkit.autopsy.corecomponentinterfaces=CoreComponentInterfaces
 project.org.sleuthkit.autopsy.corecomponents=CoreComponents
@@ -32,3 +35,4 @@ project.org.sleuthkit.autopsy.ingest=Ingest
 project.org.sleuthkit.autopsy.keywordsearch=KeywordSearch
 project.org.sleuthkit.autopsy.menuactions=MenuActions
 project.org.sleuthkit.autopsy.datamodel=DataModel
+project.org.sleuthkit.autopsy.recentactivity=RecentActivity
diff --git a/thirdparty/pasco2/.classpath b/thirdparty/pasco2/.classpath
new file mode 100644
index 0000000000000000000000000000000000000000..7bd109d7a131124e8ab9c99dff1e677247a328b4
--- /dev/null
+++ b/thirdparty/pasco2/.classpath
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="test"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry exported="true" kind="lib" path="lib/commons-cli-1.0.jar"/>
+	<classpathentry exported="true" kind="lib" path="lib/commons-collections-3.1.jar"/>
+	<classpathentry exported="true" kind="lib" path="lib/ctypes4j.jar"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
+	<classpathentry exported="true" kind="lib" path="lib/ctypes4j.zip"/>
+	<classpathentry kind="lib" path="C:/Development/42six/trunk/thirdparty/pasco2/lib/trove-3.0.2.jar"/>
+	<classpathentry kind="output" path="build"/>
+</classpath>
diff --git a/thirdparty/pasco2/.project b/thirdparty/pasco2/.project
new file mode 100644
index 0000000000000000000000000000000000000000..454c782dbe93e1c2f1d2eb380504a90ee7423dfa
--- /dev/null
+++ b/thirdparty/pasco2/.project
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>pasco2</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+	<linkedResources>
+		<link>
+			<name>lib</name>
+			<type>2</type>
+			<location>C:/Development/42six/trunk/thirdparty/pasco2/lib</location>
+		</link>
+	</linkedResources>
+	<variableList>
+		<variable>
+			<name>BIN_DIR</name>
+			<value>file:/C:/Development/42six/trunk/thirdparty/pasco2/bin</value>
+		</variable>
+	</variableList>
+</projectDescription>
diff --git a/thirdparty/pasco2/.settings/org.eclipse.jdt.core.prefs b/thirdparty/pasco2/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..e43bcbde9059e920649c7e9181ee7666689022c8
--- /dev/null
+++ b/thirdparty/pasco2/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,292 @@
+#Thu Dec 29 15:00:31 MST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=mixed
+org.eclipse.jdt.core.formatter.tabulation.size=8
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/thirdparty/pasco2/.settings/org.eclipse.jdt.ui.prefs b/thirdparty/pasco2/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..fa8570c5ec91dd7145b54a51069686378b94d667
--- /dev/null
+++ b/thirdparty/pasco2/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,6 @@
+#Thu Dec 29 15:00:31 MST 2011
+eclipse.preferences.version=1
+formatter_profile=org.eclipse.jdt.ui.default.sun_profile
+formatter_settings_version=12
+org.eclipse.jdt.ui.javadoc=false
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\r\n * @return the ${bare_field_name}\r\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\r\n * @param ${param} the ${bare_field_name} to set\r\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\r\n * \r\n */</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\r\n * @author ${user}\r\n *\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\r\n * \r\n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\r\n * ${see_to_overridden}\r\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\r\n * ${tags}\r\n * ${see_to_target}\r\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\r\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\r\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\r\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\r\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\r\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\r\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\r\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
diff --git a/thirdparty/pasco2/build.xml b/thirdparty/pasco2/build.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f1f1d01e52a8335183c005c591ae3de11e250702
--- /dev/null
+++ b/thirdparty/pasco2/build.xml
@@ -0,0 +1,94 @@
+<project name="pasco2" default="jar" basedir=".">
+
+	<!-- paths -->
+	<property file="${basedir}/build.properties"/>
+  	<property name="src.dir" location="${basedir}/src"/>
+  	<property name="java.src.dir" location="${basedir}/src"/>
+  	<property name="java.test.dir" location="${basedir}/src/test"/>
+  	<property name="doc.dir" location="${basedir}/doc"/>
+
+  	<property name="bin.dir" location="${basedir}/bin"/>
+  	<property name="dist.dir"  location="${basedir}/dist"/>
+    <property name="lib.dir"  value="${basedir}/lib"/>
+    <property name="build.dir"  location="${basedir}/build"/>
+    <property name="build.lib.dir"  location="${basedir}/lib/build"/>
+
+
+	<!-- build / compile properties -->
+    <property name="debug" value="off"/>
+    <property name="optimize" value="on"/>
+    <property name="deprecation" value="off"/>
+    <property name="compress.jars" value="true"/>
+	<property name="link" value="static"/>
+
+
+    <path id="project.class.path">
+        <pathelement path="${java.class.path}" />
+        <fileset dir="${lib.dir}">
+            <include name="*.jar" />
+        </fileset>
+    </path>
+
+    <path id="build.class.path">
+        <pathelement path="${java.class.path}" />
+        <fileset dir="${lib.dir}">
+            <include name="*.jar" />
+        </fileset>
+   </path>	
+
+	<target name="init">
+	    <tstamp/>
+	    <mkdir dir="${build.dir}"/>
+	    <mkdir dir="${dist.dir}"/>
+	</target>
+	
+  <target name="compile" depends="init"
+        description="compile the source " >
+        <javac srcdir="${java.src.dir}"
+            destdir="${build.dir}"
+            debug="${debug}"
+            optimize="${optimize}"
+            deprecation="${deprecation}"
+            target="1.5"
+        	source="1.5"
+        	includeantruntime="false">
+                <classpath refid="project.class.path" />
+            <compilerarg value="-Xlint:unchecked,-options"/>
+ 		</javac>
+  </target>
+  
+ 
+	
+	<target name="jar" depends="compile">
+		<jar jarfile="${dist.dir}/pasco2.jar" 
+				basedir="${build.dir}" 
+				includes="**/*.class,**/*.properties,**/*.bmp,**/*.gif,${lib.dir}/*.jar">  
+			<manifest>
+		      <attribute name="Main-Class"
+		            value="isi.pasco2.Main"/>
+		    </manifest>
+		</jar>
+	</target>
+
+	<target name="dist" depends="jar">
+		<zip destfile="${dist.dir}/pasco2-0.1.zip">
+			<zipfileset prefix="lib" dir="${lib.dir}" />
+			<zipfileset prefix="src" dir="${src.dir}" />
+			<zipfileset dir="${dist.dir}">
+				<include name="*.jar"/>
+			</zipfileset>
+			<zipfileset file="LICENSE.txt" />
+			<zipfileset file="LICENSE-jawin.txt" />
+			<zipfileset file="README.txt" />
+			<zipfileset file="build.xml" />
+		</zip>
+	</target>	
+
+		
+  <target name="clean"
+        description="clean up" >
+    <delete dir="${build.dir}"/>
+    <delete dir="${dist.dir}"/>
+  </target>
+
+</project>
diff --git a/thirdparty/pasco2/lib/commons-cli-1.0.jar b/thirdparty/pasco2/lib/commons-cli-1.0.jar
new file mode 100644
index 0000000000000000000000000000000000000000..22a004e14e16720cae9af97d4d1475b12d2388aa
Binary files /dev/null and b/thirdparty/pasco2/lib/commons-cli-1.0.jar differ
diff --git a/thirdparty/pasco2/lib/commons-collections-3.1.jar b/thirdparty/pasco2/lib/commons-collections-3.1.jar
new file mode 100644
index 0000000000000000000000000000000000000000..41e230feeaa53618b6ac5f8d11792c2eecf4d4fd
Binary files /dev/null and b/thirdparty/pasco2/lib/commons-collections-3.1.jar differ
diff --git a/thirdparty/pasco2/lib/ctypes4j.dll b/thirdparty/pasco2/lib/ctypes4j.dll
new file mode 100644
index 0000000000000000000000000000000000000000..3455ad1771c222ac7181c4849ce52bf61f9365d2
Binary files /dev/null and b/thirdparty/pasco2/lib/ctypes4j.dll differ
diff --git a/thirdparty/pasco2/lib/ctypes4j.jar b/thirdparty/pasco2/lib/ctypes4j.jar
new file mode 100644
index 0000000000000000000000000000000000000000..a6c6f3c3b0e1db8e5d7e9214fc0a5ad839f70282
Binary files /dev/null and b/thirdparty/pasco2/lib/ctypes4j.jar differ
diff --git a/thirdparty/pasco2/lib/ctypes4j.zip b/thirdparty/pasco2/lib/ctypes4j.zip
new file mode 100644
index 0000000000000000000000000000000000000000..84d28c2dbaeb508642386804b2f7916029070a9a
Binary files /dev/null and b/thirdparty/pasco2/lib/ctypes4j.zip differ
diff --git a/thirdparty/pasco2/lib/pasco2.jar b/thirdparty/pasco2/lib/pasco2.jar
new file mode 100644
index 0000000000000000000000000000000000000000..1f07a5e960e13be471f0eaabe6dae4b9d5f4261a
Binary files /dev/null and b/thirdparty/pasco2/lib/pasco2.jar differ
diff --git a/thirdparty/pasco2/lib/trove-1.0.2.jar b/thirdparty/pasco2/lib/trove-1.0.2.jar
new file mode 100644
index 0000000000000000000000000000000000000000..ac62eb35cdb4904289d49b6d322c6b0ebc97a2b4
Binary files /dev/null and b/thirdparty/pasco2/lib/trove-1.0.2.jar differ
diff --git a/thirdparty/pasco2/lib/trove-3.0.2.jar b/thirdparty/pasco2/lib/trove-3.0.2.jar
new file mode 100644
index 0000000000000000000000000000000000000000..12fb57681f8ca343350c8f43f1a8c007045936ec
Binary files /dev/null and b/thirdparty/pasco2/lib/trove-3.0.2.jar differ
diff --git a/thirdparty/pasco2/src/isi/pasco2/Main.java b/thirdparty/pasco2/src/isi/pasco2/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..a16914e90843251cc879e28f84120cdd26e9e2a1
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/Main.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+package isi.pasco2;
+
+import isi.pasco2.handler.CountingCacheHandler;
+import isi.pasco2.handler.Pasco2HistoryHandler;
+import isi.pasco2.io.FastReadIndexFile;
+import isi.pasco2.io.IndexFile;
+import isi.pasco2.parser.IECacheFileParser;
+import isi.pasco2.parser.IEHistoryFileParser;
+import isi.pasco2.parser.IEIndexFileParser;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.PosixParser;
+
+/**
+ * Main command line parser for pasco2
+ * 
+ * @author Bradley Schatz
+ *
+ */
+public class Main {
+ public static void main(String[] args) {
+    CommandLineParser parser = new PosixParser();
+
+    Options options = new Options();
+    Option undelete = new Option("d", "Undelete activity records");
+    options.addOption(undelete);
+    Option disableAllocation = new Option("M", "Disable allocation detection");
+    options.addOption(disableAllocation);
+    Option fieldDelimeter = OptionBuilder.withArgName( "field-delimeter" )
+                      .hasArg()
+                      .withDescription( "Field Delimeter (TAB by default)" )
+                      .create( "t" );
+    options.addOption(fieldDelimeter);
+    
+    Option timeFormat = OptionBuilder.withArgName( "time-format" )
+                    .hasArg()
+                    .withDescription( "xsd or standard (pasco1 compatible)" )
+                    .create( "f" );
+    options.addOption(timeFormat);
+    
+    Option fileTypeOption = OptionBuilder.withArgName( "file-type" )
+                    .hasArg()
+                    .withDescription( "The type of file: cache or history" )
+                    .create( "T" );
+    
+    options.addOption(fileTypeOption);
+
+    
+    try {
+        CommandLine line = parser.parse( options, args );
+        boolean undeleteMethod = false;
+        String delimeter = null;
+        String format = null;
+        String fileType = null;
+        boolean disableAllocationTest = false;
+        
+        if( line.hasOption( "d" ) ) {
+            undeleteMethod = true; 
+        }
+        
+        if( line.hasOption( 't' ) ) {
+          delimeter = line.getOptionValue( 't' ) ;
+        }
+        
+        if( line.hasOption( 'M' ) ) {
+          disableAllocationTest = true ;
+        }
+        
+        if( line.hasOption( 'T' ) ) {
+          fileType = line.getOptionValue( 'T' ) ;
+        }
+        
+        if( line.hasOption( 'f' ) ) {
+          format = line.getOptionValue( 'f' ) ;
+        }
+        
+        if (line.getArgs().length != 1) {
+          System.err.println("No file specified.");
+          HelpFormatter formatter = new HelpFormatter();
+          formatter.printHelp( "pasco2", options );
+          System.exit(1);
+        }
+        String fileName = line.getArgs()[0];
+        
+        try {
+          IndexFile fr = new FastReadIndexFile(fileName, "r");
+ 
+          CountingCacheHandler handler = null;
+          
+          if (fileType == null) {
+            handler = new CountingCacheHandler();
+          }
+          if (fileType == null) {
+            handler = new CountingCacheHandler();
+          } else if (fileType.equals("cache")) {
+            handler = new CountingCacheHandler();
+          } else if (fileType.equals("history")) {
+            handler = new Pasco2HistoryHandler();
+          } 
+          
+          if (format != null) {
+            if (format.equals("pasco")) { 
+              DateFormat regularDateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS");
+              handler.setDateFormat(regularDateFormat);
+              TimeZone tz = TimeZone.getTimeZone("Australia/Brisbane");
+              regularDateFormat.setTimeZone(tz);
+              
+            } else if (format.equals("standard")) {
+              DateFormat xsdDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+              handler.setDateFormat(xsdDateFormat);     
+              xsdDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+            } else {
+              System.err.println("Format not supported.");
+              HelpFormatter formatter = new HelpFormatter();
+              formatter.printHelp( "pasco2", options );
+              System.exit(1);
+            }
+          }
+          
+          if (delimeter != null) {
+            handler.setDelimeter(delimeter);
+          }
+          
+          IEIndexFileParser logparser = null;
+          if (fileType == null) {
+            System.err.println("Using cache file parser.");
+            logparser = new IECacheFileParser(fileName, fr, handler);
+          } else if (fileType.equals("cache")) {
+            logparser = new IECacheFileParser(fileName, fr, handler);
+          } else if (fileType.equals("history")) {
+            logparser = new IEHistoryFileParser(fileName, fr, handler);
+          } else {
+            System.err.println("Unsupported file type.");
+            HelpFormatter formatter = new HelpFormatter();
+            formatter.printHelp( "pasco2", options );
+            System.exit(1);
+          }
+          if (disableAllocationTest) {
+            logparser.setDisableAllocationTest(true);
+          }
+          logparser.parseFile();
+          
+        } catch (Exception ex) {
+          System.err.println(ex.getMessage());
+          ex.printStackTrace();
+        }
+        
+    }
+    catch( ParseException exp ) {
+        System.out.println( "Unexpected exception:" + exp.getMessage() );
+    }
+  }
+}
+
+
diff --git a/thirdparty/pasco2/src/isi/pasco2/Poller.java b/thirdparty/pasco2/src/isi/pasco2/Poller.java
new file mode 100644
index 0000000000000000000000000000000000000000..776263f2184a27eaae2188afc12c05e945e1e069
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/Poller.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+package isi.pasco2;
+
+import isi.pasco2.io.FastReadIndexFile;
+import isi.pasco2.io.IndexFile;
+import isi.pasco2.parser.IEHistoryFileParser;
+import isi.pasco2.poller.DifferenceHandler;
+
+/**
+ * Index.dat difference observer. Periodically polls the index.dat file in question and 
+ * notes and changes.
+ * 
+ * Limitations: Very memory intensive, should watch the unknown sections better.
+ * 
+ * @author Bradley Schatz
+ *
+ */
+public class Poller {
+ public static void main(String[] args) {
+   String cachePath = "d:\\Documents and Settings\\bschatz\\Local Settings\\Temporary Internet Files\\Content.IE5\\index.dat";
+   String historyPath = "d:\\Documents and Settings\\bschatz\\Local Settings\\History\\History.IE5\\index.dat";
+   
+   //DifferenceHandler cacheHandler = new DifferenceHandler("Cache");
+   DifferenceHandler historyHandler = new DifferenceHandler("History");
+   
+   //IEIndexFileParser cacheparser = new IEIndexFileParser();
+   IEHistoryFileParser historyParser ;
+   
+   while (true) {
+      try {
+        //IndexFile f1 = new FastReadIndexFile(cachePath);
+        //cacheparser.parseFile(cachePath, f1, cacheHandler);
+        //f1.close();
+   
+        IndexFile f2 = new FastReadIndexFile(historyPath);
+        historyParser = new IEHistoryFileParser(cachePath, f2, historyHandler);
+        historyParser.parseFile();
+        f2.close();
+        
+        try {
+          Thread.sleep(10000);
+        } catch (InterruptedException ex) {
+        }
+      } catch (Exception ex) {
+        System.err.println(ex.getMessage());
+        ex.printStackTrace();
+      }
+        
+    }
+
+  }
+}
+
+
diff --git a/thirdparty/pasco2/src/isi/pasco2/handler/AbstractPrinterHandler.java b/thirdparty/pasco2/src/isi/pasco2/handler/AbstractPrinterHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..19e85c208c47ebd094862242b602b775a921a393
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/handler/AbstractPrinterHandler.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+package isi.pasco2.handler;
+
+
+import isi.pasco2.parser.DateTime;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+
+public class AbstractPrinterHandler implements DefaultHandler {
+  Writer output;
+  String delimeter = "\t";
+  DateFormat dateFormat = null;
+
+  
+  public String getDelimeter() {
+    return delimeter;
+  }
+
+  public void setDelimeter(String seperator) {
+    this.delimeter = seperator;
+  }
+
+  public AbstractPrinterHandler(Writer w) {
+    output = w;
+    dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+  }
+ 
+  public AbstractPrinterHandler(Writer w, DateFormat df) {
+    output = w;
+    dateFormat = df;
+  }
+  
+  public AbstractPrinterHandler() {
+    output = new PrintWriter(System.out);
+    dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+  }
+  
+  public void endDocument() {
+    try {
+      output.close();
+    } catch (IOException ex) {
+      handleException(ex);
+    }
+  }
+
+
+  
+  public void LEAKRecord(DateTime accessTime, DateTime modTime, String url, String file, String directory, String httpHeaders) {
+    try {
+      output.write("LEAK");
+      output.write(delimeter);
+      output.write(url);
+      output.write(delimeter);
+      output.write(dateFormat.format(modTime.asDate()));
+      output.write(delimeter);
+      output.write(dateFormat.format(accessTime.asDate()));
+      output.write(delimeter);
+      output.write(file);
+      output.write(delimeter);
+      output.write(directory);
+      output.write(delimeter);
+      output.write(removeNewlines(httpHeaders));      
+      output.write("\r\n");
+    } catch (IOException ex) {
+      handleException(ex);
+    }
+  }         
+
+  public void REDRRecord(String url) {
+    try {
+      output.write("REDR" + delimeter + url + "\r\n");
+    } catch (IOException ex) {
+      handleException(ex);
+    }  
+  }
+
+
+  public void startDocument(String fileName, float version) {
+    try {
+      output.write("History File: " + fileName + " Version: " + Float.toString(version) + "\r\n\r\n");
+      output.write("TYPE" + delimeter + "URL" + delimeter + "MODIFIED TIME" + delimeter + "ACCESS TIME" + delimeter + "FILENAME" + delimeter + "DIRECTORY" + delimeter + "HTTP HEADERS\r\n");
+    } catch (IOException ex) {
+      handleException(ex);
+    }
+  }
+
+
+
+  public void invalidRecord(int offset) {
+    try {
+      output.write("Inconsistent record " + Integer.toHexString(offset) + "\r\n");
+    } catch (IOException ex) {
+      handleException(ex);
+    }
+  }
+
+  public void unknownRecord(String type, int offset, byte[] record) {
+    try {
+      output.write("Unknown record type at offset: " + Integer.toHexString(offset) + "\r\n");
+    } catch (IOException ex) {
+      handleException(ex);
+    }   
+  }
+  protected void handleException(Exception ex) {
+    ex.printStackTrace();
+  }
+  
+  String removeNewlines(String str) {
+    return str.replaceAll("\r\n", "  ");
+  }
+
+  public DateFormat getDateFormat() {
+    return dateFormat;
+  }
+
+  public void setDateFormat(DateFormat dateFormat) {
+    this.dateFormat = dateFormat;
+  }
+
+  public void unusedRecord(int offset) {
+  }
+
+  public void record(int offset, byte[] rec) {
+  }
+  
+  
+  
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/handler/CacheAccessHandler.java b/thirdparty/pasco2/src/isi/pasco2/handler/CacheAccessHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..c773bec98b3bbf40880a3eef0151088a11e8aed7
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/handler/CacheAccessHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+package isi.pasco2.handler;
+
+import isi.pasco2.parser.DateTime;
+
+public interface CacheAccessHandler extends DefaultHandler {
+  public void LEAKRecord(DateTime accessTime, DateTime modTime, String url, String file, String directory, String httpHeaders);
+  public void URLRecord(DateTime accessTime, DateTime modTime, String url, String file, String directory, String httpHeaders);
+
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/handler/CountingCacheHandler.java b/thirdparty/pasco2/src/isi/pasco2/handler/CountingCacheHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..2adc115536278a2623446e902de9e3cc1b776314
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/handler/CountingCacheHandler.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.handler;
+
+import isi.pasco2.parser.DateTime;
+import isi.pasco2.parser.time.FileTime;
+import isi.pasco2.util.HexFormatter;
+
+import java.io.IOException;
+
+public class CountingCacheHandler extends Pasco2CacheHandler {
+  int LEAKcount = 0;
+  int URLcount = 0;
+  int REDRcount = 0;
+  int ENTcount = 0;
+  int unknowncount = 0;
+  
+  public void unknownRecord(String type, int offset, byte[] record) {
+    try {
+      if (type.startsWith("ent")) {
+        ENTcount += 1;
+      } else {
+        unknowncount += 1;
+      }
+      output.write("Unknown record type at offset: " + Integer.toHexString(offset) + "\r\n");
+      output.write(HexFormatter.convertBytesToString(record));
+      output.write("\r\n");
+    } catch (IOException ex) {
+      handleException(ex);
+    }   
+  }
+
+  public void endDocument() {
+    try {
+      output.write("LEAK entries: " + Integer.toString(LEAKcount) + "\r\n");
+      output.write("REDR entries: " + Integer.toString(REDRcount) + "\r\n");
+      output.write("URL entries: " + Integer.toString(URLcount) + "\r\n");
+      output.write("ent entries: " + Integer.toString(ENTcount) + "\r\n");
+      output.write("unknown entries: " + Integer.toString(unknowncount) + "\r\n");
+
+    } catch (IOException ex) {
+      handleException(ex);
+    } 
+    super.endDocument();
+  
+  }
+
+
+  public void LEAKRecord(FileTime accessTime, FileTime modTime, String url, String file, String directory, String httpHeaders) {
+    LEAKcount += 1;
+    super.LEAKRecord(accessTime, modTime, url, file, directory, httpHeaders);
+  }
+
+  public void REDRRecord(String url) {
+    REDRcount += 1;
+    super.REDRRecord(url);
+  }
+
+  public void URLRecord(FileTime accessTime, FileTime modTime, String url, String file, String directory, String httpHeaders) {
+    URLcount += 1;
+    super.URLRecord(accessTime, modTime, url, file, directory, httpHeaders);
+  }
+  
+  public void URLRecord(DateTime localAccessTime, DateTime accessTime, DateTime modTime, String url, String file, String directory, String httpHeaders) {
+    URLcount += 1;
+    super.URLRecord( localAccessTime,  accessTime,  modTime,  url,  file,  directory,  httpHeaders);
+  }
+
+  
+  
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/handler/DefaultHandler.java b/thirdparty/pasco2/src/isi/pasco2/handler/DefaultHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..a542b7b653dcf834da127df18c976c7d5036888a
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/handler/DefaultHandler.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.handler;
+
+
+public interface DefaultHandler {
+    public void startDocument(String fileName, float version);
+    public void endDocument();
+    public void unknownRecord(String type, int offset, byte[] record);
+    public void unusedRecord(int offset);
+    public void invalidRecord(int offset);
+    public void record(int currentOffset, byte[] rec);
+    public void REDRRecord(String url);
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/handler/HistoryAccessHandler.java b/thirdparty/pasco2/src/isi/pasco2/handler/HistoryAccessHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c1b35199547c1f4425538540b1b021c5dfdff89
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/handler/HistoryAccessHandler.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.handler;
+
+import isi.pasco2.parser.DateTime;
+
+public interface HistoryAccessHandler extends DefaultHandler {
+  public void URLRecord(DateTime localAccessTime, DateTime accessTime, DateTime modTime, String url);
+  public void URLRecord(DateTime localAccessTime, DateTime accessTime, DateTime modTime, String url, int numberOfAccesses);
+
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/handler/Pasco2CacheHandler.java b/thirdparty/pasco2/src/isi/pasco2/handler/Pasco2CacheHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..a99737d9725705fb975b43dfe8cb1743ea74b9ac
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/handler/Pasco2CacheHandler.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+package isi.pasco2.handler;
+
+import isi.pasco2.parser.DateTime;
+
+import java.io.IOException;
+
+public class Pasco2CacheHandler extends AbstractPrinterHandler implements CacheAccessHandler {
+
+  public void URLRecord(DateTime localAccessTime, DateTime accessTime, DateTime modTime, String url, String file, String directory, String httpHeaders) {
+    try {
+      output.write("URL");
+      output.write(delimeter);
+      output.write(url);
+      output.write(delimeter);
+      output.write(dateFormat.format(modTime.asDate()));
+      output.write(delimeter);
+      output.write(dateFormat.format(accessTime.asDate()));
+      output.write(delimeter);
+      output.write(dateFormat.format(localAccessTime.asDate()));
+      output.write(delimeter);
+      output.write(file);
+      output.write(delimeter);
+      output.write(directory);
+      output.write(delimeter);
+      output.write(removeNewlines(httpHeaders)); 
+      output.write("\r\n");
+    } catch (IOException ex) {
+      handleException(ex);
+    }
+  }
+  
+  public void URLRecord(DateTime accessTime, DateTime modTime, String url, String file, String directory, String httpHeaders) {
+    try {
+      output.write("URL");
+      output.write(delimeter);
+      output.write(url);
+      output.write(delimeter);
+      output.write(dateFormat.format(modTime.asDate()));
+      output.write(delimeter);
+      output.write(dateFormat.format(accessTime.asDate()));
+      output.write(delimeter);
+      output.write(file);
+      output.write(delimeter);
+      output.write(directory);
+      output.write(delimeter);
+      output.write(removeNewlines(httpHeaders)); 
+      output.write("\r\n");
+    } catch (IOException ex) {
+      handleException(ex);
+    }
+  }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/handler/Pasco2HistoryHandler.java b/thirdparty/pasco2/src/isi/pasco2/handler/Pasco2HistoryHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c3c1667800ef29b144e91b1e6ac6dc49797be17
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/handler/Pasco2HistoryHandler.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+package isi.pasco2.handler;
+
+import isi.pasco2.parser.DateTime;
+
+import java.io.IOException;
+
+public class Pasco2HistoryHandler extends CountingCacheHandler implements
+    HistoryAccessHandler {
+  public void URLRecord(DateTime localAccessTime, DateTime accessTime,
+      DateTime modTime, String url, int numberOfAccesses) {
+    try {
+      output.write("URL");
+      output.write(delimeter);
+      output.write(url);
+      output.write(delimeter);
+      output.write(dateFormat.format(modTime.asDate()));
+      output.write(delimeter);
+      output.write(dateFormat.format(accessTime.asDate()));
+      output.write(delimeter);
+      output.write(dateFormat.format(localAccessTime.asDate()));
+      output.write(delimeter);
+      output.write(Integer.toString(numberOfAccesses));
+      output.write("\r\n");
+    } catch (IOException ex) {
+      handleException(ex);
+    }
+  }
+
+  public void URLRecord(DateTime localAccessTime, DateTime accessTime,
+      DateTime modTime, String url) {
+    try {
+      output.write("URL");
+      output.write(delimeter);
+      output.write(url);
+      output.write(delimeter);
+      output.write(dateFormat.format(modTime.asDate()));
+      output.write(delimeter);
+      output.write(dateFormat.format(accessTime.asDate()));
+      output.write(delimeter);
+      output.write(dateFormat.format(localAccessTime.asDate()));
+      output.write("\r\n");
+    } catch (IOException ex) {
+      handleException(ex);
+    }
+  }
+  
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/io/EnhancedRandomAccessFile.java b/thirdparty/pasco2/src/isi/pasco2/io/EnhancedRandomAccessFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..ef5a2ebc726c3a82394c7b1c51918c723cb66d5f
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/io/EnhancedRandomAccessFile.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.io;
+
+import isi.pasco2.util.StructConverter;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+public class EnhancedRandomAccessFile extends RandomAccessFile implements
+    IndexFile {
+  public EnhancedRandomAccessFile(File arg0, String arg1)
+      throws FileNotFoundException {
+    super(arg0, arg1);
+  }
+
+  public EnhancedRandomAccessFile(String arg0, String arg1)
+      throws FileNotFoundException {
+    super(arg0, arg1);
+  }
+
+  public int readLittleEndianInt() throws IOException {
+    byte[] bytes = new byte[4];
+    read(bytes, 0, 4);
+    return StructConverter.bytesIntoInt(bytes, 0);
+  }
+
+  public long readLittleEndianUInt() throws IOException {
+    byte[] bytes = new byte[4];
+    read(bytes, 0, 4);
+    return StructConverter.bytesIntoUInt(bytes, 0);
+  }
+  
+  public int readLittleEndianShort() throws IOException {
+    byte[] bytes = new byte[2];
+    read(bytes, 0, 2);
+    return StructConverter.bytesIntoShort(bytes, 0);
+  }
+
+  void debug(byte[] bytes, int len) {
+    for (int i = 0; i < len; i++) {
+      System.out.print(Byte.toString(bytes[i]) + " ");
+    }
+    System.out.println();
+  }
+
+  public char readAsciiChar() throws IOException {
+    byte b = readByte();
+    return (char) b;
+  }
+
+  public String readStringAtOffset(long offset, int length) throws IOException {
+    seek(offset);
+    byte[] dn = new byte[length];
+    read(dn, 0, length);
+    if (dn[0] == 0) {
+      return new String();
+    } else {
+      return new String(dn);
+    }
+  }
+
+  public int readIntAtOffset(long offset) throws IOException {
+    seek(offset);
+    return readLittleEndianInt();
+  }
+
+  public long readUIntAtOffset(long offset) throws IOException {
+    seek(offset);
+    return readLittleEndianUInt();
+  }
+  
+  public int readShortAtOffset(long offset) throws IOException {
+    seek(offset);
+    return readLittleEndianShort();
+  }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/io/FastReadIndexFile.java b/thirdparty/pasco2/src/isi/pasco2/io/FastReadIndexFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..e1e7012689eaa42a75ee3b0627bfd0b2ce1b752d
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/io/FastReadIndexFile.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.io;
+
+import isi.pasco2.util.StructConverter;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+
+public class FastReadIndexFile implements IndexFile {
+  ByteBuffer content = null;
+
+  public FastReadIndexFile(String fileName) throws FileNotFoundException,
+      IOException {
+    File file = new File(fileName);
+
+    // Create a read-only memory-mapped file
+    FileChannel roChannel = new RandomAccessFile(file, "r").getChannel();
+    ByteBuffer roBuf = roChannel.map(FileChannel.MapMode.READ_ONLY, 0,
+        (int) roChannel.size());
+
+    byte[] buf = new byte[roBuf.limit()];
+    roBuf.get(buf, 0, roBuf.limit());
+    content = ByteBuffer.wrap(buf);
+    roChannel.close();
+  }
+
+  public FastReadIndexFile(String fileName, InputStream stream, long len) throws FileNotFoundException,
+      IOException {
+
+    ByteBuffer roBuf = ByteBuffer.allocate((int)len);
+    byte[] buf = roBuf.array();
+    
+    int offset = 0;
+    int res = 0;
+    while ((res = stream.read(buf, offset, (int)len-offset)) > 0) {
+      offset = offset + res;  
+      if (offset == len) {
+        break;
+      }
+    }
+    stream.close();
+    content = roBuf;
+  }
+
+  public FastReadIndexFile(String fileName, String mode)
+      throws FileNotFoundException, IOException {
+    this(fileName);
+  }
+
+  public void seek(long offset) throws IOException {
+    content.clear();
+    content.position((int) offset);
+
+  }
+
+  public int readLittleEndianInt() throws IOException {
+    byte[] bytes = new byte[4];
+    content.get(bytes, 0, 4);
+    return StructConverter.bytesIntoInt(bytes, 0);
+  }
+
+  public long readLittleEndianUInt() throws IOException {
+    byte[] bytes = new byte[4];
+    content.get(bytes, 0, 4);
+    return StructConverter.bytesIntoUInt(bytes, 0);
+  }
+
+  public int readLittleEndianShort() throws IOException {
+    byte[] bytes = new byte[2];
+    content.get(bytes, 0, 2);
+    return StructConverter.bytesIntoShort(bytes, 0);
+  }
+
+  public int read(byte[] buf, int offset, int count) throws IOException {
+    content.get(buf, offset, count);
+    return count;
+  }
+
+  public int read() throws IOException {
+    return content.get();
+  }
+
+  public char readAsciiChar() throws IOException {
+    return (char) content.get();
+  }
+
+  public int readUnsignedByte() throws IOException {
+    return content.get();
+  }
+
+  public void close() throws IOException {
+
+  }
+
+  public String readStringAtOffset(long offset, int length) throws IOException {
+    seek(offset);
+    byte[] dn = new byte[length];
+    read(dn, 0, length);
+    if (dn[0] == 0) {
+      return new String();
+    } else {
+      return new String(dn);
+    }
+  }
+
+  public int readIntAtOffset(long offset) throws IOException {
+    seek(offset);
+    return readLittleEndianInt();
+  }
+
+  public long readUIntAtOffset(long offset) throws IOException {
+    seek(offset);
+    return readLittleEndianUInt();
+  }
+
+  public int readShortAtOffset(long offset) throws IOException {
+    seek(offset);
+    return readLittleEndianShort();
+  }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/io/IndexFile.java b/thirdparty/pasco2/src/isi/pasco2/io/IndexFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b1762d07055722f099163eafd62845ac3be20da
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/io/IndexFile.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.io;
+
+import java.io.IOException;
+
+public interface IndexFile {
+  public void seek(long offset) throws IOException;
+  public int readLittleEndianInt() throws IOException;
+  public long readLittleEndianUInt() throws IOException;
+  public int readLittleEndianShort() throws IOException;
+  public int read(byte[] buf, int offset, int count) throws IOException;
+  public int read() throws IOException;
+  public char readAsciiChar() throws IOException;
+  public int readUnsignedByte() throws IOException;
+  public void close() throws IOException;
+  public String readStringAtOffset(long offset, int length) throws IOException ;
+  public int readIntAtOffset(long offset) throws IOException;
+  public long readUIntAtOffset(long offset) throws IOException;
+  public int readShortAtOffset(long offset) throws IOException;
+
+
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/model/REDRRecord.java b/thirdparty/pasco2/src/isi/pasco2/model/REDRRecord.java
new file mode 100644
index 0000000000000000000000000000000000000000..cfa288049d1355a012a87027744672141b251d27
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/model/REDRRecord.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.model;
+
+public class REDRRecord extends RecognisedRecord {
+    public REDRRecord(String url, int offset) {
+      this.url = url;
+      this.type = "REDR";
+      this.offset = offset;
+    }
+    
+    public boolean equals(Object obj) {
+      if (obj instanceof REDRRecord) {
+        REDRRecord rec = (REDRRecord) obj;
+        if (rec.offset != this.offset) { 
+          return false;
+        }
+        if (!rec.url.equals(this.url)) {
+          return false;
+        }   
+      }
+      return true;
+    }
+
+
+    public int hashCode() {
+      return offset + url.hashCode();
+    }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/model/RecognisedRecord.java b/thirdparty/pasco2/src/isi/pasco2/model/RecognisedRecord.java
new file mode 100644
index 0000000000000000000000000000000000000000..90718d5bc9adb1238cba44aa67b6d7b995837ed1
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/model/RecognisedRecord.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+package isi.pasco2.model;
+
+public class RecognisedRecord extends Record {
+  String url = null;
+  
+  public String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.append(type);
+    sb.append(' ');
+    if (url != null) {
+      sb.append(url);
+      sb.append(' ');
+    }
+
+    return sb.toString();
+  }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/model/Record.java b/thirdparty/pasco2/src/isi/pasco2/model/Record.java
new file mode 100644
index 0000000000000000000000000000000000000000..f6728eef493601e6700b22599bad992916245a5b
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/model/Record.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.model;
+
+public class Record {
+  String type = null; 
+  int offset;
+  byte[] buf;
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/model/URLLEAKRecord.java b/thirdparty/pasco2/src/isi/pasco2/model/URLLEAKRecord.java
new file mode 100644
index 0000000000000000000000000000000000000000..90ac7f3a7f484a9e249ef01b7e4e1acbfab7e47e
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/model/URLLEAKRecord.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.model;
+
+import isi.pasco2.parser.DateTime;
+import isi.pasco2.util.HexFormatter;
+
+public class URLLEAKRecord extends RecognisedRecord {
+  public String filename = null;
+  public String httpheaders = null;
+  public String dirname = null;
+  public DateTime modTime = null;
+  public DateTime accessTime = null;
+  public DateTime localAccessTime = null;
+  public int accessedCount = 0;
+  
+  public URLLEAKRecord(String type, DateTime accessTime, DateTime modTime, String url, String file, String directory, String httpHeaders, int offset, byte[] rec) {
+    this.accessTime = accessTime;
+    this.modTime = modTime;
+    this.url = url;
+    this.filename = file;
+    this.dirname = directory;
+    this.httpheaders = httpHeaders;
+    this.offset = offset;
+    this.type = type;
+    this.buf = rec;
+  }
+  
+  public URLLEAKRecord(String type, DateTime localAccessTime, DateTime accessTime, DateTime modTime, String url, String file, String directory, String httpHeaders, int offset, byte[] rec) {
+    this.accessTime = accessTime;
+    this.modTime = modTime;
+    this.url = url;
+    this.filename = file;
+    this.dirname = directory;
+    this.httpheaders = httpHeaders;
+    this.offset = offset;
+    this.type = type;
+    this.buf = rec;
+    this.localAccessTime = localAccessTime;
+  }
+  
+  public String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.append(type);
+    sb.append(" [");
+    sb.append(offset);
+    sb.append("]");
+    
+    if (url != null) {
+      sb.append(url);
+      sb.append(' ');
+    }
+    if (filename != null) {
+      sb.append(filename);
+      sb.append(' ');
+    }
+    if (dirname != null) {
+      sb.append(dirname);
+      sb.append(' ');
+    }
+    if (modTime != null) {
+      sb.append(modTime.toString());
+      sb.append(' ');
+    }
+    if (accessTime != null) {
+      sb.append(accessTime.toString());
+      sb.append(' ');
+    }
+    if (localAccessTime != null) {
+      sb.append(localAccessTime.toString());
+      sb.append(' ');
+    }
+    if (httpheaders != null) {
+      sb.append(httpheaders);
+      sb.append(' ');
+    }
+
+    sb.append("\r\n");
+    sb.append(HexFormatter.convertBytesToString(buf));
+    
+    return sb.toString();
+  }
+  
+  public boolean equals(Object obj) {
+    if (!(obj instanceof URLLEAKRecord)) {
+      return false;
+    }
+    
+    URLLEAKRecord rec = (URLLEAKRecord) obj;
+    if (rec.offset != this.offset) { 
+      return false;
+    }
+    if (!rec.modTime.equals(this.modTime)) {
+      return false;
+    }   
+    if (!rec.accessTime.equals(this.accessTime)) {
+      return false;
+    }   
+    if (!rec.url.equals(this.url)) {
+      return false;
+    }
+    if (rec.filename != null && this.filename == null) {
+      return false;
+    }
+    if (rec.filename == null && this.filename != null) {
+      return false;
+    }
+    if (rec.filename != null && filename != null && !rec.filename.equals(this.filename)) {
+      return false;
+    }   
+    if (rec.dirname != null && dirname != null && !rec.dirname.equals(this.dirname)) {
+      return false;
+    }   
+    if (rec.httpheaders != null && httpheaders != null && !rec.httpheaders.equals(this.httpheaders)) {
+      return false;
+    }   
+    
+    if (rec.accessedCount != accessedCount) {
+      return false;
+    }
+    return true;
+  }
+
+
+  public int hashCode() {
+    return offset + filename.hashCode() + httpheaders.hashCode() << 1 + dirname.hashCode() << 2 + modTime.hashCode() << 4 + accessTime.hashCode() << 8;
+  }
+  
+  
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/model/UnknownRecord.java b/thirdparty/pasco2/src/isi/pasco2/model/UnknownRecord.java
new file mode 100644
index 0000000000000000000000000000000000000000..0dcc6e089ed69b4f98b53b8f2a825e6e03d5badf
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/model/UnknownRecord.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.model;
+
+import isi.pasco2.util.HexFormatter;
+
+import java.io.StringWriter;
+
+public class UnknownRecord extends Record {
+  byte[] record;
+  public UnknownRecord(byte[] record, int offset) {
+    this.record = record;
+    this.offset = offset;   
+  }
+  
+  public String toString() {
+
+      StringWriter output = new StringWriter();
+      output.write("Unknown record type at offset: " + Integer.toHexString(offset) + "\r\n");
+      output.write(HexFormatter.convertBytesToString(record));
+      output.write("\r\n");
+      return output.toString();
+
+  }
+  
+  public boolean equals(Object obj) {
+    if (obj instanceof UnknownRecord) {
+      UnknownRecord rec = (UnknownRecord) obj;
+      if (rec.offset != this.offset) { 
+        return false;
+      }
+      if (this.offset != rec.offset) {
+        return false;
+      }
+      if (this.record.length != rec.record.length) {
+        return false;
+      }
+      for (int i=0 ; i < this.record.length ; i++) {
+        if (rec.record[i] != this.record[i]) {
+          return false;
+        }
+      }   
+    }
+    return true;
+  }
+
+
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/AbstractValidRecordIterator.java b/thirdparty/pasco2/src/isi/pasco2/parser/AbstractValidRecordIterator.java
new file mode 100644
index 0000000000000000000000000000000000000000..b471605ace4c99aa6d938267b7065aaa5c082aca
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/AbstractValidRecordIterator.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser;
+
+import gnu.trove.TIntArrayList;
+
+import java.io.IOException;
+
+abstract public class AbstractValidRecordIterator implements RecordIterator {
+  HashBlockIterator hashBlockIt = null ;
+  HashBlock currentHashBlock = null;
+  HashRecordIterator hashRecIt = null;
+  IEIndexFileParser parser;
+  HashRecord nextRecord = null;
+  TIntArrayList seenRecords = new TIntArrayList();
+
+  AbstractValidRecordIterator(IEIndexFileParser parser) throws IOException {
+    this.parser = parser;
+    int hashOff = parser.getHashOffset();
+    if (hashOff != 0) {
+      hashBlockIt = parser.getHashBlocks(hashOff);
+    }
+  }
+  
+  public HashRecord getNextUnclassifiedRecord() throws IOException {
+    if (hashBlockIt == null) {
+      return null;
+    }
+    if (hashRecIt != null) {
+      if (hashRecIt.hasNext()) {
+        return hashRecIt.next();
+      } else {
+        if (hashBlockIt.hasNext()) {
+          currentHashBlock = hashBlockIt.next();
+          hashRecIt = null;
+          return getNextUnclassifiedRecord();
+        } else { 
+          return null;
+        }
+      }
+    } else {
+      if (currentHashBlock == null) {
+        if (hashBlockIt.hasNext()) {
+          currentHashBlock = hashBlockIt.next();
+          return getNextUnclassifiedRecord();
+        } else {
+          return null;
+        }
+      } else {
+        hashRecIt = currentHashBlock.getRecords();
+        return getNextUnclassifiedRecord();
+      } 
+    }
+  }
+  
+  public HashRecord next() {
+    HashRecord res = nextRecord;
+    nextRecord = null;
+    return res;
+  }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/AllRecordIterator.java b/thirdparty/pasco2/src/isi/pasco2/parser/AllRecordIterator.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9b5083350f5125a9c40d1f1ba109e4f863e5826
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/AllRecordIterator.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser;
+
+import java.io.IOException;
+
+public class AllRecordIterator extends AbstractValidRecordIterator {
+
+  public AllRecordIterator(IEIndexFileParser parser) throws IOException {
+    super(parser);
+    // TODO Auto-generated constructor stub
+  }
+
+  public boolean hasNext() throws IOException {
+    if (nextRecord == null) {
+      while (true) {
+        nextRecord = getNextUnclassifiedRecord();
+        if (nextRecord == null) {
+          return false;
+        } else {
+          if (!nextRecord.containsUnallocatedMemorySignature()
+              && nextRecord.recordOffset > parser.getHashOffset()) {
+            if (!seenRecords.contains(nextRecord.recordOffset)) {
+              if (nextRecord.isAllocated()) {
+                seenRecords.add(nextRecord.recordOffset);
+                return true;
+              }
+            }
+          }
+          nextRecord = null;
+        }
+      }
+    } else {
+      return true;
+    }
+  }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/Allocator.java b/thirdparty/pasco2/src/isi/pasco2/parser/Allocator.java
new file mode 100644
index 0000000000000000000000000000000000000000..8b32fd502d344e6d05baaa7deabbf48c517ac1cc
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/Allocator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser;
+
+import isi.pasco2.io.IndexFile;
+
+import java.io.IOException;
+
+import com.sun.org.apache.xalan.internal.xsltc.dom.BitArray;
+
+
+public class Allocator {
+  static int allocatorBitMapOffset = 0x250;
+  IEIndexFileParser parser;
+  IndexFile file;
+  public Allocator(IEIndexFileParser parser) {
+    this.parser = parser;
+    this.file = parser.indexFile;
+  }
+  
+  public boolean isRecordAllocated(long recordAddress)
+      throws IOException {
+    long bitMapIndex = ((recordAddress - parser.getHashOffset()) / 0x80);
+    long dwordOffset = bitMapIndex / 32;
+    long bitOffset = bitMapIndex % 32;
+
+    file.seek(allocatorBitMapOffset + dwordOffset * 4);
+
+    int[] bitmap = { file.readLittleEndianInt() };
+    BitArray bits = new BitArray(32, bitmap);
+
+    return bits.getBit((int) bitOffset);
+  }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/DateTime.java b/thirdparty/pasco2/src/isi/pasco2/parser/DateTime.java
new file mode 100644
index 0000000000000000000000000000000000000000..3e158680ed335decc8ade322e3976a93e28f6bfe
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/DateTime.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser;
+
+import java.util.Date;
+
+public interface DateTime {
+  public Date asDate();
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/HashBlock.java b/thirdparty/pasco2/src/isi/pasco2/parser/HashBlock.java
new file mode 100644
index 0000000000000000000000000000000000000000..59ea4d24a59f77d7d178315e353ded3af9fe4cfa
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/HashBlock.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser;
+
+import isi.pasco2.io.IndexFile;
+
+import java.io.IOException;
+
+class HashBlock {
+  int offset;
+  IndexFile file;
+  IEIndexFileParser parser;
+  public static int BLOCK_SIZE = 0x80;
+  public HashBlock(IndexFile file, IEIndexFileParser parser, int offset) {
+    this.offset = offset;
+    this.file = file;
+    this.parser = parser;
+    
+  }
+
+  public int size() throws IOException {
+    int hashsize = file.readIntAtOffset(offset + 4) * BLOCK_SIZE;
+    return hashsize;
+  }
+  
+  public int getOffset() {
+    return offset;
+  }
+ 
+  public HashRecordIterator getRecords() throws IOException {
+    return new HashRecordIterator(this, file, parser.getAllocator());
+  }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/HashBlockIterator.java b/thirdparty/pasco2/src/isi/pasco2/parser/HashBlockIterator.java
new file mode 100644
index 0000000000000000000000000000000000000000..0037200377dbc9b360c6881d5c63159b6253a09b
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/HashBlockIterator.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser;
+
+import isi.pasco2.io.IndexFile;
+
+import java.io.IOException;
+
+class HashBlockIterator {
+  int offset;
+  IndexFile file;
+  boolean started = false;
+  IEIndexFileParser parser;
+  
+  public HashBlockIterator(IndexFile file, IEIndexFileParser parser, int offset) {
+    this.offset = offset;
+    this.file = file;
+    this.parser = parser;
+  }
+  
+  public boolean hasNext() throws IOException {
+    if (offset != 0) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+  public HashBlock next() throws IOException {
+    int off = offset;
+    offset = file.readIntAtOffset(offset + 8);
+    return new HashBlock(file, parser, off);
+  }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/HashRecord.java b/thirdparty/pasco2/src/isi/pasco2/parser/HashRecord.java
new file mode 100644
index 0000000000000000000000000000000000000000..d0fdaff55a65b0847e5eb95ef98cb8756acfeb60
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/HashRecord.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser;
+
+import java.io.IOException;
+
+public class HashRecord {
+  int flags;
+  int recordOffset;
+  Allocator allocator;
+  
+  public HashRecord(Allocator allocator, int flags, int offset) {
+    this.flags = flags;
+    this.recordOffset = offset;
+    this.allocator = allocator;
+  }
+  
+  public boolean isValid() {
+    return (flags & 0x0FF) != 0x03 && recordOffset != 0;
+  }
+  public boolean containsUnallocatedMemorySignature() {
+    return recordOffset == 0xBADF00D;
+  }   
+  public boolean isAllocated() throws IOException {
+    return allocator.isRecordAllocated(recordOffset);
+  }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/HashRecordIterator.java b/thirdparty/pasco2/src/isi/pasco2/parser/HashRecordIterator.java
new file mode 100644
index 0000000000000000000000000000000000000000..4e34c6c34e72517c67b945431abad7883424c9a9
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/HashRecordIterator.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser;
+
+
+import isi.pasco2.io.IndexFile;
+
+import java.io.IOException;
+
+public class HashRecordIterator {
+  int maxBounds;
+  int offset;
+  HashBlock hashBlock;
+  IndexFile file;
+  Allocator allocator;
+  
+  public HashRecordIterator(HashBlock block, IndexFile file, Allocator allocator) throws IOException {
+     this.hashBlock = block;
+     this.file = file;
+     this.allocator = allocator;
+     maxBounds = hashBlock.getOffset() + hashBlock.size();
+     offset = hashBlock.getOffset() + 16;
+  }
+  
+  public boolean hasNext() {
+    if (offset < maxBounds) {
+      return true;
+    }
+    return false;
+  }
+  
+  public HashRecord next() throws IOException {
+    int flags = file.readIntAtOffset(offset);
+    int recordOffset = file.readIntAtOffset( offset + 4);
+    HashRecord rec = new HashRecord(allocator, flags, recordOffset);
+    offset += 8;
+    return rec;
+  }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/IECacheFileParser.java b/thirdparty/pasco2/src/isi/pasco2/parser/IECacheFileParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..273e02371868c9bddcb03fa650d44610e5a791ab
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/IECacheFileParser.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser;
+
+import isi.pasco2.handler.CacheAccessHandler;
+import isi.pasco2.handler.DefaultHandler;
+import isi.pasco2.io.IndexFile;
+import isi.pasco2.util.StructConverter;
+
+import java.io.IOException;
+
+/**
+ * A parser of index.dat files produced by MS Internet Explorer. This specific class
+ * parses the history specific elements.
+ * 
+ *      
+ * Based on:
+ *  * Keith J. Jones's implementation in pasco (http://odessa.sourceforge.net/)
+ *  * Louis K. Thomas' documentated reverse engineering efforts (http://www.latenighthacking.com/projects/2003/reIndexDat/)
+ *  
+ * @author Bradley Schatz
+ *
+ */
+public class IECacheFileParser extends IEIndexFileParser {
+
+  public IECacheFileParser(String fileName, IndexFile file, DefaultHandler handler) {
+    super(fileName, file, handler);
+  }
+
+  public IECacheFileParser(String fileName, IndexFile file) {
+    super(fileName, file);
+  }
+
+  protected void parseRecord(IndexFile file, int currrecoff,
+      DefaultHandler handler) throws IOException {
+    file.seek(currrecoff);
+    byte[] rec;
+    CacheAccessHandler cacheHandler = (CacheAccessHandler) handler;
+    file.seek(currrecoff);
+    byte[] type = new byte[4];
+    file.read(type, 0, 4);
+    String typeStr = new String(type);
+    try {
+      if (typeStr.equals("REDR")) {
+        parseREDRRecord(file, currrecoff, cacheHandler);
+      } else if (typeStr.startsWith("URL") || typeStr.equals("LEAK")) {
+        parseURLLEAKRecord(typeStr, file, currrecoff, cacheHandler);
+      } else {
+        int i = StructConverter.bytesIntoInt(type, 0);
+        if (i == 0x0badf00d) {
+          // this pattern most likely indicates uninitalized memory as allocated
+          // by
+          // a memory allocator. This is probably a mmaped file.
+          handler.unusedRecord(currrecoff);
+        } else {
+          rec = new byte[BLOCK_SIZE];
+          file.read(rec, 0, BLOCK_SIZE);
+          handler.record(currrecoff, rec);
+          handler.unknownRecord(typeStr, currrecoff, rec);
+        }
+      }
+    } catch (IOException ex) {
+      handler.invalidRecord(currrecoff);
+    }
+  }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/IEHistoryFileParser.java b/thirdparty/pasco2/src/isi/pasco2/parser/IEHistoryFileParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..b9ab051f65f86549cde529a8727046b9d5e0c8f1
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/IEHistoryFileParser.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser;
+
+import isi.pasco2.handler.DefaultHandler;
+import isi.pasco2.handler.HistoryAccessHandler;
+import isi.pasco2.io.IndexFile;
+import isi.pasco2.parser.time.DOSTime;
+import isi.pasco2.parser.time.FileTime;
+import isi.pasco2.util.StructConverter;
+
+import java.io.IOException;
+import java.util.TimeZone;
+
+/**
+ * A parser of index.dat files produced by MS Internet Explorer. This specific class
+ * parses the history specific elements.
+ * 
+ * Offsets:
+ *      (+0x00) record start 
+ *      (+0x08) FILETIME created time 
+ *      (+0x10) FILETIME created time 
+ *      (+0x50) 16-bit dos date corresponding to last visit 
+ *      (+0x52) 16-bit dos time (UTC) corresponding to last visit 
+ *      (+0x54) 32-bit int times visited
+ *      (+0x58) ASCII null terminated string URL 
+ *      (+0xBC) Unicode string Page Title
+ *      
+ * Based on:
+ *  * Keith J. Jones's implementation in pasco (http://odessa.sourceforge.net/)
+ *  * Louis K. Thomas' documentated reverse engineering efforts (http://www.latenighthacking.com/projects/2003/reIndexDat/)
+ *  
+ * @author Bradley Schatz
+ *
+ */
+
+public class IEHistoryFileParser extends IEIndexFileParser {
+  {
+    // the dos times used in this file are based on UTC
+    DOSTime.setTimeZone(TimeZone.getTimeZone("UTC"));
+  }
+
+  public IEHistoryFileParser(String fileName, IndexFile file,
+      DefaultHandler handler) {
+    super(fileName, file, handler);
+  }
+
+  public IEHistoryFileParser(String fileName, IndexFile file) {
+    super(fileName, file);
+  }
+
+  protected void parseRecord(IndexFile file, int currrecoff,
+      DefaultHandler handler) throws IOException {
+    file.seek(currrecoff);
+    byte[] rec;
+    HistoryAccessHandler cacheHandler = (HistoryAccessHandler) handler;
+    file.seek(currrecoff);
+    byte[] type = new byte[4];
+    file.read(type, 0, 4);
+    String typeStr = new String(type);
+    try {
+      if (typeStr.equals("REDR")) {
+        parseREDRRecord(file, currrecoff, cacheHandler);
+      } else if (typeStr.startsWith("URL") || typeStr.equals("LEAK")) {
+        parseURLLEAKRecord(typeStr, file, currrecoff, cacheHandler);
+      } else {
+        int i = StructConverter.bytesIntoInt(type, 0);
+        if (i == 0x0badf00d) {
+          // this pattern most likely indicates uninitalized memory as allocated
+          // by
+          // a memory allocator. This is probably a mmaped file.
+          handler.unusedRecord(currrecoff);
+        } else {
+          rec = new byte[BLOCK_SIZE];
+          file.read(rec, 0, BLOCK_SIZE);
+          handler.record(currrecoff, rec);
+          handler.unknownRecord(typeStr, currrecoff, rec);
+        }
+      }
+    } catch (IOException ex) {
+      handler.invalidRecord(currrecoff);
+    }
+  }
+  
+  public void parseURLLEAKRecord(String type, IndexFile fr, long currrecoff,
+      DefaultHandler handler) throws IOException {
+    int reclen = indexFile.readIntAtOffset(currrecoff + 4) * BLOCK_SIZE;
+    byte[] rec = new byte[reclen];
+    fr.read(rec, 0, reclen);
+    handler.record((int) currrecoff, rec);
+
+    long low = indexFile.readUIntAtOffset(currrecoff + 8);
+    long high = fr.readLittleEndianUInt();
+    FileTime modTime = new FileTime(low, high);
+
+    low = indexFile.readUIntAtOffset(currrecoff + 16);
+    high = fr.readLittleEndianUInt();
+    FileTime accessTime = new FileTime(low, high);
+
+    int date = indexFile.readShortAtOffset(currrecoff + 0x50);
+    int time = indexFile.readShortAtOffset(currrecoff + 0x52);
+    DOSTime lastAccessTime = new DOSTime(date, time);
+
+    int numberOfAccesses = indexFile.readIntAtOffset(currrecoff + 0x54);
+
+    StringBuffer url = readURL(fr, currrecoff);
+    //StringBuffer filename = readFileName(fr, currrecoff);
+    //String dirname = readDirName(fr, currrecoff);
+    //StringBuffer httpheaders = readHTTPHeaders(fr, currrecoff, reclen);
+
+    HistoryAccessHandler h = (HistoryAccessHandler) handler;
+    if (type.startsWith("URL")) {
+      h.URLRecord(lastAccessTime, accessTime, modTime, url.toString(),
+          numberOfAccesses);
+    } 
+    
+    // TODO I havent seen a History file with a LEAK record in it yet... but should
+    // handle this gracefully
+    
+    /*else {
+      handler.LEAKRecord(accessTime, modTime, url.toString(), makePrintable(
+          filename).toString(), dirname, makePrintable(httpheaders).toString());
+    }
+    */
+  }
+
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/IEIndexFileParser.java b/thirdparty/pasco2/src/isi/pasco2/parser/IEIndexFileParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..76364a8749051b1c141357a216253c85cbc60641
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/IEIndexFileParser.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser;
+
+import isi.pasco2.handler.AbstractPrinterHandler;
+import isi.pasco2.handler.CacheAccessHandler;
+import isi.pasco2.handler.DefaultHandler;
+import isi.pasco2.io.IndexFile;
+import isi.pasco2.parser.time.FileTime;
+
+import java.io.IOException;
+
+/**
+ * A parser of index.dat files produced by MS Internet Explorer. This general class
+ * parses the elements common to the cache and the history varieties.
+ * 
+ * Based on:
+ *  * Keith J. Jones's implementation in pasco (http://odessa.sourceforge.net/)
+ *  * Louis K. Thomas' documentated reverse engineering efforts (http://www.latenighthacking.com/projects/2003/reIndexDat/)
+ *  
+ * @author Bradley Schatz
+ *
+ */
+public abstract class IEIndexFileParser {
+  public static int BLOCK_SIZE = 0x80;
+
+  float version;
+
+  long filesize;
+
+  public int primaryHashOffset;
+
+  String fileName;
+
+  IndexFile indexFile;
+
+  DefaultHandler handler;
+  
+  boolean disableAllocationTest = false;
+
+  public IEIndexFileParser(String fileName, IndexFile file,
+      DefaultHandler handler) {
+    this.fileName = fileName;
+    this.indexFile = file;
+    this.handler = handler;
+  }
+
+  public IEIndexFileParser(String fileName, IndexFile file) {
+    this(fileName, file, new AbstractPrinterHandler());
+  }
+
+  public void parseFileUsingDeletedMethod(IndexFile file, DefaultHandler handler)
+      throws IOException {
+    int currrecoff = 0;
+    while (currrecoff < filesize) {
+      parseRecord(file, currrecoff, handler);
+      currrecoff = currrecoff + BLOCK_SIZE;
+    }
+  }
+
+  /*
+   * Hash Record: (+0x00) 'HASH' (+0x04) # blocks size (+0x08) next hash offset
+   * (+0x10) first record flags (+0x14) first record offset
+   */
+  public void parseFile() throws IOException {
+    version = readFileFormatVersion(indexFile);
+    handler.startDocument(fileName, version);
+
+    long filesize = getFileSize();
+    int hashoff = getHashOffset();
+    if (hashoff != 0) {
+      parseHashBlocks(hashoff);
+    }
+    handler.endDocument();
+  }
+
+
+  public HashBlockIterator getHashBlocks(int hashoff) throws IOException {
+    HashBlockIterator it = new HashBlockIterator(indexFile, this, hashoff);
+    return it;
+  }
+  
+  public ValidRecordIterator getValidRecords() throws IOException {
+    return new ValidRecordIterator(this);
+  }
+ 
+  public RecordIterator getAllRecords() throws IOException {
+    return new AllRecordIterator(this);
+  }
+  
+  public void parseHashBlocks(int hashoff) throws IOException {
+    RecordIterator it;
+    if (disableAllocationTest) {
+      it = getAllRecords();
+    } else {
+      it = getValidRecords();
+    }
+    
+    while (it.hasNext()) {
+      parseRecord(indexFile, it.next().recordOffset, handler);
+    }
+
+  }
+
+  public long getFileSize() throws IOException {
+    indexFile.seek(0x1C);
+    filesize = indexFile.readLittleEndianInt();
+    return filesize;
+  }
+
+  public int getHashOffset() throws IOException {
+    int hashoff = indexFile.readIntAtOffset(0x20);
+    primaryHashOffset = hashoff;
+    return hashoff;
+  }
+
+  abstract protected void parseRecord(IndexFile file, int currrecoff,
+      DefaultHandler handler) throws IOException; 
+
+  public void parseURLLEAKRecord(String type, IndexFile fr, long currrecoff,
+      CacheAccessHandler handler) throws IOException {
+    int reclen = fr.readIntAtOffset(currrecoff + 4) * BLOCK_SIZE;
+    byte[] rec = new byte[reclen];
+    fr.read(rec, 0, reclen);
+    
+    handler.record((int) currrecoff, rec);
+
+    long low = fr.readUIntAtOffset(currrecoff + 8);
+    long high = fr.readLittleEndianUInt();
+    FileTime modTime = new FileTime(low, high);
+
+    low = fr.readUIntAtOffset(currrecoff + 16);
+    high = fr.readLittleEndianUInt();
+    FileTime accessTime = new FileTime(low, high);
+
+    StringBuffer url = readURL(fr, currrecoff);
+    StringBuffer filename = readFileName(fr, currrecoff);
+    String dirname = readDirName(fr, currrecoff);
+    StringBuffer httpheaders = readHTTPHeaders(fr, currrecoff, reclen);
+
+    if (type.startsWith("URL")) {
+      handler.URLRecord(accessTime, modTime, url.toString(), makePrintable(
+          filename).toString(), dirname, makePrintable(httpheaders).toString());
+    } else {
+      handler.LEAKRecord(accessTime, modTime, url.toString(), makePrintable(
+          filename).toString(), dirname, makePrintable(httpheaders).toString());
+    }
+  }
+
+  protected StringBuffer readURL(IndexFile fr, long currrecoff)
+      throws IOException {
+    char c;
+    if (version >= 5) {
+      fr.seek(currrecoff + 0x34);
+    } else {
+      fr.seek(currrecoff + 0x38);
+    }
+
+    int urloff = fr.readUnsignedByte();
+    int i = 0;
+    fr.seek(currrecoff + urloff);
+    c = fr.readAsciiChar();
+
+    StringBuffer url = new StringBuffer();
+
+    while (c != '\0' && currrecoff + urloff + i + 1 < filesize) {
+      url.append(c);
+      fr.seek(currrecoff + urloff + i + 1);
+      c = fr.readAsciiChar();
+      i++;
+    }
+    return url;
+  }
+
+  protected StringBuffer readFileName(IndexFile fr, long currrecoff)
+      throws IOException {
+    char c;
+    int i;
+    if (version >= 5) {
+      fr.seek(currrecoff + 0x3C);
+    } else {
+      fr.seek(currrecoff + 0x40);
+    }
+    long filenameoff = fr.readLittleEndianInt() + currrecoff;
+
+    i = 0;
+
+    StringBuffer filename = new StringBuffer();
+
+    if (filenameoff > currrecoff + 0x3C) {
+      fr.seek(filenameoff);
+      c = fr.readAsciiChar();
+      while (c != '\0' && filenameoff + i + 1 < filesize) {
+        filename.append(c);
+        fr.seek(filenameoff + i + 1);
+        c = fr.readAsciiChar();
+        i++;
+      }
+    }
+    return filename;
+  }
+
+  protected StringBuffer readHTTPHeaders(IndexFile fr, long currrecoff,
+      int reclen) throws IOException {
+    char c;
+    int i;
+    long httpheadersoff;
+    if (version >= 5) {
+      httpheadersoff = fr.readIntAtOffset(currrecoff + 0x44) + currrecoff;
+
+    } else {
+      httpheadersoff = fr.readIntAtOffset(currrecoff + 0x48) + currrecoff;
+    }
+
+    i = 0;
+    StringBuffer httpheaders = new StringBuffer();
+    if (httpheadersoff > currrecoff + 0x44) {
+      fr.seek(httpheadersoff);
+      c = fr.readAsciiChar();
+
+      while (c != '\0' && httpheadersoff + i + 1 < currrecoff + reclen
+          && httpheadersoff + i + 1 < filesize) {
+        httpheaders.append(c);
+        fr.seek(httpheadersoff + i + 1);
+        c = fr.readAsciiChar();
+        i++;
+      }
+    }
+    return httpheaders;
+  }
+
+  protected String readDirName(IndexFile fr, long currrecoff)
+      throws IOException {
+    char c;
+    if (version >= 5.2) {
+      fr.seek(currrecoff + 0x38);
+    } else if (version >= 5) {
+      fr.seek(currrecoff + 0x39);
+    } else {
+      fr.seek(currrecoff + 0x3C);
+    }
+    c = fr.readAsciiChar();
+    int dirnameoff = (int) c;
+
+    String dirname;
+    if (0x50 + (12 * dirnameoff) + 8 < filesize) {
+      dirname = fr.readStringAtOffset(0x50 + (12 * dirnameoff), 8);
+    } else {
+      dirname = new String();
+    }
+    return dirname;
+  }
+
+
+
+  public float readFileFormatVersion(IndexFile reader) throws IOException {
+    reader.seek(0x18);
+    byte[] versionAry = new byte[3];
+    reader.read(versionAry, 0, 3);
+    reader.read();
+    if (versionAry[0] == 0) {
+      return 0F;
+    } else {
+      return Float.parseFloat(new String(versionAry));
+    }
+  }
+
+  void parseREDRRecord(IndexFile fr, long currrecoff, DefaultHandler handler)
+      throws IOException {
+
+    // int reclen = readIntAtOffset(fr,currrecoff+4 );
+
+    int i = 0;
+    fr.seek(currrecoff + 0x10);
+    char c = fr.readAsciiChar();
+
+    StringBuffer url = new StringBuffer();
+
+    while (c != '\0' && currrecoff + 0x10 + i + 1 < filesize) {
+      url.append(c);
+      fr.seek(currrecoff + 0x10 + i + 1);
+      c = fr.readAsciiChar();
+      i++;
+    }
+
+    handler.REDRRecord(url.toString());
+  }
+
+  StringBuffer makePrintable(StringBuffer buf) {
+    for (int i = 0; i < buf.length(); i++) {
+      char c = buf.charAt(i);
+      if (((byte) c) < 32 || ((byte) c) > 127) {
+        buf.setCharAt(i, ' ');
+      }
+    }
+    return buf;
+  }
+
+  public Allocator getAllocator() {
+    return new Allocator(this);
+  }
+
+  public boolean isDisableAllocationTest() {
+    return disableAllocationTest;
+  }
+
+  public void setDisableAllocationTest(boolean disableAllocationTest) {
+    this.disableAllocationTest = disableAllocationTest;
+  }
+
+  
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/RecordIterator.java b/thirdparty/pasco2/src/isi/pasco2/parser/RecordIterator.java
new file mode 100644
index 0000000000000000000000000000000000000000..a900d8e211750b1bb4ba907c3dbd546d2e13ad5e
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/RecordIterator.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser;
+
+import java.io.IOException;
+
+public interface RecordIterator {
+  public HashRecord next();
+  public boolean hasNext() throws IOException ;
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/ValidRecordIterator.java b/thirdparty/pasco2/src/isi/pasco2/parser/ValidRecordIterator.java
new file mode 100644
index 0000000000000000000000000000000000000000..6dbb3d6008104c542a2ccba06aa6461baceb780c
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/ValidRecordIterator.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser;
+
+import java.io.IOException;
+
+public class ValidRecordIterator extends AbstractValidRecordIterator {
+
+  public ValidRecordIterator(IEIndexFileParser parser) throws IOException {
+    super(parser);
+    // TODO Auto-generated constructor stub
+  }
+
+  public boolean hasNext() throws IOException {
+    if (nextRecord == null) {
+      while (true) {
+        nextRecord = getNextUnclassifiedRecord();
+        if (nextRecord == null) {
+          return false;
+        } else {
+          if (nextRecord.isValid()
+              && !nextRecord.containsUnallocatedMemorySignature()
+              && nextRecord.recordOffset > parser.getHashOffset()) {
+            if (!seenRecords.contains(nextRecord.recordOffset)) {
+              if (nextRecord.isAllocated()) {
+                seenRecords.add(nextRecord.recordOffset);
+                return true;
+              }
+            }
+          }
+          nextRecord = null;
+        }
+      }
+    } else {
+      return true;
+    }
+  }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/time/DOSTime.java b/thirdparty/pasco2/src/isi/pasco2/parser/time/DOSTime.java
new file mode 100644
index 0000000000000000000000000000000000000000..9b8d40e852b6d1aec2fd7ddfd0e73650847a14c3
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/time/DOSTime.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser.time;
+
+import isi.pasco2.parser.DateTime;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+   
+
+/**
+ * MS DOS timestamp to java time parser. The MS DOS timestamp is a 32bit timestamp format
+ * which stores timestamps in those bits as follows:
+ * bit 0 - 4    : second
+ * bit 5 - 10   : minute
+ * bit 11 - 15  : hour
+ * bit 16 - 20  : day (1-31)
+ * bit 21 - 24  : month (1-12)
+ * bit 25 - 31  : year offset from 1980
+ * 
+ * Time is based on local time, not UTC
+ * @author bradley@greystate.com
+ *
+ */
+public class DOSTime implements DateTime {
+  int date;
+  int time;
+  
+  int year;
+  int month;
+  int day;
+  
+  int hour;
+  int minute;
+  int second;
+  
+  static TimeZone timeZone = null;
+  
+  static DateFormat xsdDateFormat = null;
+  static DateFormat regularDateFormat = null;
+  {
+    xsdDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+    xsdDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+    regularDateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS");
+    regularDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+  }
+  
+/**
+ * Construct a DOSTime object from two unsigned words which are read sequentially from 
+ * a DOS timestamp.
+ * 
+ * @param date a 16bit undigned word, passed as an int as java does not have this type.
+ * @param time a 16bit undigned word, passed as an int as java does not have this type.
+ */
+  public DOSTime(int date, int time) {
+    this.date = date;
+    this.time = time;
+    parseTime();
+    parseDate();
+  }
+  
+
+  void parseTime() {
+      second = (time & 0x1F) * 2;
+      minute = (time & 0x7e0) >> 5;
+      hour = (time & 0xf800) >> 11;
+  }
+  
+  void parseDate() {
+    day = date & 0x1F;
+    month = ((date & 0x1e0) >> 5) -1;
+    year = ((date & 0x3e00) >> 9) + 1980;   
+  }
+  
+  public static DOSTime parseLittleEndianHex(String hex) {
+    assert hex.length() == 8;
+    
+    int first = Integer.parseInt(hex.substring(0,4) , 16);
+    first = ((first & 0xFF) << 8) | ((first & 0x0FF00) >> 8);
+    
+    int second  = Integer.parseInt(hex.substring(4,8) , 16);
+    second = ((second & 0xFF) << 8) | ((second & 0x0FF00) >> 8);
+   
+
+    return new DOSTime(second,first);
+  }
+  
+  public Date asDate() {
+    Calendar c;
+    if (timeZone != null) {
+      c = Calendar.getInstance(timeZone);
+    } else {
+      c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+    }
+    c.set(year, month, day, hour, minute, second);
+    c.set(Calendar.MILLISECOND, 0);
+    return c.getTime();
+  }
+  
+  public String toString() {
+    return xsdDateFormat.format(asDate());
+  }
+  
+  public boolean equals(Object obj) {
+    if (obj instanceof DOSTime) {
+      DOSTime f = (DOSTime) obj;
+      if (f.date == this.date && f.time == this.time) {
+        return true;
+      }    
+    }
+    return false;
+  }
+
+  /**
+   * @return Returns the timeZone.
+   */
+  public static TimeZone getTimeZone() {
+    return timeZone;
+  }
+
+  /**
+   * @param timeZone The timeZone to set.
+   */
+  public static void setTimeZone(TimeZone tz) {
+    timeZone = tz;
+  }
+  
+  
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/parser/time/FileTime.java b/thirdparty/pasco2/src/isi/pasco2/parser/time/FileTime.java
new file mode 100644
index 0000000000000000000000000000000000000000..163d05c9c2299ea73533361c9b3d94a9c71a4b83
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/parser/time/FileTime.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.parser.time;
+
+import isi.pasco2.parser.DateTime;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+public class FileTime implements DateTime{
+  static DateFormat xsdDateFormat = null;
+  static DateFormat regularDateFormat = null;
+ 
+  {
+    xsdDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+    xsdDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+    regularDateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS");
+    regularDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+  }
+  
+  // the remainder in nanoseconds since the unix epoch
+  long remainderNanoSeconds;
+  
+  // the number of seconds since the unix epoch
+  long time_t;
+  
+  public long gettime_t() {
+    return time_t;
+  }
+  
+  public long getRemainderNanoSeconds() {
+    return remainderNanoSeconds;
+  }
+  
+  public long getTimeAsMillis() {
+    return time_t*1000 + (remainderNanoSeconds / 1000000);
+  }
+ 
+  public long getMillisRemainder() {
+    return remainderNanoSeconds / 1000000;
+  }
+  
+  public long getMicrosRemainder() {
+    return remainderNanoSeconds % 1000000;
+  }
+  
+  public Date asDate() {
+    return new Date(getTimeAsMillis());
+  }
+  
+  private long low;
+  private long high;
+   
+  public long getHigh() {
+    return high;
+  }
+
+  public long getLow() {
+    return low;
+  }
+
+  /**
+   *  Create a parser for windows FILETIME timestamps. This is a count of the number 
+   *  of 100ns increments since the Epoch Jan 1 1601 at 00:00:00. Credits for the 
+   *  algorithm go to  cygin's to_timestruc_t() implementation found in time.cc. 
+   *  
+   * @param low 32bit unsigned int low value of the timestamp, passed as a java long
+   * @param high 32bit unsigned int low value of the timestamp, passed as a java long
+   */
+  public FileTime(long low, long high) {
+    this.low = low;
+    this.high = high;
+    parse(low, high);
+   }
+  
+  
+  // the number of 100 ns ticks between 00:00:00 on Jan 1, 1601 and 00:00:00 Jan 1, 1970
+  // validated in the unit test TestPlatform.testSkewBetweenUNIXEpochAndWindowsEpoch
+  static long skewFILETIME2timetEpochs = 0x19db1ded53e8000L;
+  static long ticksPerSecond = 10 * 1000 * 1000L;
+  
+  /**
+   * 
+   *  this code is based on cygin's times.cc/to_timestruc_t(). Author not indicated. 
+   *  
+   */
+  void parse(long low, long high) {
+      long rem;
+      long x = (high << 32) + (low);
+
+      /* return the UNIX epoch as the FILETIME epoch */
+      if (x == 0) {
+          time_t = 0;
+          rem = 0;
+          return;
+      }
+
+      x -= skewFILETIME2timetEpochs;        // remove the skew so x now is the number of 
+                                        // ticks since 00:00:00 1/1/1970
+      rem = x % ticksPerSecond;         // remaining ticks not whole seconds
+      x /= ticksPerSecond;         // number of seconds since UNIX epoch   
+      remainderNanoSeconds = rem * 100; // as remainder is in nanoseconds 
+      time_t = x;
+  }
+
+  
+   
+   public String toString() {
+     return xsdDateFormat.format(asDate());
+   }
+   
+   public String toXSDString() {
+     return xsdDateFormat.format(asDate());
+   }
+   
+   public String toStandardTime() {
+     return xsdDateFormat.format(asDate());
+   }
+   
+   public static FileTime parseLittleEndianHex(String hex) {
+       assert hex.length() == 16;
+       
+       long low = Long.parseLong(hex.substring(0,8) , 16);
+       low = ((low & 0xFF) << 24) | ((low & 0x0FF00) << 8) | ((low & 0xFF0000) >> 8) | ((low & 0xFF000000)>> 24);
+       long high = Long.parseLong(hex.substring(8,16) , 16);
+       high = ((high & 0xFF) << 24) | ((high & 0x0FF00) << 8) | ((high & 0xFF0000) >> 8) | ((high & 0xFF000000)>> 24);
+
+       return new FileTime(low,high);
+   }
+   
+   public static FileTime parseBigEndianHex(String hex) {
+     assert hex.length() == 16;
+     
+     long all = Long.parseLong(hex, 16);
+     long low = all & 0x0ffffffffL;
+     long high = (all & 0xffffffff00000000L) >> 32;
+
+     return new FileTime(low,high);
+ }
+
+  public boolean equals(Object obj) {
+    if (obj instanceof FileTime) {
+      FileTime f = (FileTime) obj;
+      if (f.time_t == this.time_t && f.remainderNanoSeconds == this.remainderNanoSeconds) {
+        return true;
+      }    
+    }
+    return false;
+  }
+   
+   
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/poller/DifferenceHandler.java b/thirdparty/pasco2/src/isi/pasco2/poller/DifferenceHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..c79edf4050703aa349f1ed31a8cb10cbc1cc6491
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/poller/DifferenceHandler.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.poller;
+
+import isi.pasco2.handler.HistoryAccessHandler;
+import isi.pasco2.io.IndexFile;
+import isi.pasco2.model.REDRRecord;
+import isi.pasco2.model.Record;
+import isi.pasco2.model.URLLEAKRecord;
+import isi.pasco2.model.UnknownRecord;
+import isi.pasco2.parser.DateTime;
+
+import java.io.StringWriter;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.TimeZone;
+import java.util.Vector;
+
+import org.apache.commons.collections.CollectionUtils;
+
+public class DifferenceHandler implements HistoryAccessHandler {
+  SimpleDateFormat xsdDateFormat;
+  {
+    xsdDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+    xsdDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+  }
+  
+  Vector<Record> currentUrlRecords = new Vector<Record>();
+  Vector<Record> newUrlRecords = new Vector<Record>();
+
+  boolean initialized = false;
+
+  String name;
+  int offset;
+  int length;
+  byte[] rec;
+  IndexFile indexFile;
+
+  public DifferenceHandler(String name) {
+    this.name = name;
+  }
+
+  public void URLRecord(DateTime localAccessTime, DateTime accessTime, DateTime modTime, String url,
+      String file, String directory, String httpHeaders) {
+    URLLEAKRecord u = new URLLEAKRecord("URL", localAccessTime, accessTime, modTime, url, file,
+        directory, httpHeaders, offset, rec);
+    if (initialized) {
+      if (!newUrlRecords.contains(u)) {
+        newUrlRecords.add(u);
+      }
+    } else {
+      if (!currentUrlRecords.contains(u)) {
+        currentUrlRecords.add(u);
+      }
+    }
+  }
+  
+  public void URLRecord(DateTime localAccessTime, DateTime accessTime, DateTime modTime, String url, int count) {
+    URLLEAKRecord u = new URLLEAKRecord("URL", localAccessTime, accessTime, modTime, url, null, null, null, offset, rec);
+    u.accessedCount = count;
+    if (initialized) {
+      if (!newUrlRecords.contains(u)) {
+        newUrlRecords.add(u);
+      }
+    } else {
+      if (!currentUrlRecords.contains(u)) {
+        currentUrlRecords.add(u);
+      }
+    }
+  }
+  
+  public void URLRecord(DateTime localAccessTime, DateTime accessTime, DateTime modTime, String url) {
+    URLLEAKRecord u = new URLLEAKRecord("URL", localAccessTime, accessTime, modTime, url, null, null, null, offset, rec);
+
+    if (initialized) {
+      if (!newUrlRecords.contains(u)) {
+        newUrlRecords.add(u);
+      }
+    } else {
+      if (!currentUrlRecords.contains(u)) {
+        currentUrlRecords.add(u);
+      }
+    }
+  }
+  public void URLRecord(DateTime accessTime, DateTime modTime, String url,
+      String file, String directory, String httpHeaders) {
+    URLLEAKRecord u = new URLLEAKRecord("URL", accessTime, modTime, url, file,
+        directory, httpHeaders, offset, rec);
+    if (initialized) {
+      if (!newUrlRecords.contains(u)) {
+        newUrlRecords.add(u);
+      }
+    } else {
+      if (!currentUrlRecords.contains(u)) {
+        currentUrlRecords.add(u);
+      }
+    }
+  }
+
+  
+  public void startDocument(String fileName, float version) {
+  }
+
+  public void endDocument() {
+    if (!initialized) {
+      // it is now
+      initialized = true;
+    } else {
+      Collection<Record> deletedRecords = CollectionUtils.subtract(
+          currentUrlRecords, newUrlRecords);
+      Collection<Record> newRecords = CollectionUtils.subtract(newUrlRecords,
+          currentUrlRecords);
+
+      if (deletedRecords.size() > 0 || newRecords.size() > 0) {
+        StringWriter outWriter = new StringWriter();
+        outWriter.write(name + "\r\n");
+        for (Record rec : newRecords) {
+          Calendar c = Calendar.getInstance();
+          outWriter.write("New record: (" + xsdDateFormat.format(c.getTime()) + rec.toString() + "\r\n");
+        }
+        for (Record rec : deletedRecords) {
+          outWriter.write("Deleted record: " + rec.toString() + "\r\n");
+        }
+
+        System.out.println(outWriter.toString());
+      }
+      currentUrlRecords = newUrlRecords;
+      newUrlRecords = new Vector<Record>();
+    }
+  }
+
+  public void invalidRecord(int offset) {
+
+  }
+
+  public void LEAKRecord(DateTime accessTime, DateTime modTime, String url,
+      String file, String directory, String httpHeaders) {
+    URLLEAKRecord u = new URLLEAKRecord("LEAK", accessTime, modTime, url, file,
+        directory, httpHeaders, offset, rec);
+    if (initialized) {
+      if (!newUrlRecords.contains(u)) {
+        newUrlRecords.add(u);
+      }
+    } else {
+      if (!currentUrlRecords.contains(u)) {
+        currentUrlRecords.add(u);
+      }
+    }
+  }
+
+  public void REDRRecord(String url) {
+    REDRRecord u = new REDRRecord(url, offset);
+    if (initialized) {
+      if (!newUrlRecords.contains(u)) {
+        newUrlRecords.add(u);
+      }
+    } else {
+      if (!currentUrlRecords.contains(u)) {
+        currentUrlRecords.add(u);
+      }
+    }
+  }
+
+  public void unknownRecord(String type, int offset, byte[] record) {
+    UnknownRecord u = new UnknownRecord(record, offset);
+    if (initialized) {
+      if (!newUrlRecords.contains(u)) {
+        newUrlRecords.add(u);
+      }
+    } else {
+      if (!currentUrlRecords.contains(u)) {
+        currentUrlRecords.add(u);
+      }
+    }
+  }
+
+  public void unusedRecord(int offset) {
+  }
+
+  public void record(int currentOffset, byte[] rec) {
+    this.offset = offset;
+    this.rec = rec;
+    this.length = length;
+  }
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/util/HexFormatter.java b/thirdparty/pasco2/src/isi/pasco2/util/HexFormatter.java
new file mode 100644
index 0000000000000000000000000000000000000000..897dbf3ed577b89ee5b54844b06fdf9ed97e0e2f
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/util/HexFormatter.java
@@ -0,0 +1,268 @@
+//******************************************************************
+// Released under the DevelopMentor OpenSource Software License.
+// Please consult the LICENSE.jawin file in the project root directory,
+// or at http://www.develop.com for details before using this
+// software.
+//******************************************************************
+
+// From the JAWIN source distribution.
+package isi.pasco2.util;
+
+/**
+
+ * Helper class for doing hex dumps of arrays to String.  Useful for 
+
+ * debugging, esp. on IDEs that are not hex-friendly.
+
+ */
+
+public class HexFormatter {
+
+	public static String convertBytesToString(byte[] bytes) {
+
+		return convertBytesToString(bytes, 16, 0, true);
+
+	}
+
+	public static String convertBytesToString(
+		byte[] bytes,
+		int lineLength,
+		int level,
+		boolean showChars) {
+
+		if (bytes == null) {
+
+			return "(null array)";
+
+		}
+
+		return convertBytesToString(
+			bytes,
+			0,
+			bytes.length,
+			lineLength,
+			level,
+			showChars);
+
+	}
+
+	public static String convertBytesToString(
+		byte[] bytes,
+		int startOffset,
+		int endOffset,
+		int lineLength,
+		int level,
+		boolean showChars) {
+
+		if (bytes == null) {
+
+			return "(null array)";
+
+		}
+
+		int loop = 0;
+
+		//each byte creates 3-4 chars in the  string, so the *5 makes a 
+
+		//buffer that is large enough
+
+		StringBuffer strb = new StringBuffer(bytes.length * 5);
+
+		int boundary = (startOffset + lineLength - 1) % lineLength;
+
+		int charLoop = 0;
+
+		for (charLoop = loop = startOffset; loop < endOffset; loop++) {
+			if ((loop % lineLength) == 0) {
+				for (int j = 0; j < level + 1; j++) {
+					strb.append("\t");
+				}
+			}
+
+			strb.append(getHexString(bytes[loop]));
+
+			if ((loop % lineLength) == boundary) {
+
+				if (showChars) {
+
+					strb.append(' ');
+
+					while (charLoop <= loop) {
+
+						strb.append(printChars[bytes[charLoop] & 0x00ff]);
+
+						charLoop++;
+
+					}
+
+				}
+
+				strb.append("\r\n");
+
+			}
+
+		}
+
+		// Added this code to print chars of last line.
+
+		if (showChars && (charLoop < loop)) {
+
+			for (int gap = loop % lineLength; gap < lineLength; ++gap) {
+
+				strb.append("   ");
+
+			}
+
+			strb.append(' ');
+
+			while (charLoop < loop) {
+
+				strb.append(printChars[bytes[charLoop] & 0x00ff]);
+
+				charLoop++;
+
+			}
+
+		}
+
+		return strb.toString();
+
+	}
+
+	public static String convertBytesToProxyTypeString(
+		byte[] bytes,
+		int startOffset,
+		int endOffset,
+		int lineLength,
+		boolean showChars) {
+
+		if (bytes == null) {
+			return "(null array)";
+		}
+
+		int loop = 0;
+
+		//each byte creates 3-4 chars in the  string, so the *5 makes a 
+
+		//buffer that is large enough
+
+		StringBuffer strb = new StringBuffer(bytes.length * 5);
+
+		int boundary = (startOffset + lineLength - 1) % lineLength;
+
+		int charLoop = 0;
+
+		for (charLoop = loop = startOffset; loop < endOffset; loop++) {
+
+			if (loop == 2) {
+				strb.append("-");
+			}
+			strb.append(getHexProxyTypeString(bytes[loop]));
+
+			/*if ((loop % lineLength) == boundary) 
+			
+			{
+			
+			if (showChars) 
+			
+			  {
+			
+			    strb.append(' ');
+			
+			    while (charLoop <= loop)    
+			
+				{
+			
+				  strb.append(printChars[bytes[charLoop] & 0x00ff]);
+			
+				  charLoop++;
+			
+				}
+			
+			  }
+			
+			strb.append("\r\n");
+			
+			}*/
+
+		}
+
+		// Added this code to print chars of last line.
+
+		/*if ( showChars && ( charLoop < loop ) ) {
+		
+		  for ( int gap = loop%lineLength; gap < lineLength; ++gap ) {
+		
+		strb.append("   ");
+		
+		  }
+		
+		  strb.append(' ');
+		
+		  while ( charLoop < loop ) {
+		
+		strb.append( printChars[bytes[charLoop] & 0x00ff] );
+		
+		charLoop++;
+		
+		  }
+		
+		}*/
+
+		return strb.toString();
+
+	}
+
+	public final static char[] hexchars = new char[16];
+
+	public final static char[] printChars = new char[256];
+
+	static {
+
+		for (char n = 0; n < 10; n++)
+			hexchars[n] = (char) ('0' + n);
+
+		for (char n = 10; n < 16; n++)
+			hexchars[n] = (char) ('A' - 10 + n);
+
+		for (char n = 0; n < 32; n++)
+			printChars[n] = '.';
+
+		for (char n = 32; n < 256; n++)
+			printChars[n] = (char) n;
+
+		//for (char n=128; n<256; n++)
+
+		//  printChars[n] = '.';
+
+	}
+
+	public static char[] getHexString(byte b) {
+
+		char[] result = new char[3];
+
+		result[0] = hexchars[(b & 0x00f0) >> 4];
+
+		result[1] = hexchars[b & 0x000f];
+
+		result[2] = ' ';
+
+		return result;
+
+	}
+
+	public static char[] getHexProxyTypeString(byte b) {
+
+		char[] result = new char[2];
+
+		result[0] = hexchars[(b & 0x00f0) >> 4];
+
+		result[1] = hexchars[b & 0x000f];
+
+		//    result[2] = ' ';
+
+		return result;
+
+	}
+
+}
diff --git a/thirdparty/pasco2/src/isi/pasco2/util/StructConverter.java b/thirdparty/pasco2/src/isi/pasco2/util/StructConverter.java
new file mode 100644
index 0000000000000000000000000000000000000000..ddc2a14d319ade399e41f7ddb87ad7ff3e6e342e
--- /dev/null
+++ b/thirdparty/pasco2/src/isi/pasco2/util/StructConverter.java
@@ -0,0 +1,280 @@
+package isi.pasco2.util;
+
+//******************************************************************
+//Released under the DevelopMentor OpenSource Software License.
+//Please consult the LICENSE.jawin file in the project root directory,
+//or at http://www.develop.com for details before using this
+//software.
+//******************************************************************
+//From the JAWIN source distribution.
+
+public class StructConverter {
+    /*
+    
+      public static INative structToMem(IStruct s)
+    
+      throws COMException
+    
+      {
+    
+      byte[] bytes = s.instToBytes();
+    
+      System.out.println(HexFormatter.convertBytesToString(bytes, 16, true));
+    
+      if (bytes == null)  {
+    
+      throw new Error("reflective marshalling not implemented yet");
+    
+      }
+    
+      MemPtr mp = new MemPtr(bytes);
+    
+      return mp;
+    
+      }
+    
+    */
+    static public long parseLong(String val) {
+        int length = val.length();
+        if (length > 16) {
+            throw new NumberFormatException("too many digits");
+        }
+        int shift = 0;
+        long res = 0;
+        for (int i = length - 1; i >= 0; i--) {
+            res = res + ((long) Character.digit(val.charAt(i), 16) << shift);
+            shift += 4;
+        }
+        return res;
+    }
+    static public int parseInt(String val) {
+        int length = val.length();
+        if (length > 8) {
+            throw new NumberFormatException("too many digits");
+        }
+        int shift = 0;
+        int res = 0;
+        for (int i = length - 1; i >= 0; i--) {
+            res = res + (Character.digit(val.charAt(i), 16) << shift);
+            shift += 4;
+        }
+        return res;
+    }
+    static public short parseShort(String val) {
+        int length = val.length();
+        if (length > 4) {
+            throw new NumberFormatException("too many digits");
+        }
+        int shift = 0;
+        int res = 0;
+        for (int i = length - 1; i >= 0; i--) {
+            res = res + (Character.digit(val.charAt(i), 16) << shift);
+            shift += 4;
+        }
+        return (short) res;
+    }
+    static public int longIntoBEBytes(long data, byte[] bytes, int start) {
+        bytes[start++] = (byte) (data >>> 56);
+        bytes[start++] = (byte) (data >>> 48);
+        bytes[start++] = (byte) (data >>> 40);
+        bytes[start++] = (byte) (data >>> 32);
+        bytes[start++] = (byte) (data >>> 24);
+        bytes[start++] = (byte) (data >>> 16);
+        bytes[start++] = (byte) (data >>> 8);
+        bytes[start++] = (byte) (data);
+        return start;
+    }
+    static public long bytesIntoLong(byte[] bytes, int offset) {
+        int nLo = bytesIntoInt(bytes, offset);
+        int nHi = bytesIntoInt(bytes, offset + 4);
+        return ((long) (nHi) << 32) + (nLo & 0xFFFFFFFFL);
+    }
+    static public double bytesIntoDouble(byte[] bytes, int offset) {
+        double d = Double.longBitsToDouble(bytesIntoLong(bytes, offset));
+        return d;
+    }
+    static public boolean bytesIntoBoolean(byte[] bytes, int offset) {
+        return bytes[offset] != 0;
+    }
+    static public int bytesIntoInt(byte[] bytes, int offset) {
+        int l =
+            (bytes[offset] & 0xff)
+                | ((bytes[offset + 1] & 0xff) << 8)
+                | ((bytes[offset + 2] & 0xff) << 16)
+                | ((bytes[offset + 3] & 0xff) << 24);
+        return l;
+    }
+    
+    static public long bytesIntoUInt(byte[] bytes, int offset) {
+      long l = ( ((long)bytes[offset] & 0xff)
+              | (((long)bytes[offset + 1] & 0xff) << 8)
+              | (((long)bytes[offset + 2] & 0xff) << 16)
+              | (((long)bytes[offset + 3] & 0xff) << 24) ) ;
+      return l;
+  }
+    static public int BEBytesIntoInt(byte[] bytes, int offset) {
+        int l =
+            (bytes[offset + 3] & 0xff)
+                | ((bytes[offset + 2] & 0xff) << 8)
+                | ((bytes[offset + 1] & 0xff) << 16)
+                | ((bytes[offset + 0] & 0xff) << 24);
+        return l;
+    }
+    static public short bytesIntoShort(byte[] bytes, int offset) {
+        int l = (bytes[offset] & 0xff) | ((bytes[offset + 1] & 0xff) << 8);
+        return (short) l;
+    }
+    static public int longIntoBytes(long data, byte[] bytes, int start) {
+        bytes[start++] = (byte) (data);
+        bytes[start++] = (byte) (data >>> 8);
+        bytes[start++] = (byte) (data >>> 16);
+        bytes[start++] = (byte) (data >>> 24);
+        bytes[start++] = (byte) (data >>> 32);
+        bytes[start++] = (byte) (data >>> 40);
+        bytes[start++] = (byte) (data >>> 48);
+        bytes[start++] = (byte) (data >>> 56);
+        return start;
+    }
+    static public int intIntoBytes(int data, byte[] bytes, int start) {
+        bytes[start++] = (byte) (data);
+        bytes[start++] = (byte) (data >>> 8);
+        bytes[start++] = (byte) (data >>> 16);
+        bytes[start++] = (byte) (data >>> 24);
+        return start;
+    }
+    static public int shortIntoBytes(short data, byte[] bytes, int start) {
+        bytes[start++] = (byte) (data);
+        bytes[start++] = (byte) (data >>> 8);
+        return start;
+    }
+    static public int byteArrayIntoBytes(byte[] src, byte[] dest, int start) {
+        System.arraycopy(src, 0, dest, start, src.length);
+        return start + src.length;
+    }
+
+
+    static public int stringIntoNullTerminatedASCIIBytes(
+        String str,
+        byte[] bytes,
+        int start) {
+        int index = stringIntoASCIIBytes(str, bytes, start);
+        bytes[index++] = 0;
+        return index;
+    }
+
+    static public int stringIntoASCIIBytes(
+        String str,
+        byte[] bytes,
+        int start) {
+        if (str == null) {
+            return -1;
+        }
+        for (int n = 0; n < str.length(); n++) {
+            bytes[start++] = (byte) str.charAt(n);
+        }
+        return start;
+    }
+
+    /*
+     * Does not null terminate the bytes
+     */
+    static public int stringIntoUnicodeBytes(
+        String data,
+        byte[] bytes,
+        int start) {
+        for (int i = 0; i < data.length(); i++) {
+            int v = data.charAt(i);
+            bytes[start++] = (byte) ((v >>> 0) & 0xFF);
+            bytes[start++] = (byte) ((v >>> 8) & 0xFF);
+        }
+        return start;
+    }
+    static public int stringIntoNullTermintedUnicodeBytes(
+        String data,
+        byte[] bytes,
+        int start) {
+        start = stringIntoUnicodeBytes(data, bytes, start);
+        bytes[start++] = (byte) 0;
+        bytes[start++] = (byte) 0;
+        return start;
+    }
+    /*
+    * Does not null terminate the bytes
+    */
+    static public String unicodeBytesIntoString(
+        byte[] bytes,
+        int offset,
+        int length) {
+        StringBuffer res = new StringBuffer();
+        for (int i = 0; i < length; i++) {
+            int v =
+                ((bytes[offset + i * 2]) | (bytes[offset + i * 2 + 1] << 8));
+            char c = (char) v;
+            res.append(c);
+        }
+        return res.toString();
+    }
+    /*
+    * Does deal with null terminated bytes
+    */
+    static public String nullTerminatedUnicodeBytesIntoString(
+        byte[] bytes,
+        int offset,
+        int length) {
+        StringBuffer res = new StringBuffer();
+        for (int i = 0; i < length; i++) {
+            int v =
+                ((bytes[offset + i * 2]) | (bytes[offset + i * 2 + 1] << 8));
+            if (v == 0) {
+                break;
+            } else {
+                char c = (char) v;
+                res.append(c);
+            }
+        }
+        return res.toString();
+    }
+    static public String nullTerminatedAsciiBytesIntoString(
+        byte[] bytes,
+        int offset,
+        int length) {
+        StringBuffer res = new StringBuffer();
+        for (int i = 0; i < length; i++) {
+            int v = (bytes[offset + i]);
+            if (v == 0)
+                break;
+            char c = (char) v;
+            res.append(c);
+        }
+        return res.toString();
+    }
+    static public String asciiBytesIntoString(
+        byte[] bytes,
+        int offset,
+        int length) {
+        StringBuffer res = new StringBuffer();
+        for (int i = 0; i < length; i++) {
+            int v = (bytes[offset + i]);
+            char c = (char) v;
+            res.append(c);
+        }
+        return res.toString();
+    }
+    
+    public static short lowword(int word) {
+        return (short) (word & 0x0000FFFF);
+    }
+    
+    public static short highword(int word) {
+        return (short) ((word & 0xFFFF0000) >> 16);
+    }
+    
+    public static byte lowbyte(short word) {
+        return (byte) (word & 0x00FF);
+    }
+    
+    public static byte highbyte(short word) {
+        return (byte) ((word & 0xFF00) >> 8);
+    }
+}
+
diff --git a/thirdparty/pasco2/test/isi/pasco2/TestAllocationLayer.java b/thirdparty/pasco2/test/isi/pasco2/TestAllocationLayer.java
new file mode 100644
index 0000000000000000000000000000000000000000..e87537724411df8bfe89e0c771fb544fdb4d9e0b
--- /dev/null
+++ b/thirdparty/pasco2/test/isi/pasco2/TestAllocationLayer.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2;
+
+
+import isi.pasco2.handler.CountingCacheHandler;
+import isi.pasco2.io.FastReadIndexFile;
+import isi.pasco2.io.IndexFile;
+import isi.pasco2.parser.IEHistoryFileParser;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import com.sun.org.apache.xalan.internal.xsltc.dom.BitArray;
+
+public class TestAllocationLayer extends TestCase {
+  
+    public static TestSuite suite() {
+        return new TestSuite(TestAllocationLayer.class);
+    }
+   
+ 
+
+  public void testHistoryFile() {
+    try {
+      String f = "D:\\Documents and Settings\\bschatz\\Local Settings\\History\\History.IE5\\index.dat";
+      IndexFile fr = new FastReadIndexFile(f, "r");
+      CountingCacheHandler handler = new CountingCacheHandler();
+      IEHistoryFileParser parser = new IEHistoryFileParser(f, fr);
+      
+      int allocatorBitMapOffset = 0x250;
+      int bitMapIndex = 0;
+      int storageStart = 0x4000;
+      parser.primaryHashOffset = storageStart;
+      int address = 0;
+      while (address != storageStart) {
+        fr.seek(allocatorBitMapOffset + bitMapIndex*4);
+
+        int[] bitmap = {fr.readLittleEndianInt()};
+        BitArray bits = new BitArray(32, bitmap);
+ 
+        for (int i = 0 ; i < 32 ; i++ ){
+          address = (bitMapIndex*32+i) * 0x80 + storageStart;
+          fr.seek(address);
+          int dword = fr.readLittleEndianInt();
+  
+          System.out.println((bitMapIndex*32+i) + " " + Integer.toHexString(dword) + " " + Integer.toHexString(address));
+          assertTrue(bits.getBit(i) == parser.getAllocator().isRecordAllocated(address));
+
+        }
+        bitMapIndex += 1;
+      }
+    } catch (Exception e) {
+    }
+  }
+
+  public void testCacheFile() {
+    try {
+      String f = "D:\\mysrc\\squidbro\\IFIP2006\\anon\\source\\minnow.willk.content.index.dat";
+      IndexFile fr = new FastReadIndexFile(f, "r");
+      CountingCacheHandler handler = new CountingCacheHandler();
+      IEHistoryFileParser parser = new IEHistoryFileParser(f, fr);
+      
+      int allocatorBitMapOffset = 0x250;
+      int bitMapIndex = 0;
+      int storageStart = 0x5000;
+      parser.primaryHashOffset = storageStart;
+      int address = 0;
+      while (address != storageStart) {
+        fr.seek(allocatorBitMapOffset + bitMapIndex*4);
+
+        int[] bitmap = {fr.readLittleEndianInt()};
+        BitArray bits = new BitArray(32, bitmap);
+ 
+        for (int i = 0 ; i < 32 ; i++ ){
+          address = (bitMapIndex*32+i) * 0x80 + storageStart;
+          fr.seek(address);
+          int dword = fr.readLittleEndianInt();
+  
+          System.out.println((bitMapIndex*32+i) + " " + Integer.toHexString(dword) + " " + Integer.toHexString(address));
+          assertTrue(bits.getBit(i) == parser.getAllocator().isRecordAllocated(address));
+
+        }
+        bitMapIndex += 1;
+      }
+    } catch (Exception e) {
+    }
+  }
+  
+  
+}
diff --git a/thirdparty/pasco2/test/isi/pasco2/TestDOSTime.java b/thirdparty/pasco2/test/isi/pasco2/TestDOSTime.java
new file mode 100644
index 0000000000000000000000000000000000000000..d187e25d8ddb62f5efb15f82fdb09e7f135f2645
--- /dev/null
+++ b/thirdparty/pasco2/test/isi/pasco2/TestDOSTime.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2;
+
+
+import isi.pasco2.parser.time.DOSTime;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class TestDOSTime extends TestCase {
+  
+    public static TestSuite suite() {
+        return new TestSuite(TestDOSTime.class);
+    }
+    
+  public void testHexLittleEndian() {
+    String hex = "F788F41E";
+    DOSTime ft = DOSTime.parseLittleEndianHex(hex);
+    //Sat, 30 September 2000 14:46:43  GMT
+    assertEquals("1995-07-20T17:07:46.000Z", ft.toString()); 
+    
+    //Wed, 26 April 2000 22:58:55  GMT
+    assertEquals("2000-01-31T15:21:44.000Z", DOSTime.parseLittleEndianHex("B67A3F28").toString());
+    //Sat, 30 March 2002 05:15:11  GMT
+    assertEquals("2001-10-12T22:10:02.000Z", DOSTime.parseLittleEndianHex("41B14C2B").toString());
+  }
+  
+  public void testCorrectLocal() {
+    
+    DOSTime ft = new DOSTime(13404, 1075);
+    //Sat, 30 September 2000 14:46:43  GMT
+    assertEquals("2006-02-28T00:33:38.000Z", ft.toString()); 
+  }
+}
diff --git a/thirdparty/pasco2/test/isi/pasco2/TestFileTime.java b/thirdparty/pasco2/test/isi/pasco2/TestFileTime.java
new file mode 100644
index 0000000000000000000000000000000000000000..7ab910ab0dfabfdb7e1d3bded1ef435a6ec3c74c
--- /dev/null
+++ b/thirdparty/pasco2/test/isi/pasco2/TestFileTime.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2;
+
+
+import isi.pasco2.parser.time.FileTime;
+import isi.pasco2.util.StructConverter;
+
+import java.util.Date;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class TestFileTime extends TestCase {
+  
+    public static TestSuite suite() {
+        return new TestSuite(TestFileTime.class);
+    }
+    
+  public void testFileTime() {
+    long low = -543274336;
+    long high = 29744990;
+    FileTime ft = new FileTime(low, high);
+    long millis = ft.getTimeAsMillis();
+    //assertEquals(1130902272657L, millis);
+    
+    Date d = ft.asDate();
+    assertEquals("Wed Nov 02 13:31:12 EST 2005", d.toString());
+    assertEquals("2005-11-02T03:31:12.657Z", ft.toString());
+  }
+  
+  public void testBitStuff() {
+    String hex = "40B3B13F";
+    byte[] bytes = new byte[4];
+    for (int i=0 ; i < 4 ; i++) {
+      bytes[i] = (byte)Integer.parseInt(hex.substring(i*2, i*2+2), 16);
+    }
+    
+    long res = StructConverter.bytesIntoInt(bytes,0);
+    assertEquals(1068610368,res);
+    long low = Long.parseLong(hex.substring(0,8) , 16);
+    low = ((low & 0xFF) << 24) | ((low & 0x0FF00) << 8) | ((low & 0xFF0000) >> 8) | ((low & 0xFF000000)>> 24);
+    assertEquals(1068610368,low);
+  }
+  
+  public void testHexLittleEndian() {
+    String hex = "40B3B13FED2AC001";
+    FileTime ft = FileTime.parseLittleEndianHex(hex);
+    //Sat, 30 September 2000 14:46:43  GMT
+    assertEquals("2000-09-30T14:46:43.060Z", ft.toString()); 
+    
+    //Wed, 26 April 2000 22:58:55  GMT
+    assertEquals("2000-04-26T22:58:55.899Z", FileTime.parseLittleEndianHex("39B1C8FFD2AFBF01").toString());
+    //Sat, 30 March 2002 05:15:11  GMT
+    assertEquals("2002-03-30T05:15:11.620Z", FileTime.parseLittleEndianHex("69D8F2DDA9D7C101").toString());
+    //Mon, 17 October 2005 02:59:22  UTC
+    assertEquals("2005-10-17T02:59:22.147Z", FileTime.parseLittleEndianHex("308F41C6C6D2C501").toString());
+  }
+  
+  public void testHexBigEndian() {
+    String hex = "01C1D7A9DDF2D869";
+    FileTime ft = FileTime.parseBigEndianHex(hex);
+    //Sat, 30 March 2002 05:15:11  GMT
+    assertEquals("2002-03-30T05:15:11.620Z", ft.toString()); 
+    
+    // Sun, 10 March 2002 06:07:32  GMT
+    assertEquals("2002-03-10T06:07:32.813Z", FileTime.parseBigEndianHex("01C1C7F9DDFBD86F").toString());
+    // Tue, 20 January 2004 04:58:58  GMT
+    assertEquals("2004-01-20T04:58:58.985Z", FileTime.parseBigEndianHex("01C3DF121D432432").toString());
+    
+  }
+  
+  public void testPassingInts() {
+    int[] intsLow = { 0x30, 0x8F, 0x41, 0xC6 };
+    byte[] bytesLow = new byte[4];
+      
+    for (int i=0 ; i < 4 ; i++) {
+      bytesLow[i] = (byte) (intsLow[i] & 0xFF); 
+    }
+    long low = StructConverter.bytesIntoUInt(bytesLow, 0);
+    
+    long lowA = Long.parseLong("308F41C6", 16);
+    lowA = ((lowA & 0xFF) << 24) | ((lowA & 0x0FF00) << 8) | ((lowA & 0xFF0000) >> 8) | ((lowA & 0xFF000000)>> 24);
+
+    assertEquals(lowA, low);
+    
+    
+    int[] intsHigh = { 0xC6, 0xD2, 0xC5, 0x01  };
+    byte[] bytesHigh = new byte[4];
+      
+    for (int i=0 ; i < 4 ; i++) {
+      bytesHigh[i] = (byte) (intsHigh[i] & 0xFF); 
+    }
+    long high = StructConverter.bytesIntoUInt(bytesHigh, 0);
+
+    FileTime ft = new FileTime(low, high);
+    assertEquals("2005-10-17T02:59:22.147Z", ft.toString());
+    
+
+
+  }
+  
+}
diff --git a/thirdparty/pasco2/test/isi/pasco2/TestPackage.java b/thirdparty/pasco2/test/isi/pasco2/TestPackage.java
new file mode 100644
index 0000000000000000000000000000000000000000..383cbb682eaa166fe3584027a89b7f6837ba74db
--- /dev/null
+++ b/thirdparty/pasco2/test/isi/pasco2/TestPackage.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class TestPackage extends TestSuite {
+
+    static public Test suite() {
+        return new TestPackage();
+    }
+
+    /** Creates new TestPackage */
+    private TestPackage() {
+        super("fore");
+        addTest("FileTime", TestFileTime.suite());
+        addTest("DOSTime", TestDOSTime.suite());
+        addTest("Allocation", TestAllocationLayer.suite());
+        addTest("Record", TestRecordLayer.suite());
+        addTest("Supporting byte manipulation functions", TestReadFunctions.suite());
+        addTest("Compaison of results with the Win32 API", TestPlatform.suite());
+    }
+
+    private void addTest(String name, TestSuite tc) {
+        tc.setName(name);
+        addTest(tc);
+    }
+
+}
\ No newline at end of file
diff --git a/thirdparty/pasco2/test/isi/pasco2/TestPlatform.java b/thirdparty/pasco2/test/isi/pasco2/TestPlatform.java
new file mode 100644
index 0000000000000000000000000000000000000000..f4bc2cbc61457647d60f920a3b972201192089c0
--- /dev/null
+++ b/thirdparty/pasco2/test/isi/pasco2/TestPlatform.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2;
+
+import isi.pasco2.parser.time.FileTime;
+import isi.pasco2.platform.FILETIME;
+import isi.pasco2.platform.SYSTEMTIME;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import ctypes.java.CDLL;
+import ctypes.java.CFunction;
+import ctypes.java.CInt;
+
+public class TestPlatform extends TestCase {
+
+  public static TestSuite suite() {
+    return new TestSuite(TestPlatform.class);
+  }
+
+  public void testSystemTimeAPIs() {
+    try {
+      CDLL dll = CDLL.LoadLibrary("kernel32.dll");
+      CFunction getSystemTimeAsFileTime = dll
+          .loadFunction("GetSystemTimeAsFileTime");
+
+      FILETIME ft = new FILETIME();
+      Object[] ary = { ft };
+      Object o = getSystemTimeAsFileTime.call(null, ary,
+          CFunction.FUNCFLAG_STDCALL);
+      long lowValue = ft.dwLowDateTime.getValue();
+      long highValue = ft.dwHighDateTime.getValue();
+      System.out.println(lowValue);
+      System.out.println(highValue);
+      assertTrue(highValue >= 29767328);
+      /*
+       * BOOL FileTimeToSystemTime( const FILETIME* lpFileTime, LPSYSTEMTIME
+       * lpSystemTime );
+       */
+
+      CFunction fileTimeToSystemTime = dll.loadFunction("FileTimeToSystemTime");
+      SYSTEMTIME st = new SYSTEMTIME();
+      Object[] ary1 = { ft, st };
+      o = fileTimeToSystemTime.call(CInt.class, ary1,
+          CFunction.FUNCFLAG_STDCALL);
+      int year = st.wYear.getValue();
+      assertTrue(year >= 2006);
+
+    } catch (Exception e) {
+      fail();
+    }
+  }
+
+  public void testComparingSystemTimesWithOurAlgorithm2() {
+    try {
+      CDLL dll = CDLL.LoadLibrary("kernel32.dll");
+      CFunction getSystemTimeAsFileTime = dll
+          .loadFunction("GetSystemTimeAsFileTime");
+
+      int lowValue = 926944912;
+      int highValue = 29767328;
+
+      FILETIME ft = new FILETIME();
+      ft.dwLowDateTime.setValue(lowValue);
+      ft.dwHighDateTime.setValue(highValue);
+
+      CFunction fileTimeToSystemTime = dll.loadFunction("FileTimeToSystemTime");
+      SYSTEMTIME st = new SYSTEMTIME();
+      Object[] ary1 = { ft, st };
+
+      Object o = fileTimeToSystemTime.call(CInt.class, ary1,
+          CFunction.FUNCFLAG_STDCALL);
+      assertEquals(2006, st.wYear.getValue());
+      assertEquals(2, st.wMonth.getValue());
+      assertEquals(21, st.wDay.getValue());
+      assertEquals(4, st.wHour.getValue());
+      assertEquals(35, st.wMinute.getValue());
+      assertEquals(17, st.wSecond.getValue());
+      assertEquals(625, st.wMilliseconds.getValue());
+
+      FileTime nonSystemFileTime = new FileTime(lowValue, highValue);
+      assertEquals("2006-02-21T04:35:17.625Z", nonSystemFileTime.toXSDString());
+
+    } catch (Exception e) {
+      fail();
+    }
+  }
+  
+  public void testComparingSystemTimesWithOurAlgorithm() {
+    try {
+      CDLL dll = CDLL.LoadLibrary("kernel32.dll");
+      CFunction getSystemTimeAsFileTime = dll
+          .loadFunction("GetSystemTimeAsFileTime");
+
+      String hex = "40B3B13FED2AC001";
+      FileTime f = FileTime.parseLittleEndianHex(hex);
+
+      FILETIME ft = new FILETIME();
+      ft.dwLowDateTime.setValue((int) f.getLow());
+      ft.dwHighDateTime.setValue((int) f.getHigh());
+
+      CFunction fileTimeToSystemTime = dll.loadFunction("FileTimeToSystemTime");
+      SYSTEMTIME st = new SYSTEMTIME();
+      Object[] ary1 = { ft, st };
+
+      //Sat, 30 September 2000 14:46:43
+      Object o = fileTimeToSystemTime.call(CInt.class, ary1,
+          CFunction.FUNCFLAG_STDCALL);
+      assertEquals(2000, st.wYear.getValue());
+      assertEquals(9, st.wMonth.getValue());
+      assertEquals(30, st.wDay.getValue());
+      assertEquals(14, st.wHour.getValue());
+      assertEquals(46, st.wMinute.getValue());
+      assertEquals(43, st.wSecond.getValue());
+      assertEquals(60, st.wMilliseconds.getValue());
+
+
+    } catch (Exception e) {
+      fail();
+    }
+  }
+  
+  public void testZeroFiletime() {
+    try {
+      CDLL dll = CDLL.LoadLibrary("kernel32.dll");
+
+      FILETIME ft = new FILETIME();
+      ft.dwLowDateTime.setValue((int) 0);
+      ft.dwHighDateTime.setValue((int) 0);
+
+      CFunction fileTimeToSystemTime = dll.loadFunction("FileTimeToSystemTime");
+      CFunction getFileTimeAsSystemTime = dll.loadFunction("SystemTimeToFileTime");
+      
+      SYSTEMTIME st = new SYSTEMTIME();
+      Object[] ary1 = { ft, st };
+
+      //Sat, 30 September 2000 14:46:43
+      Object o = fileTimeToSystemTime.call(CInt.class, ary1,
+          CFunction.FUNCFLAG_STDCALL);
+      assertEquals(1601, st.wYear.getValue());
+      assertEquals(1, st.wMonth.getValue());
+      assertEquals(1, st.wDay.getValue());
+      assertEquals(0, st.wHour.getValue());
+      assertEquals(0, st.wMinute.getValue());
+      assertEquals(0, st.wSecond.getValue());
+      assertEquals(0, st.wMilliseconds.getValue());
+
+      FILETIME zeroFileTime = new FILETIME();
+      Object[] a = { st, zeroFileTime };
+      Object o1 = getFileTimeAsSystemTime.call(CInt.class, ary1,
+          CFunction.FUNCFLAG_STDCALL);
+      
+      assertEquals(0, zeroFileTime.dwHighDateTime.getValue());
+      assertEquals(0, zeroFileTime.dwLowDateTime.getValue());
+      
+    } catch (Exception e) {
+      fail();
+    }
+  }
+  
+  /**
+   * This test validates the value of the constant called skewFILETIME2timetEpochs 
+   * used as the difference in 100ns ticks between the UNIX and FILETIME epochs.
+   *
+   */
+  public void testSkewBetweenUNIXEpochAndWindowsEpoch() {
+    try {
+      CDLL dll = CDLL.LoadLibrary("kernel32.dll");
+
+      CFunction systemTimeToFileTime = dll
+      .loadFunction("SystemTimeToFileTime");
+      
+      SYSTEMTIME zeroTime = new SYSTEMTIME();
+      zeroTime.wDay.setValue((short)1);
+      zeroTime.wMonth.setValue((short)1);
+      zeroTime.wYear.setValue((short)1601);
+      zeroTime.wHour.setValue((short)0);
+      zeroTime.wMinute.setValue((short)0);
+      zeroTime.wSecond.setValue((short)0);
+      zeroTime.wMilliseconds.setValue((short)0);
+      
+      SYSTEMTIME UNIXepochTime = new SYSTEMTIME();
+      UNIXepochTime.wDay.setValue((short)1);
+      UNIXepochTime.wMonth.setValue((short)1);
+      UNIXepochTime.wYear.setValue((short)1970);
+      UNIXepochTime.wHour.setValue((short)0);
+      UNIXepochTime.wMinute.setValue((short)0);
+      UNIXepochTime.wSecond.setValue((short)0);
+      UNIXepochTime.wMilliseconds.setValue((short)0);
+      
+      FILETIME zeroFileTime = new FILETIME();
+      FILETIME UNIXepochFileTime = new FILETIME();
+
+      Object[] ary1 = { zeroTime, zeroFileTime };
+      CInt o = (CInt) systemTimeToFileTime.call(CInt.class, ary1,
+          CFunction.FUNCFLAG_STDCALL);
+      assertTrue(o.getValue() != 0);
+
+      Object[] ary2 = { UNIXepochTime, UNIXepochFileTime };
+      CInt o1 = (CInt) systemTimeToFileTime.call(CInt.class, ary2,
+          CFunction.FUNCFLAG_STDCALL);
+      assertTrue(o.getValue() != 0);
+      
+      long zeroCount = (zeroFileTime.dwHighDateTime.getValue() << 32) + (zeroFileTime.dwLowDateTime.getValue());
+      long hi = U32Jint2Jlong(UNIXepochFileTime.dwHighDateTime.getValue());
+      long lo = U32Jint2Jlong(UNIXepochFileTime.dwLowDateTime.getValue());
+      long UNIXepochCount = ( hi << 32) + (lo);
+      assertEquals(0, zeroCount);
+      assertEquals(0x19db1ded53e8000L, UNIXepochCount - zeroCount);
+
+    } catch (Exception e) {
+      fail();
+    }
+  }
+  public static final long U32Jint2Jlong(int i) {
+    return (((long)i) & 0xffff0000L) | i & 0x00ffff;
+  }
+}
diff --git a/thirdparty/pasco2/test/isi/pasco2/TestReadFunctions.java b/thirdparty/pasco2/test/isi/pasco2/TestReadFunctions.java
new file mode 100644
index 0000000000000000000000000000000000000000..750216b5a4c62b5a73a0cdccbb8d5a7ca9534efe
--- /dev/null
+++ b/thirdparty/pasco2/test/isi/pasco2/TestReadFunctions.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2;
+
+import isi.pasco2.util.StructConverter;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class TestReadFunctions extends TestCase {
+  public static TestSuite suite() {
+    return new TestSuite(TestReadFunctions.class);
+  }
+
+  public void testVersionReader() {
+    try {
+      byte[] fourbytes = { 0, 0, 40, 0 };
+      assertEquals(2621440, StructConverter.bytesIntoInt(fourbytes, 0), 0);
+
+      byte[] nextfourbytes = { 0, -112, 1, 0 };
+      assertEquals(102400, StructConverter.bytesIntoInt(nextfourbytes, 0));
+    } catch (Exception ex) {
+      fail();
+    }
+  }
+}
diff --git a/thirdparty/pasco2/test/isi/pasco2/TestRecordLayer.java b/thirdparty/pasco2/test/isi/pasco2/TestRecordLayer.java
new file mode 100644
index 0000000000000000000000000000000000000000..1e2400714418be788d0386c36c5ff1179cda26a9
--- /dev/null
+++ b/thirdparty/pasco2/test/isi/pasco2/TestRecordLayer.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2;
+
+import isi.pasco2.io.FastReadIndexFile;
+import isi.pasco2.io.IndexFile;
+import isi.pasco2.parser.IECacheFileParser;
+import isi.pasco2.parser.IEHistoryFileParser;
+import isi.pasco2.parser.IEIndexFileParser;
+import isi.pasco2.parser.ValidRecordIterator;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class TestRecordLayer extends TestCase {
+
+  public static TestSuite suite() {
+    return new TestSuite(TestRecordLayer.class);
+  }
+
+  public void testEmptyCacheFile() {
+    try {
+      String f = "D:\\mysrc\\pasco2\\src\\test\\isrc\\pasco2\\empty.cache.index.dat";
+      IndexFile fr = new FastReadIndexFile(f, "r");
+      IEIndexFileParser parser = new IECacheFileParser(f, fr);
+      parser.parseFile();
+
+      ValidRecordIterator it = parser.getValidRecords();
+      int count = 0;
+      while (it.hasNext()) {
+        count += 1;
+        it.next();
+      }
+      assertEquals(00, count);
+    } catch (Exception e) {
+      fail();
+    }
+  }
+
+  public void testInitialCacheFile() {
+    try {
+      String f = "D:\\mysrc\\pasco2\\src\\test\\isrc\\pasco2\\first.cache.index.dat";
+      IndexFile fr = new FastReadIndexFile(f, "r");
+      IEIndexFileParser parser = new IECacheFileParser(f, fr);
+
+      ValidRecordIterator it = parser.getValidRecords();
+      int count = 0;
+      while (it.hasNext()) {
+        count += 1;
+        it.next();
+      }
+      assertEquals(30, count);
+    } catch (Exception e) {
+      fail();
+    }
+  }
+
+  public void testEmptyHistoryFile() {
+    try {
+      String f = "D:\\mysrc\\pasco2\\src\\test\\isrc\\pasco2\\empty.history.index.dat";
+      IndexFile fr = new FastReadIndexFile(f, "r");
+      IEIndexFileParser parser = new IEHistoryFileParser(f, fr);
+      parser.parseFile();
+
+      ValidRecordIterator it = parser.getValidRecords();
+      int count = 0;
+      while (it.hasNext()) {
+        count += 1;
+        it.next();
+      }
+      assertEquals(00, count);
+    } catch (Exception e) {
+      fail();
+    }
+  }
+
+  public void testInitialHistoryFile() {
+    try {
+      String f = "D:\\mysrc\\pasco2\\src\\test\\isrc\\pasco2\\first.history.index.dat";
+      IndexFile fr = new FastReadIndexFile(f, "r");
+      IEIndexFileParser parser = new IEHistoryFileParser(f, fr);
+
+      ValidRecordIterator it = parser.getValidRecords();
+      int count = 0;
+      while (it.hasNext()) {
+        count += 1;
+        it.next();
+      }
+      assertEquals(2, count);
+    } catch (Exception e) {
+      fail();
+    }
+  }
+
+}
diff --git a/thirdparty/pasco2/test/isi/pasco2/empty.cache.index.dat b/thirdparty/pasco2/test/isi/pasco2/empty.cache.index.dat
new file mode 100644
index 0000000000000000000000000000000000000000..407ed3f8d3de06b6dd2c494910a5045e47157866
Binary files /dev/null and b/thirdparty/pasco2/test/isi/pasco2/empty.cache.index.dat differ
diff --git a/thirdparty/pasco2/test/isi/pasco2/empty.history.index.dat b/thirdparty/pasco2/test/isi/pasco2/empty.history.index.dat
new file mode 100644
index 0000000000000000000000000000000000000000..cebcc9bbed4ce533839a383b15d1bcfbad9deee3
Binary files /dev/null and b/thirdparty/pasco2/test/isi/pasco2/empty.history.index.dat differ
diff --git a/thirdparty/pasco2/test/isi/pasco2/first.cache.index.dat b/thirdparty/pasco2/test/isi/pasco2/first.cache.index.dat
new file mode 100644
index 0000000000000000000000000000000000000000..8f5d8f0bc735af8006ba98b3c58764361fa50f34
Binary files /dev/null and b/thirdparty/pasco2/test/isi/pasco2/first.cache.index.dat differ
diff --git a/thirdparty/pasco2/test/isi/pasco2/first.history.index.dat b/thirdparty/pasco2/test/isi/pasco2/first.history.index.dat
new file mode 100644
index 0000000000000000000000000000000000000000..de442adc063a56dcb682c2882de4463e381d9173
Binary files /dev/null and b/thirdparty/pasco2/test/isi/pasco2/first.history.index.dat differ
diff --git a/thirdparty/pasco2/test/isi/pasco2/platform/FILETIME.java b/thirdparty/pasco2/test/isi/pasco2/platform/FILETIME.java
new file mode 100644
index 0000000000000000000000000000000000000000..d4add486abb50e00b7bede180bc6930b968f1831
--- /dev/null
+++ b/thirdparty/pasco2/test/isi/pasco2/platform/FILETIME.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.platform;
+
+import ctypes.java.CInt;
+import ctypes.java.CStruct;
+
+public class FILETIME extends CStruct {
+  public CInt dwLowDateTime = new CInt();
+  public CInt dwHighDateTime = new CInt();
+  
+}
diff --git a/thirdparty/pasco2/test/isi/pasco2/platform/SYSTEMTIME.java b/thirdparty/pasco2/test/isi/pasco2/platform/SYSTEMTIME.java
new file mode 100644
index 0000000000000000000000000000000000000000..75222fd81c1eb05bd970a8c82314454bd2af2c83
--- /dev/null
+++ b/thirdparty/pasco2/test/isi/pasco2/platform/SYSTEMTIME.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2006 Bradley Schatz. All rights reserved.
+ *
+ * This file is part of pasco2, the next generation Internet Explorer cache
+ * and history record parser.
+ *
+ * pasco2 is free software; you can redistribute it and/or modify
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * pasco2 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with pasco2; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+package isi.pasco2.platform;
+
+import ctypes.java.CShort;
+import ctypes.java.CStruct;
+
+/*
+ * typedef struct _SYSTEMTIME {
+  WORD wYear;
+  WORD wMonth;
+  WORD wDayOfWeek;
+  WORD wDay;
+  WORD wHour;
+  WORD wMinute;
+  WORD wSecond;
+  WORD wMilliseconds;
+} SYSTEMTIME, 
+ */
+public class SYSTEMTIME extends CStruct{
+ public  CShort wYear = new CShort();
+ public   CShort wMonth = new CShort();
+ public  CShort wDayOfWeek = new CShort();
+ public  CShort wDay = new CShort();
+ public   CShort wHour = new CShort();
+ public   CShort wMinute = new CShort();
+ public  CShort wSecond = new CShort();
+ public  CShort wMilliseconds = new CShort();
+}
diff --git a/thirdparty/rr/p2x588.dll b/thirdparty/rr/p2x588.dll
new file mode 100644
index 0000000000000000000000000000000000000000..e250d47eedd893bbc79e81411590278b5c5b11f8
Binary files /dev/null and b/thirdparty/rr/p2x588.dll differ
diff --git a/thirdparty/rr/plugins/acmru.pl b/thirdparty/rr/plugins/acmru.pl
new file mode 100644
index 0000000000000000000000000000000000000000..55efea5f5d04569e23282a7c7e56bf642627e47a
--- /dev/null
+++ b/thirdparty/rr/plugins/acmru.pl
@@ -0,0 +1,72 @@
+#-----------------------------------------------------------
+# acmru.pl
+# Plugin for Registry Ripper, NTUSER.DAT edition - gets the 
+# ACMru values 
+#
+# Change history
+#
+#
+# References
+#
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package acmru;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of user's ACMru key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching acmru v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Microsoft\\Search Assistant\\ACMru';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("ACMru - Search Assistant");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) { 
+				::rptMsg($s->get_name()." [".gmtime($s->get_timestamp())." (UTC)]");
+				my @vals = $s->get_list_of_values();
+				my %ac_vals;
+				foreach my $v (@vals) {
+					$ac_vals{$v->get_name()} = $v->get_data();
+				}
+				foreach my $a (sort {$a <=> $b} keys %ac_vals) {
+					::rptMsg("\t".$a." -> ".$ac_vals{$a});
+				}
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/adoberdr.pl b/thirdparty/rr/plugins/adoberdr.pl
new file mode 100644
index 0000000000000000000000000000000000000000..f46e5ebd674759b86ad375c6e2d6328ccedff071
--- /dev/null
+++ b/thirdparty/rr/plugins/adoberdr.pl
@@ -0,0 +1,93 @@
+#-----------------------------------------------------------
+# adoberdr.pl
+# Plugin for Registry Ripper 
+# Parse Adobe Reader MRU keys
+#
+# Change history
+#   20100218 - added checks for versions 4.0, 5.0, 9.0
+#   20091125 - modified output to make a bit more clear
+#
+# References
+#
+# Note: LastWrite times on c subkeys will all be the same,
+#       as each subkey is modified as when a new entry is added
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package adoberdr;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100218);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets user's Adobe Reader cRecentFiles values";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching adoberdr v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	::rptMsg("Adoberdr v.".$VERSION);
+# First, let's find out which version of Adobe Acrobat Reader is installed
+	my $version;
+	my $tag = 0;
+	my @versions = ("4\.0","5\.0","6\.0","7\.0","8\.0","9\.0");
+	foreach my $ver (@versions) {		
+		my $key_path = "Software\\Adobe\\Acrobat Reader\\".$ver."\\AVGeneral\\cRecentFiles";
+		if (defined($root_key->get_subkey($key_path))) {
+			$version = $ver;
+			$tag = 1;
+		}
+	}
+	
+	if ($tag) {
+		::rptMsg("Adobe Acrobat Reader version ".$version." located."); 
+		my $key_path = "Software\\Adobe\\Acrobat Reader\\".$version."\\AVGeneral\\cRecentFiles";   
+		my $key = $root_key->get_subkey($key_path);
+		if ($key) {
+			::rptMsg($key_path);
+			::rptMsg("");
+#			::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+			my %arkeys;
+			my @subkeys = $key->get_list_of_subkeys();
+			if (scalar @subkeys > 0) {
+				foreach my $s (@subkeys) {
+					my $num = $s->get_name();
+					my $data = $s->get_value('sDI')->get_data();
+					$num =~ s/^c//;
+					$arkeys{$num}{lastwrite} = $s->get_timestamp();
+					$arkeys{$num}{data} = $data;
+				}
+				::rptMsg("Most recent PDF opened: ".gmtime($arkeys{1}{lastwrite})." (UTC)");
+				foreach my $k (sort keys %arkeys) {
+					::rptMsg("  c".$k."   ".$arkeys{$k}{data});
+				}
+			}
+			else {
+				::rptMsg($key_path." has no subkeys.");
+			}
+		}
+		else {
+			::rptMsg("Could not access ".$key_path);
+		}
+	}
+	else {
+		::rptMsg("Adobe Acrobat Reader version not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/aim.pl b/thirdparty/rr/plugins/aim.pl
new file mode 100644
index 0000000000000000000000000000000000000000..32eeeae713a302a5fa70582ce608fd1d87a4386e
--- /dev/null
+++ b/thirdparty/rr/plugins/aim.pl
@@ -0,0 +1,95 @@
+#-----------------------------------------------------------
+# aim
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package aim;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080325);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets info from the AOL Instant Messenger (not AIM) install";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching aim plugin v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = 'Software\\America Online\\AOL Instant Messenger (TM)\\CurrentVersion\\Users';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("AIM");
+		::rptMsg($key_path);
+		::rptMsg("");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) { 
+				my $user = $s->get_name();
+				::rptMsg("User: $user  [".gmtime($s->get_timestamp())."]");
+				
+				my $login = "Login";
+				my $recent  = "recent IM ScreenNames";
+				my $recent2 = "recent ScreenNames";
+				
+				my @userkeys = $s->get_list_of_subkeys();
+				foreach my $u (@userkeys) {
+					my $us = $u->get_name();
+# See if we can get the encrypted password
+					if ($us =~ m/^$login/) {
+						my $pwd = "";
+						eval {
+							$pwd = $u->get_value("Password1")->get_data();
+						};
+						::rptMsg("Pwd: ".$pwd) if ($pwd ne "");
+					}
+# See if we can get recent folks they've chatted with...					
+					if ($us eq $recent || $us eq $recent2) {
+						
+						my @vals = $u->get_list_of_values();
+						if (scalar(@vals) > 0) {
+							::rptMsg($user."\\".$us);
+							my %sns;
+							foreach my $v (@vals) {
+								$sns{$v->get_name()} = $v->get_data();
+							}
+							
+							foreach my $i (sort {$a <=> $b} keys %sns) {
+								::rptMsg("\t\t".$i." -> ".$sns{$i});
+							}
+						}
+						else {
+# No values							
+						}
+					}
+				}
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/all b/thirdparty/rr/plugins/all
new file mode 100644
index 0000000000000000000000000000000000000000..5f28a06eb62a000e03850a2c72aeb3c44517c97f
--- /dev/null
+++ b/thirdparty/rr/plugins/all
@@ -0,0 +1,3 @@
+#-------------------------------------
+# All
+regtime
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/appinitdlls.pl b/thirdparty/rr/plugins/appinitdlls.pl
new file mode 100644
index 0000000000000000000000000000000000000000..29c75915b153dccd5562a1a2559d16939689945c
--- /dev/null
+++ b/thirdparty/rr/plugins/appinitdlls.pl
@@ -0,0 +1,61 @@
+#-----------------------------------------------------------
+# appinitdlls
+#
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package appinitdlls;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of AppInit_DLLs value";	
+}
+sub getDescr{}
+sub getRefs {
+	my %refs = ("Working with the AppInit_DLLs Reg Value" => 
+	            "http://support.microsoft.com/kb/q197571");
+	return %refs;
+}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching appinitdlls v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Microsoft\\Windows NT\\CurrentVersion\\Windows';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("AppInit_DLLs");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		foreach my $v (@vals) {
+			my $name = $v->get_name();
+			if ($name eq "AppInit_DLLs") {
+				my $data = $v->get_data();
+				$data = "{blank}" if ($data eq "");
+				::rptMsg($name." -> ".$data);
+			}
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/applets.pl b/thirdparty/rr/plugins/applets.pl
new file mode 100644
index 0000000000000000000000000000000000000000..e29fffa083d515c03f1d3f75ed022cdb92de9b1f
--- /dev/null
+++ b/thirdparty/rr/plugins/applets.pl
@@ -0,0 +1,96 @@
+#-----------------------------------------------------------
+# applets.pl
+# Plugin for Registry Ripper 
+# Windows\CurrentVersion\Applets Recent File List values 
+#
+# Change history
+#
+#
+# References
+#
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package applets;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of user's Applets key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching applets v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Applets';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("Applets");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+# Locate files opened in MS Paint		
+		my $paint_key = 'Paint\\Recent File List';
+		my $paint = $key->get_subkey($paint_key);
+		if (defined $paint) {
+			::rptMsg($key_path."\\".$paint_key);
+			::rptMsg("LastWrite Time ".gmtime($paint->get_timestamp())." (UTC)");
+			
+			my @vals = $paint->get_list_of_values();
+			if (scalar(@vals) > 0) {
+				my %files;
+# Retrieve values and load into a hash for sorting			
+				foreach my $v (@vals) {
+					my $val = $v->get_name();
+					my $data = $v->get_data();
+					my $tag = (split(/File/,$val))[1];
+					$files{$tag} = $val.":".$data;
+				}
+# Print sorted content to report file			
+				foreach my $u (sort {$a <=> $b} keys %files) {
+					my ($val,$data) = split(/:/,$files{$u},2);
+					::rptMsg("  ".$val." -> ".$data);
+				}
+			}
+			else {
+				::rptMsg($key_path."\\".$paint_key." has no values.");
+			}			
+		}
+		else {
+			::rptMsg($key_path."\\".$paint_key." not found.");
+		}
+# Get Last Registry key opened in RegEdit
+		my $reg_key = "Regedit";
+		my $reg = $key->get_subkey($reg_key);
+		if (defined $reg) {
+			::rptMsg("");
+			::rptMsg($key_path."\\".$reg_key);
+			::rptMsg("LastWrite Time ".gmtime($reg->get_timestamp())." (UTC)"); 
+			my $lastkey = $reg->get_value("LastKey")->get_data();
+			::rptMsg("RegEdit LastKey value -> ".$lastkey);
+		}		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/apppaths.pl b/thirdparty/rr/plugins/apppaths.pl
new file mode 100644
index 0000000000000000000000000000000000000000..85e00aab25d1cfcbc09e0f032cc10c01efcb397e
--- /dev/null
+++ b/thirdparty/rr/plugins/apppaths.pl
@@ -0,0 +1,83 @@
+#-----------------------------------------------------------
+# apppaths
+# Gets contents of App Paths subkeys from the Software hive,
+# diplaying the EXE name and path; all entries are sorted by
+# LastWrite time
+# 
+# References
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package apppaths;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              version       => 20080404);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Gets content of App Paths key";	
+}
+sub getDescr{}
+sub getRefs {
+	my %refs = ("You cannot open Help and Support Center in Windows XP" => 
+	            "http://support.microsoft.com/kb/888018",
+	            "Another installation program starts..." => 
+	            "http://support.microsoft.com/kb/888470");	
+	return %refs;
+}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching apppaths v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows\\CurrentVersion\\App Paths";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("App Paths");
+		::rptMsg($key_path);
+		::rptMsg("");
+		my %apps;
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				
+				my $name = $s->get_name();
+				my $lastwrite = $s->get_timestamp();
+				my $path;
+				eval {
+					$path = $s->get_value("")->get_data();
+				};
+				push(@{$apps{$lastwrite}},$name." [".$path."]");
+			}
+			
+			foreach my $t (reverse sort {$a <=> $b} keys %apps) {
+				::rptMsg(gmtime($t)." (UTC)");
+				foreach my $item (@{$apps{$t}}) {
+					::rptMsg("  $item");
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/arpcache.pl b/thirdparty/rr/plugins/arpcache.pl
new file mode 100644
index 0000000000000000000000000000000000000000..b8ed74f88ffc8f9098112e814f358f4291253cc5
--- /dev/null
+++ b/thirdparty/rr/plugins/arpcache.pl
@@ -0,0 +1,133 @@
+#-----------------------------------------------------------
+# arpcache.pl
+# Retrieves CurrentVersion\App Management\ARPCache entries; subkeys appear
+# to maintain information about paths to installed applications in the 
+# SlowInfoCache value(0x10 - FILETIME object, null term. string with path
+# starts at 0x1c)
+#
+# Change history
+#    20090413 - Created
+#
+# References
+#    No references, but the subkeys appear to hold information about
+#    installed applications; some SlowInfoCache values appear to contain
+#    timestamp data (FILETIME object) and/or path information.  Posts on
+#    the Internet indicate the existence of Kazaa beneath the APRCache key,
+#    as well as possibly an "Outerinfo" subkey indicating that spyware is 
+#    installed.
+# 
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package arpcache;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20090413);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Retrieves CurrentVersion\\App Management\\ARPCache entries";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+my %arpcache;
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching arpcache v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\App Management\\ARPCache';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) { 
+				my $lw = $s->get_timestamp();
+				my $name = $s->get_name();
+	
+				my $path;
+				eval {
+					my $i = $s->get_value("SlowInfoCache")->get_data();
+					$path = parsePath($i);
+				};
+				($@) ? ($name .= "|") : ($name .= "|".$path);
+				
+				my $date;
+				eval {
+					my $i = $s->get_value("SlowInfoCache")->get_data();
+					$date = parseDate($i);
+				};
+				($@) ? ($name .= "|") : ($name .= "|".$date);
+				push(@{$arpcache{$lw}},$name);
+			}
+			
+			
+			foreach my $t (reverse sort {$a <=> $b} keys %arpcache) {
+				::rptMsg(gmtime($t)." (UTC)");
+				foreach my $item (@{$arpcache{$t}}) {
+					my ($name,$path,$date) = split(/\|/,$item,3);
+					::rptMsg("  ".$name);
+					my $str = $path unless ($path eq "");
+					$str .= " [".gmtime($date)."]" unless ($date == 0);
+					::rptMsg("    -> ".$str) unless ($str eq ""); 
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
+
+sub parseDate {
+	my $data = shift;
+	my ($t1,$t2) = unpack("VV",substr($data,0x10,8));
+	return ::getTime($t1,$t2);
+}
+
+sub parsePath {
+	my $data = shift;
+	my $ofs = 0x1c;
+	my $tag = 1;
+	
+	my $str = substr($data,$ofs,2);
+	if (unpack("v",$str) == 0) {
+		return "";
+	}
+	else {
+		while($tag) {
+			$ofs += 2;
+			my $i = substr($data,$ofs,2);
+			if (unpack("v",$i) == 0) {
+				$tag = 0;
+			}
+			else {
+				$str .= $i;
+			}
+		}
+	}	
+	$str =~ s/\00//g;
+	return $str;
+}
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/assoc.pl b/thirdparty/rr/plugins/assoc.pl
new file mode 100644
index 0000000000000000000000000000000000000000..a2587da110b56070af392b79895a3eab16a8a845
--- /dev/null
+++ b/thirdparty/rr/plugins/assoc.pl
@@ -0,0 +1,87 @@
+#-----------------------------------------------------------
+# assoc.pl
+# Plugin to extract file association data from the Software hive file
+# Can take considerable time to run; recommend running it via rip.exe
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package assoc;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080815);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get list of file ext associations";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching assoc v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Classes";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("assoc");
+		::rptMsg($key_path);
+#		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+# First step will be to get a list of all of the file extensions
+		my %ext;
+		my @sk = $key->get_list_of_subkeys();
+		if (scalar(@sk) > 0) {
+			foreach my $s (@sk) {
+				my $name = $s->get_name();
+				next unless ($name =~ m/^\.\w+$/);
+				my $data;
+				eval {
+					$data = $s->get_value("")->get_data();
+				};
+				if ($@) {
+# Error generated, as "(Default)" value was not found					
+				}
+				else {
+					$ext{$name} = $data if ($data ne "");
+				}
+			}
+# Once a list of all file ext subkeys has been compiled, access the file type
+# to determine the command line used to launch files with that extension
+			foreach my $e (keys %ext) {
+				my $cmd;
+				eval {
+					$cmd = $key->get_subkey($ext{$e}."\\shell\\open\\command")->get_value("")->get_data();
+				};
+				if ($@) {
+# error generated attempting to locate <file type>.\shell\open\command\(Default) value					
+				}
+				else {
+					::rptMsg($e." : ".$cmd);
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/auditfail.pl b/thirdparty/rr/plugins/auditfail.pl
new file mode 100644
index 0000000000000000000000000000000000000000..019ec15eda4ca159635b2d2bb4257a9c48afeebb
--- /dev/null
+++ b/thirdparty/rr/plugins/auditfail.pl
@@ -0,0 +1,66 @@
+#-----------------------------------------------------------
+# auditfail.pl
+#
+# Ref: 
+#   http://support.microsoft.com/kb/140058
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package auditfail;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20081212);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get CrashOnAuditFail value";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+my %val = (0 => "Feature is off; the system will not halt",
+           1 => "Feature is on; the system will halt when events cannot be written to the ".
+                "Security Event Log",
+           2 => "Feature is on and has been triggered; only Administrators can log in");
+           
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching auditfail v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		
+		my $lsa_path = "ControlSet00".$current."\\Control\\Lsa";
+		my $lsa;
+		if ($lsa = $root_key->get_subkey($lsa_path)) {
+			
+			eval {
+				my $crash = $lsa->get_value("crashonauditfail")->get_data();
+				::rptMsg("CrashOnAuditFail = ".$crash);
+				::rptMsg($val{$crash});
+			};
+			::rptMsg($@) if ($@);
+		}	
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
diff --git a/thirdparty/rr/plugins/auditpol.pl b/thirdparty/rr/plugins/auditpol.pl
new file mode 100644
index 0000000000000000000000000000000000000000..11ea9a10960d897241113cfc75d5110ec3c32a55
--- /dev/null
+++ b/thirdparty/rr/plugins/auditpol.pl
@@ -0,0 +1,88 @@
+#-----------------------------------------------------------
+# auditpol
+# Get the audit policy from the Security hive file
+# 
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package auditpol;
+use strict;
+
+my %config = (hive          => "Security",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              osmask        => 22,
+              version       => 20080327);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get audit policy from the Security hive file";	
+}
+sub getDescr{}
+sub getRefs {
+	my %refs = ("How To Determine Audit Policies from the Registry" => 
+	            "http://support.microsoft.com/default.aspx?scid=kb;EN-US;q246120");
+	return %refs;	
+}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+my %audit = (0 => "N",
+             1 => "S",
+             2 => "F",
+             3 => "S/F");
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching auditpol v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Policy\\PolAdtEv";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("auditpol");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my $data;
+		eval {
+			$data = $key->get_value("")->get_data();
+		};
+		if ($@) {
+			::rptMsg("Error occurred getting data from ".$key_path);
+			::rptMsg(" - ".$@);
+		}
+		else {
+# Check to see if auditing is enabled
+			my $enabled = unpack("C",substr($data,0,1));
+			if ($enabled) {
+				::rptMsg("Auditing is enabled.");
+# Get audit configuration settings			
+				my @vals = unpack("V*",$data);
+				::rptMsg("\tAudit System Events        = ".$audit{$vals[1]});
+				::rptMsg("\tAudit Logon Events         = ".$audit{$vals[2]});
+				::rptMsg("\tAudit Object Access        = ".$audit{$vals[3]});
+				::rptMsg("\tAudit Privilege Use        = ".$audit{$vals[4]});
+				::rptMsg("\tAudit Process Tracking     = ".$audit{$vals[5]});
+				::rptMsg("\tAudit Policy Change        = ".$audit{$vals[6]});
+				::rptMsg("\tAudit Account Management   = ".$audit{$vals[7]});
+				::rptMsg("\tAudit Dir Service Access   = ".$audit{$vals[8]});
+				::rptMsg("\tAudit Account Logon Events = ".$audit{$vals[9]});
+			}
+			else {
+				::rptMsg("**Auditing is NOT enabled.");
+			}
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/autoendtasks.pl b/thirdparty/rr/plugins/autoendtasks.pl
new file mode 100644
index 0000000000000000000000000000000000000000..29b89d20ae37f7d0cac9ed3cd8dbad81a3019dd1
--- /dev/null
+++ b/thirdparty/rr/plugins/autoendtasks.pl
@@ -0,0 +1,66 @@
+#-----------------------------------------------------------
+# autoendtasks.pl
+#
+# History
+#   20081128 - created
+# 
+# Ref: 
+#   http://support.microsoft.com/kb/555619
+#   This Registry setting tells XP (and Vista) to automatically
+#   end non-responsive tasks; value may not exist on Vista.
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package autoendtasks;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20081128);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Automatically end a non-responsive task";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching autoendtasks v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Control Panel\\Desktop';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+#		::rptMsg("autoendtasks");
+		::rptMsg($key_path);
+#		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my $autoend;
+		eval {
+			$autoend = $key->get_value("AutoEndTasks")->get_data();
+		};
+		if ($@) {
+			::rptMsg("AutoEndTasks value not found.");
+		}
+		else {
+			::rptMsg("AutoEndTasks = ".$autoend);
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/autorun.pl b/thirdparty/rr/plugins/autorun.pl
new file mode 100644
index 0000000000000000000000000000000000000000..50604cf4ddc9f63034d391294e361b0c0e1ba47e
--- /dev/null
+++ b/thirdparty/rr/plugins/autorun.pl
@@ -0,0 +1,74 @@
+#-----------------------------------------------------------
+# autorun.pl
+# Get autorun settings
+#
+# Change history
+#
+#
+# References
+#    http://support.microsoft.com/kb/953252
+#    http://www.microsoft.com/technet/prodtechnol/windows2000serv/reskit
+#         /regentry/91525.mspx?mfr=true
+#
+# copyright 2008-2009 H. Carvey
+#-----------------------------------------------------------
+package autorun;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20081212);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets autorun settings";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching autorun v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+#		::rptMsg($key_path);
+#		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		eval {
+			my $nodrive = $key->get_value("NoDriveTypeAutoRun")->get_data();
+			my $str = sprintf "%-20s 0x%x","NoDriveTypeAutoRun",$nodrive;
+			::rptMsg($str);
+		};
+		::rptMsg("Error: ".$@) if ($@);
+
+# http://support.microsoft.com/kb/953252		
+		eval {
+			my $honor = $key->get_value("HonorAutorunSetting")->get_data();
+			my $str = sprintf "%-20s 0x%x","HonorAutorunSetting",$honor;
+			::rptMsg($str);
+		};
+		::rptMsg("HonorAutorunSetting not found.") if ($@);
+		::rptMsg("");
+		::rptMsg("Autorun settings in the HKLM hive take precedence over those in");
+		::rptMsg("the HKCU hive.");
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/bagtest.pl b/thirdparty/rr/plugins/bagtest.pl
new file mode 100644
index 0000000000000000000000000000000000000000..cdc5600d5cbef6cc517afec90d6acb14d4ff2603
--- /dev/null
+++ b/thirdparty/rr/plugins/bagtest.pl
@@ -0,0 +1,170 @@
+#-----------------------------------------------------------
+# bagtest.pl
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package bagtest;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090828);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Test -- BagMRU";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching bagtest v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\Shell\\BagMRU";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+#		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my $subtree_iter = $key->get_subtree_iterator;
+  	while (my ($k, $val) = $subtree_iter->get_next) {
+  		if (defined $val) {
+      	next unless ($val->get_name() =~ m/^\d+/);
+      	
+      	my $path;
+      	my $data = $val->get_data();
+      	my $size = unpack("v",substr($data,0,20));
+      	my $type = unpack("C",substr($data,2,1));
+      	my $name = (split(/BagMRU/,$k->get_path()))[1];
+      	
+      	if ($type == 0x47 || $type == 0x46 || $type == 0x42 || $type == 0x41 || 
+      	    $type == 0xc3) {
+      		
+      		my $str1 = getStrings1($data);
+      		$path = $str1;
+      		    	
+      	}
+      	elsif ($type == 0x31 || $type == 0x32) {
+      		my($ascii,$uni) = getStrings2($data);
+      		$path = $uni;
+      	}
+      	elsif ($type == 0x2f) {
+# bytes 3-5 of $data contain a drive letter      		  
+					$path = substr($data,0x03,3);   		
+      	}
+      	else {
+# Nothing      		
+      	}    	    
+#      	my $str = sprintf "%-30s %-3s %-4s 0x%x",$name."\\".$val->get_name(),$size,length($data),$type; 	
+				my $str = sprintf "%-25s  ".$path,$name."\\".$val->get_name();
+      	::rptMsg($str);
+      	
+  		}
+   		else {
+           
+  		}
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+#sub getStrings1 {
+#	my $data = shift;
+#	my $str;
+#	my $cursor = 0x05;
+#	my $tag = 1;
+#	
+#	while($tag) {
+#		my $byte = substr($data,$cursor,1);
+#		if (unpack("C",$byte) == 0x00) {
+#			$tag = 0;
+#		}
+#		else {
+#			$str .= $byte;
+#			$cursor += 1;
+#		}
+#	}
+#	return $str;
+#}
+
+sub getStrings1 {
+	my $data = shift;
+	my $d = substr($data,0x05,length($data) - 1);
+	$d =~ s/\00/-/g;
+	$d =~ s/[[:cntrl:]]//g;
+	
+	my @t = split(/-/,$d);
+	
+	my @s;
+	for my $i (1..scalar(@t) - 1) {
+		push(@s,$t[$i]) if (length($t[$i]) > 2);
+	}
+	
+	return $t[0]." (".join(',',@s).")";	
+}
+
+sub getStrings2 {
+# ASCII short name starts at 0x0E, and is \00 terminated; 0x14 bytes
+# after that is the null-term Unicode name
+	my $data = shift;
+	my ($ascii,$uni);
+	my $cursor = 0x0e;
+	my $tag = 1;
+	
+	while($tag) {
+		my $byte = substr($data,$cursor,1);
+		if (unpack("C",$byte) == 0x00) {
+			$tag = 0;
+		}
+		else {
+			$ascii .= $byte;
+			$cursor += 1;
+		}
+	}
+	
+	$cursor += 0x14;
+	
+	$uni = substr($data,$cursor,length($data) - 1);
+	$uni =~ s/\00//g;
+	$uni =~ s/[[:cntrl:]]//g;
+	return ($ascii,$uni);
+}
+
+1;
+
+
+
+
+
+# Original code to traverse through values and subkeys
+# Retain for legacy code purposes
+#sub traverse {
+#	my $key = shift;
+#  
+#  foreach my $val ($key->get_list_of_values()) {
+#  	next unless ($val->get_name() =~ m/\d+/);
+#  	
+#  	::rptMsg($val->get_name());
+#  	
+#  }
+#  
+#	foreach my $subkey ($key->get_list_of_subkeys()) {
+#		traverse($subkey);
+#  }
+#}
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/bagtest2.pl b/thirdparty/rr/plugins/bagtest2.pl
new file mode 100644
index 0000000000000000000000000000000000000000..59716d2fd814d96ae24da43da76ce056c5c904df
--- /dev/null
+++ b/thirdparty/rr/plugins/bagtest2.pl
@@ -0,0 +1,161 @@
+#-----------------------------------------------------------
+# bagtest2.pl
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package bagtest2;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090828);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Test -- BagMRU";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+my %bagmru;
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching bagtest v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\Shell\\BagMRU";
+	my $key;
+
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+#		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		traverse($key);
+		
+		foreach my $i (sort keys %bagmru) {
+			my $str = sprintf "%-30s ".$bagmru{$i},$i;
+			::rptMsg($str);
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+sub traverse {
+	my $key = shift;
+  my $name = (split(/BagMRU/,$key->get_path()))[1];
+  
+  my @bags;
+  
+  foreach my $val ($key->get_list_of_values()) {
+  	next unless ($val->get_name() =~ m/\d+/);
+  	
+  	my $path;
+    my $data = $val->get_data();
+    my $size = unpack("v",substr($data,0,20));
+    my $type = unpack("C",substr($data,2,1));
+    
+      	
+    if ($type == 0x47 || $type == 0x46 || $type == 0x42 || $type == 0x41 || 
+        $type == 0xc3) {
+      		
+    	my $str1 = getStrings1($data);
+    	$path = $str1;
+      		    	
+    }
+    elsif ($type == 0x31 || $type == 0x32 || $type == 0xb1) {
+    	my($ascii,$uni) = getStrings2($data);
+    	$path = $uni;
+    }
+    elsif ($type == 0x2f) {
+# bytes 3-5 of $data contain a drive letter      		  
+			$path = substr($data,0x03,3);   		
+    }
+    else {
+# Nothing      		
+    }   
+    $bagmru{$name."\\".$val->get_name()} = $path;
+  }
+  
+	foreach my $subkey ($key->get_list_of_subkeys()) {
+		traverse($subkey);
+  }
+}
+
+
+sub getStrings1 {
+	my $data = shift;
+	my $d = substr($data,0x05,length($data) - 1);
+	$d =~ s/\00/-/g;
+	$d =~ s/[[:cntrl:]]//g;
+	
+	my @t = split(/-/,$d);
+	
+	my @s;
+	for my $i (1..scalar(@t) - 1) {
+		push(@s,$t[$i]) if (length($t[$i]) > 2);
+	}
+	
+	return $t[0]." (".join(',',@s).")";	
+}
+
+sub getStrings2 {
+# ASCII short name starts at 0x0E, and is \00 terminated; 0x14 bytes
+# after that is the null-term Unicode name
+	my $data = shift;
+	my ($ascii,$uni);
+	my $cursor = 0x0e;
+	my $tag = 1;
+	
+	while($tag) {
+		my $byte = substr($data,$cursor,1);
+		if (unpack("C",$byte) == 0x00) {
+			$tag = 0;
+		}
+		else {
+			$ascii .= $byte;
+			$cursor += 1;
+		}
+	}
+	
+	$cursor += 0x14;
+	
+	if ($ascii eq "RECENT") {
+		$uni = substr($data,$cursor,length($data) - 1);
+		$uni =~ s/\00//g;
+		$uni =~ s/[[:cntrl:]]//g;
+	}
+	else {
+		my $tag = 1;
+		my $count = 0;
+		while($tag) {
+			my $byte = substr($data,$cursor,2);
+			if ($count > 2 && unpack("v",$byte) == 0x00) {
+				$tag = 0;
+			}
+			else {
+				$uni .= $byte;
+				$count++;
+				$cursor += 2;
+			}
+		}
+		$uni =~ s/\00//g;
+		$uni =~ s/[[:cntrl:]]//g;
+	}
+	return ($ascii,$uni);
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/banner.pl b/thirdparty/rr/plugins/banner.pl
new file mode 100644
index 0000000000000000000000000000000000000000..44ae62a274638704e0f79eefb460e27acdb1bca0
--- /dev/null
+++ b/thirdparty/rr/plugins/banner.pl
@@ -0,0 +1,127 @@
+#-----------------------------------------------------------
+# banner
+# Get banner information from the SOFTWARE hive file (if any)
+# 
+# Written By:
+# Special Agent Brook William Minnick
+# Brook_Minnick@doioig.gov
+# U.S. Department of the Interior - Office of Inspector General
+# Computer Crimes Unit
+# 12030 Sunrise Valley Drive Suite 250
+# Reston, VA 20191
+#-----------------------------------------------------------
+package banner;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20081119);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get HKLM\\SOFTWARE.. Logon Banner Values";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching banner v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows\\CurrentVersion\\policies\\system";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("Logon Banner Information");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+
+# GET LEGALNOTICECAPTION --
+
+		my $caption;
+		eval {
+			$caption = $key->get_value("Legalnoticecaption")->get_data();
+		};
+		if ($@) {
+			::rptMsg("Legalnoticecaption value not found.");
+		}
+		else {
+			::rptMsg("Legalnoticecaption value = ".$caption);
+		}
+		::rptMsg("");
+
+# GET LEGALNOTICETEXT --
+
+		my $banner;
+		eval {
+			$banner = $key->get_value("Legalnoticetext")->get_data();
+		};
+		if ($@) {
+			::rptMsg("Legalnoticetext value not found.");
+		}
+		else {
+			::rptMsg("Legalnoticetext value = ".$banner);
+		}
+		::rptMsg("");
+	
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+
+my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\Winlogon";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+
+# GET LEGALNOTICECAPTION --
+
+		my $caption2;
+		eval {
+			$caption2 = $key->get_value("Legalnoticecaption")->get_data();
+		};
+		if ($@) {
+			::rptMsg("Legalnoticecaption value not found.");
+		}
+		else {
+			::rptMsg("Legalnoticecaption value = ".$caption2);
+		}
+		::rptMsg("");
+
+# GET LEGALNOTICETEXT --
+
+		my $banner2;
+		eval {
+			$banner2 = $key->get_value("Legalnoticetext")->get_data();
+		};
+		if ($@) {
+			::rptMsg("Legalnoticetext value not found.");
+		}
+		else {
+			::rptMsg("Legalnoticetext value = ".$banner2);
+		}
+		::rptMsg("");
+	
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/bho.pl b/thirdparty/rr/plugins/bho.pl
new file mode 100644
index 0000000000000000000000000000000000000000..be3b8f6c852de50a02000ff7c30bd460733e812b
--- /dev/null
+++ b/thirdparty/rr/plugins/bho.pl
@@ -0,0 +1,107 @@
+#-----------------------------------------------------------
+# bho
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package bho;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              osmask        => 22,
+              version       => 20080418);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets Browser Helper Objects from Software hive";	
+}
+sub getDescr{}
+sub getRefs {
+	my %refs = ("Browser Helper Objects" => 
+	             "http://msdn2.microsoft.com/en-us/library/bb250436.aspx");	
+	return %refs;
+}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	my %bhos;
+	::logMsg("Launching bho v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects";;
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("Browser Helper Objects");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar (@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				my $name = $s->get_name();
+				next if ($name =~ m/^-/);
+				my $clsid_path = "Classes\\CLSID\\".$name;
+				my $clsid;
+				if ($clsid = $root_key->get_subkey($clsid_path)) {
+					my $class;
+					my $mod;
+					my $lastwrite;
+					
+					eval {
+						$class = $clsid->get_value("")->get_data();
+						$bhos{$name}{class} = $class;
+					};
+					if ($@) {
+						::logMsg("\tError getting Class name for CLSID\\".$name);
+						::logMsg("\t".$@);
+					}
+					eval {
+						$mod = $clsid->get_subkey("InProcServer32")->get_value("")->get_data();
+						$bhos{$name}{module} = $mod;
+					};
+					if ($@) {
+						::logMsg("\tError getting Module name for CLSID\\".$name);
+						::logMsg("\t".$@);
+					}
+					eval{
+						$lastwrite = $clsid->get_subkey("InProcServer32")->get_timestamp();
+						$bhos{$name}{lastwrite} = $lastwrite;
+					};
+					if ($@) {
+						::logMsg("\tError getting LastWrite time for CLSID\\".$name);
+						::logMsg("\t".$@);
+					}
+					
+					foreach my $b (keys %bhos) {
+						::rptMsg($b);
+						::rptMsg("\tClass     => ".$bhos{$b}{class});
+						::rptMsg("\tModule    => ".$bhos{$b}{module});
+						::rptMsg("\tLastWrite => ".gmtime($bhos{$b}{lastwrite}));
+						::rptMsg("");
+					}
+				}
+				else {
+					::rptMsg($clsid_path." not found.");
+					::rptMsg("");
+					::logMsg($clsid_path." not found.");
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.  No BHOs installed.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/bitbucket.pl b/thirdparty/rr/plugins/bitbucket.pl
new file mode 100644
index 0000000000000000000000000000000000000000..16e61480e968f705cf4650c86682feb27ea14499
--- /dev/null
+++ b/thirdparty/rr/plugins/bitbucket.pl
@@ -0,0 +1,81 @@
+#-----------------------------------------------------------
+# bitbucket
+# Get HKLM\..\BitBucket keys\values (if any)
+# 
+# Change history
+#   20091020 - Updated; collected additional values
+#
+# References
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package bitbucket;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080418);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get HKLM\\..\\BitBucket keys\\values";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching bitbucket v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows\\CurrentVersion\\Explorer\\BitBucket";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		eval {
+			my $global = $key->get_value("UseGlobalSettings")->get_data();
+			::rptMsg("UseGlobalSettings = ".$global);
+		};
+		
+		eval {
+			my $nuke = $key->get_value("NukeOnDelete")->get_data();
+			::rptMsg("NukeOnDelete      = ".$nuke);
+		};	
+		::rptMsg("");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				::rptMsg($key_path."\\".$s->get_name());
+				::rptMsg("LastWrite Time = ".gmtime($s->get_timestamp())." (UTC)");
+				eval {
+					my $vol = $s->get_value("VolumeSerialNumber")->get_data();
+					::rptMsg("VolumeSerialNumber = 0x".uc(sprintf "%1x",$vol));
+				};
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/bitbucket_user.pl b/thirdparty/rr/plugins/bitbucket_user.pl
new file mode 100644
index 0000000000000000000000000000000000000000..e3374fd193a82ac3244f5475e0b3b71a2d5b958a
--- /dev/null
+++ b/thirdparty/rr/plugins/bitbucket_user.pl
@@ -0,0 +1,71 @@
+#-----------------------------------------------------------
+# bitbucket_user
+# Get HKLM\..\BitBucket keys\values (if any)
+# 
+# Change history
+#
+# References
+#
+# NOTE: In limited testing, the volume letter subkeys beneath the
+#       BitBucket key appear to be volatile.
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package bitbucket_user;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20091020);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "TEST - Get user BitBucket values";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching bitbucket_user v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\BitBucket";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				::rptMsg($key_path."\\".$s->get_name());
+				::rptMsg("LastWrite Time = ".gmtime($s->get_timestamp())." (UTC)");
+				eval {
+					my $purge = $s->get_value("NeedToPurge")->get_data();
+					::rptMsg("  NeedToPurge = ".$purge);
+				};
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/brisv.pl b/thirdparty/rr/plugins/brisv.pl
new file mode 100644
index 0000000000000000000000000000000000000000..c79aa3e651b96b883cf354406c7cfe0b2169f5bb
--- /dev/null
+++ b/thirdparty/rr/plugins/brisv.pl
@@ -0,0 +1,63 @@
+#-----------------------------------------------------------
+# brisv.pl
+# Plugin to detect the presence of Trojan.Brisv.A
+# Symantec write-up: http://www.symantec.com/security_response/writeup.jsp
+#                    ?docid=2008-071823-1655-99
+#
+# Change History:
+#   20090210: Created
+#
+# Info on URLAndExitCommandsEnabled value:
+#   http://support.microsoft.com/kb/828026
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package brisv;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090210);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Detect artifacts of a Troj\.Brisv\.A infection";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching brisv v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\PIMSRV";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my $mp_path = "Software\\Microsoft\\MediaPlayer\\Preferences";
+		my $url;
+		eval {
+			$url = $key->get_subkey($mp_path)->get_value("URLAndExitCommandsEnabled")->get_data();
+			::rptMsg($mp_path."\\URLAndExitCommandsEnabled value set to ".$url);
+		};
+# if an error occurs within the eval{} statement, do nothing		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/clampi.pl b/thirdparty/rr/plugins/clampi.pl
new file mode 100644
index 0000000000000000000000000000000000000000..abf0ae537a2cf3b0d86637396bed5b10165ca2a7
--- /dev/null
+++ b/thirdparty/rr/plugins/clampi.pl
@@ -0,0 +1,120 @@
+#-----------------------------------------------------------
+# clampi.pl
+# Checks keys/values set by new version of Trojan.Clampi
+#
+# Change history
+#   20091019 - created
+#
+# NOTE: This is purely a test plugin, and based solely on the below
+#       reference.  It has not been tested on any systems that were
+#       known to be infected.
+#
+# References
+#   http://www.symantec.com/connect/blogs/inside-trojanclampi-stealing-your-information
+# 
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package clampi;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20091019);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "TEST - Checks for keys set by Trojan\.Clampi PROT module";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching clampi v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	
+	my $count = 0;
+	
+	my $key_path = 'Software\\Microsoft\\Internet Explorer\\Main';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my ($form1, $form2, $form3);
+		
+		eval {
+			$form1 = $key->get_value("Use FormSuggest")->get_data();
+			::rptMsg("\tUse FormSuggest = ".$form1);
+			$count++ if ($form1 eq "true");
+		};
+		
+		eval {
+			$form2 = $key->get_value("FormSuggest_Passwords")->get_data();
+			::rptMsg("\tFormSuggest_Passwords = ".$form2);
+			$count++ if ($form2 eq "true");
+		};
+		
+		eval {
+			$form3 = $key->get_value("FormSuggest_PW_Ask")->get_data();
+			::rptMsg("\tUse FormSuggest = ".$form3);
+			$count++ if ($form3 eq "no");
+		};
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+	::rptMsg("");
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoComplete";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my $auto;
+		eval {
+			$auto = $key->get_value("AutoSuggest")->get_data();
+			::rptMsg("\tAutoSuggest = ".$auto);
+			$count++ if ($auto eq "true");
+		};
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+	::rptMsg("");
+	my $key_path = "Software\\Microsoft\\Internet Account Manager\\Accounts";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my $prompt;
+		eval {
+			$prompt = $key->get_value("POP3 Prompt for Password")->get_data();
+			::rptMsg("\tPOP3 Prompt for Password = ".$prompt);
+			$count++ if ($prompt eq "true");
+		};
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+	::rptMsg("");
+	if ($count == 5) {
+		::rptMsg("The system may have been infected with the Trojan.Clampi PROT module.");
+	}
+	else {
+		::rptMsg("The system does not appear to have been infected with the Trojan.Clampi");
+		::rptMsg("PROT module.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/clampitm.pl b/thirdparty/rr/plugins/clampitm.pl
new file mode 100644
index 0000000000000000000000000000000000000000..60f21738c684074b9b8257ef249937b0826b001e
--- /dev/null
+++ b/thirdparty/rr/plugins/clampitm.pl
@@ -0,0 +1,78 @@
+#-----------------------------------------------------------
+# clampitm.pl
+# Checks keys/values set by new version of Trojan.Clampi
+#
+# Change history
+#   20100624 - created
+#
+# NOTE: This is purely a test plugin, and based solely on the below
+#       reference.  It has not been tested on any systems that were
+#       known to be infected.
+#
+# References
+#   http://us.trendmicro.com/imperia/md/content/us/trendwatch/researchandanalysis/ilomo_external.pdf
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package clampitm;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100624);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Checks for IOCs for Clampi (per Trend Micro)";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching clampitm v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	
+	my $count = 0;
+	
+	my $key_path = 'Software\\Microsoft\\Internet Explorer\\Settings';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("ClampiTM plugin");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my $tag = 1;
+		my @list = qw/GatesList GID KeyE KeyM PID/;
+		my @vals = $key->get_list_of_values();
+		if (scalar (@vals) > 0) {
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				if (grep(/$name/,@list)) {
+					::rptMsg(sprintf "%-10s %-30s",$name,$v->get_data());
+					$tag = 0;
+				}
+			}
+			if ($tag) {
+				::rptMsg("No Clampi values found.");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/clsid.pl b/thirdparty/rr/plugins/clsid.pl
new file mode 100644
index 0000000000000000000000000000000000000000..1823600295ed2e2dbda5fe40215968feb4e4970e
--- /dev/null
+++ b/thirdparty/rr/plugins/clsid.pl
@@ -0,0 +1,80 @@
+#-----------------------------------------------------------
+# clsid.pl
+# Plugin to extract file association data from the Software hive file
+# Can take considerable time to run; recommend running it via rip.exe
+#
+# History
+#   20100227 - created
+#
+# References
+#   http://msdn.microsoft.com/en-us/library/ms724475%28VS.85%29.aspx
+#
+# copyright 2010, Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package clsid;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100227);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get list of CLSID/registered classes";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	my %clsid;
+	::logMsg("Launching clsid v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Classes\\CLSID";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+#		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+# First step will be to get a list of all of the file extensions
+		my %ext;
+		my @sk = $key->get_list_of_subkeys();
+		if (scalar(@sk) > 0) {
+			foreach my $s (@sk) {
+				
+				my $name = $s->get_name();
+				eval {
+					my $n = $s->get_value("")->get_data();
+					$name .= "  ".$n unless ($n eq "");
+				};
+				
+				push(@{$clsid{$s->get_timestamp()}},$name);
+			}
+			
+			foreach my $t (reverse sort {$a <=> $b} keys %clsid) {
+				::rptMsg(gmtime($t)." Z");
+				foreach my $item (@{$clsid{$t}}) {
+					::rptMsg("  ".$item);
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/cmd_shell.pl b/thirdparty/rr/plugins/cmd_shell.pl
new file mode 100644
index 0000000000000000000000000000000000000000..84e40a7735e64d3579b540ae601b181be8b7a4b3
--- /dev/null
+++ b/thirdparty/rr/plugins/cmd_shell.pl
@@ -0,0 +1,75 @@
+#-----------------------------------------------------------
+# cmd_shell
+# 
+#
+# Change History
+#   20100830 - added "cs" shell command to the path
+#   20080328 - created
+# 
+# References
+#   http://www.microsoft.com/security/portal/Threat/Encyclopedia/Entry.aspx?
+#        Name=TrojanClicker%3AWin32%2FVB.GE
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package cmd_shell;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              version       => 20100830);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Gets shell open cmds for various file types";	
+}
+sub getDescr{}
+sub getRefs {
+	my %refs = ("You Are Unable to Start a Program with an .exe File Extension" =>
+	            "http://support.microsoft.com/kb/310585");
+	return %refs;	
+}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching cmd_shell v.".$VERSION);
+	
+	my @shells = ("exe","cmd","bat","cs","hta","pif");
+	
+	foreach my $sh (@shells) {
+		
+		my $reg = Parse::Win32Registry->new($hive);
+		my $root_key = $reg->get_root_key;
+
+		my $key_path = "Classes\\".$sh."file\\shell\\open\\command";
+		my $key;
+		if ($key = $root_key->get_subkey($key_path)) {
+			::rptMsg("cmd_shell");
+			::rptMsg($key_path);
+			::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+			::rptMsg("");
+			my $val;
+			eval {
+				$val = $key->get_value("")->get_data();
+				::rptMsg("\tCmd: ".$val);
+			};
+			::rptMsg("Error: ".$@) if ($@);
+		
+		}
+		else {
+			::rptMsg($key_path." not found.");
+			::logMsg($key_path." not found.");
+		}
+	}
+	::rptMsg("");
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/codeid.pl b/thirdparty/rr/plugins/codeid.pl
new file mode 100644
index 0000000000000000000000000000000000000000..f3eec03151a3bc6221003658057ab3e876cf19a4
--- /dev/null
+++ b/thirdparty/rr/plugins/codeid.pl
@@ -0,0 +1,75 @@
+#-----------------------------------------------------------
+# codeid
+# Get DefaultLevel value from CodeIdentifiers key
+# 
+#
+# Change History
+#   20100608 - created
+#
+# References
+#   SANS ISC blog - http://isc.sans.edu/diary.html?storyid=8917
+#   CodeIdentifiers key
+#       - http://technet.microsoft.com/en-us/library/bb457006.aspx
+#   SAFER_LEVELID_FULLYTRUSTED value 
+#       - http://msdn.microsoft.com/en-us/library/ms722424%28VS.85%29.aspx
+#         (262144 == Unrestricted)
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package codeid;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100608);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Gets CodeIdentifier DefaultLevel value";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching codeid v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Policies\\Microsoft\\Windows\\Safer\\CodeIdentifiers";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("CodeID");
+		::rptMsg($key_path);
+		my $lastwrite = $key->get_timestamp();
+		::rptMsg("  LastWrite time: ".gmtime($lastwrite)." Z");
+		::rptMsg("");
+		
+		my $level;
+		eval {
+			$level = $key->get_value("DefaultLevel")->get_data();
+			::rptMsg(sprintf "DefaultLevel = 0x%08x",$level);
+		};
+		
+		my $exe;
+		eval {
+			$exe = $key->get_value("ExecutableTypes")->get_data();
+			$exe =~ s/\s/,/g;
+			::rptMsg("ExecutableTypes = ".$exe);
+			
+		};
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/comdlg32.pl b/thirdparty/rr/plugins/comdlg32.pl
new file mode 100644
index 0000000000000000000000000000000000000000..61cda3c1e6b8163122b175417e6776a27a2ad1a3
--- /dev/null
+++ b/thirdparty/rr/plugins/comdlg32.pl
@@ -0,0 +1,145 @@
+#-----------------------------------------------------------
+# comdlg32.pl
+# Plugin for Registry Ripper 
+#
+# Change history
+#   20100402 - updated IAW Chad Tilbury's post to SANS
+#              Forensic Blog
+#   20080324 - created
+#
+# References
+#   Win2000 - http://support.microsoft.com/kb/319958
+#   XP - http://support.microsoft.com/kb/322948/EN-US/
+#		
+# copyright 20100402 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package comdlg32;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100402);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of user's ComDlg32 key";
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching comdlg32 v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	::rptMsg("comdlg32 v.".$VERSION);
+	
+# LastVistedMRU	
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU";
+	my $key;
+	my @vals;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("ComDlg32\\LastVisitedMRU");
+		::rptMsg("**All values printed in MRUList order.");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my %lvmru;
+		my @mrulist;
+		@vals = $key->get_list_of_values();
+		
+		if (scalar(@vals) > 0) {
+# First, read in all of the values and the data
+			foreach my $v (@vals) {
+				$lvmru{$v->get_name()} = $v->get_data();
+			}
+# Then, remove the MRUList value
+			if (exists $lvmru{MRUList}) {
+				::rptMsg("  MRUList = ".$lvmru{MRUList});
+				@mrulist = split(//,$lvmru{MRUList});
+				delete($lvmru{MRUList});
+				foreach my $m (@mrulist) {
+					my ($file,$dir) = split(/\00\00/,$lvmru{$m},2);
+					$file =~ s/\00//g;
+					$dir  =~ s/\00//g;
+					::rptMsg("  ".$m." -> EXE: ".$file);
+					::rptMsg("    -> Last Dir: ".$dir);
+				}
+			}
+			else {
+				::rptMsg($key_path." does not have an MRUList value.");
+			}				
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+	::rptMsg("");
+	
+# OpenSaveMRU	
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\OpenSaveMRU";
+	my $key;
+	my @vals;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("ComDlg32\\OpenSaveMRU");
+		::rptMsg("**All values printed in MRUList order.");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+# First, process OpenSaveMRU key values
+		parseOpenSaveValues($key);
+		::rptMsg("");
+# Now, let's get the subkeys
+		my @sk = $key->get_list_of_subkeys();
+		if (scalar(@sk) > 0) {
+			foreach my $s (@sk) {
+				parseOpenSaveValues($s);
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}	
+
+sub parseOpenSaveValues {
+	my $key = shift;
+	::rptMsg("OpenSaveMRU\\".$key->get_name());
+	::rptMsg("LastWrite Time: ".gmtime($key->get_timestamp())." Z");
+	my %osmru;
+	my @vals = $key->get_list_of_values();
+	if (scalar(@vals) > 0) {
+		map{$osmru{$_->get_name()} = $_->get_data()}(@vals);
+		if (exists $osmru{MRUList}) {
+			::rptMsg("  MRUList = ".$osmru{MRUList});
+			my @mrulist = split(//,$osmru{MRUList});
+			delete($osmru{MRUList});
+			foreach my $m (@mrulist) {
+				::rptMsg("  ".$m." -> ".$osmru{$m});
+			}
+		}
+		else {
+			::rptMsg($key->get_name()." does not have an MRUList value.");
+		}	
+	}
+	else {
+		::rptMsg($key->get_name()." has no values.");
+	}	
+}
+
+
+1;		
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/comdlg32a.pl b/thirdparty/rr/plugins/comdlg32a.pl
new file mode 100644
index 0000000000000000000000000000000000000000..0187b945d53c5ff7b28cbdd9c6aca5d3550f1970
--- /dev/null
+++ b/thirdparty/rr/plugins/comdlg32a.pl
@@ -0,0 +1,225 @@
+#-----------------------------------------------------------
+# comdlg32a.pl
+# Plugin for Registry Ripper 
+#
+# Change history
+#   20100409 - updated to include Vista and above
+#   20100402 - updated IAW Chad Tilbury's post to SANS
+#              Forensic Blog
+#   20080324 - created
+#
+# References
+#   Win2000 - http://support.microsoft.com/kb/319958
+#   XP - http://support.microsoft.com/kb/322948/EN-US/
+#		
+# copyright 20100402 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package comdlg32a;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100409);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of user's ComDlg32 key";
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching comdlg32a v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	::rptMsg("comdlg32 v.".$VERSION);
+	
+# LastVistedMRU	
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32";
+	my $key;
+	my @vals;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		
+		if (scalar @subkeys > 0) {
+			foreach my $s (@subkeys) {
+				parseLastVisitedMRU($s) if ($s->get_name() eq "LastVisitedMRU");
+				parseOpenSaveMRU($s) if ($s->get_name() eq "OpenSaveMRU");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+}	
+
+sub parseLastVisitedMRU {
+	my $key = shift;
+	my %lvmru;
+	my @mrulist;
+	my @vals = $key->get_list_of_values();
+	
+	if (scalar(@vals) > 0) {
+# First, read in all of the values and the data
+		foreach my $v (@vals) {
+			$lvmru{$v->get_name()} = $v->get_data();
+		}
+# Then, remove the MRUList value
+		if (exists $lvmru{MRUList}) {
+			::rptMsg("  MRUList = ".$lvmru{MRUList});
+			@mrulist = split(//,$lvmru{MRUList});
+			delete($lvmru{MRUList});
+			foreach my $m (@mrulist) {
+				my ($file,$dir) = split(/\00\00/,$lvmru{$m},2);
+				$file =~ s/\00//g;
+				$dir  =~ s/\00//g;
+				::rptMsg("  ".$m." -> EXE: ".$file);
+				::rptMsg("    -> Last Dir: ".$dir);
+			}
+		}
+		else {
+			::rptMsg("LastVisitedMRU key does not have an MRUList value.");
+		}				
+	}
+	else {
+		::rptMsg("LastVisitedMRU key has no values.");
+	}	
+	::rptMsg("");
+}
+
+sub parseOpenSaveMRU {
+	my $key = shift;
+	
+	parseOpenSaveValues($key);
+	::rptMsg("");
+# Now, let's get the subkeys
+	my @sk = $key->get_list_of_subkeys();
+	if (scalar(@sk) > 0) {
+		foreach my $s (@sk) {
+			parseOpenSaveValues($s);
+			::rptMsg("");
+		}
+	}
+	else {
+		::rptMsg("OpenSaveMRU key has no subkeys.");
+	}	
+	::rptMsg("");
+}
+
+sub parseOpenSaveValues {
+	my $key = shift;
+	::rptMsg("OpenSaveMRU\\".$key->get_name());
+	::rptMsg("LastWrite Time: ".gmtime($key->get_timestamp())." Z");
+	my %osmru;
+	my @vals = $key->get_list_of_values();
+	if (scalar(@vals) > 0) {
+		map{$osmru{$_->get_name()} = $_->get_data()}(@vals);
+		if (exists $osmru{MRUList}) {
+			::rptMsg("  MRUList = ".$osmru{MRUList});
+			my @mrulist = split(//,$osmru{MRUList});
+			delete($osmru{MRUList});
+			foreach my $m (@mrulist) {
+				::rptMsg("  ".$m." -> ".$osmru{$m});
+			}
+		}
+		else {
+			::rptMsg($key->get_name()." does not have an MRUList value.");
+		}	
+	}
+	else {
+		::rptMsg($key->get_name()." has no values.");
+	}	
+}
+
+sub parseCIDSizeMRU {
+	my $key = shift;
+	my %lvmru;
+	my @mrulist;
+	my @vals = $key->get_list_of_values();
+		
+	if (scalar(@vals) > 0) {
+# First, read in all of the values and the data
+		foreach my $v (@vals) {
+			$lvmru{$v->get_name()} = $v->get_data();
+		}
+# Then, remove the MRUList value
+		if (exists $lvmru{MRUListEx}) {
+			delete($lvmru{MRUListEx});
+			foreach my $m (keys %lvmru) {
+				my $file = parseStr($lvmru{$m});
+				my $str = sprintf "%-4s ".$file,$m;
+				::rptMsg("  ".$str);
+			}
+		}
+		else {
+			::rptMsg($key_path." does not have an MRUList value.");
+		}				
+	}
+	else {
+		::rptMsg($key_path." has no values.");
+	}
+}
+
+
+sub parseLastVisitedPidlMRU {
+	my $key = shift;
+	my %lvmru;
+	my @mrulist;
+	@vals = $key->get_list_of_values();
+	
+	if (scalar(@vals) > 0) {
+# First, read in all of the values and the data
+		foreach my $v (@vals) {
+			$lvmru{$v->get_name()} = $v->get_data();
+		}
+# Then, remove the MRUList value
+		if (exists $lvmru{MRUListEx}) {
+			delete($lvmru{MRUListEx});
+			foreach my $m (keys %lvmru) {
+				my $file = parseStr($lvmru{$m});
+				my $str = sprintf "%-4s ".$file,$m;
+				::rptMsg("  ".$str);
+			}
+		}
+		else {
+			::rptMsg("LastVisitedPidlMRU key does not have an MRUList value.");
+		}				
+	}
+	else {
+		::rptMsg("LastVisitedPidlMRU key has no values.");
+	}	
+}
+
+sub parseStr {
+	my $data = $_[0];
+	my $temp;
+	my $tag = 1;
+	my $ofs = 0;
+	
+	while ($tag) {
+		my $t = substr($data,$ofs,2);
+		if (unpack("v",$t) == 0x00) {
+			$tag = 0;
+		}
+		else {
+			$temp .= $t;
+			$ofs += 2;
+		}
+	}
+	$temp =~ s/\00//g;
+	return $temp;
+}
+
+1;		
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/compdesc.pl b/thirdparty/rr/plugins/compdesc.pl
new file mode 100644
index 0000000000000000000000000000000000000000..fc1f2920891e1517b0d02bc1263ea9539d4a3d39
--- /dev/null
+++ b/thirdparty/rr/plugins/compdesc.pl
@@ -0,0 +1,65 @@
+#-----------------------------------------------------------
+# compdesc.pl
+# Plugin for Registry Ripper,
+# ComputerDescriptions key parser
+#
+# Change history
+#
+#
+# References
+#
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package compdesc;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of user's ComputerDescriptions key";
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching compdesc v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComputerDescriptions';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("ComputerDescriptions");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				::rptMsg("  ".$v->get_name()."   ".$v->get_data());
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/compname.pl b/thirdparty/rr/plugins/compname.pl
new file mode 100644
index 0000000000000000000000000000000000000000..b07c44183c6595f602539a479c7328a4eea2b739
--- /dev/null
+++ b/thirdparty/rr/plugins/compname.pl
@@ -0,0 +1,75 @@
+#-----------------------------------------------------------
+# compname.pl
+# Plugin for Registry Ripper; Access System hive file to get the
+# computername
+# 
+# Change history
+#   20090727 - added Hostname
+#
+# References
+#   http://support.microsoft.com/kb/314053/
+# 
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package compname;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20090727);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets ComputerName and Hostname values from System hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching compname v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my ($current,$ccs);
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+		my $cn_path = $ccs."\\Control\\ComputerName\\ComputerName";
+		my $cn;
+		if ($cn = $root_key->get_subkey($cn_path)) {
+			my $name = $cn->get_value("ComputerName")->get_data();
+			::rptMsg("ComputerName    = ".$name);
+		}
+		else {
+			::rptMsg($cn_path." not found.");
+			::logMsg($cn_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+	my $hostname;
+	eval {
+		my $host_path = $ccs."\\Services\\Tcpip\\Parameters";
+		$hostname = $root_key->get_subkey($host_path)->get_value("Hostname")->get_data();
+		::rptMsg("TCP/IP Hostname = ".$hostname);
+	};
+	
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/controlpanel.pl b/thirdparty/rr/plugins/controlpanel.pl
new file mode 100644
index 0000000000000000000000000000000000000000..67e06a906ab78e7f6463d4875acc5ec779b91962
--- /dev/null
+++ b/thirdparty/rr/plugins/controlpanel.pl
@@ -0,0 +1,64 @@
+#-----------------------------------------------------------
+# controlpanel.pl
+# Vista ControlPanel key seems to contain some interesting info about the
+# user's activities...
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package controlpanel;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 64,  
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080428);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Look for RecentTask* values in ControlPanel key (Vista)";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching controlpanel v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		::rptMsg("Analysis Tip: The RecentTask* entries appear to only be populated through the");
+		::rptMsg("choices in the Control Panel Home view (in Vista).  As each new choice is");
+		::rptMsg("selected, the most recent choice is added as RecentTask1, and each ");
+		::rptMsg("RecentTask* entry is incremented and pushed down in the stack.");
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $str = sprintf "%-15s %-45s",$v->get_name(),$v->get_data();
+				::rptMsg($str);
+			}
+			::rptMsg("");
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/cpldontload.pl b/thirdparty/rr/plugins/cpldontload.pl
new file mode 100644
index 0000000000000000000000000000000000000000..620419ef9b83f3be5c61c8cbce235d6b597e28dd
--- /dev/null
+++ b/thirdparty/rr/plugins/cpldontload.pl
@@ -0,0 +1,72 @@
+#-----------------------------------------------------------
+# cpldontload.pl
+# Check contents of user's Control Panel\don't load key
+#
+# Change history
+#   20100116 - created
+#
+# References
+#   W32.Nekat - http://www.symantec.com/security_response/
+#               writeup.jsp?docid=2008-011419-0705-99&tabid=2
+#   http://www.2-viruses.com/remove-antispywarexp2009
+#
+# Notes: Some malware appears to hide various Control Panel applets
+#        using this means.  If some sort of malware/spyware is thought
+#        to be on the system, check the settings and note the key 
+#        LastWrite time.
+#
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package cpldontload;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100116);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of user's Control Panel don't load key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching cpldontload v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Control Panel\\don\'t load";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my @vals = $key->get_list_of_values();
+		if (scalar @vals > 0) {
+			foreach my $v (@vals) {
+				my $str = sprintf "%-20s %-5s",$v->get_name(),$v->get_data();
+				::rptMsg($str);
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/crashcontrol.pl b/thirdparty/rr/plugins/crashcontrol.pl
new file mode 100644
index 0000000000000000000000000000000000000000..61cc30b815efa77b47ddf0066a475203a3fa219a
--- /dev/null
+++ b/thirdparty/rr/plugins/crashcontrol.pl
@@ -0,0 +1,93 @@
+#-----------------------------------------------------------
+# crashcontrol.pl
+#
+# Ref: 
+#   http://support.microsoft.com/kb/254649
+#   http://support.microsoft.com/kb/274598
+#
+# copyright 2008-2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package crashcontrol;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20081212);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get crash control information";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+my %dumpenabled = (0 => "None",
+                   1 => "Complete memory dump",
+                   2 => "Kernel memory dump",
+                   3 => "Small (64kb) memory dump");
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching crashcontrol v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		
+		my $cc_path = "ControlSet00".$current."\\Control\\CrashControl";
+		my $cc;
+		
+		if ($cc = $root_key->get_subkey($cc_path)) {
+			
+			eval {
+				my $cde = $cc->get_value("CrashDumpEnabled")->get_data();
+				::rptMsg("CrashDumpEnabled = ".$cde." [".$dumpenabled{$cde}."]");
+			};
+			
+			eval {
+				my $df = $cc->get_value("DumpFile")->get_data();
+				::rptMsg("DumpFile         = ".$df);
+			};
+			
+			eval {
+				my $mini = $cc->get_value("MinidumpDir")->get_data();
+				::rptMsg("MinidumpDir      = ".$mini);
+			};
+			
+			eval {
+				my $logevt = $cc->get_value("LogEvent")->get_data();
+				::rptMsg("LogEvent         = ".$logevt);
+				::rptMsg("  Logs an event to the System Event Log (event ID = 1001, source = Save Dump)") if ($logevt == 1);
+			};
+			
+			eval {
+				my $sendalert = $cc->get_value("SendAlert")->get_data();
+				::rptMsg("SendAlert        = ".$sendalert);
+				::rptMsg("  Sends a \'net send\' pop-up if a crash occurs") if ($sendalert == 1);
+			};
+			
+			
+		}	
+		else {
+			::rptMsg($cc_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
diff --git a/thirdparty/rr/plugins/crashdump.pl b/thirdparty/rr/plugins/crashdump.pl
new file mode 100644
index 0000000000000000000000000000000000000000..eea639e8271ebcc42850f2abf191162ab8a9ebe5
--- /dev/null
+++ b/thirdparty/rr/plugins/crashdump.pl
@@ -0,0 +1,115 @@
+#-----------------------------------------------------------
+# crashdump.pl
+# Author: Don C. Weber
+# Plugin for Registry Ripper; Access System hive file to get the
+# crashdump settings from System hive
+# 
+# Change history
+#
+#
+# References
+#  Overview of memory dump file options for Windows Server 2003, Windows XP, and Windows 2000: http://support.microsoft.com/kb/254649/
+# 
+# Author: Don C. Weber, http://www.cutawaysecurity.com/blog/cutaway-security
+#-----------------------------------------------------------
+package crashdump;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20081219);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets crashdump settings from System hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching crashdump v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+		my $win_path = $ccs."\\Control\\CrashControl";
+		my $win;
+		if ($win = $root_key->get_subkey($win_path)) {
+			::rptMsg("CrashControl Configuration");
+			::rptMsg($win_path);
+			::rptMsg("LastWrite Time ".gmtime($win->get_timestamp())." (UTC)");
+		}
+		else {
+			::rptMsg($win_path." not found.");
+		}
+		
+		my %vals = getKeyValues($win);
+		if (scalar(keys %vals) > 0) {
+			foreach my $v (keys %vals) {
+				if ($v eq "CrashDumpEnabled"){
+					if ($vals{$v} == 0x00){
+						::rptMsg("\t".$v." -> None");
+					} elsif ($vals{$v} == 0x01){
+						::rptMsg("\t".$v." -> Complete memory dump");
+					} elsif ($vals{$v} == 0x02){
+						::rptMsg("\t".$v." -> Kernel memory dump");
+					} elsif ($vals{$v} == 0x03){
+						::rptMsg("\t".$v." -> Small memory dump (64KB)");
+					} else{
+						::rptMsg($v." has no value.");
+					}
+				}else{
+					if (($v eq "MinidumpDir") || ($v eq "DumpFile")){
+						::rptMsg("\t".$v." location ".$vals{$v});
+					} else{
+						($vals{$v}) ? ::rptMsg("\t".$v." is Enabled") : ::rptMsg("\t".$v." is Disabled");
+					}
+				}
+			}
+		}
+		else {
+#			::rptMsg($key_path." has no values.");
+		}
+		::rptMsg("");
+		::rptMsg("Analysis Tips: For crash dump information and tools check http://support.microsoft.com/kb/254649/");
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+sub getKeyValues {
+	my $key = shift;
+	my %vals;
+	
+	my @vk = $key->get_list_of_values();
+	if (scalar(@vk) > 0) {
+		foreach my $v (@vk) {
+			next if ($v->get_name() eq "" && $v->get_data() eq "");
+			$vals{$v->get_name()} = $v->get_data();
+		}
+	}
+	else {
+	
+	}
+	return %vals;
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/ctrlpnl.pl b/thirdparty/rr/plugins/ctrlpnl.pl
new file mode 100644
index 0000000000000000000000000000000000000000..13ce7bf906b6722e23a7955ab5329d34998efcc1
--- /dev/null
+++ b/thirdparty/rr/plugins/ctrlpnl.pl
@@ -0,0 +1,143 @@
+#-----------------------------------------------------------
+# ctrlpnl.pl
+# Get Control Panel info from the Software hive
+#
+# Change history:
+#   20100116 - created
+#
+# References:
+#   http://support.microsoft.com/kb/292463
+#   http://learning.infocollections.com/ebook%202/Computer/
+#          Operating%20Systems/Windows/Windows.XP.Hacks/
+#          0596005113_winxphks-chp-2-sect-3.html
+#   http://msdn.microsoft.com/en-us/library/cc144195%28VS.85%29.aspx
+#
+# Notes: 
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package ctrlpnl;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100116);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get Control Panel info from Software hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+my %comp;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching ctrlpnl v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows\\CurrentVersion\\Control Panel";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("");
+		::rptMsg($key_path);
+		::rptMsg("");
+
+# Cpls section
+		if (my $cpl = $key->get_subkey("Cpls")) {
+			my @vals = $cpl->get_list_of_values();
+			if (scalar @vals > 0) {
+				::rptMsg("Cpls key");
+				foreach my $v (@vals) {
+					my $str = sprintf "%-10s %-50s",$v->get_name(),$v->get_data();
+					::rptMsg($str);
+				}
+				::rptMsg("");
+			}
+			else {
+				::rptMsg("Cpls key has no values.");
+			}
+		}
+		else {
+			::rptMsg("Cpls key not found.");
+		}
+	
+# don't load section
+# The 'don't load' key prevents applets from being loaded
+# Be sure to check the user's don't load key, as well
+	if (my $cpl = $key->get_subkey("don't load")) {
+			my @vals = $cpl->get_list_of_values();
+			if (scalar @vals > 0) {
+				::rptMsg("don't load key");
+				foreach my $v (@vals) {
+					::rptMsg($v->get_name());
+				}
+				::rptMsg("");
+			}
+			else {
+				::rptMsg("don't load key has no values.");
+			}
+		}
+		else {
+			::rptMsg("don't load key not found.");
+		}
+
+# Extended Properties section		
+		if (my $ext = $key->get_subkey("Extended Properties")) {
+			my @sk = $ext->get_list_of_subkeys();
+			if (scalar @sk > 0) {
+				foreach my $s (@sk) {
+					my @vals = $s->get_list_of_values();
+					if (scalar @vals > 0) {
+						::rptMsg($s->get_name()." [".gmtime($s->get_timestamp)." UTC]");
+
+# Ref: http://support.microsoft.com/kb/292463						
+						my %cat = (0x00000000 => "Other Control Panel Options",
+                       0x00000001 => "Appearance and Themes",
+                       0x00000002 => "Printers and Other Hardware",
+                       0x00000003 => "Network and Internet Connections",
+                       0x00000004 => "Sounds, Speech, and Audio Devices",
+                       0x00000005 => "Performance and Maintenance",
+                       0x00000006 => "Date, Time, Language, and Regional Options",
+                       0x00000007 => "Accessibility Options",
+                       0xFFFFFFFF => "No Category");
+            my %prop;    
+						foreach my $v (@vals) {
+							push(@{$prop{$v->get_data()}},$v->get_name());
+						}
+						
+						foreach my $t (sort {$a <=> $b} keys %prop) {
+							(exists $cat{$t}) ?	(::rptMsg($cat{$t})) : (::rptMsg("Category ".$t));
+							foreach my $i (@{$prop{$t}}) {
+								::rptMsg("  ".$i);
+							}
+							::rptMsg(""); 
+						}
+					}
+				}
+				::rptMsg("");
+			}
+			else {
+				::rptMsg("Extended Properties key has no subkeys.");
+			}
+		}
+		else {
+			::rptMsg("Extended Properties key not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/ddm.pl b/thirdparty/rr/plugins/ddm.pl
new file mode 100644
index 0000000000000000000000000000000000000000..e66fb2697f136bc1d1e72d62587a72fbb64d5f70
--- /dev/null
+++ b/thirdparty/rr/plugins/ddm.pl
@@ -0,0 +1,82 @@
+#-----------------------------------------------------------
+# ddm.pl
+#
+# History:
+#   20081129 - created
+#
+# Note - Not really sure what this is for or could be used for, other
+#        than to show devices that had been connected to the system
+#
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package ddm;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20081129);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get DDM data from Control Subkey";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching ddm v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+
+		my $key_path = $ccs."\\Control\\DDM";
+		my $key;
+		my %dev;
+		if ($key = $root_key->get_subkey($key_path)) {
+			my @subkeys = $key->get_list_of_subkeys();
+			if (scalar (@subkeys) > 0) {
+				foreach my $s (@subkeys) {
+					my $name = $s->get_name();
+					my $tag = (split(/\./,$name,2))[1];
+					$dev{$tag}{timestamp} = $s->get_timestamp();
+					eval {
+						$dev{$tag}{make} = $s->get_value("MakeName")->get_data();
+						$dev{$tag}{model} = $s->get_value("ModelName")->get_data();
+					};
+				}
+				foreach my $d (sort keys %dev) {
+					::rptMsg(gmtime($dev{$d}{timestamp})."Z  Device\.".$d."  ".$dev{$d}{make}." ".$dev{$d}{model});
+				}
+			}
+			else {
+				::rptMsg($key_path." has no subkeys.");
+			}
+		}
+		else {
+			::rptMsg($key_path." not found.");
+#			::logMsg($key_path." not found.");
+		}
+	}
+	else {
+		::logMsg("Current value not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/defbrowser.pl b/thirdparty/rr/plugins/defbrowser.pl
new file mode 100644
index 0000000000000000000000000000000000000000..ae7055aba152e5a6eeb6c88560762c357d9d577f
--- /dev/null
+++ b/thirdparty/rr/plugins/defbrowser.pl
@@ -0,0 +1,78 @@
+#-----------------------------------------------------------
+# defbrowser.pl
+# Get default browser information - check #1 can apply to HKLM
+# as well as to HKCU
+#
+# Change History: 
+#   20091116 - Added Check #1
+#   20081105 - created
+# 
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package defbrowser;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20091116);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Gets default browser setting from HKLM";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching defbrowser v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Clients\\StartMenuInternet";
+	if (my $key = $root_key->get_subkey($key_path)) {
+		::rptMsg("Default Browser Check #1");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my $browser = $key->get_value("")->get_data();
+		::rptMsg("Default Browser : ".$browser);
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+
+	::rptMsg("");
+
+	my $key_path = "Classes\\HTTP\\shell\\open\\command";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("Default Browser Check #2");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my $browser;
+		eval {
+			$browser = $key->get_value("")->get_data();
+		};
+		if ($@) {
+			::rptMsg("Error locating default browser setting.");
+		}
+		else {
+			::rptMsg("Default Browser = ".$browser);
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/devclass.pl b/thirdparty/rr/plugins/devclass.pl
new file mode 100644
index 0000000000000000000000000000000000000000..b6a57fff2f46c234388e6c8ad44637efd1f7df5f
--- /dev/null
+++ b/thirdparty/rr/plugins/devclass.pl
@@ -0,0 +1,125 @@
+#-----------------------------------------------------------
+# devclass
+# Get USB device info from the DeviceClasses keys in the System
+# hive (Disks and Volumes GUIDs)
+#
+# Change History:
+#   20100901 - spelling error in output corrected
+#   20080331 - created
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package devclass;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100901);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get USB device info from the DeviceClasses keys in the System hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching devclass v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ 	my $current;
+ 	my $ccs;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+	}
+	else {
+		::logMsg("Could not find ".$key_path);
+		return
+	}
+# Get devices from the Disk GUID
+	my $key_path = $ccs."\\Control\\DeviceClasses\\{53f56307-b6bf-11d0-94f2-00a0c91efb8b}";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("DevClasses - Disks");
+		::rptMsg($key_path);
+		::rptMsg("");
+		my %disks;
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				my $name = $s->get_name();
+				next unless (grep(/USBSTOR/,$name));
+				my $lastwrite = $s->get_timestamp();
+				my ($dev, $serial) = (split(/#/,$name))[4,5];
+				push(@{$disks{$lastwrite}},$dev.",".$serial);
+			}
+			
+			foreach my $t (reverse sort {$a <=> $b} keys %disks) {
+				::rptMsg(gmtime($t)." (UTC)");
+				foreach my $item (@{$disks{$t}}) {
+					::rptMsg("\t$item");
+				}
+			}
+			
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	::rptMsg("");
+# Get devices from the Volume GUID
+	my $key_path = $ccs."\\Control\\DeviceClasses\\{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("DevClasses - Volumes");
+		::rptMsg($key_path);
+		::rptMsg("");
+		my %vols;
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				my $name = $s->get_name();
+				next unless (grep(/RemovableMedia/,$name));
+				my $lastwrite = $s->get_timestamp();
+				my $ppi = (split(/#/,$name))[5];
+				push(@{$vols{$lastwrite}},$ppi);
+			}
+			
+			foreach my $t (reverse sort {$a <=> $b} keys %vols) {
+				::rptMsg(gmtime($t)." (UTC)");
+				foreach my $item (@{$vols{$t}}) {
+					::rptMsg("\tParentIdPrefix: ".$item);
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/dfrg.pl b/thirdparty/rr/plugins/dfrg.pl
new file mode 100644
index 0000000000000000000000000000000000000000..29ac3b80ecb54fddd37b3fe37652238853e14c82
--- /dev/null
+++ b/thirdparty/rr/plugins/dfrg.pl
@@ -0,0 +1,63 @@
+#-----------------------------------------------------------
+# dfrg.pl
+# Gets contents of Dfrg\BootOptimizeFunction key
+#
+# Change history:
+#   20110321 - created
+#
+# References
+#   http://technet.microsoft.com/en-us/library/cc784391%28WS.10%29.aspx
+#
+# copyright 2011 Quantum Analytics Research, LLC (keydet89@yahoo.com)
+#-----------------------------------------------------------
+package dfrg;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20110321);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Gets content of Dfrg BootOptim. key";	
+}
+sub getDescr{}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching dfrg v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Dfrg\\BootOptimizeFunction";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("Dfrg");
+		::rptMsg($key_path);
+		::rptMsg("");
+		
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				::rptMsg(sprintf "%-20s %-20s",$v->get_name(),$v->get_data());
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/disablelastaccess.pl b/thirdparty/rr/plugins/disablelastaccess.pl
new file mode 100644
index 0000000000000000000000000000000000000000..e064521726e80b00bd43430df1d28825bea1ac94
--- /dev/null
+++ b/thirdparty/rr/plugins/disablelastaccess.pl
@@ -0,0 +1,73 @@
+#-----------------------------------------------------------
+# disablelastaccess.pl
+# 
+# References:
+#    http://support.microsoft.com/kb/555041
+#    http://support.microsoft.com/kb/894372
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package disablelastaccess;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090118);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get NTFSDisableLastAccessUpdate value";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching disablelastaccess v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ my $current;
+	my $key_path = 'Select';
+	my $key;
+	my $ccs;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+	}
+
+	my $key_path = $ccs."\\Control\\FileSystem";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("NtfsDisableLastAccessUpdate");
+		::rptMsg($key_path);
+		my @vals = $key->get_list_of_values();
+		my $found = 0;
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				if ($v->get_name() eq "NtfsDisableLastAccessUpdate") {
+					::rptMsg("NtfsDisableLastAccessUpdate = ".$v->get_data());
+					$found = 1;
+				}
+			}
+			::rptMsg("NtfsDisableLastAccessUpdate value not found.") if ($found == 0);
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/dllsearch.pl b/thirdparty/rr/plugins/dllsearch.pl
new file mode 100644
index 0000000000000000000000000000000000000000..767042a8ec3c32ea7fcf4ba4b3ad242714e86014
--- /dev/null
+++ b/thirdparty/rr/plugins/dllsearch.pl
@@ -0,0 +1,69 @@
+#-----------------------------------------------------------
+# dllsearch.pl
+#
+# References: 
+#  http://support.microsoft.com/kb/2264107
+#
+# Change History:
+#  20100824: created
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package dllsearch;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100824);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get crash control information";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching dllsearch v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		
+		my $cc_path = "ControlSet00".$current."\\Control\\Session Manager";
+		my $cc;
+		if ($cc = $root_key->get_subkey($cc_path)) {
+			::rptMsg("dllsearch v.".$VERSION);
+			::rptMsg("");
+			my $found = 1;
+			eval {
+				my $cde = $cc->get_value("CWDIllegalInDllSearch")->get_data();
+				$found = 0;
+				::rptMsg(sprintf "CWDIllegalInDllSearch = 0x%x",$cde);
+			};
+			::rptMsg("CWDIllegalInDllSearch value not found.") if ($found);
+		}	
+		else {
+			::rptMsg($cc_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
diff --git a/thirdparty/rr/plugins/domains.pl b/thirdparty/rr/plugins/domains.pl
new file mode 100644
index 0000000000000000000000000000000000000000..633ad87cfd68705d005d748628fd01961dc11874
--- /dev/null
+++ b/thirdparty/rr/plugins/domains.pl
@@ -0,0 +1,74 @@
+#-----------------------------------------------------------
+# domains.pl
+#  
+#
+# Change history
+#		 20100116 - Created
+#
+# References
+#    http://support.microsoft.com/kb/919748
+#    http://support.microsoft.com/kb/922704
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package domains;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100116);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents Internet Settings\\ZoneMap\\Domains key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching domains v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path."\\Domains")) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) { 
+				::rptMsg($s->get_name()." [".gmtime($s->get_timestamp())." (UTC)]");
+				
+				my @vals = $s->get_list_of_values();
+				if (scalar @vals > 0) {
+					foreach my $v (@vals) {
+						::rptMsg("  ".$v->get_name()." -> ".$v->get_data);
+					}
+				}
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/drwatson.pl b/thirdparty/rr/plugins/drwatson.pl
new file mode 100644
index 0000000000000000000000000000000000000000..0360c33fb35de97916aef72bea07952055cd3641
--- /dev/null
+++ b/thirdparty/rr/plugins/drwatson.pl
@@ -0,0 +1,77 @@
+#-----------------------------------------------------------
+# drwatson.pl
+# Author: Don C. Weber
+# Plugin for Registry Ripper; Access Software hive file to get the
+# Dr. Watson settings from Software hive
+# 
+# Change history
+#
+#
+# References
+#  Dr Watson: http://www.windowsnetworking.com/kbase/WindowsTips/Windows2000/RegistryTips/RegistryTools/DrWatson.html
+# 
+# Author: Don C. Weber, http://www.cutawaysecurity.com/blog/cutaway-security
+#-----------------------------------------------------------
+package drwatson;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20081219);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets Dr. Watson settings from Software hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching drwatson v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\AeDebug";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		($key->get_value('Auto') == 0x0) ? ::rptMsg("Debugging is Disabled") : ::rptMsg("Debugging is Enabled");
+		eval {
+			::rptMsg("Debugger: ".$key->get_value('Debugger')->get_data());
+		};
+			
+	} else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+		
+	::rptMsg("");
+	my $key_path = "Microsoft\\DrWatson";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		($key->get_value('LogFilePath')) ? ::rptMsg("DrWatson LogFile Path location: ".$key->get_value('LogFilePath')->get_data()) : ::rptMsg("DrWatson LogFile Path location: %SystemRoot%\\Documents and Settings\\All Users\\Documents\\DrWatson");
+		($key->get_value('CreateCrashDump') == 0x0) ? ::rptMsg("CreateCrashDump is Disabled") : ::rptMsg("CreateCrashDump is Enabled");
+		($key->get_value('CrashDumpFile')) ? ::rptMsg("Crash Dump Path and Name: ".$key->get_value('CrashDumpFile')->get_data()) : ::rptMsg("CrashDumpFile is not set");
+		($key->get_value('AppendToLogFile') == 0x0) ? ::rptMsg("AppendToLogFile is set to create a new file each time") : ::rptMsg("AppendToLogFile is set to append");
+			
+	} else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+	::rptMsg("");
+	::rptMsg("Analysis Tips: For Dr. Watson settings information check: http://www.windowsnetworking.com/kbase/WindowsTips/Windows2000/RegistryTips/RegistryTools/DrWatson.html");
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/esent.pl b/thirdparty/rr/plugins/esent.pl
new file mode 100644
index 0000000000000000000000000000000000000000..4ae7cd21b50eeb02b949e46d7aaf69bb880929e6
--- /dev/null
+++ b/thirdparty/rr/plugins/esent.pl
@@ -0,0 +1,78 @@
+#-----------------------------------------------------------
+# esent
+# Get contents of Esent\Process key from Software hive
+# 
+# Note: Not sure why I wrote this one; just thought it might come
+#       in handy as info about this key is developed.
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package esent;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              version       => 20101202);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get ESENT\\Process key contents";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching esent v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\ESENT\\Process";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+#		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my @sk = $key->get_list_of_subkeys();
+		
+		if (scalar(@sk) > 0) {
+			my %esent;
+			
+			foreach my $s (@sk) {
+				my $sk = $s->get_subkey("DEBUG");
+#				my $lw = $s->get_timestamp();
+				my $lw = $sk->get_timestamp();
+
+				my $name = $s->get_name();
+				
+				push(@{$esent{$lw}},$name);
+			}
+			
+			foreach my $t (reverse sort {$a <=> $b} keys %esent) {
+				::rptMsg(gmtime($t)." (UTC)");
+				foreach my $item (@{$esent{$t}}) {
+					::rptMsg("  $item");
+				}
+			}
+			
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/eventlog.pl b/thirdparty/rr/plugins/eventlog.pl
new file mode 100644
index 0000000000000000000000000000000000000000..a51ca91282c548190f94c535cc567d8f0d5ecedb
--- /dev/null
+++ b/thirdparty/rr/plugins/eventlog.pl
@@ -0,0 +1,156 @@
+#-----------------------------------------------------------
+# eventlog.pl
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package eventlog;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090112);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get EventLog configuration info";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching eventlog v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		
+		my $evt_path = "ControlSet00".$current."\\Services\\Eventlog";
+		my $evt;
+		if ($evt = $root_key->get_subkey($evt_path)) {
+			::rptMsg("");
+			my @subkeys = $evt->get_list_of_subkeys();
+			if (scalar (@subkeys) > 0) {
+				foreach my $s (@subkeys) {
+					my $logname = $s->get_name();
+					::rptMsg($logname." \\ ".scalar gmtime($s->get_timestamp())."Z");
+					eval {
+						my $file = $s->get_value("File")->get_data();
+						::rptMsg("  File               = ".$file);
+					};
+					
+					eval {
+						my $display = $s->get_value("DisplayNameFile")->get_data();
+						::rptMsg("  DisplayNameFile    = ".$display);
+					};
+					
+					eval {
+						my $max = $s->get_value("MaxSize")->get_data();
+						::rptMsg("  MaxSize            = ".processSize($max));
+					};
+					
+					eval {
+						my $ret = $s->get_value("Retention")->get_data();
+						::rptMsg("  Retention          = ".processRetention($ret));
+					};
+
+# AutoBackupLogFiles; http://support.microsoft.com/kb/312571/					
+					eval {
+						my $auto = $s->get_value("AutoBackupLogFiles")->get_data();
+						::rptMsg("  AutoBackupLogFiles = ".$auto);
+					};
+
+# Check WarningLevel value on Security EventLog; http://support.microsoft.com/kb/945463
+					eval {
+						if ($logname eq "Security") {
+							my $wl = $s->get_value("WarningLevel")->get_data();
+							::rptMsg("  WarningLevel       = ".$wl);
+						}
+					};
+					
+					::rptMsg("");
+				}
+				
+			}
+			else {
+				::rptMsg($evt_path." has no subkeys.");
+			}
+		}
+		else {
+			::rptMsg($evt_path." not found.");
+			::logMsg($evt_path." not found.");
+		}	
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
+
+sub processSize {
+	my $sz = shift;
+	
+	my $kb = 1024;
+	my $mb = $kb * 1024;
+	my $gb = $mb * 1024;
+	
+	if ($sz > $gb) {
+		my $d = $sz/$gb;
+		my $l = length((split(/\./,$d,2))[0]) + 2;
+		return sprintf "%$l.2fGB",$d;
+	}
+	elsif ($sz > $mb) {
+		my $d = $sz/$mb;
+		my $l = length((split(/\./,$d,2))[0]) + 2;
+		return sprintf "%$l.2fMB",$d;
+	}
+	elsif ($sz > $kb) {
+		my $d = $sz/$kb;
+		my $l = length((split(/\./,$d,2))[0]) + 2;
+		return sprintf "%$l.2fKB",$d;
+	}
+	else {return $sz."B"};
+}
+
+sub processRetention {
+# Retention maintained in seconds
+# http://www.microsoft.com/technet/prodtechnol/windows2000serv/reskit/
+#        regentry/30709.mspx?mfr=true
+	my $ret = shift;
+	
+	my $min = 60;
+	my $hr  = $min * 60;
+	my $day = $hr * 24;
+	
+	if ($ret > $day) {
+		my $d = $ret/$day;
+		my $l = length((split(/\./,$d,2))[0]) + 2;
+		return sprintf "%$l.2f days",$d; 
+	}
+	elsif ($ret > $hr) {
+		my $d = $ret/$hr;
+		my $l = length((split(/\./,$d,2))[0]) + 2;
+		return sprintf "%$l.2f hr",$d;
+	}
+	elsif ($ret > $min) {
+		my $d = $ret/$min;
+		my $l = length((split(/\./,$d,2))[0]) + 2;
+		return sprintf "%$l.2f min",$d;
+	}
+	else {return $ret." sec"};
+}
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/eventlogs.pl b/thirdparty/rr/plugins/eventlogs.pl
new file mode 100644
index 0000000000000000000000000000000000000000..d7557218c2f51f823fecf6099f336cffc5cfcde7
--- /dev/null
+++ b/thirdparty/rr/plugins/eventlogs.pl
@@ -0,0 +1,98 @@
+#-----------------------------------------------------------
+# eventlogs.pl
+# Author: Don C. Weber
+# Plugin for Registry Ripper; Access System hive file to get the
+# Event Log settings from System hive
+# 
+# Change history
+#
+#
+# References
+#  Eventlog Key: http://msdn.microsoft.com/en-us/library/aa363648(VS.85).aspx
+# 
+# Author: Don C. Weber, http://www.cutawaysecurity.com/blog/cutaway-security
+#-----------------------------------------------------------
+package eventlogs;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20081219);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets Event Log settings from System hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching eventlogs v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+		my $win_path = $ccs."\\Services\\Eventlog";
+		my $win;
+		if ($win = $root_key->get_subkey($win_path)) {
+			::rptMsg("EventLog Configuration");
+			::rptMsg($win_path);
+			::rptMsg("LastWrite Time ".gmtime($win->get_timestamp())." (UTC)");
+			my $cn;
+			if ($cn = $win->get_value("ComputerName")->get_data()) {
+				::rptMsg("ComputerName = ".$cn);				
+			}
+			else {
+				::rptMsg("ComputerName value not found.");
+			}
+		}
+		else {
+			::rptMsg($win_path." not found.");
+		}
+
+#		Cycle through each type of log
+		my $logname;
+		my $evpath;
+		my $evlog;
+		my @list_logs = $win->get_list_of_subkeys();
+		foreach $logname (@list_logs){
+			::rptMsg("");
+			$evpath = $win_path."\\".$logname->get_name();
+			if ($evlog = $root_key->get_subkey($evpath)) {
+				::rptMsg("	".$logname->get_name()." EventLog");
+				::rptMsg("	".$evpath);
+				::rptMsg("	LastWrite Time ".gmtime($evlog->get_timestamp())." (UTC)");
+				::rptMsg("	Configuration Settings");
+				::rptMsg("		Log location: ".$evlog->get_value('File')->get_data());
+				::rptMsg("		Log Size: ".$evlog->get_value('MaxSize')->get_data()." Bytes");
+				($evlog->get_value('AutoBackupLogFiles') == 0x0) ? ::rptMsg("		AutoBackupLogFiles is Disabled") : ::rptMsg("		AutoBackupLogFiles is Enabled")
+			}
+			else {
+				::rptMsg($logname->get_name()." Event Log not found.");
+			}				
+		}		
+		::rptMsg("");
+		::rptMsg("Analysis Tips: For Event Log settings information check: http://msdn.microsoft.com/en-us/library/aa363648(VS.85).aspx");
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/fileexts.pl b/thirdparty/rr/plugins/fileexts.pl
new file mode 100644
index 0000000000000000000000000000000000000000..5bd04db82565a5fb3e66c8b256f2c1177d7e42d1
--- /dev/null
+++ b/thirdparty/rr/plugins/fileexts.pl
@@ -0,0 +1,73 @@
+#-----------------------------------------------------------
+# fileexts.pl
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package fileexts;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080818);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get user FileExts values";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching fileexts v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("fileexts");
+		::rptMsg($key_path);
+		::rptMsg("");
+		
+		my @sk = $key->get_list_of_subkeys();
+		if (scalar(@sk) > 0) {
+			foreach my $s (@sk) {
+				my $name = $s->get_name();
+				next unless ($name =~ m/^\.\w+/);
+				
+				eval {
+					my $data = $s->get_subkey("OpenWithList")->get_value("MRUList")->get_data();
+					if ($data =~ m/^\w/) {
+						::rptMsg("File Extension: ".$name);
+						::rptMsg("LastWrite: ".gmtime($s->get_subkey("OpenWithList")->get_timestamp()));
+						::rptMsg("MRUList: ".$data);
+						my @list = split(//,$data);
+						foreach my $l (@list) {
+							my $valdata = $s->get_subkey("OpenWithList")->get_value($l)->get_data();
+							::rptMsg("  ".$l." => ".$valdata);
+						}
+						::rptMsg("");
+					}
+				};
+			}
+		}
+		else {
+			::rptMsg($key_path." does not have subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/findexes.pl b/thirdparty/rr/plugins/findexes.pl
new file mode 100644
index 0000000000000000000000000000000000000000..ee2f027b35286336d93bf314c85dfa31a137329e
--- /dev/null
+++ b/thirdparty/rr/plugins/findexes.pl
@@ -0,0 +1,95 @@
+#! c:\perl\bin\perl.exe
+#-----------------------------------------------------------
+# findexes.pl
+# Plugin for RegRipper; traverses through a Registry hive,
+# looking for values with binary data types, and checks to see
+# if they start with "MZ"; if so, records the value path, key 
+# LastWrite time, and length of the data
+#
+# Change history
+#    20090728 - Created
+# 
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package findexes;
+use strict;
+
+my %config = (hive          => "All",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20090728);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Scans a hive file looking for binary value data that contains MZ";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+my %vals;
+my $bin_count = 0;
+my $exe_count = 0;
+
+sub pluginmain {
+	my $class = shift;
+	my $file = shift;
+	my $reg = Parse::Win32Registry->new($file);
+	my $root_key = $reg->get_root_key;
+	::logMsg("Launching findexes v.".$VERSION);
+	
+	traverse($root_key);
+# Data structure containing findings is a hash of hashes	
+	foreach my $k (keys %vals) {
+		::rptMsg("Key: ".$k."   LastWrite time: ".gmtime($vals{$k}{lastwrite}));
+		foreach my $i (keys %{$vals{$k}}) {
+			next if ($i eq "lastwrite");
+			::rptMsg("  Value: ".$i."  Length: ".$vals{$k}{$i}." bytes");
+		}
+		::rptMsg("");
+	}
+	::rptMsg("Number of values w/ binary data types: ".$bin_count);
+	::rptMsg("Number of values w/ MZ in binary data:   ".$exe_count);
+}
+
+sub traverse {
+	my $key = shift;
+#  my $ts = $key->get_timestamp();
+  
+  foreach my $val ($key->get_list_of_values()) {
+  	my $type = $val->get_type();
+  	if ($type == 0 || $type == 3) {
+  		$bin_count++;
+  		my $data = $val->get_data();
+# This code looks for data that starts with MZ
+#  		my $i    = unpack("v",substr($data,0,2)); 		
+#  		if ($i == 0x5a4d) {
+			if (grep(/MZ/,$data)) {
+				$exe_count++;		
+				my $path;
+				my @p = split(/\\/,$key->get_path());
+				if (scalar(@p) == 1) {
+					$path = "root";
+				}
+				else {
+					shift(@p);
+					$path = join('\\',@p);
+				}
+				
+				$vals{$path}{lastwrite} = $key->get_timestamp();
+				$vals{$path}{$val->get_name()}    = length($data);			
+			}
+  	}
+  }
+  
+	foreach my $subkey ($key->get_list_of_subkeys()) {
+		traverse($subkey);
+  }
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/fw_config.pl b/thirdparty/rr/plugins/fw_config.pl
new file mode 100644
index 0000000000000000000000000000000000000000..e43e2458371046a53fd931d33e0a608dfa9a1bff
--- /dev/null
+++ b/thirdparty/rr/plugins/fw_config.pl
@@ -0,0 +1,116 @@
+#-----------------------------------------------------------
+# fw_config
+#
+# References
+#   http://technet2.microsoft.com/WindowsServer/en/library/47f25d7d-
+#          882b-4f87-b05f-31e5664fc15e1033.mspx?mfr=true
+#
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package fw_config;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 20,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080328);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Gets the Windows Firewall config from the System hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching fw_config v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# Code for System file, getting CurrentControlSet
+ 	my $current;
+ 	my $ccs;
+	my $select_path = 'Select';
+	my $sel;
+	if ($sel = $root_key->get_subkey($select_path)) {
+		$current = $sel->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+	}
+	else {
+		::rptMsg($select_path." could not be found.");
+		::logMsg($select_path." could not be found.");
+		return;
+	}
+
+	my @profiles = ("DomainProfile","StandardProfile");
+	foreach my $profile (@profiles) {
+		my $key_path = $ccs."\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\".$profile;
+		my $key;
+		if ($key = $root_key->get_subkey($key_path)) {
+			::rptMsg("Windows Firewall Configuration");
+			::rptMsg($key_path);
+			::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+			my %vals = getKeyValues($key);
+			if (scalar(keys %vals) > 0) {
+				foreach my $v (keys %vals) {
+					::rptMsg("\t".$v." -> ".$vals{$v});
+				}
+			}
+			else {
+#				::rptMsg($key_path." has no values.");
+			}
+			
+			my @configs = ("RemoteAdminSettings", 
+			               "IcmpSettings",
+			               "GloballyOpenPorts\\List",
+			               "AuthorizedApplications\\List");
+		
+			foreach my $config (@configs) {
+				eval {
+					my %vals = getKeyValues($key->get_subkey($config));
+					if (scalar(keys %vals) > 0) {
+						::rptMsg("");
+						::rptMsg($key_path."\\".$config);
+						::rptMsg("LastWrite Time ".gmtime($key->get_subkey($config)->get_timestamp())." (UTC)");
+						foreach my $v (keys %vals) {
+							::rptMsg("\t".$v." -> ".$vals{$v});
+						}
+					}
+				};
+			}
+		}
+		else {
+			::rptMsg($key_path." not found.");
+			::logMsg($key_path." not found.");
+		}
+		::rptMsg("");
+	} # end foreach
+}
+
+sub getKeyValues {
+	my $key = shift;
+	my %vals;
+	
+	my @vk = $key->get_list_of_values();
+	if (scalar(@vk) > 0) {
+		foreach my $v (@vk) {
+			next if ($v->get_name() eq "" && $v->get_data() eq "");
+			$vals{$v->get_name()} = $v->get_data();
+		}
+	}
+	else {
+	
+	}
+	return %vals;
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/gthist.pl b/thirdparty/rr/plugins/gthist.pl
new file mode 100644
index 0000000000000000000000000000000000000000..bc52f909a9706728355784d4337cac5c29ef6682
--- /dev/null
+++ b/thirdparty/rr/plugins/gthist.pl
@@ -0,0 +1,71 @@
+#-----------------------------------------------------------
+# gthist.pl
+# Google Toolbar Search History plugin
+# 
+#
+# Change history
+#   20100218 - created
+#
+# References
+#
+# 
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package gthist;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100218);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets Google Toolbar Search History";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	my %hist;
+	::logMsg("Launching gthist v.".$VERSION);
+	
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Google\\NavClient\\1.1\\History';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @vals = $key->get_list_of_values();
+		if (scalar @vals > 0) {
+			::rptMsg("");
+			foreach my $v (@vals) {
+				my $tv = unpack("V",$v->get_data());
+				$hist{$tv} = $v->get_name();
+			}
+			
+			foreach my $t (reverse sort {$a <=> $b} keys %hist) {
+				my $str = gmtime($t)."  ".$hist{$t};
+				::rptMsg($str);
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/gtwhitelist.pl b/thirdparty/rr/plugins/gtwhitelist.pl
new file mode 100644
index 0000000000000000000000000000000000000000..e8d0695eea2ae03379d37905071b1b175271ee1a
--- /dev/null
+++ b/thirdparty/rr/plugins/gtwhitelist.pl
@@ -0,0 +1,74 @@
+#-----------------------------------------------------------
+# gtwhitelist.pl
+# Google Toolbar Search History plugin
+# 
+#
+# Change history
+#   20100218 - created
+#
+# References
+#
+# 
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package gtwhitelist;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100218);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets Google Toolbar whitelist values";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	my %hist;
+	::logMsg("Launching gtwhitelist v.".$VERSION);
+	
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Google\\Google Toolbar\\4.0\\whitelist';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my $allow2;
+		eval {
+			$allow2 = $key->get_value("allow2")->get_data();
+			my @vals = split(/\|/,$allow2);
+			::rptMsg("");
+			::rptMsg("whitelist");
+			foreach my $v (@vals) {
+				next if ($v eq "");
+				::rptMsg("  ".$v);
+			}
+			::rptMsg("");
+		};
+		
+		my $lastmod;
+		eval {
+			$lastmod = $key->get_value("lastmod")->get_data();
+			::rptMsg("lastmod ".gmtime($lastmod)." (UTC)");
+		};
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/hibernate.pl b/thirdparty/rr/plugins/hibernate.pl
new file mode 100644
index 0000000000000000000000000000000000000000..64c5b3e359fe62ac1fbd9c7a1f64298543c5115b
--- /dev/null
+++ b/thirdparty/rr/plugins/hibernate.pl
@@ -0,0 +1,78 @@
+#-----------------------------------------------------------
+# hibernate.pl
+#
+# Ref: 
+#   http://support.microsoft.com/kb/293399 & testing
+#
+# copyright 2008-2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package hibernate;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20081216);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Check hibernation status";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching hibernate v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+
+		my $power_path = $ccs."\\Control\\Session Manager\\Power";
+		my $power;
+		if ($power = $root_key->get_subkey($power_path)) {
+			
+			my $heur;
+			eval {
+				my $bin_val = $power->get_value("Heuristics")->get_data();
+				$heur = (unpack("v*",$bin_val))[3];
+				if ($heur == 0) {
+					::rptMsg("Hibernation disabled.");
+				}
+				elsif ($heur == 1) {
+					::rptMsg("Hibernation enabled.");
+				}
+				else {
+					::rptMsg("Unknown hibernation value: ".$heur);
+				}
+				
+			};
+			::rptMsg("Error reading Heuristics value.") if ($@);
+			
+		}
+		else {
+			::rptMsg($power_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+#		::logMsg($key_path." not found.");
+	}
+	
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/ide.pl b/thirdparty/rr/plugins/ide.pl
new file mode 100644
index 0000000000000000000000000000000000000000..789cbd14958fef76beeb7826318b320126c354b8
--- /dev/null
+++ b/thirdparty/rr/plugins/ide.pl
@@ -0,0 +1,123 @@
+#-----------------------------------------------------------
+# ide.pl
+# Get IDE device info from the System hive file
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package ide;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080418);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get IDE device info from the System hive file";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching ide v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	::rptMsg("IDE");
+	 
+# Code for System file, getting CurrentControlSet
+ 	my $current;
+ 	my $ccs;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+	}
+	else {
+		::logMsg("Could not find ".$key_path);
+		return
+	}
+
+	my $key_path = $ccs."\\Enum\\IDE";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				::rptMsg("");
+				::rptMsg($s->get_name()." [".gmtime($s->get_timestamp())."]");
+				my @sk = $s->get_list_of_subkeys();
+				if (scalar(@sk) > 0) {
+					foreach my $s2 (@sk) {
+						::rptMsg($s2->get_name()." [".gmtime($s2->get_timestamp())." (UTC)]");
+						eval {
+							::rptMsg("FriendlyName : ".$s2->get_value("FriendlyName")->get_data());
+						};
+						::rptMsg("");
+					}
+				}
+				
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+	my $key_path = $ccs."\\Control\\DeviceClasses\\{53f56307-b6bf-11d0-94f2-00a0c91efb8b}";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("DevClasses - Disks");
+		::rptMsg($key_path);
+		my %disks;
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				my $name = $s->get_name();
+				next unless (grep(/IDE/,$name));
+				my $lastwrite = $s->get_timestamp();
+				my ($dev, $serial) = (split(/#/,$name))[4,5];
+				push(@{$disks{$lastwrite}},$dev.",".$serial);
+			}
+			
+			if (scalar(keys %disks) == 0) {
+				::rptMsg("No IDE subkeys were found.");
+				return;
+			}
+			::rptMsg("");
+			foreach my $t (reverse sort {$a <=> $b} keys %disks) {
+				::rptMsg(gmtime($t)." (UTC)");
+				foreach my $item (@{$disks{$t}}) {
+					::rptMsg("\t$item");
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/ie_main.pl b/thirdparty/rr/plugins/ie_main.pl
new file mode 100644
index 0000000000000000000000000000000000000000..aa48c4d4a3f7c6ec604e781f677bce449c3ba80b
--- /dev/null
+++ b/thirdparty/rr/plugins/ie_main.pl
@@ -0,0 +1,82 @@
+#-----------------------------------------------------------
+# ie_main.pl
+# Checks keys/values set by new version of Trojan.Clampi
+#
+# Change history
+#   20091019 - created
+#
+#
+# References
+#   http://support.microsoft.com/kb/895339
+#   http://support.microsoft.com/kb/176497
+# 
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package ie_main;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20091019);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets values beneath user's Internet Explorer\\Main key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching ie_main v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	
+	my $key_path = 'Software\\Microsoft\\Internet Explorer\\Main';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my %main;
+		
+		my @vals = $key->get_list_of_values();
+		
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				my $data = $v->get_data();
+				next if ($name eq "Window_Placement");
+				
+				$data = unpack("V",$data) if ($name eq "Do404Search");
+				
+				if ($name eq "IE8RunOnceLastShown_TIMESTAMP" || $name eq "IE8TourShownTime") {
+					my ($t0,$t1) = unpack("VV",$data);
+					$data = gmtime(::getTime($t0,$t1))." UTC";
+				}
+				$main{$name} = $data;
+			}
+		
+			foreach my $n (keys %main) {
+				my $str = sprintf "%-35s  %-20s",$n,$main{$n};
+				::rptMsg($str);
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/ie_settings.pl b/thirdparty/rr/plugins/ie_settings.pl
new file mode 100644
index 0000000000000000000000000000000000000000..fd3ee3857e8e37a5645677b2e26e86b2ac4403d1
--- /dev/null
+++ b/thirdparty/rr/plugins/ie_settings.pl
@@ -0,0 +1,72 @@
+#! c:\perl\bin\perl.exe
+#-----------------------------------------------------------
+# ie_settings.pl
+# Gets IE settings
+#
+# Change history
+#
+#
+# References
+#   
+# 
+# 
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package ie_settings;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              osmask        => 22,
+              version       => 20091016);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets IE settings";	
+}
+sub getDescr{}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching ie_settings v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	
+	my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+#		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my $ua;
+		eval {
+			$ua = $key->get_value("User Agent")->get_data();
+			::rptMsg("User Agent = ".$ua);
+		};
+		
+		my $zonessecupgrade;
+		eval {
+			$zonessecupgrade = $key->get_value("ZonesSecurityUpgrade")->get_data();
+			my ($z0,$z1) = unpack("VV",$zonessecupgrade);
+			::rptMsg("ZonesSecurityUpgrade = ".gmtime(::getTime($z0,$z1))." (UTC)");
+		};
+		
+		my $daystokeep;
+		eval {
+			$daystokeep = $key->get_subkey("Url History")->get_value("DaysToKeep")->get_data();
+			::rptMsg("DaysToKeep = ".$daystokeep);
+		};
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/ie_version.pl b/thirdparty/rr/plugins/ie_version.pl
new file mode 100644
index 0000000000000000000000000000000000000000..64ce73b0465b04b0b0cac641d69a817efc261ff2
--- /dev/null
+++ b/thirdparty/rr/plugins/ie_version.pl
@@ -0,0 +1,60 @@
+#-----------------------------------------------------------
+# ie_version
+# Get IE version and build
+# 
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package ie_version;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20091016);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get IE version and build";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching ie_version v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Internet Explorer";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+
+		my $version;
+		my $build;
+		eval {
+			$build = $key->get_value("Build")->get_data();
+			::rptMsg("IE Build   = ".$build);
+		};
+		
+		eval {
+			$version= $key->get_value("Version")->get_data();
+			::rptMsg("IE Version = ".$version);
+		};
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/imagedev.pl b/thirdparty/rr/plugins/imagedev.pl
new file mode 100644
index 0000000000000000000000000000000000000000..5822ae7a158c4ec756bdc720ca0c02cd63b52475
--- /dev/null
+++ b/thirdparty/rr/plugins/imagedev.pl
@@ -0,0 +1,85 @@
+#-----------------------------------------------------------
+# imagedev.pl
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package imagedev;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080730);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return " -- ";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching imagedev v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ 	my $current;
+ 	my $ccs;
+ 	eval {
+		my $key_path = 'Select';
+		my $key;
+		if ($key = $root_key->get_subkey($key_path)) {
+			$current = $key->get_value("Current")->get_data();
+			$ccs = "ControlSet00".$current;
+		}
+	};
+	if ($@) {
+		::rptMsg("Problem locating proper controlset: $@");
+		return;
+	}
+	
+	my $key_path = $ccs."\\Control\\Class\\{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("imagedev");
+		::rptMsg($key_path);
+#		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my @sk = $key->get_list_of_subkeys();
+		
+		if (scalar(@sk) > 0) {
+			::rptMsg("Still Image Capture Devices");
+			foreach my $s (@sk) {
+				my $name = $s->get_name();
+				next unless ($name =~ m/^\d{4}$/);
+				my $friendly;
+				eval {
+					$friendly = $s->get_value("FriendlyName")->get_data();
+					::rptMsg("  ".$friendly);
+				};
+				if ($@) {
+					::logMsg("Error getting device FriendlyName in imagedev: ".$@);
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/imagefile.pl b/thirdparty/rr/plugins/imagefile.pl
new file mode 100644
index 0000000000000000000000000000000000000000..1f31f674b7bb9137f712ab66d9142d0905f57f5c
--- /dev/null
+++ b/thirdparty/rr/plugins/imagefile.pl
@@ -0,0 +1,99 @@
+#-----------------------------------------------------------
+# imagefile
+#
+# References:
+#  http://msdn2.microsoft.com/en-us/library/a329t4ed(VS\.80)\.aspx
+#  http://support.microsoft.com/kb/2264107
+#
+# Change history:
+#  20100824 - added check for "CWDIllegalInDllSearch" value
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package imagefile;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100824);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Checks IFEO subkeys for Debugger/CWDIllegalInDllSearch values";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching imagefile v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("Image File Execution Options");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			my %debug;
+			my $i = "Your Image File Name here without a path";
+			foreach my $s (@subkeys) {
+				my $name = $s->get_name();
+				next if ($name =~ m/^$i/i);
+				my $debugger = "";
+				eval {
+					$debugger = $s->get_value("Debugger")->get_data();
+				};
+# If the eval{} throws an error, it's b/c the Debugger value isn't
+# found within the key, so we don't need to do anything w/ the error
+				if ($debugger ne "") {
+					$debug{$name}{debug} = $debugger;
+					$debug{$name}{lastwrite} = $s->get_timestamp();
+				}
+			
+				my $dllsearch = "";
+				eval {
+					$dllsearch = $s->get_value("CWDIllegalInDllSearch")->get_data();
+				};
+# If the eval{} throws an error, it's b/c the Debugger value isn't
+# found within the key, so we don't need to do anything w/ the error
+				if ($dllsearch ne "") {
+					$debug{$name}{dllsearch} = $debugger;
+					$debug{$name}{lastwrite} = $s->get_timestamp();
+				}
+			}
+			
+			if (scalar (keys %debug) > 0) {
+				foreach my $d (keys %debug) {
+					::rptMsg($d."  LastWrite: ".gmtime($debug{$d}{lastwrite}));
+					::rptMsg("  Debugger             : ".$debug{$d}{debug}) if (exists $debug{$d}{debug});
+					::rptMsg("  CWDIllegalInDllSearch: ".$debug{$d}{dllsearch}) if (exists $debug{$d}{dllsearch});
+				}
+			}
+			else {
+				::rptMsg("No Debugger/CWDIllegalInDllSearch values found.");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/init_dlls.pl b/thirdparty/rr/plugins/init_dlls.pl
new file mode 100644
index 0000000000000000000000000000000000000000..d729a6b7166fbb6a169d0c90f6b63ad59e89af67
--- /dev/null
+++ b/thirdparty/rr/plugins/init_dlls.pl
@@ -0,0 +1,77 @@
+#-----------------------------------------------------------
+# init_dlls.pl
+# Plugin to assist in the detection of malware per Mark Russinovich's
+#   blog post (References, below)
+#
+# Change History:
+#   20110309 - created
+#
+# References
+#   http://blogs.technet.com/b/markrussinovich/archive/2011/02/27/3390475.aspx
+#
+# copyright 2011 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package init_dlls;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20110309);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Check for odd **pInit_Dlls keys";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+my @init;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching init_dlls v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\Windows";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("init_dlls");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite: ".gmtime($key->get_timestamp()));
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				next if ($name eq "AppInit_DLLs");
+				push(@init,$name) if ($name =~ m/Init_DLLs$/);
+			}
+			
+			if (scalar @init > 0) {
+				foreach my $n (@init) {
+					::rptMsg($n);
+				}
+			}
+			else {
+				::rptMsg("No additional values named *Init_DLLs located.");
+			}
+			
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/installedcomp.pl b/thirdparty/rr/plugins/installedcomp.pl
new file mode 100644
index 0000000000000000000000000000000000000000..9fd730301fa119789425912f08bdc6e7676799a3
--- /dev/null
+++ b/thirdparty/rr/plugins/installedcomp.pl
@@ -0,0 +1,120 @@
+#-----------------------------------------------------------
+# installedcomp.pl
+# Get info about Installed Components
+#
+# Change history:
+#   20100116 - updated for slightly better coverage
+#   20100115 - created
+#
+# References:
+#   
+# Notes: Look for out of place entries, particularly those 
+#        that point to the Recycle Bin or a temp directory
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package installedcomp;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100116);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get info about Installed Components/StubPath";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+my %comp;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching installedcomp v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Active Setup\\Installed Components";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				my $lastwrite = $s->get_timestamp();
+							
+				my $str;
+				eval {
+					$str = $s->get_value("ComponentID")->get_data();
+				};
+				
+				eval {
+					my $ver = $s->get_value("Version")->get_data();
+					$str .= " v.".$ver if ($ver && $s->get_value("Version")->get_type() == 1);
+				};
+				
+				eval {
+					my $stub = $s->get_value("StubPath")->get_data();
+					$str .= "; ".$stub if ($stub ne "");
+				};
+
+# If the $str scalar is empty at this point, that means that for
+# some reason, we haven't been able to populate the information
+# we're looking for; in this case, we'll go looking for some info
+# in a different area of the hive; the BHO.pl plugin does this, as
+# well.  I'd rather that the plugin look for the Classes info than
+# leave a blank entry in the output.
+				if ($str eq "") {
+					my $name = $s->get_name();
+					my $class_path = "Classes\\CLSID\\".$name;
+					my $proc;
+					if ($proc = $root_key->get_subkey($class_path)) {
+# Try these two eval{} statements because I've seen the different 
+# spellings for InProcServer32/InprocServer32 in sequential keys
+						eval {
+							$str = $proc->get_subkey("InprocServer32")->get_value("")->get_data();
+						};
+						
+						eval {
+							$str = $proc->get_subkey("InProcServer32")->get_value("")->get_data();
+						};
+					}
+					else {
+						$str = $name." class not found.";
+					}
+				}
+				
+				push(@{$comp{$lastwrite}},$str);
+			}
+
+			foreach my $t (reverse sort {$a <=> $b} keys %comp) {
+				::rptMsg(gmtime($t)." (UTC)");
+				foreach my $item (@{$comp{$t}}) {
+					::rptMsg("  ".$item);
+				}
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/javafx.pl b/thirdparty/rr/plugins/javafx.pl
new file mode 100644
index 0000000000000000000000000000000000000000..118e82cb5866815eccbfa6b4a419b1ef3ce620b9
--- /dev/null
+++ b/thirdparty/rr/plugins/javafx.pl
@@ -0,0 +1,67 @@
+#-----------------------------------------------------------
+# javafx.pl
+# Plugin written based on Cory Harrell's Exploit Artifacts posts at
+# http://journeyintoir.blogspot.com/
+#
+# Change history
+#   20110322 - created
+#
+# References
+#   http://java.sun.com/j2se/1.4.2/runtime_win32.html
+#		
+# copyright 2011 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package javafx;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20110322);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of user's JavaFX key";
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching javafx v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	
+	my $key_path = "Software\\JavaSoft\\Java Update\\Policy\\JavaFX";
+	my $key;
+	my @vals;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("javafx v.".$VERSION);
+		::rptMsg($key_path);
+		::rptMsg("LastWrite time: ".gmtime($key->get_timestamp()));
+		::rptMsg("");
+		@vals = $key->get_list_of_values();
+		
+		if (scalar(@vals) > 0) {
+# First, read in all of the values and the data
+			foreach my $v (@vals) {
+				::rptMsg(sprintf "%-25s %-20s",$v->get_name(), $v->get_data());
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}	
+
+1;		
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/kb950582.pl b/thirdparty/rr/plugins/kb950582.pl
new file mode 100644
index 0000000000000000000000000000000000000000..4e24fe3dd2e839343480378ad9b279c46675bc70
--- /dev/null
+++ b/thirdparty/rr/plugins/kb950582.pl
@@ -0,0 +1,90 @@
+#-----------------------------------------------------------
+# kb950582.pl
+# Get autorun settings WRT KB950582
+#
+# Change history
+#    18 Dec 2008 - Updated to new name; added checks for Registry
+#                  keys
+#
+# References
+#    http://support.microsoft.com/kb/953252
+#    http://www.microsoft.com/technet/prodtechnol/windows2000serv/reskit
+#         /regentry/91525.mspx?mfr=true
+#
+# copyright 2008-2009 H. Carvey
+#-----------------------------------------------------------
+package kb950582;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20081212);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "KB950582 - Gets autorun settings from HKLM hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching kb950582 v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	
+	eval {
+		my $path = "Microsoft\\Windows\\CurrentVersion\\Uninstall\\KB950582";
+		if (my $kbkey = $root_key->get_subkey($path)) {
+			my $install = $kbkey->get_value("InstallDate")->get_data();
+			::rptMsg("KB950528 Uninstall Key   ".gmtime($kbkey->get_timestamp()));
+			::rptMsg("  InstallDate = ".$install."\n");
+		}
+	};
+	::rptMsg("Uninstall\\KB950528 does not appear to be installed.\n") if ($@);
+	
+	eval {
+		my $path = "Microsoft\\Updates\\Windows XP\\SP4\\KB950582";
+		if (my $kbkey = $root_key->get_subkey($path)) {
+			my $install = $kbkey->get_value("InstalledDate")->get_data();
+			::rptMsg("KB950528 Update Key ".gmtime($kbkey->get_timestamp()));
+			::rptMsg("  InstalledDate = ".$install."\n");
+		}
+	};
+	::rptMsg("KB950528 does not appear to be installed.\n") if ($@);
+	
+	my $key_path = "Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		
+		eval {
+			my $nodrive = $key->get_value("NoDriveTypeAutoRun")->get_data();
+			my $str = sprintf "%-20s 0x%x","NoDriveTypeAutoRun",$nodrive;
+			::rptMsg($str);
+		};
+		::rptMsg("Error: ".$@) if ($@);
+
+# http://support.microsoft.com/kb/953252		
+		eval {
+			my $honor = $key->get_value("HonorAutorunSetting")->get_data();
+			my $str = sprintf "%-20s 0x%x","HonorAutorunSetting",$honor;
+			::rptMsg($str);
+		};
+		::rptMsg("HonorAutorunSetting not found.") if ($@);
+		::rptMsg("");
+		::rptMsg("Autorun settings in the HKLM hive take precedence over those in");
+		::rptMsg("the HKCU hive.");
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/kbdcrash.pl b/thirdparty/rr/plugins/kbdcrash.pl
new file mode 100644
index 0000000000000000000000000000000000000000..560aef97859c6b87a90d39684f5933aeaa60282d
--- /dev/null
+++ b/thirdparty/rr/plugins/kbdcrash.pl
@@ -0,0 +1,65 @@
+#-----------------------------------------------------------
+# kbdcrash.pl
+#
+# Ref: 
+#   http://support.microsoft.com/kb/244139
+#
+# copyright 2008-2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package kbdcrash;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20081212);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Checks to see if system is config to crash via keyboard";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+my $enabled = 0;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching kbdcrash v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ 	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $svc = "ControlSet00".$current."\\Services";
+		
+		eval {
+			my $ps2 = $svc->get_subkey("i8042prt\\Parameters")->get_value("CrashOnCtrlScroll")->get_data();
+			::rptMsg("CrashOnCtrlScroll set for PS2 keyboard") if ($ps2 == 1);
+			$enabled = 1 if ($ps2 == 1);
+		};
+		
+		eval {
+			my $usb = $svc->get_subkey("kbdhid\\Parameters")->get_value("CrashOnCtrlScroll")->get_data();
+			::rptMsg("CrashOnCtrlScroll set for USB keyboard") if ($usb == 1);
+			$enabled = 1 if ($usb == 1);
+		};
+		::rptMsg("CrashOnCtrlScroll not set");
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
diff --git a/thirdparty/rr/plugins/landesk.pl b/thirdparty/rr/plugins/landesk.pl
new file mode 100644
index 0000000000000000000000000000000000000000..d3dd8c532091a59ded039f1e387b8a82d945cb0d
--- /dev/null
+++ b/thirdparty/rr/plugins/landesk.pl
@@ -0,0 +1,71 @@
+#-----------------------------------------------------------
+# LANDESK Monitor Logs
+#
+#
+# Change history
+#   20090729 - updates, H. Carvey
+#
+# copyright 2009 Don C. Weber
+#-----------------------------------------------------------
+package landesk;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090729);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get list of programs monitored by LANDESK from Software hive file";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+my %ls;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching LANDESK v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+    
+	my $key_path = "LANDesk\\ManagementSuite\\WinClient\\SoftwareMonitoring\\MonitorLog";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("");
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				eval {
+					my ($val1,$val2) = unpack("VV",$s->get_value("Last Started")->get_data());
+# Push the data into a hash of arrays 
+					push(@{$ls{::getTime($val1,$val2)}},$s->get_name());
+				};
+			}
+			
+			foreach my $t (reverse sort {$a <=> $b} keys %ls) {
+				::rptMsg(gmtime($t)." (UTC)");
+				foreach my $item (@{$ls{$t}}) {
+					::rptMsg("\t$item");
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." does not appear to have any subkeys.")
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/legacy.pl b/thirdparty/rr/plugins/legacy.pl
new file mode 100644
index 0000000000000000000000000000000000000000..3c34a1a26ae468711d6852d411ceda519c69b6e5
--- /dev/null
+++ b/thirdparty/rr/plugins/legacy.pl
@@ -0,0 +1,96 @@
+#-----------------------------------------------------------
+# legacy.pl
+# 
+#
+# Change history
+#   20090429 - created
+# 
+# Reference: http://support.microsoft.com/kb/310592
+#   
+#
+# Analysis Tip: 
+#
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package legacy;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20090429);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Lists LEGACY_ entries in Enum\\Root key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key();
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+		my $root_path = $ccs."\\Enum\\Root";
+		
+		my %legacy;
+		if (my $root = $root_key->get_subkey($root_path)) {
+			my @sk = $root->get_list_of_subkeys();
+			if (scalar(@sk) > 0) {
+				foreach my $s (@sk) {
+					my $name = $s->get_name();
+					next unless ($name =~ m/^LEGACY_/);
+					push(@{$legacy{$s->get_timestamp()}},$name);
+				
+					eval {
+						my @s_sk = $s->get_list_of_subkeys();
+						if (scalar(@s_sk) > 0) {
+							foreach my $s_s (@s_sk) {
+								
+								my $desc;
+								eval {
+									$desc = $s_s->get_value("DeviceDesc")->get_data();
+									push(@{$legacy{$s_s->get_timestamp()}},$name."\\".$s_s->get_name()." - ".$desc);
+								};
+								push(@{$legacy{$s_s->get_timestamp()}},$name."\\".$s_s->get_name()) if ($@);
+							}
+						}
+					};
+				}
+			}
+			else {
+				::rptMsg($root_path." has no subkeys.");
+			}
+			
+			foreach my $t (reverse sort {$a <=> $b} keys %legacy) {
+				::rptMsg(gmtime($t)." (UTC)");
+				foreach my $item (@{$legacy{$t}}) {
+					::rptMsg("\t$item");
+				}
+			}
+		}
+		else {
+			::rptMsg($root_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/listsoft.pl b/thirdparty/rr/plugins/listsoft.pl
new file mode 100644
index 0000000000000000000000000000000000000000..ae1c50a540192854446fbbc9d2d4448a9a58e025
--- /dev/null
+++ b/thirdparty/rr/plugins/listsoft.pl
@@ -0,0 +1,69 @@
+#! c:\perl\bin\perl.exe
+#-----------------------------------------------------------
+# listsoft.pl
+# Plugin for Registry Ripper; traverses thru the Software
+# key of an NTUSER.DAT file, extracting all of the subkeys 
+# and listing them in order by LastWrite time.
+#
+# Change history
+# 
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package listsoft;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Lists contents of user's Software key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $file = shift;
+	my $reg = Parse::Win32Registry->new($file);
+	my $root_key = $reg->get_root_key;
+	::logMsg("Launching listsoft v.".$VERSION);
+	my %soft;
+	my $key_path = 'Software';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("listsoft v.".$VERSION);
+		::rptMsg("List the contents of the Software key in the NTUSER\.DAT hive");
+		::rptMsg("file, in order by LastWrite time.");
+		::rptMsg("");
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				push(@{$soft{$s->get_timestamp()}},$s->get_name());
+			}
+			
+			foreach my $t (reverse sort {$a <=> $b} keys %soft) {
+				foreach my $item (@{$soft{$t}}) {
+					::rptMsg(gmtime($t)."Z \t".$item);
+				}
+			}	
+		}
+		else {
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::logMsg("Could not access ".$key_path);
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/load.pl b/thirdparty/rr/plugins/load.pl
new file mode 100644
index 0000000000000000000000000000000000000000..3ce6ca655e5147428d4d3b5bbd62543ef5728468
--- /dev/null
+++ b/thirdparty/rr/plugins/load.pl
@@ -0,0 +1,81 @@
+#-----------------------------------------------------------
+# load.pl
+# The load and run values in the Windows NT\CurrentVersion\Windows 
+# key are throw-backs to the old win.ini file, and can be/are used 
+# by malware.
+#
+# Change history
+#   20100811 - created
+#
+# References
+#   http://support.microsoft.com/kb/103865
+#   http://security.fnal.gov/cookbook/WinStartup.html
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package load;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100811);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets load and run values from user hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching load v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("load");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			::rptMsg("");
+			my %win;
+			foreach my $v (@vals) { 
+				$win{$v->get_name()} = $v->get_data();
+			}
+			
+			if (exists $win{"load"}) {
+				::rptMsg("load = ".$win{"load"});
+			}
+			else {
+				::rptMsg("load value not found.");
+			}
+				
+			if (exists $win{"run"}) {
+				::rptMsg("run = ".$win{"run"});
+			}
+			else {
+				::rptMsg("run value not found.");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/logon_xp_run.pl b/thirdparty/rr/plugins/logon_xp_run.pl
new file mode 100644
index 0000000000000000000000000000000000000000..831a5cd910be0da9a921aa30c65cd86cabe27534
--- /dev/null
+++ b/thirdparty/rr/plugins/logon_xp_run.pl
@@ -0,0 +1,98 @@
+#-----------------------------------------------------------
+# logon_xp_run
+# Get contents of Run key from Software hive
+#
+# References:
+#   http://support.microsoft.com/kb/314488
+#   
+# Note: Needs testing to see if it applies beyond XP/XP-64
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package logon_xp_run;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 12,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080328);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Autostart - Get XP user logon Run key contents from NTUSER\.DAT hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching user_xp_run v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\policies\\Explorer\\Run";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my %vals = getKeyValues($key);
+		if (scalar(keys %vals) > 0) {
+			foreach my $v (keys %vals) {
+				::rptMsg("\t".$v." -> ".$vals{$v});
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+		
+#		my @sk = $key->get_list_of_subkeys();
+#		if (scalar(@sk) > 0) {
+#			foreach my $s (@sk) {
+#				::rptMsg("");
+#				::rptMsg($key_path."\\".$s->get_name());
+#				::rptMsg("LastWrite Time ".gmtime($s->get_timestamp())." (UTC)");
+#				my %vals = getKeyValues($s);
+#				foreach my $v (keys %vals) {
+#					::rptMsg("\t".$v." -> ".$vals{$v});
+#				}
+#			}
+#		}
+#		else {
+#			::rptMsg("");
+#			::rptMsg($key_path." has no subkeys.");
+#		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+}
+
+sub getKeyValues {
+	my $key = shift;
+	my %vals;
+	
+	my @vk = $key->get_list_of_values();
+	if (scalar(@vk) > 0) {
+		foreach my $v (@vk) {
+			next if ($v->get_name() eq "" && $v->get_data() eq "");
+			$vals{$v->get_name()} = $v->get_data();
+		}
+	}
+	else {
+# do nothing	
+	}
+	return %vals;
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/logonusername.pl b/thirdparty/rr/plugins/logonusername.pl
new file mode 100644
index 0000000000000000000000000000000000000000..098d89f5e651142169accb6aff6efc043a3f6312
--- /dev/null
+++ b/thirdparty/rr/plugins/logonusername.pl
@@ -0,0 +1,68 @@
+#! c:\perl\bin\perl.exe
+#-----------------------------------------------------------
+# logonusername.pl
+# Plugin for Registry Ripper, NTUSER.DAT edition - gets the 
+# "Logon User Name" value 
+#
+# Change history
+#
+#
+#
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package logonusername;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get user's Logon User Name value";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching logonusername v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	
+	my $logon_name = "Logon User Name";
+	
+	my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			::rptMsg("Logon User Name");
+			::rptMsg($key_path);
+			::rptMsg("LastWrite Time [".gmtime($key->get_timestamp())." (UTC)]");
+			foreach my $v (@vals) {
+				if ($v->get_name() eq $logon_name) {
+					::rptMsg($logon_name." = ".$v->get_data());
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/lsasecrets.pl b/thirdparty/rr/plugins/lsasecrets.pl
new file mode 100644
index 0000000000000000000000000000000000000000..1e0048e973afcb781011cf3bf5e8bcf57be34527
--- /dev/null
+++ b/thirdparty/rr/plugins/lsasecrets.pl
@@ -0,0 +1,71 @@
+#-----------------------------------------------------------
+# lsasecrets.pl
+# Get update times for LSA Secrets from the Security hive file
+# 
+# History
+#   20100219 - created
+#
+# References
+#   http://moyix.blogspot.com/2008/02/decrypting-lsa-secrets.html
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package lsasecrets;
+use strict;
+
+my %config = (hive          => "Security",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100219);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "TEST - Get update times for LSA Secrets";	
+}
+sub getDescr{}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching lsasecrets v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Policy\\Secrets";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+
+#
+# http://support.microsoft.com/kb/175468
+		eval {
+			::rptMsg("");
+			::rptMsg("Domain secret - \$MACHINE\.ACC");
+			my $c = $key->get_subkey("\$MACHINE\.ACC\\CupdTime")->get_value("")->get_data();
+			my @v = unpack("VV",$c);
+			my $cupd = gmtime(::getTime($v[0],$v[1]));
+			::rptMsg("CupdTime = ".$cupd);
+			
+			my $o = $key->get_subkey("\$MACHINE\.ACC\\OupdTime")->get_value("")->get_data();
+			my @v = unpack("VV",$c);
+			my $oupd = gmtime(::getTime($v[0],$v[1]));
+			::rptMsg("OupdTime = ".$oupd);
+		};
+		::rptMsg("Error: ".$@) if ($@);
+		
+		
+		
+		
+		
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/macaddr.pl b/thirdparty/rr/plugins/macaddr.pl
new file mode 100644
index 0000000000000000000000000000000000000000..50a034981a0bc94d1880ccd331b973d3ac3a4826
--- /dev/null
+++ b/thirdparty/rr/plugins/macaddr.pl
@@ -0,0 +1,156 @@
+#-----------------------------------------------------------
+# macaddr.pl
+# Attempt to locate MAC address in either Software or System hive files;
+# The plugin will determine which one its in and use the appropriate
+# code
+#
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package macaddr;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090118);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return " -- ";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching macaddr v.".$VERSION);
+	
+	my $guess = guessHive($hive);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	
+	if ($guess eq "System") {
+# Code for System file, getting CurrentControlSet
+ 		my $current;
+		my $key_path = 'Select';
+		my $key;
+		if ($key = $root_key->get_subkey($key_path)) {
+			$current = $key->get_value("Current")->get_data();
+			my $ccs = "ControlSet00".$current;
+
+			my $key_path = $ccs."\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}";
+			my $key;
+			my $found = 0;
+			::rptMsg($key_path);
+			if ($key = $root_key->get_subkey($key_path)) {
+				my @subkeys = $key->get_list_of_subkeys();
+				if (scalar (@subkeys) > 0) {
+					foreach my $s (@subkeys) {
+						my $name = $s->get_name();
+						my $na;
+						eval {
+							$na = $key->get_subkey($name)->get_value("NetworkAddress")->get_data();
+							::rptMsg("  ".$name.": NetworkAddress = ".$na);
+							$found = 1;
+						};	
+					}
+					::rptMsg("No NetworkAddress value found.") if ($found == 0);
+				}
+				else {
+					::rptMsg($key_path." has no subkeys.");
+				}
+			}
+			else {
+				::rptMsg($key_path." not found.");
+			}
+		}
+		else {
+			::rptMsg($key_path." not found.");
+		}
+	}
+	elsif ($guess eq "Software") {
+		my $key_path = "Microsoft\\Windows Genuine Advantage";
+		my $key;
+		if ($key = $root_key->get_subkey($key_path)) {
+			my $mac;
+			my $found = 0;
+			eval {
+				$mac = $key->get_value("MAC")->get_data();
+				::rptMsg("Mac Address(es) = ".$mac);
+				$found = 1;
+			};
+			::rptMsg("No MAC address(es) found.") if ($found == 0);	
+		}
+		else {
+			::rptMsg($key_path." not found.");
+		}	
+	}
+	else {
+		::rptMsg("Hive file ".$hive." appeared to be neither a Software nor a");
+		::rptMsg("System hive file.");
+	}
+}
+
+#-------------------------------------------------------------
+# guessHive() - attempts to determine the hive type; if NTUSER.DAT,
+#   attempt to retrieve the SID for the user; this function populates
+#   global variables (%config, @sids)
+#-------------------------------------------------------------
+sub guessHive {
+	my $hive = shift;
+	my $hive_guess;
+	my $reg;
+	my $root_key;
+	eval {
+		$reg = Parse::Win32Registry->new($hive);
+	  $root_key = $reg->get_root_key;
+	};
+	::rptMsg($hive." may not be a valid hive.") if ($@);
+	
+# Check for SAM
+	eval {
+		if (my $key = $root_key->get_subkey("SAM\\Domains\\Account\\Users")) {
+			$hive_guess = "SAM";
+		}
+	};
+# Check for Software	
+	eval {
+		if ($root_key->get_subkey("Microsoft\\Windows\\CurrentVersion") &&
+				$root_key->get_subkey("Microsoft\\Windows NT\\CurrentVersion")) {
+			$hive_guess = "Software";
+		}
+	};
+
+# Check for System	
+	eval {
+		if ($root_key->get_subkey("MountedDevices") && $root_key->get_subkey("Select")) {
+			$hive_guess = "System";
+		}
+	};
+	
+# Check for Security	
+	eval {
+		if ($root_key->get_subkey("Policy\\Accounts") &&	$root_key->get_subkey("Policy\\PolAdtEv")) {
+			$hive_guess = "Security";
+		}
+	};
+# Check for NTUSER.DAT	
+	eval {
+	 	if ($root_key->get_subkey("Software\\Microsoft\\Windows\\CurrentVersion")) { 
+	 		$hive_guess = "NTUSER\.DAT";
+	 	}
+	};	
+	return $hive_guess;
+}
+
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/mmc.pl b/thirdparty/rr/plugins/mmc.pl
new file mode 100644
index 0000000000000000000000000000000000000000..d66557c5da47e25176695e7a8e35d8b85069f9bc
--- /dev/null
+++ b/thirdparty/rr/plugins/mmc.pl
@@ -0,0 +1,75 @@
+#-----------------------------------------------------------
+# mmc.pl
+# Plugin for Registry Ripper, NTUSER.DAT edition - gets the 
+# Microsoft Management Console Recent File List values 
+#
+# Change history
+#
+#
+# References
+#
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package mmc;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get contents of user's MMC\\Recent File List key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching mmc v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Microsoft\\Microsoft Management Console\\Recent File List';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("MMC - Recent File List");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			my %files;
+# Retrieve values and load into a hash for sorting			
+			foreach my $v (@vals) {
+				my $val = $v->get_name();
+				my $data = $v->get_data();
+				my $tag = (split(/File/,$val))[1];
+				$files{$tag} = $val.":".$data;
+			}
+# Print sorted content to report file			
+			foreach my $u (sort {$a <=> $b} keys %files) {
+				my ($val,$data) = split(/:/,$files{$u},2);
+				::rptMsg("  ".$val." -> ".$data);
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/mndmru.pl b/thirdparty/rr/plugins/mndmru.pl
new file mode 100644
index 0000000000000000000000000000000000000000..d223d7f49c873eb28fcd42f7b91b812d90b1e30f
--- /dev/null
+++ b/thirdparty/rr/plugins/mndmru.pl
@@ -0,0 +1,77 @@
+#-----------------------------------------------------------
+# mndmru.pl
+# Plugin for Registry Ripper,
+# Map Network Drive MRU parser
+#
+# Change history
+#
+#
+# References
+#
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package mndmru;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get contents of user's Map Network Drive MRU";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching mndmru v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Map Network Drive MRU';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("Map Network Drive MRU");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			my %mnd;
+# Retrieve values and load into a hash for sorting			
+			foreach my $v (@vals) {
+				my $val = $v->get_name();
+				my $data = $v->get_data();
+				$mnd{$val} = $data;
+			}
+# Print sorted content to report file			
+			if (exists $mnd{"MRUList"}) {
+				::rptMsg("  MRUList = ".$mnd{"MRUList"});
+				delete $mnd{"MRUList"};
+			}
+			foreach my $m (sort {$a <=> $b} keys %mnd) {
+				::rptMsg("  ".$m."   ".$mnd{$m});
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/mountdev.pl b/thirdparty/rr/plugins/mountdev.pl
new file mode 100644
index 0000000000000000000000000000000000000000..ae0d58b26b1291347632c52e8ac7ec406c0a9c45
--- /dev/null
+++ b/thirdparty/rr/plugins/mountdev.pl
@@ -0,0 +1,101 @@
+#-----------------------------------------------------------
+# mountdev.pl
+# Plugin for Registry Ripper; Access System hive file to get the
+# MountedDevices
+# 
+# Change history
+#
+#
+# References
+#
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package mountdev;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Return contents of System hive MountedDevices key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching mountdev v.".$VERSION);
+	::rptMsg("mountdev v.".$VERSION);
+	::rptMsg("Get MountedDevices key information from the System hive file.");
+	::rptMsg("");
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = 'MountedDevices';
+	my $key;
+	my %md;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite time = ".gmtime($key->get_timestamp())."Z");
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $data = $v->get_data();
+				my $len = length($data);
+				if ($len == 12) {
+					my $sig = _translateBinary(substr($data,0,4));
+					::rptMsg($v->get_name());
+					::rptMsg("\tDrive Signature = ".$sig);
+				}
+				elsif ($len > 12) {
+					$data =~ s/\00//g;
+					push(@{$md{$data}},$v->get_name());
+				}
+				else {
+					::logMsg("mountdev v.".$VERSION."\tData length = $len");
+				}
+			}
+			
+			::rptMsg("");
+			foreach my $m (keys %md) {
+				::rptMsg("Device: ".$m);
+				foreach my $item (@{$md{$m}}) {
+					::rptMsg("\t".$item);
+				}
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		::logMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+sub _translateBinary {
+	my $str = unpack("H*",$_[0]);
+	my $len = length($str);
+	my @nstr = split(//,$str,$len);
+	my @list = ();
+	foreach (0..($len/2)) {
+		push(@list,$nstr[$_*2].$nstr[($_*2)+1]);
+	}
+	return join(' ',@list);
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/mountdev2.pl b/thirdparty/rr/plugins/mountdev2.pl
new file mode 100644
index 0000000000000000000000000000000000000000..d5b1c3e324107cb2b9f65b47bb80f4fa4fcd6330
--- /dev/null
+++ b/thirdparty/rr/plugins/mountdev2.pl
@@ -0,0 +1,106 @@
+#-----------------------------------------------------------
+# mountdev2.pl
+# Plugin for Registry Ripper; Access System hive file to get the
+# MountedDevices
+# 
+# Change history
+#   20091116 - changed output
+#
+# References
+#
+# 
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package mountdev2;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20091116);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Return contents of System hive MountedDevices key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching mountdev2 v.".$VERSION);
+	::rptMsg("");
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = 'MountedDevices';
+	my $key;
+	my (%md,%dos,%vol);
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite time = ".gmtime($key->get_timestamp())."Z");
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $data = $v->get_data();
+				my $len = length($data);
+				if ($len == 12) {
+					my $sig = _translateBinary(substr($data,0,4));
+#					my $sig = _translateBinary($data);
+					$vol{$v->get_name()} = $sig;
+				}
+				elsif ($len > 12) {
+					$data =~ s/\00//g;
+					push(@{$md{$data}},$v->get_name());
+				}
+				else {
+					::logMsg("mountdev2 v.".$VERSION."\tData length = $len");
+				}
+			}
+			
+			::rptMsg(sprintf "%-50s  %-20s","Volume","Disk Sig");
+			::rptMsg(sprintf "%-50s  %-20s","-------","--------");
+			foreach my $v (sort keys %vol) {
+				my $str = sprintf "%-50s  %-20s",$v,$vol{$v};
+				::rptMsg($str);
+			}
+			
+			::rptMsg("");
+			foreach my $m (sort keys %md) {
+				::rptMsg("Device: ".$m);
+				foreach my $item (@{$md{$m}}) {
+					::rptMsg("\t".$item);
+				}
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		::logMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+sub _translateBinary {
+	my $str = unpack("H*",$_[0]);
+	my $len = length($str);
+	my @nstr = split(//,$str,$len);
+	my @list = ();
+	foreach (0..($len/2)) {
+		push(@list,$nstr[$_*2].$nstr[($_*2)+1]);
+	}
+	return join(' ',@list);
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/mountdev3.pl b/thirdparty/rr/plugins/mountdev3.pl
new file mode 100644
index 0000000000000000000000000000000000000000..ff4d4cfbf04174bd2107a8d3a14d951e158a74eb
--- /dev/null
+++ b/thirdparty/rr/plugins/mountdev3.pl
@@ -0,0 +1,110 @@
+#-----------------------------------------------------------
+# mountdev3.pl
+# Plugin for Registry Ripper; Access System hive file to get the
+# MountedDevices
+# 
+# Change history
+#
+#
+# References
+#
+# 
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package mountdev3;
+use Math::BigInt;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20090909);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Return contents of System hive MountedDevices key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+#	::logMsg("Launching mountdev3 v.".$VERSION);
+	::rptMsg("mountdev3 v.".$VERSION);
+	::rptMsg("Get MountedDevices key information from the System hive file.");
+	::rptMsg("");
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = 'MountedDevices';
+	my $key;
+	my %md;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite time = ".gmtime($key->get_timestamp())."Z");
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $data = $v->get_data();
+				my $len = length($data);
+				if ($len == 12) {
+					my $sig = _translateBinary(substr($data,0,4));
+					my ($low,$high) = unpack("VV",substr($data,4,8));
+					my $val64 = Math::BigInt->new($high)->blsft(32)->bxor($low);
+					my $driveoffset = ($val64/512);
+					::rptMsg($v->get_name());
+					::rptMsg("\tDrive Signature  = ".$sig);
+					::rptMsg("\tPartition offset = ".$driveoffset);
+				}
+				elsif ($len == 16) {
+					::rptMsg($v->get_name());
+					::rptMsg("\t".$data);
+				}
+				elsif ($len > 16) {
+					$data =~ s/\00//g;
+					push(@{$md{$data}},$v->get_name());
+				}
+				else {
+					::logMsg("mountdev v.".$VERSION."\tData length = $len");
+				}
+			}
+			
+			::rptMsg("");
+			foreach my $m (keys %md) {
+				::rptMsg("Device: ".$m);
+				foreach my $item (@{$md{$m}}) {
+					::rptMsg("\t".$item);
+				}
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		::logMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+sub _translateBinary {
+	my $str = unpack("H*",$_[0]);
+	my $len = length($str);
+	my @nstr = split(//,$str,$len);
+	my @list = ();
+	foreach (0..($len/2)) {
+		push(@list,$nstr[$_*2].$nstr[($_*2)+1]);
+	}
+	return join(' ',@list);
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/mp2.pl b/thirdparty/rr/plugins/mp2.pl
new file mode 100644
index 0000000000000000000000000000000000000000..b7ef8f76d67337f76129c7498bd4ab541cbfb197
--- /dev/null
+++ b/thirdparty/rr/plugins/mp2.pl
@@ -0,0 +1,114 @@
+#-----------------------------------------------------------
+# mp2.pl
+# Plugin for Registry Ripper,
+# MountPoints2 key parser
+#
+# Change history
+#   20091116 - updated output/sorting; added getting 
+#              _LabelFromReg value
+#   20090115 - Removed printing of "volumes"
+#
+# References
+#   http://support.microsoft.com/kb/932463
+# 
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package mp2;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20090115);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets user's MountPoints2 key contents";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching mp2 v.".$VERSION);
+	
+	my %drives;
+	my %volumes;
+	my %remote;
+	
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MountPoints2';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("MountPoints2");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar @subkeys > 0) {
+			foreach my $s (@subkeys) {
+				my $name = $s->get_name();
+				if ($name =~ m/^{/) {
+					my $label;
+					eval {
+						$label = $s->get_value("_LabelFromReg")->get_data();
+					};
+					$name = $name." (".$label.")" unless ($@);
+					push(@{$volumes{$s->get_timestamp()}},$name);
+				}
+				elsif ($name =~ m/^[A-Z]/) {
+					push(@{$drives{$s->get_timestamp()}},$name);
+				}
+				elsif ($name =~ m/^#/) {
+					push(@{$remote{$s->get_timestamp()}},$name);
+				}
+				else {
+					::rptMsg("  Key name = ".$name);
+				}
+			}
+			::rptMsg("");
+			::rptMsg("Remote Drives:");
+			foreach my $t (reverse sort {$a <=> $b} keys %remote) {
+				::rptMsg(gmtime($t)." (UTC)");
+				foreach my $item (@{$remote{$t}}) {
+					::rptMsg("  $item");
+				}
+			}
+			
+			::rptMsg("");
+			::rptMsg("Volumes:");
+			foreach my $t (reverse sort {$a <=> $b} keys %volumes) {
+				::rptMsg(gmtime($t)." (UTC)");
+				foreach my $item (@{$volumes{$t}}) {
+					::rptMsg("  $item");
+				}
+			}
+			::rptMsg("");
+			::rptMsg("Drives:");
+			foreach my $t (reverse sort {$a <=> $b} keys %drives) {
+				my $d = join(',',(@{$drives{$t}}));
+				::rptMsg(gmtime($t)." (UTC) - ".$d);
+			}
+		
+			::rptMsg("");
+			::rptMsg("Analysis Tip: Correlate the Volume entries to those found in the MountedDevices");
+			::rptMsg("entries that begin with \"\\??\\Volume\"\.");
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/mpmru.pl b/thirdparty/rr/plugins/mpmru.pl
new file mode 100644
index 0000000000000000000000000000000000000000..701f0a802d607d782f940b76c03913cdb51f1df1
--- /dev/null
+++ b/thirdparty/rr/plugins/mpmru.pl
@@ -0,0 +1,75 @@
+#-----------------------------------------------------------
+# mpmru.pl
+# Plugin for Registry Ripper, NTUSER.DAT edition - gets the 
+# Media Player RecentFileList values 
+#
+# Change history
+#
+#
+# References
+#
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package mpmru;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets user's Media Player RecentFileList values";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching mpmru v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	
+	my $key_path = 'Software\\Microsoft\\MediaPlayer\\Player\\RecentFileList';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("Media Player - RecentFileList");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			my %files;
+# Retrieve values and load into a hash for sorting			
+			foreach my $v (@vals) {
+				my $val = $v->get_name();
+				my $data = $v->get_data();
+				my $tag = (split(/File/,$val))[1];
+				$files{$tag} = $val.":".$data;
+			}
+# Print sorted content to report file			
+			foreach my $u (sort {$a <=> $b} keys %files) {
+				my ($val,$data) = split(/:/,$files{$u},2);
+				::rptMsg("  ".$val." -> ".$data);
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/mrt.pl b/thirdparty/rr/plugins/mrt.pl
new file mode 100644
index 0000000000000000000000000000000000000000..89e9ebddafb7f6e5b53676f3da536f124220fb60
--- /dev/null
+++ b/thirdparty/rr/plugins/mrt.pl
@@ -0,0 +1,72 @@
+#-----------------------------------------------------------
+# mrt.pl
+#
+# Per http://support.microsoft.com/kb/891716/, whenever MRT is run, a new
+# GUID is written to the Version value.  Check the KB article to compare
+# GUIDs against the last time the tool was run.  Also be sure to check the 
+# MRT logs in %WinDir%\Debug (mrt.log)
+#
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package mrt;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              version       => 20080804);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Check to see if Malicious Software Removal Tool has been run";	
+}
+sub getDescr{}
+sub getRefs {"Deployment of the Microsoft Windows Malicious Software Removal Tool" => 
+	           		"http://support.microsoft.com/kb/891716/",
+	           "The Microsoft Windows Malicious Software Removal Tool" => "http://support.microsoft.com/?kbid=890830"}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching MRT v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+
+	my $key_path = "Microsoft\\RemovalTools\\MRT";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("Key Path: ".$key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my $version;
+		eval {
+			$version = $key->get_value("Version")->get_data();
+		};
+		if ($@) {
+			::rptMsg("Error getting Version information: ".$@);
+			
+		}
+		else {
+			::rptMsg("Version: ".$version);
+			::rptMsg("");
+			::rptMsg("Analysis Tip:  Go to http://support.microsoft.com/kb/891716/ to see when MRT");
+			::rptMsg("was last run.  According to the KB article, each time MRT is run, a new GUID");
+			::rptMsg("is written to the Version value.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/msis.pl b/thirdparty/rr/plugins/msis.pl
new file mode 100644
index 0000000000000000000000000000000000000000..cda7bc4cdd6b38a1c7a32ca32974d1dfd9396e9f
--- /dev/null
+++ b/thirdparty/rr/plugins/msis.pl
@@ -0,0 +1,96 @@
+#-----------------------------------------------------------
+# msis.pl
+# Plugin to determine the MSI packages installed on the system
+#
+# Change history:
+#   20090911 - created
+#
+# References:
+#   http://support.microsoft.com/kb/290134
+#   http://support.microsoft.com/kb/931401
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package msis;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090911);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Determine MSI packages installed on the system";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+my %msi;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching msis v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Classes\\Installer\\Products";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				my $lastwrite = $s->get_timestamp();
+				
+				my $product;
+				eval {
+					$product = $s->get_value("ProductName")->get_data();
+				};
+				
+				my $path;
+				my $pkg;
+				
+				eval {
+					my $p = $s->get_subkey("SourceList")->get_value("LastUsedSource")->get_data();
+					$path = (split(/;/,$p,3))[2];
+				};
+				
+				eval {
+					$pkg = $s->get_subkey("SourceList")->get_value("PackageName")->get_data();
+				};
+				
+				push(@{$msi{$lastwrite}},$product.";".$path.$pkg);
+			}
+			
+			
+			foreach my $t (reverse sort {$a <=> $b} keys %msi) {
+				::rptMsg(gmtime($t)." (UTC)");
+				foreach my $item (@{$msi{$t}}) {
+					::rptMsg("  ".$item);
+				}
+			}
+			
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/mspaper.pl b/thirdparty/rr/plugins/mspaper.pl
new file mode 100644
index 0000000000000000000000000000000000000000..da25ba65a09e61c3418e39d7cf3e28cbd888d442
--- /dev/null
+++ b/thirdparty/rr/plugins/mspaper.pl
@@ -0,0 +1,100 @@
+#-----------------------------------------------------------
+# mspaper.pl
+# Plugin for Registry Ripper, NTUSER.DAT edition - gets the 
+# MSPaper Recent File List values 
+#
+# Change history
+#
+#
+# References
+#
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package mspaper;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets images listed in user's MSPaper key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching mspaper v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $tick = 0;
+	my $key_path = 'Software\\Microsoft';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		my @subkeys = $key->get_list_of_subkeys();
+		
+		if (scalar @subkeys > 0) {
+			foreach my $sk (@subkeys) {
+				if ($sk->get_name() =~ m/^mspaper/i) {
+					$tick = 1;
+					my $nkey = $sk->get_name()."\\Recent File List";
+					my $msp;
+					if ($msp = $key->get_subkey($nkey)) {
+						::rptMsg("MSPaper - Recent File List");
+						::rptMsg($key_path."\\".$nkey);
+						::rptMsg("LastWrite Time ".gmtime($msp->get_timestamp())." (UTC)");
+						my @vals = $msp->get_list_of_values();
+						if (scalar(@vals) > 0) {
+							my %files;
+# Retrieve values and load into a hash for sorting			
+							foreach my $v (@vals) {
+								my $val = $v->get_name();
+								my $data = $v->get_data();
+								my $tag = (split(/File/,$val))[1];
+								$files{$tag} = $val.":".$data;
+							}
+# Print sorted content to report file			
+							foreach my $u (sort {$a <=> $b} keys %files) {
+								my ($val,$data) = split(/:/,$files{$u},2);
+								::rptMsg("  ".$val." -> ".$data);
+							}
+						}
+						else {
+							::rptMsg($key_path."\\".$nkey." has no values.");
+						}
+					}
+					else {
+						::rptMsg($key_path."\\".$nkey." not found.");
+						::logMsg("Error: ".$key_path."\\".$nkey." not found.");
+					}
+				}
+			}
+			if ($tick == 0) {
+				::rptMsg("SOFTWARE\\Microsoft\\MSPaper* not found.");
+				::logMsg("SOFTWARE\\Microsoft\\MSPaper* not found.");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/muicache.pl b/thirdparty/rr/plugins/muicache.pl
new file mode 100644
index 0000000000000000000000000000000000000000..8a980e3531d43d26da8743515c185ffb166cd17d
--- /dev/null
+++ b/thirdparty/rr/plugins/muicache.pl
@@ -0,0 +1,66 @@
+#! c:\perl\bin\perl.exe
+#-----------------------------------------------------------
+# muicache.pl
+# Plugin for Registry Ripper, NTUSER.DAT edition - gets the 
+# MUICache values 
+#
+# Change history
+#
+#
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package muicache;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets EXEs from user's MUICache key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching muicache v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	my $key_path = 'Software\\Microsoft\\Windows\\ShellNoRoam\\MUICache';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("MUICache");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				next if ($name =~ m/^@/ || $name eq "LangID");
+				my $data = $v->get_data();
+				::rptMsg("\t".$name." (".$data.")");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/nero.pl b/thirdparty/rr/plugins/nero.pl
new file mode 100644
index 0000000000000000000000000000000000000000..30b861326a30a141d8b29384a48331a680107061
--- /dev/null
+++ b/thirdparty/rr/plugins/nero.pl
@@ -0,0 +1,75 @@
+#-----------------------------------------------------------
+# nero.pl
+#   **Very Beta!  Based on one sample hive file only!
+#
+# Change history
+#   20100218 - created
+#
+# References
+#    
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package nero;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100218);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of Ahead\\Nero Recent File List subkeys";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+my @nerosubkeys = ("Cover Designer","FlmgPlg","Nero PhotoSnap",
+                   "NSPluginMgr","PhotoEffects","XlmgPlg");
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	my %hist;
+	::logMsg("Launching nero v.".$VERSION);
+	
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Ahead';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("");
+		foreach my $nsk (@nerosubkeys) {
+			eval {
+				my $nk;
+				if ($nk = $key->get_subkey($nsk."\\Recent File List")) {
+					my @vals = $nk->get_list_of_values();
+					if (scalar @vals > 0) {
+						::rptMsg($nsk."\\Recent File List");
+						::rptMsg("LastWrite Time ".gmtime($nk->get_timestamp())." (UTC)");
+						foreach my $v (@vals) {
+							::rptMsg("  ".$v->get_name()." -> ".$v->get_data());
+						}
+						::rptMsg("");
+					}
+					else {
+						::rptMsg($nsk."\\Recent File List has no values.");
+					}
+				}
+			};
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/network.pl b/thirdparty/rr/plugins/network.pl
new file mode 100644
index 0000000000000000000000000000000000000000..32853b31105d4b4624edb737dba119506c96b5e6
--- /dev/null
+++ b/thirdparty/rr/plugins/network.pl
@@ -0,0 +1,95 @@
+#-----------------------------------------------------------
+# network.pl
+# Plugin for Registry Ripper; Get information on network 
+# interfaces from the System hive file - from the
+# Control\Network GUID subkeys...
+# 
+# Change history
+#
+#
+# References
+#   
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package network;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets info from System\\Control\\Network GUIDs";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	my %nics;
+	my $ccs;
+	::logMsg("Launching network v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+		my $nw_path = $ccs."\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}";
+		my $nw;
+		if ($nw = $root_key->get_subkey($nw_path)) {
+			::rptMsg("Network key");
+			::rptMsg($nw_path);
+# Get all of the subkey names
+			my @sk = $nw->get_list_of_subkeys();
+			if (scalar(@sk) > 0) {
+				foreach my $s (@sk) {
+					my $name = $s->get_name();
+					next if ($name eq "Descriptions");
+					if (my $conn = $nw->get_subkey($name."\\Connection")) {
+						::rptMsg("Interface ".$name);
+						::rptMsg("LastWrite time ".gmtime($conn->get_timestamp())." (UTC)");
+						my %conn_vals;
+						my @vals = $conn->get_list_of_values();
+						map{$conn_vals{$_->get_name()} = $_->get_data()}@vals;
+						::rptMsg("\tName              = ".$conn_vals{Name});
+						::rptMsg("\tPnpInstanceID     = ".$conn_vals{PnpInstanceID});
+						::rptMsg("\tMediaSubType      = ".$conn_vals{MediaSubType});
+						::rptMsg("\tIpCheckingEnabled = ".$conn_vals{IpCheckingEnabled}) 
+							if (exists $conn_vals{IpCheckingEnabled});
+						
+					}
+					::rptMsg("");
+				}
+				
+			}
+			else {
+				::rptMsg($nw_path." has no subkeys.");
+			}			
+		}
+		else {
+			::rptMsg($nw_path." could not be found.");
+			::logMsg($nw_path." could not be found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/networkcards.pl b/thirdparty/rr/plugins/networkcards.pl
new file mode 100644
index 0000000000000000000000000000000000000000..c0ce64f41dcbec31d7c858bbce45d60a990b6ed7
--- /dev/null
+++ b/thirdparty/rr/plugins/networkcards.pl
@@ -0,0 +1,62 @@
+#-----------------------------------------------------------
+# networkcards
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package networkcards;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080325);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get NetworkCards";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching networkcards v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("NetworkCards");
+		::rptMsg($key_path);
+		::rptMsg("");
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			my %nc;
+			foreach my $s (@subkeys) {
+				my $service = $s->get_value("ServiceName")->get_data();
+				$nc{$service}{descr} = $s->get_value("Description")->get_data();
+				$nc{$service}{lastwrite} = $s->get_timestamp();
+			}
+			
+			foreach my $n (keys %nc) {
+				::rptMsg($nc{$n}{descr}."  [".gmtime($nc{$n}{lastwrite})."]");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/networklist.pl b/thirdparty/rr/plugins/networklist.pl
new file mode 100644
index 0000000000000000000000000000000000000000..babf87d7d647e3d120a54c44b8396fd6a2e58913
--- /dev/null
+++ b/thirdparty/rr/plugins/networklist.pl
@@ -0,0 +1,142 @@
+#-----------------------------------------------------------
+# networklist.pl - Plugin to extract information from the 
+#   NetworkList key, including the MAC address of the default
+#   gateway
+#
+#
+# Change History:
+#    20090812 - updated code to parse DateCreated and DateLastConnected
+#               values; modified output, as well
+#    20090811 - created
+#
+# References
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package networklist;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090811);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Collects network info from Vista NetworkList key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching networklist v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $base_path = "Microsoft\\Windows NT\\CurrentVersion\\NetworkList";
+	
+# First, get profile info	
+	my $key_path = $base_path."\\Profiles";
+	my $key;
+	my %nl; # hash of hashes to hold data
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+	
+		my @sk = $key->get_list_of_subkeys();
+		if (scalar(@sk) > 0) {
+			foreach my $s (@sk) {
+				my $name = $s->get_name();
+				$nl{$name}{LastWrite} = $s->get_timestamp();
+				eval {
+					$nl{$name}{ProfileName} = $s->get_value("ProfileName")->get_data();
+					$nl{$name}{Description} = $s->get_value("Description")->get_data();
+					$nl{$name}{Managed} = $s->get_value("Managed")->get_data();
+					
+					my $create = $s->get_value("DateCreated")->get_data();
+					$nl{$name}{DateCreated} = parseDate128($create) if (length($create) == 16);
+					my $conn   = $s->get_value("DateLastConnected")->get_data();
+					$nl{$name}{DateLastConnected} = parseDate128($conn) if (length($conn) == 16);
+					
+#					$nl{$name}{NameType} = $s->get_value("ProfileName")->get_data();
+				};
+			}
+
+# Get additional information from the Signatures subkey
+			$key_path = $base_path."\\Signatures\\Managed";
+			if ($key = $root_key->get_subkey($key_path)) { 
+				my @sk = $key->get_list_of_subkeys();
+				if (scalar(@sk) > 0) {
+					foreach my $s (@sk) {
+						eval {
+							my $prof = $s->get_value("ProfileGuid")->get_data();
+							my $tmp = substr($s->get_value("DefaultGatewayMac")->get_data(),0,6);
+							my $mac = uc(unpack("H*",$tmp));
+							my @t = split(//,$mac);
+							$nl{$prof}{DefaultGatewayMac} = $t[0].$t[1]."-".$t[2].$t[3].
+							         "-".$t[4].$t[5]."-".$t[6].$t[7]."-".$t[8].$t[9]."-".$t[10].$t[11];
+						};
+					}
+				}
+			}
+		
+			$key_path = $base_path."\\Signatures\\Unmanaged";
+			if ($key = $root_key->get_subkey($key_path)) { 
+				my @sk = $key->get_list_of_subkeys();
+				if (scalar(@sk) > 0) {
+					foreach my $s (@sk) {
+						eval {
+							my $prof = $s->get_value("ProfileGuid")->get_data();
+							my $tmp = substr($s->get_value("DefaultGatewayMac")->get_data(),0,6);
+							my $mac = uc(unpack("H*",$tmp));
+							my @t = split(//,$mac);
+							$nl{$prof}{DefaultGatewayMac} = $t[0].$t[1]."-".$t[2].$t[3].
+							         "-".$t[4].$t[5]."-".$t[6].$t[7]."-".$t[8].$t[9]."-".$t[10].$t[11]; 
+						};
+					}
+				}
+			}
+			
+# Now, display the information			
+			foreach my $n (keys %nl) {
+				my $str = sprintf "%-15s Gateway Mac: ".$nl{$n}{DefaultGatewayMac},$nl{$n}{ProfileName};
+				::rptMsg($nl{$n}{ProfileName});
+				::rptMsg("  Key LastWrite    : ".gmtime($nl{$n}{LastWrite})." UTC");
+				::rptMsg("  DateLastConnected: ".$nl{$n}{DateLastConnected});
+				::rptMsg("  DateCreated      : ".$nl{$n}{DateCreated});
+				::rptMsg("  DefaultGatewayMac: ".$nl{$n}{DefaultGatewayMac});
+				::rptMsg("");
+			}
+			
+		}
+		else {
+			::rptMsg($key_path." has not subkeys");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+
+
+sub parseDate128 {
+	my $date = $_[0];
+	my @months = ("Jan","Feb","Mar","Apr","May","Jun","Jul",
+	              "Aug","Sep","Oct","Nov","Dec");
+	my @days = ("Sun","Mon","Tue","Wed","Thu","Fri","Sat");
+	my ($yr,$mon,$dow,$dom,$hr,$min,$sec,$ms) = unpack("v*",$date);
+	$hr = "0".$hr if ($hr < 10);
+	$min = "0".$min if ($min < 10);
+	$sec = "0".$sec if ($sec < 10);
+	my $str = $days[$dow]." ".$months[$mon - 1]." ".$dom." ".$hr.":".$min.":".$sec." ".$yr;
+	return $str;
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/networkuid.pl b/thirdparty/rr/plugins/networkuid.pl
new file mode 100644
index 0000000000000000000000000000000000000000..7a457e111f3d493e4e165a7133dda6c1f7cd6751
--- /dev/null
+++ b/thirdparty/rr/plugins/networkuid.pl
@@ -0,0 +1,57 @@
+#-----------------------------------------------------------
+# networkuid.pl
+# Gets UID value from Network key
+# 
+# References
+#   http://blogs.technet.com/mmpc/archive/2010/03/11/got-zbot.aspx
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package networkuid;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100312);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Gets Network key UID value";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching networkuid v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\Network";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite time = ".gmtime($key->get_timestamp()));
+		::rptMsg("");
+		
+		eval {
+			my $uid = $key->get_value("UID")->get_data();
+			::rptMsg("UID value = ".$uid);
+		};
+		::rptMsg("UID value not found.") if ($@);
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/nic.pl b/thirdparty/rr/plugins/nic.pl
new file mode 100644
index 0000000000000000000000000000000000000000..f176150a92dcc485ddf23e855ab83d089e3c2906
--- /dev/null
+++ b/thirdparty/rr/plugins/nic.pl
@@ -0,0 +1,80 @@
+#-----------------------------------------------------------
+# nic.pl
+# 
+# 
+# Change history
+#    20100401 - created
+#
+# References
+#   LeaseObtainedTime - http://technet.microsoft.com/en-us/library/cc978465.aspx
+#   T1 - http://technet.microsoft.com/en-us/library/cc978470.aspx
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package nic;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100401);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets NIC info from System hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	my %nics;
+	my $ccs;
+	::logMsg("Launching nic v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	eval {
+		$current = $root_key->get_subkey("Select")->get_value("Current")->get_data();
+	};
+	my @nics;
+	my $key_path = "ControlSet00".$current."\\Services";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		my @svcs = $key->get_list_of_subkeys();
+		foreach my $s (@svcs) {
+			push(@nics,$s) if ($s->get_name() =~ m/^{/);
+		}
+		foreach my $n (@nics) {
+			eval {
+				my @vals = $n->get_subkey("Parameters\\Tcpip")->get_list_of_values();
+				::rptMsg("Adapter: ".$n->get_name());
+				::rptMsg("LastWrite Time: ".gmtime($n->get_timestamp())." Z");
+				foreach my $v (@vals) {
+					my $name = $v->get_name();
+					my $data = $v->get_data();
+					$data = gmtime($data)." Z" if ($name eq "T1" || $name eq "T2");
+					$data = gmtime($data)." Z" if ($name =~ m/Time$/);
+					
+					::rptMsg(sprintf "  %-20s %-20s",$name,$data);
+					
+				}
+				::rptMsg("");
+			};
+		}	
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/nic2.pl b/thirdparty/rr/plugins/nic2.pl
new file mode 100644
index 0000000000000000000000000000000000000000..44d4d8099a07ab12678a9a4912254adb0dc1eb5d
--- /dev/null
+++ b/thirdparty/rr/plugins/nic2.pl
@@ -0,0 +1,80 @@
+#-----------------------------------------------------------
+# nic2.pl
+# 
+# 
+# Change history
+#    20100401 - created
+#
+# References
+#   LeaseObtainedTime - http://technet.microsoft.com/en-us/library/cc978465.aspx
+#   T1 - http://technet.microsoft.com/en-us/library/cc978470.aspx
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package nic2;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100401);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets NIC info from System hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	my %nics;
+	my $ccs;
+	::logMsg("Launching nic v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	eval {
+		$current = $root_key->get_subkey("Select")->get_value("Current")->get_data();
+	};
+	my @nics;
+	my $key_path = "ControlSet00".$current."\\Services\\Tcpip\\Parameters\\Interfaces";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		my @guids = $key->get_list_of_subkeys();
+		if (scalar @guids > 0) {
+			foreach my $g (@guids) {
+				::rptMsg("Adapter: ".$g->get_name());
+				::rptMsg("LastWrite Time: ".gmtime($g->get_timestamp())." Z");
+				eval {
+					my @vals = $g->get_list_of_values();
+					foreach my $v (@vals) {
+						my $name = $v->get_name();
+						my $data = $v->get_data();
+						$data = gmtime($data)." Z" if ($name eq "T1" || $name eq "T2");
+						$data = gmtime($data)." Z" if ($name =~ m/Time$/);
+						::rptMsg(sprintf "  %-28s %-20s",$name,$data);
+					}
+					::rptMsg("");
+				};
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}	
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/nic_mst2.pl b/thirdparty/rr/plugins/nic_mst2.pl
new file mode 100644
index 0000000000000000000000000000000000000000..36c98b42708335c8e9bb9bd863bbf131a6a68353
--- /dev/null
+++ b/thirdparty/rr/plugins/nic_mst2.pl
@@ -0,0 +1,148 @@
+#-----------------------------------------------------------
+# nic_mst2.pl
+# Plugin for Registry Ripper; Get information on network 
+# interfaces from the System hive file - start with the
+# Control\Network GUID subkeys...within the Connection key,
+# look for MediaSubType == 2, and maintain a list of GUIDs.
+# Then go over to the Services\Tcpip\Parameters\Interfaces 
+# key and get the IP configurations for each of the interface
+# GUIDs
+# 
+# Change history
+#
+#
+# References
+#   http://support.microsoft.com/kb/555382
+#   http://support.microsoft.com/kb/894564
+#   http://support.microsoft.com/kb/899868
+#
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package nic_mst2;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets NICs from System hive; looks for MediaType = 2";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	my %nics;
+	my $ccs;
+	::logMsg("Launching nic_mst2 v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+		my $nw_path = $ccs."\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}";
+		my $nw;
+		if ($nw = $root_key->get_subkey($nw_path)) {
+			::rptMsg("Network key");
+			::rptMsg($nw_path);
+# Get all of the subkey names
+			my @sk = $nw->get_list_of_subkeys();
+			if (scalar(@sk) > 0) {
+				foreach my $s (@sk) {
+					my $name = $s->get_name();
+					next if ($name eq "Descriptions");
+					if (my $conn = $nw->get_subkey($name."\\Connection")) {
+						my %conn_vals;
+						my @vals = $conn->get_list_of_values();
+						map{$conn_vals{$_->get_name()} = $_->get_data()}@vals;
+# See what the active NICs were on the system; "active" based on PnpInstanceID having
+# a string value
+# Get the GUID of the interface, the name, and the LastWrite time of the Connection
+# key						
+						if (exists $conn_vals{PnpInstanceID} && $conn_vals{PnpInstanceID} ne "") {
+							$nics{$name}{Name} = $conn_vals{Name};
+							$nics{$name}{LastWrite} = $conn->get_timestamp();
+						}
+					}
+				}
+				
+			}
+			else {
+				::rptMsg($nw_path." has no subkeys.");
+			}			
+		}
+		else {
+			::rptMsg($nw_path." could not be found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+	::rptMsg("");
+# access the Tcpip Services key to get the IP address information	
+	if (scalar(keys %nics) > 0) {
+		my $key_path = $ccs."\\Services\\Tcpip\\Parameters\\Interfaces";
+		if ($key = $root_key->get_subkey($key_path)) {
+			my %guids;
+			::rptMsg($key_path);
+			::rptMsg("LastWrite time ".gmtime($key->get_timestamp())." (UTC)");
+			::rptMsg("");
+# Dump the names of the subkeys under Parameters\Interfaces into a hash			
+			my @sk = $key->get_list_of_subkeys();
+			map{$guids{$_->get_name()} = 1}(@sk);
+			
+			foreach my $n (keys %nics) {
+				if (exists $guids{$n}) {
+					my $if = $key->get_subkey($n);
+					::rptMsg("Interface ".$n);
+					::rptMsg("Name: ".$nics{$n}{Name});
+					::rptMsg("Control\\Network key LastWrite time ".gmtime($nics{$n}{LastWrite})." (UTC)");
+					::rptMsg("Services\\Tcpip key LastWrite time ".gmtime($if->get_timestamp())." (UTC)");
+					
+					my @vals = $if->get_list_of_values;
+					my %ip;
+					map{$ip{$_->get_name()} = $_->get_data()}@vals;
+					
+					if (exists $ip{EnableDHCP} && $ip{EnableDHCP} == 1) {
+						::rptMsg("\tDhcpDomain     = ".$ip{DhcpDomain});
+						::rptMsg("\tDhcpIPAddress  = ".$ip{DhcpIPAddress});
+						::rptMsg("\tDhcpSubnetMask = ".$ip{DhcpSubnetMask});
+						::rptMsg("\tDhcpNameServer = ".$ip{DhcpNameServer});
+						::rptMsg("\tDhcpServer     = ".$ip{DhcpServer});
+					}
+					else {
+						::rptMsg("\tIPAddress      = ".$ip{IPAddress});
+						::rptMsg("\tSubnetMask     = ".$ip{SubnetMask});
+						::rptMsg("\tDefaultGateway = ".$ip{DefaultGateway});
+					}
+					
+				}
+				else {
+					::rptMsg("Interface ".$n." not found in the ".$key_path." key.");
+				}
+				::rptMsg("");
+			}
+		}
+	}
+	else {
+		::rptMsg("No active network interface cards were found.");
+		::logMsg("No active network interface cards were found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/nolmhash.pl b/thirdparty/rr/plugins/nolmhash.pl
new file mode 100644
index 0000000000000000000000000000000000000000..94f253e63d3c893f528a115055f60083068f36d7
--- /dev/null
+++ b/thirdparty/rr/plugins/nolmhash.pl
@@ -0,0 +1,74 @@
+#-----------------------------------------------------------
+# nolmhash.pl
+# Gets NoLMHash value
+# 
+# Change history
+#   20100712 - created
+#
+# References
+#   http://support.microsoft.com/kb/299656
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package nolmhash;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100712);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets NoLMHash value";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching lsa v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my ($current,$ccs);
+	my $sel_path = 'Select';
+	my $sel;
+	if ($sel = $root_key->get_subkey($sel_path)) {
+		$current = $sel->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+		my $key_path = $ccs."\\Control\\Lsa";
+		my $key;
+		if ($key = $root_key->get_subkey($key_path)) {
+			::rptMsg("nolmhash v.".$VERSION);
+			::rptMsg($key_path);
+			::rptMsg("LastWrite: ".gmtime($key->get_timestamp()));
+			::rptMsg("");
+			my $nolmhash;
+			eval {
+				$nolmhash = $key->get_value("NoLMHash")->get_data();
+				::rptMsg("NoLMHash value = ".$nolmhash);
+				::rptMsg("");
+				::rptMsg("A value of 1 indicates that LMHashes are not stored in the SAM.");
+			};
+			::rptMsg("Error occurred getting NoLMHash value: $@") if ($@);
+		}
+		else {
+			::rptMsg($key_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($sel_path." not found.");
+		::logMsg($sel_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/notify.pl b/thirdparty/rr/plugins/notify.pl
new file mode 100644
index 0000000000000000000000000000000000000000..8919b6dbd9ff6c9d1b8db806f6d616c7eedb1bd3
--- /dev/null
+++ b/thirdparty/rr/plugins/notify.pl
@@ -0,0 +1,79 @@
+#-----------------------------------------------------------
+# notify.pl
+# 
+#
+# Change History:
+#   20110309 - updated output format to sort entries based on
+#              LastWrite time
+#   20110308 - created
+#
+# References
+#   http://blogs.technet.com/b/markrussinovich/archive/2011/03/08/3392087.aspx
+#
+# copyright 2011 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package notify;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20110309);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get Notify subkey entries";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+my %notify;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching notify v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("notify");
+		::rptMsg($key_path);
+		::rptMsg("");
+		my @sk = $key->get_list_of_subkeys();
+		if (scalar(@sk) > 0) {
+			foreach my $s (@sk) {
+				my $name = $s->get_name();
+				my $lw = $s->get_timestamp();
+				my $dll;
+				eval {
+					$dll = $s->get_value("DLLName")->get_data();
+					push(@{$notify{$lw}},sprintf "%-15s %-25s",$name,$dll);
+				};
+			}
+			
+			foreach my $t (reverse sort {$a <=> $b} keys %notify) {
+				::rptMsg(gmtime($t)." UTC");
+				foreach my $i (@{$notify{$t}}) {
+					::rptMsg("  ".$i);
+				}
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/ntuser b/thirdparty/rr/plugins/ntuser
new file mode 100644
index 0000000000000000000000000000000000000000..f2d6b0a3666232c8fc373e52cd021d8335c19c80
--- /dev/null
+++ b/thirdparty/rr/plugins/ntuser
@@ -0,0 +1,50 @@
+# List of plugins for the Registry Ripper
+
+#-------------------------------------
+# NTUSER.DAT
+logonusername
+autoendtasks
+autorun
+acmru
+adoberdr
+aim
+applets
+comdlg32
+compdesc
+# The controlpanel plugin is intended for Vista systems only
+# User hives from systems prior to Vista will show 'not found'
+controlpanel
+listsoft  
+logon_xp_run
+load
+mmc
+mndmru 
+mp2
+mpmru 
+mspaper  
+officedocs
+oisc
+recentdocs
+realplayer6
+runmru
+tsclient
+ie_main
+ie_settings
+typedurls
+muicache
+#userassist
+userassist2
+user_run
+userlocsvc
+vncviewer
+winzip
+user_win
+winrar
+winlogon_u
+policies_u
+wallpaper
+vista_bitbucket
+shellfolders
+arpcache
+clampitm
+unreadmail
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/officedocs.pl b/thirdparty/rr/plugins/officedocs.pl
new file mode 100644
index 0000000000000000000000000000000000000000..8182a3d177a67f68132cc22795097ddd2a9b978f
--- /dev/null
+++ b/thirdparty/rr/plugins/officedocs.pl
@@ -0,0 +1,145 @@
+#-----------------------------------------------------------
+# officedocs.pl
+# Plugin for Registry Ripper 
+#
+# Change history
+#
+#
+# References
+#
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package officedocs;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of user's Office doc MRU keys";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching officedocs v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	::rptMsg("officedocs v.".$VERSION);
+# First, let's find out which version of Office is installed
+	my $version;
+	my $tag = 0;
+	my @versions = ("7\.0","8\.0", "9\.0", "10\.0", "11\.0","12\.0");
+	foreach my $ver (@versions) {
+		my $key_path = "Software\\Microsoft\\Office\\".$ver."\\Common\\Open Find";
+		if (defined($root_key->get_subkey($key_path))) {
+			$version = $ver;
+			$tag = 1;
+		}
+	}
+	
+	if ($tag) {
+		::rptMsg("MSOffice version ".$version." located.");
+		my $key_path = "Software\\Microsoft\\Office\\".$version;	                 
+		my $of_key = $root_key->get_subkey($key_path);
+		if ($of_key) {
+# Attempt to retrieve Word docs			
+			my @funcs = ("Open","Save As","File Save");
+			foreach my $func (@funcs) {
+				my $word = "Common\\Open Find\\Microsoft Office Word\\Settings\\".$func."\\File Name MRU";
+				my $word_key = $of_key->get_subkey($word);
+				if ($word_key) {
+					::rptMsg($word);
+					::rptMsg("LastWrite Time ".gmtime($word_key->get_timestamp())." (UTC)");
+					::rptMsg("");
+					my $value = $word_key->get_value("Value")->get_data();
+					my @data = split(/\00/,$value);
+					map{::rptMsg("$_");}@data;
+				}
+				else {
+#					::rptMsg("Could not access ".$word);
+				}
+				::rptMsg("");
+			}
+# Attempt to retrieve Excel docs
+			my $excel = 'Excel\\Recent Files';
+			if (my $excel_key = $of_key->get_subkey($excel)) {
+				::rptMsg($key_path."\\".$excel);
+				::rptMsg("LastWrite Time ".gmtime($excel_key->get_timestamp())." (UTC)");
+				my @vals = $excel_key->get_list_of_values();
+				if (scalar(@vals) > 0) {
+					my %files;
+# Retrieve values and load into a hash for sorting			
+					foreach my $v (@vals) {
+						my $val = $v->get_name();
+						my $data = $v->get_data();
+						my $tag = (split(/File/,$val))[1];
+						$files{$tag} = $val.":".$data;
+					}
+# Print sorted content to report file			
+					foreach my $u (sort {$a <=> $b} keys %files) {
+						my ($val,$data) = split(/:/,$files{$u},2);
+						::rptMsg("  ".$val." -> ".$data);
+					}
+				}
+				else {
+					::rptMsg($key_path.$excel." has no values.");
+				}
+			}
+			else {
+				::rptMsg($key_path.$excel." not found.");
+			}
+			::rptMsg("");
+# Attempt to retrieve PowerPoint docs			
+			my $ppt = 'PowerPoint\\Recent File List';
+			if (my $ppt_key = $of_key->get_subkey($ppt)) {
+				::rptMsg($key_path."\\".$ppt);
+				::rptMsg("LastWrite Time ".gmtime($ppt_key->get_timestamp())." (UTC)");
+				my @vals = $ppt_key->get_list_of_values();
+				if (scalar(@vals) > 0) {
+					my %files;
+# Retrieve values and load into a hash for sorting			
+					foreach my $v (@vals) {
+						my $val = $v->get_name();
+						my $data = $v->get_data();
+						my $tag = (split(/File/,$val))[1];
+						$files{$tag} = $val.":".$data;
+					}
+# Print sorted content to report file			
+					foreach my $u (sort {$a <=> $b} keys %files) {
+						my ($val,$data) = split(/:/,$files{$u},2);
+						::rptMsg("  ".$val." -> ".$data);
+					}
+				}
+				else {
+					::rptMsg($key_path."\\".$ppt." has no values.");
+				}		
+			}
+			else {
+				::rptMsg($key_path."\\".$ppt." not found.");
+			}			
+		}
+		else {
+			::rptMsg("Could not access ".$key_path);
+			::logMsg("Could not access ".$key_path);
+		}
+	}
+	else {
+		::logMsg("MSOffice version not found.");
+		::rptMsg("MSOffice version not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/oisc.pl b/thirdparty/rr/plugins/oisc.pl
new file mode 100644
index 0000000000000000000000000000000000000000..2ddad0697396c99d788ddc49e8084dc449247033
--- /dev/null
+++ b/thirdparty/rr/plugins/oisc.pl
@@ -0,0 +1,123 @@
+#-----------------------------------------------------------
+# oisc.pl
+# Plugin for Registry Ripper 
+#
+# Change history
+#   20091125 - modified by H. Carvey
+#   20091110 - created
+#
+# References
+#   http://support.microsoft.com/kb/838028
+#   http://support.microsoft.com/kb/916658
+# 
+# Derived from the officeDocs plugin
+# copyright 2008-2009 H. Carvey, mangled 2009 M. Tarnawsky
+#
+# Michael Tarnawsky
+# forensics@mialta.com
+#-----------------------------------------------------------
+package oisc;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20091125);
+
+my %prot = (0 => "Read-only HTTP",
+            1 => "WEC to FPSE-enabled web folder",
+            2 => "DAV to DAV-ext. web folder");
+
+my %types = (0 => "no collaboration",
+            1 => "SharePoint Team Server",
+            2 => "Exchange 2000 Server",
+            3 => "SharePoint Portal 2001 Server",
+            4 => "SharePoint 2001 enhanced folder",
+            5 => "Windows SharePoint Server/SharePoint Portal 2003 Server");
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of user's Office Internet Server Cache";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching oisc v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+# First, let's find out which version of Office is installed
+	my $version;
+	my $tag = 0;
+	my @versions = ("7\.0","8\.0", "9\.0", "10\.0", "11\.0","12\.0");
+	foreach my $ver (@versions) {
+		my $key_path = "Software\\Microsoft\\Office\\".$ver."\\Common\\Internet\\Server Cache";
+		if (defined($root_key->get_subkey($key_path))) {
+			$version = $ver;
+			$tag = 1;
+		}
+	}
+	
+	if ($tag) {
+		
+		my %isc;
+		
+		::rptMsg("MSOffice version ".$version." located.");
+		my $key_path = "Software\\Microsoft\\Office\\".$version."\\Common\\Internet\\Server Cache";			
+		my $sc_key;
+		if ($sc_key = $root_key->get_subkey($key_path)) {
+# Attempt to retrieve Servers Cache subkeys
+			my @sc = ($sc_key->get_list_of_subkeys());
+			if (scalar(@sc) > 0) {
+				foreach my $s (@sc) {
+					my $name = $s->get_name();
+					$isc{$name}{lastwrite} = $s->get_timestamp();
+					
+					eval {
+						my $t = $s->get_value("Type")->get_data();
+						(exists $types{$t}) ? ($isc{$name}{type} = $types{$t})
+						                    : ($isc{$name}{type} = $t);
+					};
+					
+					eval {
+						my $p = $s->get_value("Protocol")->get_data();
+						(exists $prot{$p}) ? ($isc{$name}{protocol} = $prot{$p}) 
+						                   : ($isc{$name}{protocol} = $p);
+					};
+					
+					eval {
+						my @e = unpack("VV",$s->get_value("Expiration")->get_data());
+						$isc{$name}{expiry} = ::getTime($e[0],$e[1]);
+					};
+				}
+				::rptMsg("");
+				foreach my $i (keys %isc) {
+					::rptMsg($i);
+					::rptMsg("  LastWrite : ".gmtime($isc{$i}{lastwrite})." UTC");
+					::rptMsg("  Expiry    : ".gmtime($isc{$i}{expiry})." UTC");
+					::rptMsg("  Protocol  : ".$isc{$i}{protocol});
+					::rptMsg("  Type      : ".$isc{$i}{type});
+					::rptMsg("");
+				}
+			}
+			else {
+				::rptMsg($key_path." has no subkeys.");
+			}
+		}
+		else {
+			::rptMsg($key_path." not found.");
+		}
+	}
+	else {
+		::rptMsg("MSOffice version not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/outlook.pl b/thirdparty/rr/plugins/outlook.pl
new file mode 100644
index 0000000000000000000000000000000000000000..eafc9b3ade16c0b2733ba9f969009b0153a145b3
--- /dev/null
+++ b/thirdparty/rr/plugins/outlook.pl
@@ -0,0 +1,186 @@
+#-----------------------------------------------------------
+# outlook.pl
+#   **Very Beta!  Based on one sample hive file only!
+#
+# Change history
+#   20100218 - created
+#
+# References
+#    
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package outlook;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100218);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets user's Outlook settings";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	my %hist;
+	::logMsg("Launching outlook v.".$VERSION);
+	
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows Messaging Subsystem\\Profiles';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar @subkeys > 0) {
+			::rptMsg("");
+			foreach my $s (@subkeys) {
+				
+				my $profile = $s->get_name();
+				::rptMsg($profile." Profile");
+
+# AutoArchive settings
+# http://support.microsoft.com/kb/198479				
+				eval {
+					my $data = $s->get_subkey("0a0d020000000000c000000000000046")->get_value("001f0324")->get_data();
+					$data =~ s/\00//g;
+					::rptMsg("  Outlook 2007 AutoArchive path -> ".$data);
+				};
+				
+				eval {
+					my $data = $s->get_subkey("0a0d020000000000c000000000000046")->get_value("001e0324")->get_data();
+					$data =~ s/\00//g;
+					::rptMsg("  Outlook 2003 AutoArchive path -> ".$data);
+				};
+				
+				eval {
+					my $data = $s->get_subkey("0a0d020000000000c000000000000046")->get_value("001e032c")->get_data();
+					$data =~ s/\00//g;
+					::rptMsg("  Outlook 2003 AutoArchive path (alt) -> ".$data);
+				};
+				
+# http://support.microsoft.com/kb/288570				
+				eval {
+					my $data = $s->get_subkey("0a0d020000000000c000000000000046")->get_value("101e0384")->get_data();
+					$data =~ s/\00//g;
+					::rptMsg("  Open Other Users MRU (Outlook 97) -> ".$data);
+				};
+				
+				eval {
+					my $data = $s->get_subkey("0a0d020000000000c000000000000046")->get_value("101f0390")->get_data();
+					$data =~ s/\00//g;
+					::rptMsg("  Open Other Users MRU (Outlook 2003) -> ".$data);
+				};
+				
+				
+				
+				eval {
+					my $data = unpack("V",$s->get_subkey("13dbb0c8aa05101a9bb000aa002fc45a")->get_value("00036601")->get_data());
+					my $str;
+					if ($data == 4) {
+						$str = "  Cached Exchange Mode disabled.";
+					}
+					elsif ($data == 4484) {
+						$str = "  Cached Exchange Mode enabled.";
+					}
+					else {
+						$str = sprintf "  Cached Exchange Mode: 0x%x",$data;
+					}
+					::rptMsg($str);
+				};
+				
+				eval {
+					my $data = $s->get_subkey("13dbb0c8aa05101a9bb000aa002fc45a")->get_value("001f6610")->get_data();
+					$data =~ s/\00//g;
+					::rptMsg("  Path to OST file: ".$data);
+				};
+				
+				eval {
+					my $data = $s->get_subkey("13dbb0c8aa05101a9bb000aa002fc45a")->get_value("001f6607")->get_data();
+					$data =~ s/\00//g;
+					::rptMsg("  Email: ".$data);
+				};
+				
+				eval {
+					my $data = $s->get_subkey("13dbb0c8aa05101a9bb000aa002fc45a")->get_value("001f6620")->get_data();
+					$data =~ s/\00//g;
+					::rptMsg("  Email: ".$data);
+				};
+				
+# http://support.microsoft.com/kb/959956				
+#				eval {
+#					my $data = $s->get_subkey("13dbb0c8aa05101a9bb000aa002fc45a")->get_value("01026687")->get_data();
+#					$data =~ s/\00/\./g;
+#					$data =~ s/\W//g;
+#					::rptMsg("  Non-SMTP Email: ".$data);
+#				};
+				
+				
+					
+					
+					
+					
+					
+				
+				
+				
+				
+				
+				
+				
+				eval {
+					my $data = $s->get_subkey("0a0d020000000000c000000000000046")->get_value("001e032c")->get_data();
+					$data =~ s/\00//g;
+					::rptMsg("  Outlook 2003 AutoArchive path (alt) -> ".$data);
+				};
+		
+		
+			
+				
+				
+				
+				eval {
+					my $data = $s->get_subkey("0a0d020000000000c000000000000046")->get_value("001f0418")->get_data();
+					$data =~ s/\00//g;
+					::rptMsg("  001f0418 -> ".$data);
+				};
+#				::rptMsg("Error : ".$@) if ($@);
+				
+				
+# Account Names and signatures
+# http://support.microsoft.com/kb/938360			
+				my @subkeys = $s->get_subkey("9375CFF0413111d3B88A00104B2A6676")->get_list_of_subkeys();
+				if (scalar @subkeys > 0) {
+					
+					foreach my $s2 (@subkeys) {
+						eval {
+							
+							
+						};
+					}
+				}
+				
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/pagefile.pl b/thirdparty/rr/plugins/pagefile.pl
new file mode 100644
index 0000000000000000000000000000000000000000..f0484de43169f3628d117b2474caca9dfb0ff05b
--- /dev/null
+++ b/thirdparty/rr/plugins/pagefile.pl
@@ -0,0 +1,71 @@
+#-----------------------------------------------------------
+# pagefile.pl
+#
+# Ref: 
+#
+#   http://support.microsoft.com/kb/314834 - ClearPagefileAtShutdown
+#
+# copyright 2008-2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package pagefile;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20081212);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get info on pagefile(s)";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching pagefile v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		
+		my $mm_path = "ControlSet00".$current."\\Control\\Session Manager\\Memory Management";
+		my $mm;
+		if ($mm = $root_key->get_subkey($mm_path)) {
+			
+			eval {
+				my $files = $mm->get_value("PagingFiles")->get_data();
+				::rptMsg("PagingFiles = ".$files);
+			};
+			::rptMsg($@) if ($@);
+			
+			eval {
+				my $cpf = $mm->get_value("ClearPageFileAtShutdown")->get_data();
+				::rptMsg("ClearPageFileAtShutdown = ".$cpf);
+			};
+			
+		}	
+		else {
+			::rptMsg($mm_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
diff --git a/thirdparty/rr/plugins/polacdms.pl b/thirdparty/rr/plugins/polacdms.pl
new file mode 100644
index 0000000000000000000000000000000000000000..83efc86670d858e4fb11a2db9dd8c9d978e16830
--- /dev/null
+++ b/thirdparty/rr/plugins/polacdms.pl
@@ -0,0 +1,93 @@
+#-----------------------------------------------------------
+# polacdms
+# Get the audit policy from the Security hive file; also, gets
+# 
+# 
+# Change History:
+#   20100531 - Created
+#
+# References:
+#   http://en.wikipedia.org/wiki/Security_Identifier
+#
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package polacdms;
+use strict;
+
+my %config = (hive          => "Security",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100531);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get local machine SID from Security hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching polacdms v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Policy\\PolAcDmS";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("PolAcDmS");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my $data;
+		eval {
+			$data = $key->get_value("")->get_data();
+		};
+		if ($@) {
+			::rptMsg("Error occurred getting data from ".$key_path);
+			::rptMsg(" - ".$@);
+		}
+		else {
+			my @d = unpack("V4",substr($data,8,16));
+			::rptMsg("Machine SID: S-1-5-".(join('-',@d)));
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+	::rptMsg("");
+	my $key_path = "Policy\\PolPrDmS";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("PolPrDmS");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my $data;
+		eval {
+			$data = $key->get_value("")->get_data();
+		};
+		if ($@) {
+			::rptMsg("Error occurred getting data from ".$key_path);
+			::rptMsg(" - ".$@);
+		}
+		else {
+			my @d = unpack("V4",substr($data,8,16));
+			::rptMsg("Primary Domain SID: S-1-5-".(join('-',@d)));
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/policies_u.pl b/thirdparty/rr/plugins/policies_u.pl
new file mode 100644
index 0000000000000000000000000000000000000000..9a15c131124053e686181634e9d467353da6caf8
--- /dev/null
+++ b/thirdparty/rr/plugins/policies_u.pl
@@ -0,0 +1,73 @@
+#-----------------------------------------------------------
+# policies_u
+# Get values from user's WinLogon key
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package policies_u;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20091021);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get values from the user's Policies key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching policies_u v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path."\\policies")) {
+#		::rptMsg("policies key found.");
+		
+	}
+	elsif ($key = $root_key->get_subkey($key_path."\\Policies")) {
+#		::rptMsg("Policies key found.");
+		
+	}
+	else {
+		::rptMsg("Neither policies nor Policies key found.");
+		return;
+	}
+	
+	eval {
+		my @vals = $key->get_subkey("Explorer")->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			::rptMsg("");
+			::rptMsg("Explorer subkey values:");
+			foreach my $v (@vals) {
+				my $str = sprintf "%-20s %-20s",$v->get_name(),$v->get_data();
+				::rptMsg("  ".$str);
+			}
+		}
+	};
+	::rptMsg("");
+	eval {
+		my $quota = $key->get_subkey("System")->get_value("EnableProfileQuota")->get_data();
+		::rptMsg("EnableProfileQuota = ".$quota);
+		::rptMsg("");
+		::rptMsg("The EnableProfileQuota = 1 setting causes the proquota\.exe to be run");
+		::rptMsg("automatically in order to limit the size of roaming profiles\.  This");
+		::rptMsg("corresponds to the Limit Profile Size GPO setting\.");
+	};
+	::rptMsg("System\\EnableProfileQuota value not found\.") if ($@);
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/port_dev.pl b/thirdparty/rr/plugins/port_dev.pl
new file mode 100644
index 0000000000000000000000000000000000000000..3ceaf1ae7336a41ba7e4dabd8eeb726d42ece711
--- /dev/null
+++ b/thirdparty/rr/plugins/port_dev.pl
@@ -0,0 +1,89 @@
+#-----------------------------------------------------------
+# port_dev
+# Parse Microsoft\Windows Portable Devices\Devices key on Vista
+# Get historical information about drive letter assigned to devices
+#
+# NOTE: Credit for "discovery" goes to Rob Lee
+#
+# Change History:
+#  20090118 - changed the name of the plugin from "removdev"
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package port_dev;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 192,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090118);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Parses Windows Portable Devices key (Vista)";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching port_dev v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows Portable Devices\\Devices";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("RemovDev");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			
+			foreach my $s (@subkeys) {
+				my $name = $s->get_name();
+				my $lastwrite = $s->get_timestamp();
+				
+				my $letter;
+				eval {
+					$letter = $s->get_value("FriendlyName")->get_data();
+				};
+				::rptMsg($name." key error: $@") if ($@);
+				
+				my $half;
+				if (grep(/##/,$name)) {
+					$half = (split(/##/,$name))[1];
+				}
+					
+				if (grep(/\?\?/,$name)) {
+					$half = (split(/\?\?/,$name))[1];
+				}
+			
+				my ($dev,$sn) = (split(/#/,$half))[1,2];
+				
+				::rptMsg("Device    : ".$dev);
+				::rptMsg("LastWrite : ".gmtime($lastwrite)." (UTC)");
+				::rptMsg("SN        : ".$sn);				
+				::rptMsg("Drive     : ".$letter);
+				::rptMsg("");
+				
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/printermru.pl b/thirdparty/rr/plugins/printermru.pl
new file mode 100644
index 0000000000000000000000000000000000000000..531f1f19adbfaa9f93dd195aa9830ea93fe8765e
--- /dev/null
+++ b/thirdparty/rr/plugins/printermru.pl
@@ -0,0 +1,74 @@
+#-----------------------------------------------------------
+# printermru.pl
+# Plugin to get RealVNC MRU listings from NTUSER.DAT 
+#
+# Change history
+#   20091125 - created
+#
+# References
+#
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package printermru;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20091125);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets user's Printer Wizard MRU listing";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching printermru v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Printers\\Settings\\Wizard\\ConnectMRU';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			my %mru;
+			my @list;
+			foreach my $v (@vals) {
+				$mru{$v->get_name()} = $v->get_data();
+			}
+			
+			if (exists $mru{MRUList}) {
+				@list = split(//,$mru{MRUList});
+			}
+			
+			::rptMsg("Printers listed in MRUList order.");
+			foreach my $i (0..scalar(@list) - 1) {
+				::rptMsg("  ".$list[$i]." -> ".$mru{$list[$i]});
+			}
+			
+			
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/printers.pl b/thirdparty/rr/plugins/printers.pl
new file mode 100644
index 0000000000000000000000000000000000000000..b01c920078dc60f2b94e077f0a037bc72f325f72
--- /dev/null
+++ b/thirdparty/rr/plugins/printers.pl
@@ -0,0 +1,83 @@
+#-----------------------------------------------------------
+# printers.pl
+#   Get information about printers used by a user; System hive
+#   info is volatile
+#
+# Ref: 
+#   http://support.microsoft.com/kb/102966
+#   http://support.microsoft.com/kb/252388
+#   http://support.microsoft.com/kb/102116
+#
+#   The following references contain information from the System
+#   hive that is volatile.
+#   http://www.undocprint.org/winspool/registry
+#   http://msdn.microsoft.com/en-us/library/aa394363(VS.85).aspx
+#   
+# copyright 2008-2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package printers;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090223);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get user's printers";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching printers v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows NT\\CurrentVersion\\PrinterPorts";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time: ".gmtime($key->get_timestamp()));
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				::rptMsg("  ".$v->get_name()." (".$v->get_data().")");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+		::rptMsg("");
+# Get default printer
+		my $def_path = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows";
+		my $def;
+		eval {
+			$def = $root_key->get_subkey($def_path)->get_value("Device")->get_data();
+			::rptMsg("Default Printer (via CurrentVersion\\Windows): ".$def);
+		};
+# another attempt to get the default printer
+		my $def_path = "Printers";
+		my $def;
+		eval {
+			$def = $root_key->get_subkey($def_path)->get_value("DeviceOld")->get_data();
+			::rptMsg("Default Printer (via Printers->DeviceOld): ".$def);
+		};		
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/product.pl b/thirdparty/rr/plugins/product.pl
new file mode 100644
index 0000000000000000000000000000000000000000..6a70d719f496a7dd4cdd438589e856c62cc07c9e
--- /dev/null
+++ b/thirdparty/rr/plugins/product.pl
@@ -0,0 +1,118 @@
+#-----------------------------------------------------------
+# product.pl
+# Plugin to determine the MSI packages installed on the system
+#
+# Change history:
+#   20100325 - created
+#
+# References:
+#   http://support.microsoft.com/kb/236590
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package product;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100325);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get installed product info";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+my %msi;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching product v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows\\CurrentVersion\\Installer\\UserData";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("");
+		::rptMsg($key_path);
+#		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+# Each of these subkeys should be SIDs
+			foreach my $s (@subkeys) {
+				next unless ($s->get_name() =~ m/^S/);
+				::rptMsg($s->get_name());
+				if ($s->get_subkey("Products")) {
+					processSIDKey($s->get_subkey("Products"));
+					::rptMsg("");
+				}
+				else {
+					::rptMsg($s->get_name()."\\Products subkey not found.");
+				}
+			}			
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+sub processSIDKey {
+	my $key = shift;
+	my %prod;
+	my @subkeys = $key->get_list_of_subkeys();
+	if (scalar(@subkeys) > 0) {
+#		::rptMsg($key->get_name());
+		foreach my $s (@subkeys) {
+			my ($displayname,$lastwrite);
+			eval {
+				$displayname = $s->get_subkey("InstallProperties")->get_value("DisplayName")->get_data();
+				$lastwrite   = $s->get_subkey("InstallProperties")->get_timestamp();
+			};
+			
+			my $displayversion;
+			eval {
+				$displayversion = $s->get_subkey("InstallProperties")->get_value("DisplayVersion")->get_data();
+			};
+			
+			my $installdate;
+			eval {
+				$installdate = $s->get_subkey("InstallProperties")->get_value("InstallDate")->get_data();
+			};
+			
+			my $str = $displayname." v.".$displayversion.", ".$installdate;
+			push(@{$prod{$lastwrite}},$str);
+		}
+		
+		foreach my $t (reverse sort {$a <=> $b} keys %prod) {
+			::rptMsg(gmtime($t)." Z");
+			foreach my $i (@{$prod{$t}}) {
+				::rptMsg("  ".$i);
+			}
+		}
+		
+		
+	}
+	else {
+		::rptMsg($key->get_name()." has no subkeys.");
+		return;
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/productpolicy.pl b/thirdparty/rr/plugins/productpolicy.pl
new file mode 100644
index 0000000000000000000000000000000000000000..9437b84fbe3b12a527baf445e65de0b4c5b04de5
--- /dev/null
+++ b/thirdparty/rr/plugins/productpolicy.pl
@@ -0,0 +1,145 @@
+#-----------------------------------------------------------
+# productpolicy.pl
+# Extract/parse the ControlSet00x\Control\ProductOptions\ProductPolicy value
+# 
+# NOTE: For Vista and 2008 ONLY; the value structure changed with Windows 7
+# 
+# Change History:
+#    20091116 - created
+#
+# Ref: 
+#    http://www.geoffchappell.com/viewer.htm?doc=studies/windows/km/ntoskrnl/
+#            api/ex/slmem/productpolicy.htm&tx=19
+#    http://www.geoffchappell.com/viewer.htm?doc=notes/windows/license/
+#            install.htm&tx=3,5,6;4        
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package productpolicy;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20091116);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Parse ProductPolicy value (Vista & Win2008 ONLY)";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+my %prodinfo = (1 => "Ultimate",
+                2 => "Home Basic",
+                3 => "Home Premium",
+                5 => "Home Basic N",
+                6 => "Business",
+                7 => "Standard",
+                8 => "Data Center",
+                10 => "Enterprise",
+                11 => "Starter",
+                12 => "Data Center Core",
+                13 => "Standard Core",
+                14 => "Enterprise Core",
+                15 => "Business N");
+	
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	
+	::logMsg("Launching productpolicy v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	
+	my $curr;
+	eval {
+		$curr = $root_key->get_subkey("Select")->get_value("Current")->get_data();
+	};
+	$curr = 1 if ($@); 
+	
+	my $key;
+	my $key_path = "ControlSet00".$curr."\\Control\\ProductOptions";
+	if ($key = $root_key->get_subkey($key_path)) {
+		my $prod;
+		eval {
+			$prod = $key->get_value("ProductPolicy")->get_data();
+		};
+		if ($@) {
+			::rptMsg("Error getting ProductPolicy value: $@");
+		}
+		else {	
+			my %pol = parseData($prod);	
+			::rptMsg("");
+			::rptMsg("Note: This plugin applies to Vista and Windows 2008 ONLY.");
+			::rptMsg("For a listing of names and values, see:");
+			::rptMsg("http://www.geoffchappell.com/viewer.htm?doc=notes/windows/license/install.htm&tx=3,5,6;4");
+			::rptMsg("");	
+			foreach my $p (sort keys %pol) {
+				::rptMsg($p." - ".$pol{$p});
+			}
+			
+			if (exists $prodinfo{$pol{"Kernel\-ProductInfo"}}) {
+				::rptMsg("");
+				::rptMsg("Kernel\-ProductInfo = ".$prodinfo{$pol{"Kernel\-ProductInfo"}});
+			}
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+sub parseHeader {
+# Ref: http://www.geoffchappell.com/viewer.htm?doc=studies/windows/km/ntoskrnl/
+#             api/ex/slmem/productpolicy.htm&tx=19,21
+	my %h;
+	my @v = unpack("V*",shift);
+	$h{size} = $v[0];
+	$h{array} = $v[1];
+	$h{marker} = $v[2];
+	$h{version} = $v[4];
+	return %h;
+}
+
+sub parseData {
+	my $pd = shift;
+	my %policy;
+	my $h = substr($pd,0,0x14);
+	my %hdr = parseHeader($h);
+	my $total_size = $hdr{size};
+	my $cursor = 0x14;
+	
+	while ($cursor <= $total_size) {
+		my @vals = unpack("v4V2",	substr($pd,$cursor,0x10));	
+		my $value = substr($pd,$cursor,$vals[0]);
+		my $name = substr($value,0x10,$vals[1]);
+		$name =~ s/\00//g;
+		
+		my $data = substr($value,0x10 + $vals[1],$vals[3]);
+		if ($vals[2] == 4) {
+#			$data = sprintf "0x%x",unpack("V",$data);
+			$data = unpack("V",$data);
+		}
+		elsif ($vals[2] == 1) {
+			$data =~ s/\00//g;
+		}
+		elsif ($vals[2] == 3) {
+			$data = unpack("H*",$data);
+		}
+		else {
+			
+		} 
+		$policy{$name} = $data;
+		$cursor += $vals[0];
+	}
+	delete $policy{""};
+	return %policy;
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/producttype.pl b/thirdparty/rr/plugins/producttype.pl
new file mode 100644
index 0000000000000000000000000000000000000000..41b39677b6debb09debdadedf3de584ebf2a9585
--- /dev/null
+++ b/thirdparty/rr/plugins/producttype.pl
@@ -0,0 +1,88 @@
+#-----------------------------------------------------------
+# producttype.pl
+# Determine Windows product information
+#
+# History
+#    20100713 - updated reference info, formatting
+#    20100325 - renamed to producttype.pl
+#
+# References
+#    http://support.microsoft.com/kb/181412
+#    http://support.microsoft.com/kb/152078
+#
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package producttype;
+use strict;
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100325);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Queries System hive for Windows Product info";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching producttype v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+		my $prod_key_path = $ccs."\\Control\\ProductOptions";
+		if (my $prod_key = $root_key->get_subkey($prod_key_path)) {
+			::rptMsg($prod_key_path);
+			::rptMsg("LastWrite = ".gmtime($prod_key->get_timestamp()));
+			::rptMsg("");
+			::rptMsg("Ref: http://support.microsoft.com/kb/152078");
+			::rptMsg("     http://support.microsoft.com/kb/181412"); 
+			::rptMsg("");
+			my $type;
+			eval {
+				$type = $prod_key->get_value("ProductType")->get_data();
+				::rptMsg("ProductType  = ".$type);
+				::rptMsg("Ref: http://technet.microsoft.com/en-us/library/cc782360%28WS.10%29.aspx");
+				::rptMsg("WinNT indicates a workstation.");
+				::rptMsg("ServerNT indicates a standalone server.");
+				::rptMsg("LanmanNT indicates a domain controller (pri/backup).");
+			};
+			::rptMsg("");
+#-----------------------------------------------------------			
+# http://technet.microsoft.com/en-us/library/cc784364(WS.10).aspx
+#
+# http://www.geoffchappell.com/viewer.htm?doc=studies/windows/
+#        km/ntoskrnl/api/ex/exinit/productsuite.htm
+#
+#-----------------------------------------------------------			
+			my $suite;
+			eval {
+				$suite = $prod_key->get_value("ProductSuite")->get_data();
+				::rptMsg("ProductSuite = ".$suite);
+				::rptMsg("Ref: http://technet.microsoft.com/en-us/library/cc784364%28WS.10%29.aspx");
+			};
+		}
+		else {
+			::rptMsg($prod_key_path." not found.");
+		}
+	}
+	else {
+		::rptMsg("Select key not found.");
+	}
+}
+1
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/profilelist.pl b/thirdparty/rr/plugins/profilelist.pl
new file mode 100644
index 0000000000000000000000000000000000000000..bfeae8a6e70095603aec37b6b4c90274e8d0ccbd
--- /dev/null
+++ b/thirdparty/rr/plugins/profilelist.pl
@@ -0,0 +1,137 @@
+#-----------------------------------------------------------
+# profilelist.pl
+# Gets ProfileList subkeys and ProfileImagePath value; also
+# gets the ProfileLoadTimeHigh and Low values, and translates them
+# into a readable time
+#
+# History:
+#   20100219 - updated to gather SpecialAccounts and domain
+#              user info
+#   20080415 - created
+#
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package profilelist;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100219);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get content of ProfileList key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	
+	my %profiles;
+	
+	::logMsg("Launching profilelist v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\ProfileList";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				my $path;
+				eval {
+					$path = $s->get_value("ProfileImagePath")->get_data();
+				};
+				
+				::rptMsg("Path      : ".$path);
+				::rptMsg("SID       : ".$s->get_name());
+				::rptMsg("LastWrite : ".gmtime($s->get_timestamp())." (UTC)");
+				
+				my $user;
+				if ($path) {
+					my @a = split(/\\/,$path);
+					my $end = scalar @a - 1;
+					$user = $a[$end];
+					$profiles{$s->get_name()} = $user;
+				}
+				
+				my @load;
+				eval {
+					$load[0] = $s->get_value("ProfileLoadTimeLow")->get_data();
+					$load[1] = $s->get_value("ProfileLoadTimeHigh")->get_data();
+				};
+				if (@load) {
+					my $loadtime = ::getTime($load[0],$load[1]);
+					::rptMsg("LoadTime  : ".gmtime($loadtime)." (UTC)");
+				}
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+# The following was added 20100219
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\Winlogon";
+	if ($key = $root_key->get_subkey($key_path)) {
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar @subkeys > 0) {
+			::rptMsg("Domain Accounts");
+			foreach my $s (@subkeys) {
+				my $name = $s->get_name();
+				next unless ($name =~ m/^S\-1/);
+				
+				(exists $profiles{$name}) ? (::rptMsg($name." [".$profiles{$name}."]")) 
+				                          : (::rptMsg($name));
+#				::rptMsg("LastWrite time: ".gmtime($s->get_timestamp()));
+#				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+		
+# Domain Cache?
+		eval {
+			my @cache = $key->get_subkey("DomainCache")->get_list_of_values();
+			if (scalar @cache > 0) {
+				::rptMsg("");
+				::rptMsg("DomainCache");
+				foreach my $d (@cache) {
+					my $str = sprintf "%-15s %-20s",$d->get_name(),$d->get_data();
+					::rptMsg($str);
+				}
+			}
+		};
+		
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	} 
+	
+	
+
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/proxysettings.pl b/thirdparty/rr/plugins/proxysettings.pl
new file mode 100644
index 0000000000000000000000000000000000000000..d403c487d332679efd0793e1ac5f5c43f66a85ad
--- /dev/null
+++ b/thirdparty/rr/plugins/proxysettings.pl
@@ -0,0 +1,70 @@
+#-----------------------------------------------------------
+# proxysettings.pl
+# Plugin for Registry Ripper,
+# Internet Explorer ProxySettings key parser
+#
+# Change history
+#    20081224 - H. Carvey, updated sorting and printing routine
+#
+#
+# copyright 2008 C. Bentley
+#-----------------------------------------------------------
+package proxysettings;
+use strict;
+
+my %config = (hive => "NTUSER\.DAT",
+							hasShortDescr => 1,
+							hasDescr => 0,
+							hasRefs => 0,
+							osmask => 22,
+							version => 20081224);
+
+sub getConfig{return %config}
+sub getShortDescr {return "Gets contents of user's Proxy Settings";}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching proxysettings v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("ProxySettings");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			my %proxy;
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				my $data = $v->get_data();
+				my $type = $v->get_type();
+				$data = unpack("V",$data) if ($type == 3);
+				$proxy{$name} = $data;
+			}
+			foreach my $n (sort keys %proxy) {
+			 	my $str = sprintf "  %-30s %-30s",$n,$proxy{$n};
+				::rptMsg($str);
+#				::rptMsg(" ".$v->get_name()." ".$v->get_data());
+			}
+		}
+		else {
+			::rptMsg($key_path." key has no values.");
+			::logMsg($key_path." key has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." hat key not found.");
+		::logMsg($key_path." hat key not found.");
+	}
+}
+1; 
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/rdphint.pl b/thirdparty/rr/plugins/rdphint.pl
new file mode 100644
index 0000000000000000000000000000000000000000..680165812ad118218bb0b9a512b6108fde01d8b0
--- /dev/null
+++ b/thirdparty/rr/plugins/rdphint.pl
@@ -0,0 +1,61 @@
+#-----------------------------------------------------------
+# rdphint.pl - http://www.regripper.net/
+# Gathers servers logged onto via RDP and last successful username
+#
+# by Brandon Nesbit, Trustwave
+#-----------------------------------------------------------
+package rdphint;
+use strict;
+
+my %config = (hive => "NTUSER",
+              osmask => 22,
+              hasShortDescr => 1,
+              hasDescr => 0,
+              hasRefs => 0,
+              version => 20090715);
+
+sub getConfig{return %config}
+sub getShortDescr { return "Gets hosts logged onto via RDP and the Domain\\Username";}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching RDPHint v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = 'Software\\Microsoft\\Terminal Server Client\\Servers';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("Terminal Server Client\\Servers");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				my $path;
+				eval {
+					$path = $s->get_value("UsernameHint")->get_data();
+				};
+				::rptMsg("");
+				::rptMsg("Hostname: ".$s->get_name());
+				::rptMsg("Domain/Username: ".$path);
+				::rptMsg("LastWrite: ".gmtime($s->get_timestamp())." (UTC)");
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/rdpport.pl b/thirdparty/rr/plugins/rdpport.pl
new file mode 100644
index 0000000000000000000000000000000000000000..44110d33cb13c416c07ead0465c0599882f90966
--- /dev/null
+++ b/thirdparty/rr/plugins/rdpport.pl
@@ -0,0 +1,59 @@
+#-----------------------------------------------------------
+# rdpport.pl
+# Determine the RDP Port used
+#
+# History
+#  20100713 - created
+#
+# References
+#   http://support.microsoft.com/kb/306759
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package rdpport;
+use strict;
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100713);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Queries System hive for RDP Port";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	my $key;
+	
+	::logMsg("Launching rdpport v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	
+	my $ccs = $root_key->get_subkey("Select")->get_value("Current")->get_data();
+	my $key_path = "ControlSet00".$ccs."\\Control\\Terminal Server\\WinStations\\RDP-Tcp";
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("rdpport v.".$VERSION);
+		::rptMsg("");
+		my $port;
+		eval {
+			$port = $key->get_value("PortNumber")->get_data();
+			::rptMsg("Remote Desktop Listening Port Number = ".$port);
+		};
+		::rptMsg("Error getting PortNumber: ".$@) if ($@);
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/realplayer6.pl b/thirdparty/rr/plugins/realplayer6.pl
new file mode 100644
index 0000000000000000000000000000000000000000..7ea5913a5f3fa936252bd3c165ade9bb40a8da7d
--- /dev/null
+++ b/thirdparty/rr/plugins/realplayer6.pl
@@ -0,0 +1,79 @@
+#-----------------------------------------------------------
+# realplayer6.pl
+# Plugin for Registry Ripper 
+# Get Real Player 6 MostRecentClipsx values
+#
+# Change history
+#
+#
+# References
+#
+# Note: LastWrite times on c subkeys will all be the same,
+#       as each subkey is modified as when a new entry is added
+#
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package realplayer6;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets user's RealPlayer v6 MostRecentClips\(Default) values";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching realplayer6 v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	::rptMsg("Realplayer6 v.".$VERSION);
+
+	my $key_path = "Software\\RealNetworks\\RealPlayer\\6.0\\Preferences";   
+	my $key = $root_key->get_subkey($key_path);
+	if ($key) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my %rpkeys;
+		my $tag = "MostRecentClips";
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar @subkeys > 0) {
+			foreach my $s (@subkeys) {
+				my $name = $s->get_name();
+				if ($name =~ m/^$tag/) {
+					my $num = $name;
+					$num =~ s/$tag//;
+					$rpkeys{$num}{name} = $name;
+					$rpkeys{$num}{data} = $s->get_value('')->get_data();
+					$rpkeys{$num}{lastwrite} = $s->get_timestamp();
+				}
+			}
+			foreach my $k (sort keys %rpkeys) {
+				::rptMsg("\t".$rpkeys{$k}{name}." -> ".$rpkeys{$k}{data});
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/realvnc.pl b/thirdparty/rr/plugins/realvnc.pl
new file mode 100644
index 0000000000000000000000000000000000000000..667766aca4cd98e55101f31874a96a0df7097cd7
--- /dev/null
+++ b/thirdparty/rr/plugins/realvnc.pl
@@ -0,0 +1,75 @@
+#-----------------------------------------------------------
+# realvnc.pl
+# Plugin to get RealVNC MRU listings from NTUSER.DAT 
+#
+# Change history
+#   20091125 - created
+#
+# References
+#
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package realvnc;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20091125);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets user's RealVNC MRU listing";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching realvnc v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\RealVNC\\VNCViewer4\\MRU';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			my %mru;
+			my @order;
+			foreach my $v (@vals) { 
+				$mru{$v->get_name()} = $v->get_data();
+			}
+				
+			if (exists($mru{Order})) {
+				@order = unpack("C*",$mru{Order});				
+# List systems connected to based on Order MRU value	
+				::rptMsg("*Systems output in \"Order\" sequence");		
+				foreach my $i (0..scalar(@order) - 1) {
+					$order[$i] = "0".$order[$i] if ($order[$i] < 10);
+					::rptMsg("  ".$order[$i]." -> ".$mru{$order[$i]});
+				}
+			}
+			else {
+				::rptMsg("Could not find Order value.");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/recentdocs.pl b/thirdparty/rr/plugins/recentdocs.pl
new file mode 100644
index 0000000000000000000000000000000000000000..78506653763137d1243d8566d40c60980102715d
--- /dev/null
+++ b/thirdparty/rr/plugins/recentdocs.pl
@@ -0,0 +1,161 @@
+#-----------------------------------------------------------
+# recentdocs.pl
+# Plugin for Registry Ripper 
+# Parses RecentDocs keys/values in NTUSER.DAT 
+#
+# Change history
+#    20100405 - Updated to use Encode::decode to translate strings
+#    20090115 - Minor update to keep plugin from printing terminating
+#               MRUListEx value of 0xFFFFFFFF
+#    20080418 - Minor update to address NTUSER.DAT files that have
+#               MRUList values in this key, rather than MRUListEx
+#               values
+#
+# References
+#
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package recentdocs;
+use strict;
+use Encode;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100405);
+
+sub getShortDescr {
+	return "Gets contents of user's RecentDocs key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching recentdocs v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RecentDocs";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("RecentDocs");
+		::rptMsg("**All values printed in MRUList\\MRUListEx order.");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+# Get RecentDocs values		
+		my %rdvals = getRDValues($key);
+		if (%rdvals) {
+			my $tag;
+			if (exists $rdvals{"MRUListEx"}) {
+				$tag = "MRUListEx";
+			}
+			elsif (exists $rdvals{"MRUList"}) {
+				$tag = "MRUList";
+			}
+			else {
+				
+			}
+			
+			my @list = split(/,/,$rdvals{$tag});
+			foreach my $i (@list) {
+				::rptMsg("  ".$i." = ".$rdvals{$i});
+			}
+			::rptMsg("");
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg("Error: ".$key_path." has no values.");
+		}
+# Get RecentDocs subkeys' values		
+	my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				::rptMsg($key_path."\\".$s->get_name());
+				::rptMsg("LastWrite Time ".gmtime($s->get_timestamp())." (UTC)");
+				
+				my %rdvals = getRDValues($s);
+				if (%rdvals) {
+					my $tag;
+					if (exists $rdvals{"MRUListEx"}) {
+						$tag = "MRUListEx";
+					}
+					elsif (exists $rdvals{"MRUList"}) {
+						$tag = "MRUList";
+					}
+					else {
+				
+					}
+			
+					my @list = split(/,/,$rdvals{$tag});
+					::rptMsg($tag." = ".$rdvals{$tag});
+					foreach my $i (@list) {
+						::rptMsg("  ".$i." = ".$rdvals{$i});
+					}
+					
+					::rptMsg("");
+				}
+				else {
+					::rptMsg($key_path." has no values.");
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+
+sub getRDValues {
+	my $key = shift;
+	
+	my $mru = "MRUList";
+	my %rdvals;
+	
+	my @vals = $key->get_list_of_values();
+	if (scalar @vals > 0) {
+		foreach my $v (@vals) {
+			my $name = $v->get_name();
+			my $data = $v->get_data();
+			if ($name =~ m/^$mru/) {
+				my @mru;
+				if ($name eq "MRUList") {
+					@mru = split(//,$data);
+				}
+				elsif ($name eq "MRUListEx") {
+					@mru = unpack("V*",$data);
+				}
+# Horrible, ugly cludge; the last, terminating value in MRUListEx
+# is 0xFFFFFFFF, so we remove it.
+				pop(@mru);
+				$rdvals{$name} = join(',',@mru);
+			}
+			else {
+# New code
+				$data = decode("ucs-2le", $data);
+				my $file = (split(/\00/,$data))[0];
+#				my $file = (split(/\00\00/,$data))[0];
+#				$file =~ s/\00//g;
+				$rdvals{$name} = $file;
+			}
+		}
+		return %rdvals;
+	}
+	else {
+		return undef;
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/regtime.pl b/thirdparty/rr/plugins/regtime.pl
new file mode 100644
index 0000000000000000000000000000000000000000..03510c46d9938a5df83dd52b4b55c01078677165
--- /dev/null
+++ b/thirdparty/rr/plugins/regtime.pl
@@ -0,0 +1,65 @@
+#! c:\perl\bin\perl.exe
+#-----------------------------------------------------------
+# regtime.pl
+# Plugin for Registry Ripper; traverses through a Registry 
+# hive file, pulling out keys and their LastWrite times, and
+# then listing them in order, sorted by the most recent time
+# first - works with any Registry hive file.
+#
+# Change history
+# 
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package regtime;
+use strict;
+
+my %config = (hive          => "All",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Dumps entire hive - all keys sorted by LastWrite time";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+my %regkeys;
+
+sub pluginmain {
+	my $class = shift;
+	my $file = shift;
+	my $reg = Parse::Win32Registry->new($file);
+	my $root_key = $reg->get_root_key;
+	::logMsg("Launching regtime v.".$VERSION);
+	
+	traverse($root_key);
+
+	foreach my $t (reverse sort {$a <=> $b} keys %regkeys) {
+		foreach my $item (@{$regkeys{$t}}) {
+			::rptMsg(gmtime($t)."Z \t".$item);
+		}
+	}
+}
+
+sub traverse {
+	my $key = shift;
+  my $ts = $key->get_timestamp();
+  my $name = $key->as_string();
+  $name =~ s/\$\$\$PROTO\.HIV//;
+  $name = (split(/\[/,$name))[0];
+  push(@{$regkeys{$ts}},$name);  
+	foreach my $subkey ($key->get_list_of_subkeys()) {
+		traverse($subkey);
+  }
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/regtime_tln.pl b/thirdparty/rr/plugins/regtime_tln.pl
new file mode 100644
index 0000000000000000000000000000000000000000..558d7f0eebfc03a647280382a5adf3ee49ff7c6c
--- /dev/null
+++ b/thirdparty/rr/plugins/regtime_tln.pl
@@ -0,0 +1,66 @@
+#! c:\perl\bin\perl.exe
+#-----------------------------------------------------------
+# regtime.pl
+# Plugin for Registry Ripper; traverses through a Registry 
+# hive file, pulling out keys and their LastWrite times, and
+# then listing them in order, sorted by the most recent time
+# first - works with any Registry hive file.
+#
+# Change history
+# 
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package regtime_tln;
+use strict;
+
+my %config = (hive          => "All",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Dumps entire hive - all keys sorted by LastWrite time";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+my %regkeys;
+
+sub pluginmain {
+	my $class = shift;
+	my $file = shift;
+	my $reg = Parse::Win32Registry->new($file);
+	my $root_key = $reg->get_root_key;
+	::logMsg("Launching regtime_tln v.".$VERSION);
+	
+	traverse($root_key);
+
+	foreach my $t (reverse sort {$a <=> $b} keys %regkeys) {
+		foreach my $item (@{$regkeys{$t}}) {
+			#::rptMsg(gmtime($t)."Z \t".$item);
+			::rptMsg($t."|REG|M... ".$item);
+		}
+	}
+}
+
+sub traverse {
+	my $key = shift;
+  my $ts = $key->get_timestamp();
+  my $name = $key->as_string();
+  $name =~ s/\$\$\$PROTO\.HIV//;
+  $name = (split(/\[/,$name))[0];
+  push(@{$regkeys{$ts}},$name);  
+	foreach my $subkey ($key->get_list_of_subkeys()) {
+		traverse($subkey);
+  }
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/renocide.pl b/thirdparty/rr/plugins/renocide.pl
new file mode 100644
index 0000000000000000000000000000000000000000..5f71f922f9651102cec4656f4aa489f0cc2cd5a6
--- /dev/null
+++ b/thirdparty/rr/plugins/renocide.pl
@@ -0,0 +1,65 @@
+#-----------------------------------------------------------
+# renocide.pl
+# Plugin to assist in the detection of malware per MMPC
+#   blog post (References, below)
+#
+# Change History:
+#   20110309 - created
+#
+# References
+#   http://www.microsoft.com/security/portal/Threat/Encyclopedia/Entry.aspx?Name=Win32/Renocide
+#
+# copyright 2011 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package renocide;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20110309);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Check for Renocide malware";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching renocide v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\DRM\\amty";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("renocide");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite: ".gmtime($key->get_timestamp()));
+		::rptMsg("");
+		::rptMst($key_path." found; possible Win32\\Renocide infection.");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				::rptMsg(sprintf "%-12s %-20s",$v->get_name(),$v->get_data());
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/routes.pl b/thirdparty/rr/plugins/routes.pl
new file mode 100644
index 0000000000000000000000000000000000000000..823f097b3ef0180c8695867ba1deb23e35ddb423
--- /dev/null
+++ b/thirdparty/rr/plugins/routes.pl
@@ -0,0 +1,81 @@
+#-----------------------------------------------------------
+# routes.pl
+#
+# Some malware is known to create persistent routes
+#
+# Change History:
+#  20100817 - created
+#	
+# Ref: 
+#  http://support.microsoft.com/kb/141383
+#  http://www.symantec.com/security_response/writeup.jsp?docid=
+#         2010-041308-3301-99&tabid=2
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package routes;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100817);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get persistent routes";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching routes v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+	
+		my $sb_path = $ccs."\\Services\\Tcpip\\Parameters\\PersistentRoutes";
+		
+		my $sb;
+		if ($sb = $root_key->get_subkey($sb_path)) {
+			::rptMsg($sb_path);
+			::rptMsg("LastWrite: ".gmtime($sb->get_timestamp()));
+			::rptMsg("");
+			my @vals = $sb->get_list_of_values();
+			
+			if (scalar(@vals) > 0) {
+				::rptMsg(sprintf "%-15s  %-15s %-15s %-5s","Address","Netmask","Gateway","Metric");
+				foreach my $v (@vals) {
+					my ($addr,$netmask,$gateway,$metric) = split(/,/,$v->get_name(),4);
+					::rptMsg(sprintf "%-15s  %-15s %-15s %-5s",$addr,$netmask,$gateway,$metric);
+				}
+			}
+			else {
+				::rptMsg($sb_path." has no values.");
+			}
+		}
+		else {
+			::rptMsg($sb_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/runmru.pl b/thirdparty/rr/plugins/runmru.pl
new file mode 100644
index 0000000000000000000000000000000000000000..f18a9ec43446eab93726ca1215b4f534ba5b8aae
--- /dev/null
+++ b/thirdparty/rr/plugins/runmru.pl
@@ -0,0 +1,72 @@
+#-----------------------------------------------------------
+# runmru.pl
+# Plugin for Registry Ripper, NTUSER.DAT edition - gets the 
+# RunMru values 
+#
+# Change history
+#
+#
+# References
+#
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package runmru;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of user's RunMRU key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching runmru v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("RunMru");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @vals = $key->get_list_of_values();
+		my %runvals;
+		my $mru;
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				$runvals{$v->get_name()} = $v->get_data() unless ($v->get_name() =~ m/^MRUList/i);
+				$mru = $v->get_data() if ($v->get_name() =~ m/^MRUList/i);
+			}
+			::rptMsg("MRUList = ".$mru);
+			foreach my $r (sort keys %runvals) {
+				::rptMsg($r."   ".$runvals{$r});
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/safeboot.pl b/thirdparty/rr/plugins/safeboot.pl
new file mode 100644
index 0000000000000000000000000000000000000000..66ee850137ecc77e71c137460fdc78ae56ec147d
--- /dev/null
+++ b/thirdparty/rr/plugins/safeboot.pl
@@ -0,0 +1,104 @@
+#-----------------------------------------------------------
+# safeboot.pl
+#
+# Some malware is known to maintain persistence, even when the system
+# is booted to SafeMode by writing entries to the SafeBoot subkeys
+# ex: http://www.symantec.com/security_response/writeup.jsp?
+#            docid=2008-011507-0108-99&tabid=2
+#	
+# Ref: 
+#   http://support.microsoft.com/kb/315222
+#   http://support.microsoft.com/kb/202485/
+#
+# copyright 2008-2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package safeboot;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20081216);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Check SafeBoot entries";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching safeboot v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+
+		my $sb_path = $ccs."\\Control\\SafeBoot";
+		my $sb;
+		if ($sb = $root_key->get_subkey($sb_path)) {
+			
+			my @sks = $sb->get_list_of_subkeys();
+			
+			if (scalar(@sks) > 0) {
+				
+				foreach my $s (@sks) {
+					my $name = $s->get_name();
+					my $ts   = $s->get_timestamp();
+					::rptMsg($name."  [".gmtime($ts)." Z]");
+					my %sk;
+					my @subkeys = $s->get_list_of_subkeys();
+					
+					if (scalar(@subkeys) > 0) {
+						foreach my $s2 (@subkeys) {
+							my $str;
+							my $default;
+							eval {
+								$default = $s2->get_value("")->get_data();
+							};
+							($@)?($str = $s2->get_name()):($str = $s2->get_name()." (".$default.")");
+							push(@{$sk{$s2->get_timestamp()}},$str);
+						}
+						
+						foreach my $t (sort keys %sk) {
+							::rptMsg(gmtime($t)." Z");
+							foreach my $i (@{$sk{$t}}) {
+								::rptMsg("  ".$i);
+							}
+						}
+						::rptMsg("");
+					}
+					else {
+						::rptMsg($name." has no subkeys.");
+					}
+				}
+			}
+			else {
+				::rptMsg($sb_path." has no subkeys.");
+			}
+		}
+		else {
+			::rptMsg($sb_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+#		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/sam b/thirdparty/rr/plugins/sam
new file mode 100644
index 0000000000000000000000000000000000000000..84568779ff241e6e26887f0bf9a62f0c300e8548
--- /dev/null
+++ b/thirdparty/rr/plugins/sam
@@ -0,0 +1,3 @@
+#-------------------------------------
+# SAM
+samparse
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/samparse.pl b/thirdparty/rr/plugins/samparse.pl
new file mode 100644
index 0000000000000000000000000000000000000000..001857728e13b5a9a07964332cda920642a011ca
--- /dev/null
+++ b/thirdparty/rr/plugins/samparse.pl
@@ -0,0 +1,323 @@
+#-----------------------------------------------------------
+# samparse.pl
+# Parse the SAM hive file for user/group membership info
+#
+# Change history:
+#    20110303 - Fixed parsing of SID, added check for account type
+#               Acct type determined based on Dustin Hulburt's "Forensic
+#               Determination of a User's Logon Status in Windows" 
+#               from 10 Aug 2009 (link below)
+#    20100712 - Added References entry
+#    20091020 - Added extracting UserPasswordHint value
+#    20090413 - Added account creation date
+#    20080415 - created
+#
+# References
+#    Source available here: http://pogostick.net/~pnh/ntpasswd/
+#    http://accessdata.com/downloads/media/Forensic_Determination_Users_Logon_Status.pdf
+#
+# copyright 2011 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package samparse;
+use strict;
+
+my %config = (hive          => "SAM",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              version       => 20110303);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Parse SAM file for user/group mbrshp info";	
+}
+sub getDescr{}
+sub getRefs {
+	my %refs = ("Well-known SIDs" => "http://support.microsoft.com/kb/243330");	
+	return %refs;
+}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+my %acb_flags = (0x0001 => "Account Disabled",
+                 0x0002 => "Home directory required",
+								 0x0004 => "Password not required",
+ 								 0x0008 => "Temporary duplicate account",
+                 0x0010 => "Normal user account",
+                 0x0020 => "MNS logon user account",
+                 0x0040 => "Interdomain trust account",
+                 0x0080 => "Workstation trust account",
+                 0x0100 => "Server trust account",
+                 0x0200 => "Password does not expire",
+                 0x0400 => "Account auto locked");
+                 
+my %types = (0xbc => "Default Admin User",
+             0xd4 => "Custom Limited Acct",
+             0xb0 => "Default Guest Acct");
+             
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching samparse v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	::rptMsg("");
+# Get user information
+	::rptMsg("User Information");
+	::rptMsg("-" x 25);
+	my $key_path = 'SAM\\Domains\\Account\\Users';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		my @user_list = $key->get_list_of_subkeys();
+		if (scalar(@user_list) > 0) {
+			foreach my $u (@user_list) {
+				my $rid = $u->get_name();
+				my $ts  = $u->get_timestamp();
+				my $tag = "0000";
+				if ($rid =~ m/^$tag/) {	
+					my $v_value = $u->get_value("V");
+					my $v = $v_value->get_data();
+					my %v_val = parseV($v);
+					$rid =~ s/^0000//;
+					$rid = hex($rid);
+					
+					my $c_date;
+					eval {
+						my $create_path = $key_path."\\Names\\".$v_val{name};
+						if (my $create = $root_key->get_subkey($create_path)) {
+							$c_date = $create->get_timestamp();
+						}
+					};
+				
+					::rptMsg("Username        : ".$v_val{name}." [".$rid."]");
+					::rptMsg("Full Name       : ".$v_val{fullname});
+					::rptMsg("User Comment    : ".$v_val{comment});
+					::rptMsg("Account Type    : ".$v_val{type});
+					::rptMsg("Account Created : ".gmtime($c_date)." Z") if ($c_date > 0); 
+					
+					my $f_value = $u->get_value("F");
+					my $f = $f_value->get_data();
+					my %f_val = parseF($f);
+					
+					my $lastlogin;
+					my $pwdreset;
+					my $pwdfail;
+					($f_val{last_login_date} == 0) ? ($lastlogin = "Never") : ($lastlogin = gmtime($f_val{last_login_date})." Z");
+					($f_val{pwd_reset_date} == 0) ? ($pwdreset = "Never") : ($pwdreset = gmtime($f_val{pwd_reset_date})." Z");
+					($f_val{pwd_fail_date} == 0) ? ($pwdfail = "Never") : ($pwdfail = gmtime($f_val{pwd_fail_date})." Z");
+					
+					my $pw_hint;
+					eval {
+						$pw_hint = $u->get_value("UserPasswordHint")->get_data();
+						$pw_hint =~ s/\00//g;
+					};
+					::rptMsg("Password Hint   : ".$pw_hint) unless ($@);
+					::rptMsg("Last Login Date : ".$lastlogin);
+					::rptMsg("Pwd Reset Date  : ".$pwdreset);
+					::rptMsg("Pwd Fail Date   : ".$pwdfail);
+					::rptMsg("Login Count     : ".$f_val{login_count});
+					foreach my $flag (keys %acb_flags) {
+						::rptMsg("  --> ".$acb_flags{$flag}) if ($f_val{acb_flags} & $flag);
+					}
+					::rptMsg("");
+				}
+			}
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	::rptMsg("-" x 25);
+	::rptMsg("Group Membership Information");
+	::rptMsg("-" x 25);
+# Get Group membership information	
+	my $key_path = 'SAM\\Domains\\Builtin\\Aliases';
+	if ($key = $root_key->get_subkey($key_path)) {
+		my %grps;
+		my @groups = $key->get_list_of_subkeys();
+		if (scalar(@groups) > 0) {
+			foreach my $k (@groups) {
+				my $name = $k->get_name();
+				if ($name =~ m/^0000/) {
+					$grps{$name}{LastWrite} = $k->get_timestamp();
+					$grps{$name}{C_value} = $k->get_value("C")->get_data(); 
+				}
+			}
+		
+			foreach my $k (keys %grps) {
+				my $name = $k;
+				$name =~ s/^0000//;
+				my %c_val = parseC($grps{$k}{C_value});
+				::rptMsg("Group Name    : ".$c_val{group_name}." [".$c_val{num_users}."]");
+				::rptMsg("LastWrite     : ".gmtime($grps{$k}{LastWrite})." Z");
+				::rptMsg("Group Comment : ".$c_val{comment});
+				if ($c_val{num_users} == 0) {
+					::rptMsg("Users         : None");
+				}else {
+					my %users = parseCUsers($grps{$k}{C_value});
+					if (scalar(keys %users) != $c_val{num_users}) {
+						::logMsg("parseC function reports ".$c_val{num_users}."; parseCUsers function returned ".(scalar(keys %users)));
+					}
+					::rptMsg("Users :");
+					foreach my $u (keys %users) {
+						::rptMsg("  ".$u);
+					}
+					
+				}
+				::rptMsg("");
+			}
+			::rptMsg("Analysis Tips:");
+			::rptMsg(" - For well-known SIDs, see http://support.microsoft.com/kb/243330");
+			::rptMsg("     - S-1-5-4  = Interactive");
+			::rptMsg("     - S-1-5-11 = Authenticated Users");
+			::rptMsg(" - Correlate the user SIDs to the output of the ProfileList plugin");
+			::rptMsg("");
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+sub parseF {
+	my $f = shift;
+	my %f_value = ();
+	my @tv;
+# last login date	
+	@tv = unpack("VV",substr($f,8,8));
+	$f_value{last_login_date} = ::getTime($tv[0],$tv[1]);
+#	password reset/acct creation
+	@tv = unpack("VV",substr($f,24,8));
+	$f_value{pwd_reset_date} = ::getTime($tv[0],$tv[1]);
+# Account expires
+	@tv = unpack("VV",substr($f,32,8));
+	$f_value{acct_exp_date} = ::getTime($tv[0],$tv[1]);
+# Incorrect password 	
+	@tv = unpack("VV",substr($f,40,8));
+	$f_value{pwd_fail_date} = ::getTime($tv[0],$tv[1]);
+	$f_value{rid} = unpack("V",substr($f,48,4));
+	$f_value{acb_flags} = unpack("v",substr($f,56,2));
+	$f_value{failed_count} = unpack("v",substr($f,64,2));
+	$f_value{login_count} = unpack("v",substr($f,66,2));
+	return %f_value;
+}
+
+sub parseV {
+	my $v = shift;
+	my %v_val = ();
+	my $header = substr($v,0,44);
+	my @vals = unpack("V*",$header);   
+	$v_val{type}     = $types{$vals[1]}; 
+	$v_val{name}     = _uniToAscii(substr($v,($vals[3] + 0xCC),$vals[4]));
+	$v_val{fullname} = _uniToAscii(substr($v,($vals[6] + 0xCC),$vals[7])) if ($vals[7] > 0);
+	$v_val{comment}  = _uniToAscii(substr($v,($vals[9] + 0xCC),$vals[10])) if ($vals[10] > 0);
+	return %v_val;
+}
+
+sub parseC {
+	my $cv = $_[0];
+	my %c_val = ();
+	my $header = substr($cv,0,0x34);
+	my @vals = unpack("V*",$header);
+	
+	$c_val{group_name} = _uniToAscii(substr($cv,(0x34 + $vals[4]),$vals[5]));
+	$c_val{comment}    = _uniToAscii(substr($cv,(0x34 + $vals[7]),$vals[8]));
+	$c_val{num_users}  = $vals[12];
+
+	return %c_val;
+}
+
+sub parseCUsers {
+	my $cv = $_[0];
+	my %members = ();
+	my $header = substr($cv,0,0x34);
+	my @vals = unpack("V*",$header);
+	
+	my $num = $vals[12];
+	
+	my @users = ();
+	my $ofs;		
+	if ($num > 0) {
+		my $count = 0;
+		foreach my $c (1..$num) {
+			my $ofs = $vals[10] + 52 + $count;
+			my $tmp = unpack("V",substr($cv,$ofs,4));
+			
+			if ($tmp == 0x101) {
+				$ofs++ if (unpack("C",substr($cv,$ofs,1)) == 0);
+				$members{_translateSID(substr($cv,$ofs,12))} = 1;
+				$count += 12;
+			}
+			elsif ($tmp == 0x501) {
+				$members{_translateSID(substr($cv,$ofs,28))} = 1;
+				$count += 28;
+			}
+			else {
+			
+			}
+		}
+	}
+	return %members;
+}
+
+#---------------------------------------------------------------------
+# _translateSID()
+# Translate binary data into a SID
+# References:
+#   http://blogs.msdn.com/oldnewthing/archive/2004/03/15/89753.aspx  
+#   http://support.microsoft.com/kb/286182/
+#   http://support.microsoft.com/kb/243330
+#---------------------------------------------------------------------
+sub _translateSID {
+	my $sid = $_[0];
+	my $len = length($sid);
+	my $revision;
+	my $dashes;
+	my $idauth;
+	if ($len < 12) {
+# Is a SID ever less than 12 bytes?		
+		return "SID less than 12 bytes";
+	}
+	elsif ($len == 12) {
+		$revision = unpack("C",substr($sid,0,1));
+		$dashes   = unpack("C",substr($sid,1,1));
+		$idauth   = unpack("H*",substr($sid,2,6));
+		$idauth   =~ s/^0+//g;
+		my $sub   = unpack("V",substr($sid,8,4));
+		return "S-".$revision."-".$idauth."-".$sub;
+	}
+	elsif ($len > 12) {
+		$revision = unpack("C",substr($sid,0,1));
+		$dashes   = unpack("C",substr($sid,1,1));
+		$idauth   = unpack("H*",substr($sid,2,6));
+		$idauth   =~ s/^0+//g;
+		my @sub   = unpack("V4",substr($sid,8,16));
+		my $rid   = unpack("V",substr($sid,24,4));
+		my $s = join('-',@sub);
+		return "S-".$revision."-".$idauth."-".$s."-".$rid;
+	}
+	else {
+# Nothing to do		
+	}
+}
+
+#---------------------------------------------------------------------
+# _uniToAscii()
+#---------------------------------------------------------------------
+sub _uniToAscii {
+  my $str = $_[0];
+  $str =~ s/\00//g;
+  return $str;
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/schedagent.pl b/thirdparty/rr/plugins/schedagent.pl
new file mode 100644
index 0000000000000000000000000000000000000000..a3f0d4012fef2a8c02381af049a8e0312b3cf691
--- /dev/null
+++ b/thirdparty/rr/plugins/schedagent.pl
@@ -0,0 +1,87 @@
+#-----------------------------------------------------------
+# schedagent
+# Get contents of SchedulingAgent key from Software hive
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package schedagent;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              version       => 20100817);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get SchedulingAgent key contents";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching schedagent v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\SchedulingAgent";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my ($oldname,$logpath,$folder,$lastrun,$size);
+		eval {
+			$oldname = $key->get_value("OldName")->get_data();
+			::rptMsg("OldName      = ".$oldname);
+		};
+		
+		eval {
+			$logpath = $key->get_value("LogPath")->get_data();
+			::rptMsg("LogPath      = ".$logpath);
+		};
+		
+		eval {
+			$size = $key->get_value("MaxLogSizeKB")->get_data();
+			::rptMsg("MaxLogSizeKB = ".$size);
+		};
+		
+		eval {
+			$folder = $key->get_value("TasksFolder")->get_data();
+			::rptMsg("TasksFolder  = ".$folder);
+		};
+#		
+		eval {
+			$lastrun = $key->get_value("LastTaskRun")->get_data();
+			::rptMsg("LastTaskRun  = ".parseSystemTime($lastrun));
+			::rptMsg("");
+			::rptMsg("Note: LastTaskRun time is written in local system time, not GMT");
+		};
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+sub parseSystemTime {
+	my ($yr,$mon,$dow,$day,$hr,$min,$sec,$mil) = unpack("v8",$_[0]);
+	$mon = "0".$mon unless ($mon =~ /^\d\d$/);
+	$day = "0".$day unless ($day =~ /^\d\d$/);
+	$hr = "0".$hr unless ($hr =~ /^\d\d$/);
+	$min = "0".$min unless ($min =~ /^\d\d$/);
+	$sec = "0".$sec unless ($sec =~ /^\d\d$/);
+	return "$yr-$mon-$day $hr:$min:$sec";
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/secctr.pl b/thirdparty/rr/plugins/secctr.pl
new file mode 100644
index 0000000000000000000000000000000000000000..19e53f71bb62dfffb1e319fc822082d690acb289
--- /dev/null
+++ b/thirdparty/rr/plugins/secctr.pl
@@ -0,0 +1,67 @@
+#-----------------------------------------------------------
+# secctr
+# Plugin to get data from Security Center keys
+#
+# Change History:
+#   20100310 - created
+#
+# References:
+#   
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package secctr;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100310);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get data from Security Center key";	
+}
+sub getDescr{}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	my $infected = 0;
+	::logMsg("Launching secctr v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = 'Microsoft\Security Center';
+	my $key;
+	::rptMsg("secctr");
+	::rptMsg("");
+	
+	if ($key = $root_key->get_subkey($key_path)) {
+		$infected++;
+		::rptMsg("");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $str = sprintf "%-25s 0x%02x",$v->get_name(),$v->get_data();
+				::rptMsg($str);
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::rptMsg("");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/security b/thirdparty/rr/plugins/security
new file mode 100644
index 0000000000000000000000000000000000000000..233d63ca8033e9a55a3d4ffbe0f2fd675cc15bd5
--- /dev/null
+++ b/thirdparty/rr/plugins/security
@@ -0,0 +1,4 @@
+#-------------------------------------
+# Security
+polacdms
+auditpol
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/services.pl b/thirdparty/rr/plugins/services.pl
new file mode 100644
index 0000000000000000000000000000000000000000..a22e24f8fa6f7797b5af4d70050bbbdec2dd7d3c
--- /dev/null
+++ b/thirdparty/rr/plugins/services.pl
@@ -0,0 +1,150 @@
+#-----------------------------------------------------------
+# services.pl
+# Plugin for Registry Ripper; Access System hive file to get the
+# services
+# 
+# Change history
+#   20080507 - Added collection of Type and Start values; separated
+#              data by Services vs. Drivers; created separate plugin
+#              for Drivers
+#   20080505 - Added collection of ImagePath and DisplayName, if avail.
+#
+# References
+#
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package services;
+#use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080507);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Lists services/drivers in Services key by LastWrite times";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+# Reference for types and start types:
+# http://msdn.microsoft.com/en-us/library/aa394420(VS.85).aspx
+my %types = (0x001 => "Kernel driver",
+             0x002 => "File system driver",
+             0x010 => "Own_Process",
+             0x020 => "Share_Process",
+             0x100 => "Interactive");
+
+my %starts = (0x00 => "Boot Start",
+              0x01 => "System Start",
+              0x02 => "Auto Start",
+              0x03 => "Manual",
+              0x04 => "Disabled");
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching services v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+		my $s_path = $ccs."\\Services";
+		my $svc;
+		my %svcs;
+		if ($svc = $root_key->get_subkey($s_path)) {
+			::rptMsg($s_path);
+			::rptMsg(getShortDescr());
+			::rptMsg("");
+# Get all subkeys and sort based on LastWrite times
+			my @subkeys = $svc->get_list_of_subkeys();
+			if (scalar (@subkeys) > 0) {
+				foreach my $s (@subkeys) {
+					
+					my $type;
+					eval {
+						$type = $s->get_value("Type")->get_data();
+# Only look for services; drivers handled in another plugin
+						if (exists $types{$type}) {
+							$type = $types{$type};
+						}
+						else {
+							$type = sprintf "0x%x",$t;
+						}
+					};
+				
+				 	$name = $s->get_name();
+					my $display;
+					eval {
+						$display = $s->get_value("DisplayName")->get_data();
+					};
+					
+					my $image;
+					eval {
+						$image = $s->get_value("ImagePath")->get_data();
+					};
+					
+					my $start;
+					eval {
+						$start = $s->get_value("Start")->get_data();
+						if (exists $starts{$start}) {
+							$start = $starts{$start};
+						}
+					};
+					
+					my $group;
+					eval {
+						$group = $s->get_value("Group")->get_data();
+					};
+					
+					my $str = $name.";".$display.";".$image.";".$type.";".$start.";".$group;
+					push(@{$svcs{$s->get_timestamp()}},$str) unless ($str eq "");
+				}
+			
+				foreach my $t (reverse sort {$a <=> $b} keys %svcs) {
+					::rptMsg(gmtime($t)."Z");
+					foreach my $item (@{$svcs{$t}}) {
+						my ($n,$d,$i,$t,$s,$g) = split(/;/,$item,6);
+						::rptMsg("  Name      = ".$n);
+						::rptMsg("  Display   = ".$d);
+						::rptMsg("  ImagePath = ".$i);
+						::rptMsg("  Type      = ".$t);
+						::rptMsg("  Start     = ".$s);
+						::rptMsg("  Group     = ".$g);
+						::rptMsg("");
+					}
+				}
+				
+			}
+			else {
+				::rptMsg($s_path." has no subkeys.");
+				::logMsg("Error: ".$s_path." has no subkeys.");
+			}			
+		}
+		else {
+			::rptMsg($s_path." not found.");
+			::logMsg($s_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/sevenzip.pl b/thirdparty/rr/plugins/sevenzip.pl
new file mode 100644
index 0000000000000000000000000000000000000000..cc90d31a168ec71a4190e7127d5b3c4d996a6465
--- /dev/null
+++ b/thirdparty/rr/plugins/sevenzip.pl
@@ -0,0 +1,83 @@
+#-----------------------------------------------------------
+# sevenzip.pl
+# Google Toolbar Search History plugin
+# 
+#
+# Change history
+#   20100218 - created
+#
+# References
+#
+# 
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package sevenzip;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100218);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets records of histories from 7-Zip keys";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	my %hist;
+	::logMsg("Launching 7-zip v.".$VERSION);
+	
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\7-Zip';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		
+		eval {
+			::rptMsg("");
+			my @arc = $key->get_subkey("Compression")->get_subkey("ArcHistory")->get_list_of_values();
+			if (scalar @arc > 0) {
+				::rptMsg("Compression\\ArcHistory");
+				foreach my $a (@arc) {
+					::rptMsg("  ".$a->get_name()." -> ".$a->get_data());
+				}
+			}
+		};
+		::rptMsg("Error: ".$@) if ($@);
+		
+		eval {
+			::rptMsg("");
+			my @arc = $key->get_subkey("Extraction")->get_subkey("PathHistory")->get_list_of_values();
+			if (scalar @arc > 0) {
+				::rptMsg("Extraction\\PathHistory");
+				foreach my $a (@arc) {
+					::rptMsg("  ".$a->get_name()." -> ".$a->get_data());
+				}
+			}
+		};
+		::rptMsg("Error: ".$@) if ($@);
+		
+		
+		
+		
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/sfc.pl b/thirdparty/rr/plugins/sfc.pl
new file mode 100644
index 0000000000000000000000000000000000000000..16e829670feeccb7c5f4b38aafe3e92499450b9a
--- /dev/null
+++ b/thirdparty/rr/plugins/sfc.pl
@@ -0,0 +1,107 @@
+#-----------------------------------------------------------
+# sfc.pl
+# Check SFC settings in the Registry
+#
+# History
+#   20100305 - updated
+#
+#
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package sfc;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100305);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get SFC values";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching sfc v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\Winlogon";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("sfc v.".$VERSION);
+		::rptMsg("");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				next unless ($name =~ m/^sfc/i);
+				my $str;
+				if ($name =~ m/^sfcquota$/i || $name =~ m/^sfcdisable$/i) {
+					$str = sprintf "  %-20s  0x%08x",$name,$v->get_data();
+				}
+				else {
+					$str = sprintf "  %-20s  %-20s",$name,$v->get_data();
+				}
+				::rptMsg($str);
+			}
+			
+		}
+		else {
+			::rptMsg($key_path." key has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." key not found.");
+		::logMsg($key_path." key not found.");
+	}
+	::rptMsg("");
+# According to http://support.microsoft.com/kb/222193, sfc* values in this key, if 
+# it exists, take precedence over and are copied into the values within the Winlogon
+# key; see also http://support.microsoft.com/kb/222473/
+	my $key_path = "Policies\\Microsoft\\Windows NT\\Windows File Protection";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				next unless ($name =~ m/^sfc/i);
+				my $str;
+				if ($name =~ m/^sfcquota$/i || $name =~ m/^sfcdisable$/i) {
+					$str = sprintf "  %-20s  0x%08x",$name,$v->get_data();
+				}
+				else {
+					$str = sprintf "  %-20s  %-20s",$name,$v->get_data();
+				}
+				::rptMsg($str);
+			}
+			
+		}
+		else {
+			::rptMsg($key_path." key has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." key not found.");
+#		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/shares.pl b/thirdparty/rr/plugins/shares.pl
new file mode 100644
index 0000000000000000000000000000000000000000..e36f4737cbf738eb1f303d3cb470177d9364dee2
--- /dev/null
+++ b/thirdparty/rr/plugins/shares.pl
@@ -0,0 +1,128 @@
+#-----------------------------------------------------------
+# shares.pl
+#
+# Retrieve information about shares from a System hive file
+#
+# References:
+#   http://support.microsoft.com/kb/556023
+#   For info about share types, see the Win32_Share  WMI class:
+#      http://msdn.microsoft.com/en-us/library/aa394435(VS.85).aspx
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package shares;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090112);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get list of shares from System hive file";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+my $root_key;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching shares v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	$root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ 	my $current;
+ 	my $ccs;
+ 	eval {
+		my $key_path = 'Select';
+		my $key;
+		if ($key = $root_key->get_subkey($key_path)) {
+			$current = $key->get_value("Current")->get_data();
+			$ccs = "ControlSet00".$current;
+		}
+	};
+	if ($@) {
+		::rptMsg("Problem locating proper controlset: $@");
+		return;
+	}
+# First, connect to the Services key; some versions of Windows appear to
+# spell the lanmanserver key as "lanmanserver" and others as "LanmanServer"
+	my $key_path = $ccs."\\Services";
+	my $key;
+	my $tag = "lanmanserver";
+	my $lanman = getKeyPath($key_path,$tag);
+	if ($lanman ne "") {
+		my $share_path = $key_path."\\".$lanman."\\Shares";
+		my $share;
+		if ($share = $root_key->get_subkey($share_path)) {
+			my @vals = $share->get_list_of_values();
+			if (scalar(@vals) > 0) {
+				foreach my $v (@vals) {
+					::rptMsg("  ".$v->get_name());
+					my @data = $v->get_data();
+					::rptMsg("    ".$data[2]);
+					::rptMsg("    ".$data[4]);
+					::rptMsg("    ".$data[5]);
+					::rptMsg("");
+				}
+			}
+			else {
+				::rptMsg($share_path." has no values.");
+			}
+		}
+		else {
+			::rptMsg($share_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($lanman." subkey not found.");
+	}
+
+# Determine of the AutoShareServer/Wks values have been set
+	my $path = $key_path."\\".$lanman;
+	my $tag  = "parameters";
+	my $para = getKeyPath($path,$tag);
+	eval {
+		if ($key = $root_key->get_subkey($path."\\".$para)) {
+			my $auto_svr = $key->get_value("AutoShareServer")->get_data();
+			::rptMsg("  AutoShareServer = ".$auto_svr);
+		}
+	};
+	
+	eval {
+		if ($key = $root_key->get_subkey($path."\\".$para)) {
+			my $auto_wks = $key->get_value("AutoShareWks")->get_data();
+			::rptMsg("  AutoShareWks = ".$auto_wks);
+		}
+	};
+}
+
+# On different versions of Windows, subkeys such as lanmanserver
+# and parameters are spelled differently; use this subroutine to get
+# the correct spelling of the name of the subkey
+# http://support.microsoft.com/kb/288164
+sub getKeyPath {
+	my $path = $_[0];
+	my $tag  = $_[1];
+	my $subkey;	
+	if (my $key = $root_key->get_subkey($path)) {
+		my @sk = $key->get_list_of_subkeys();
+		foreach my $s (@sk) {
+			my $name = $s->get_name();
+			$subkey = $name if ($name =~ m/^$tag/i);
+		}
+	}
+	return $subkey;
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/shellexec.pl b/thirdparty/rr/plugins/shellexec.pl
new file mode 100644
index 0000000000000000000000000000000000000000..608bacac02a8468866c5c3dbce747816c07a2482
--- /dev/null
+++ b/thirdparty/rr/plugins/shellexec.pl
@@ -0,0 +1,118 @@
+#-----------------------------------------------------------
+# shellexec
+# Get ShellExecuteHooks values from Software hive (based on BHO
+#   code)
+#  
+# ShellExecuteHooks are DLLs that load as part of the Explorer.exe process,
+#   and can intercept commands.  There are some legitimate applications that
+#   run as ShellExecuteHooks, but many times, malware (spy-, ad-ware) will 
+#   install here.  ShellExecuteHooks allow you to type a URL into the Start->Run
+#   box and have that URL opened in your browser.  For example, in 2001, Michael
+#   Dunn wrote KBLaunch, a ShellExecuteHook that looked for "?q" in the Run box
+#   and would open the appropriate MS KB article.
+#
+# Refs:
+#   http://support.microsoft.com/kb/914922
+#   http://support.microsoft.com/kb/170918
+#   http://support.microsoft.com/kb/943460
+#
+# History:
+#   20081229 - initial creation
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package shellexec;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20081229);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets ShellExecuteHooks from Software hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	my %bhos;
+	::logMsg("Launching shellexec v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellExecuteHooks";;
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar (@vals) > 0) {
+			foreach my $s (@vals) {
+				my $name = $s->get_name();
+				next if ($name =~ m/^-/ || $name eq "");
+				my $clsid_path = "Classes\\CLSID\\".$name;
+				my $clsid;
+				if ($clsid = $root_key->get_subkey($clsid_path)) {
+					my $class;
+					my $mod;
+					my $lastwrite;
+					
+					eval {
+						$class = $clsid->get_value("")->get_data();
+						$bhos{$name}{class} = $class;
+					};
+					if ($@) {
+						::logMsg("\tError getting Class name for CLSID\\".$name);
+						::logMsg("\t".$@);
+					}
+					eval {
+						$mod = $clsid->get_subkey("InProcServer32")->get_value("")->get_data();
+						$bhos{$name}{module} = $mod;
+					};
+					if ($@) {
+						::logMsg("\tError getting Module name for CLSID\\".$name);
+						::logMsg("\t".$@);
+					}
+					eval{
+						$lastwrite = $clsid->get_subkey("InProcServer32")->get_timestamp();
+						$bhos{$name}{lastwrite} = $lastwrite;
+					};
+					if ($@) {
+						::logMsg("\tError getting LastWrite time for CLSID\\".$name);
+						::logMsg("\t".$@);
+					}
+					
+					foreach my $b (keys %bhos) {
+						::rptMsg($b);
+						::rptMsg("\tClass     => ".$bhos{$b}{class});
+						::rptMsg("\tModule    => ".$bhos{$b}{module});
+						::rptMsg("\tLastWrite => ".gmtime($bhos{$b}{lastwrite}));
+						::rptMsg("");
+					}
+				}
+				else {
+					::rptMsg($clsid_path." not found.");
+					::rptMsg("");
+					::logMsg($clsid_path." not found.");
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.  No ShellExecuteHooks installed.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/shellext.pl b/thirdparty/rr/plugins/shellext.pl
new file mode 100644
index 0000000000000000000000000000000000000000..8f9994d9d46f606a5ebf2599c05e408fbd530988
--- /dev/null
+++ b/thirdparty/rr/plugins/shellext.pl
@@ -0,0 +1,96 @@
+#-----------------------------------------------------------
+# shellext
+# Plugin to get approved shell extensions list from the 
+#   Software hive
+#
+# This plugin retrieves the list of approved shell extensions from
+#   the Software hive; specifically, the "Shell Extensions\Approved"
+#   key.  Once it has the names (GUID) and data (string) of each value,
+#   it then goes to the Classes\CLSID\{GUID} key to get the name of/path to
+#   the associated DLL, if available. It also gets the LastWrite time of the
+#   Classes\CLSID\{GUID} key.
+#
+# Analysis of an incident showed that the intruder placed their malware in 
+# the C:\Windows dir, using the same name as a known valid shell extension.
+# When Explorer.exe launches, it reads the list of approved shell extensions,
+# then goes to the Classes\CLSID key to get the path to the associated DLL.  The
+# intruder chose a shell extension that did not have an explicit path, so when
+# explorer.exe looked for it, it started in the C:\Windows dir, and never got to
+# the legit DLL in the C:\Windows\system32 dir.
+#
+# References:
+#   http://msdn.microsoft.com/en-us/library/ms682586%28VS.85%29.aspx
+#   
+#
+# Note: This plugin can take several minutes to run
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package shellext;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100515);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets Shell Extensions from Software hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	my %bhos;
+	::logMsg("Launching shellext v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved";;
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my %exts;
+		
+		my @vals = $key->get_list_of_values();
+		if (scalar (@vals) > 0) {
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				$exts{$name}{name} = $v->get_data();
+				
+				my $clsid_path = "Classes\\CLSID\\".$name;
+				my $clsid;
+				if ($clsid = $root_key->get_subkey($clsid_path)) {
+					eval {
+						$exts{$v->get_name()}{lastwrite} = $clsid->get_timestamp();
+						$exts{$v->get_name()}{dll} = $clsid->get_subkey("InProcServer32")->get_value("")->get_data();
+					};
+				}
+			}
+			foreach my $e (keys %exts) {
+				::rptMsg($e."  ".$exts{$e}{name});
+				::rptMsg("  DLL: ".$exts{$e}{dll});
+				::rptMsg("  Timestamp: ".gmtime($exts{$e}{lastwrite})." Z");
+				::rptMsg("");
+			}		
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/shellfolders.pl b/thirdparty/rr/plugins/shellfolders.pl
new file mode 100644
index 0000000000000000000000000000000000000000..42eb461f407ed477408c6677176f237b689db111
--- /dev/null
+++ b/thirdparty/rr/plugins/shellfolders.pl
@@ -0,0 +1,71 @@
+#-----------------------------------------------------------
+# shellfolders.pl
+#
+# Retrieve the Shell Folders values from user's hive; while 
+# this may not be important in every instance, it may give the
+# examiner indications as to where to look for certain items;
+# for example, if the user's "My Documents" folder has been redirected
+# as part of configuration changes (corporate policies, etc.).  Also,
+# this may be important as part of data leakage exams, as XP and Vista
+# allow users to drop and drag files to the CD Burner.
+#
+# References:
+#   http://support.microsoft.com/kb/279157
+#   http://support.microsoft.com/kb/326982
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package shellfolders;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090115);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Retrieve user Shell Folders values";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching shellfolders v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my @vals = $key->get_list_of_values();
+		
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $str = sprintf "%-20s %-40s",$v->get_name(),$v->get_data();
+				::rptMsg($str);
+			}
+			::rptMsg("");
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/shelloverlay.pl b/thirdparty/rr/plugins/shelloverlay.pl
new file mode 100644
index 0000000000000000000000000000000000000000..67c46b858f95d0180c830c67c5fb5562a8b614f1
--- /dev/null
+++ b/thirdparty/rr/plugins/shelloverlay.pl
@@ -0,0 +1,86 @@
+#-----------------------------------------------------------
+# shelloverlay
+# Get contents of ShellIconOverlayIdentifiers subkeys; sorts data
+# based on LastWrite times of subkeys
+# 
+# History
+#   20100308 - created
+#
+# References
+#   http://msdn.microsoft.com/en-us/library/cc144123%28VS.85%29.aspx
+#   Coreflood - http://vil.nai.com/vil/content/v_102053.htm
+#   http://www.secureworks.com/research/threats/coreflood/?threat=coreflood
+#
+# Analysis Tip: Malware such as Coreflood uses a random subkey name and a
+#               random CLSID GUID value
+#
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package shelloverlay;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100308);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets ShellIconOverlayIdentifiers values";	
+}
+sub getDescr{}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching shelloverlay v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	
+	my %id;
+	
+	my $key_path = 'Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("shelloverlay");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar @subkeys > 0) {
+			foreach my $s (@subkeys) {
+				my $name = $s->get_name();
+				my $def;
+				eval {
+					$def = $s->get_value("")->get_data();
+					$name .= "  ".$def;
+				};
+				push(@{$id{$s->get_timestamp()}},$name);
+			}
+			
+			foreach my $t (reverse sort {$a <=> $b} keys %id) {
+				::rptMsg(gmtime($t)." Z");
+				foreach my $item (@{$id{$t}}) {
+					::rptMsg("  ".$item);
+				}
+				::rptMsg("");
+			}
+			
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/shutdown.pl b/thirdparty/rr/plugins/shutdown.pl
new file mode 100644
index 0000000000000000000000000000000000000000..a63914d5c021d2891e79a353f8b82d9734d349d0
--- /dev/null
+++ b/thirdparty/rr/plugins/shutdown.pl
@@ -0,0 +1,76 @@
+#-----------------------------------------------------------
+# shutdown.pl
+# Plugin for Registry Ripper; Access System hive file to get the
+# contents of the ShutdownTime value
+# 
+# Change history
+#
+#
+# References
+#   
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package shutdown;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets ShutdownTime value from System hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching shutdown v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+		my $win_path = $ccs."\\Control\\Windows";
+		my $win;
+		if ($win = $root_key->get_subkey($win_path)) {
+			::rptMsg($win_path." key, ShutdownTime value");
+			::rptMsg($win_path);
+			::rptMsg("LastWrite Time ".gmtime($win->get_timestamp())." (UTC)");
+			my $sd;
+			if ($sd = $win->get_value("ShutdownTime")->get_data()) {
+				my @vals = unpack("VV",$sd);
+				my $shutdown = ::getTime($vals[0],$vals[1]);
+				::rptMsg("  ShutdownTime = ".gmtime($shutdown)." (UTC)");
+				
+			}
+			else {
+				::rptMsg("ShutdownTime value not found.");
+			}
+		}
+		else {
+			::rptMsg($win_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/shutdowncount.pl b/thirdparty/rr/plugins/shutdowncount.pl
new file mode 100644
index 0000000000000000000000000000000000000000..73d649117d9fa812b5c024008afcdcca93575e15
--- /dev/null
+++ b/thirdparty/rr/plugins/shutdowncount.pl
@@ -0,0 +1,81 @@
+#-----------------------------------------------------------
+# shutdowncount.pl
+#
+# *Value info first seen at:
+#   http://forensicsfromthesausagefactory.blogspot.com/2008/06/install-dates-and-shutdown-times-found.html
+#   thanks to DC1743@gmail.com
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package shutdowncount;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080709);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Retrieves ShutDownCount value";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching shutdowncount v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+ 	my $current;
+ 	my $ccs;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+	}
+	else {
+		::logMsg("Could not find ".$key_path);
+		return
+	}
+
+	my $key_path = $ccs."\\Control\\Watchdog\\Display";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("ShutdownCount");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my $count = 0;
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				if ($v->get_name() eq "ShutdownCount") {
+					$count = 1;
+					::rptMsg("ShutdownCount = ".$v->get_data());
+				}
+			}
+			::rptMsg("ShutdownCount value not found.") if ($count == 0);
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/skype.pl b/thirdparty/rr/plugins/skype.pl
new file mode 100644
index 0000000000000000000000000000000000000000..3c83bc65f15920d688a3d349e20ad3b27a4d7468
--- /dev/null
+++ b/thirdparty/rr/plugins/skype.pl
@@ -0,0 +1,60 @@
+#-----------------------------------------------------------
+# skype.pl
+#  
+#
+# History
+#   20100713 - created
+#
+# References
+#
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package skype;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100713);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets data user's Skype key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching acmru v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Skype';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my $install;
+		eval {
+			$install = $key->get_subkey("Installer")->get_value("DonwloadLastModified")->get_data();
+			::rptMsg("DonwloadLastModified = ".$install);
+		};
+		::rptMsg("DonwloadLastModified value not found: ".$@) if ($@);
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/snapshot.pl b/thirdparty/rr/plugins/snapshot.pl
new file mode 100644
index 0000000000000000000000000000000000000000..29bf42b93b3022ea4076aa15cdd2d5e3f18564f4
--- /dev/null
+++ b/thirdparty/rr/plugins/snapshot.pl
@@ -0,0 +1,96 @@
+#-----------------------------------------------------------
+# snapshot.pl
+# Plugin to check the ActiveX component for the MS Access Snapshot
+# Viewer kill bit
+#
+# Ref: US-CERT Vuln Note #837785, http://www.kb.cert.org/vuls/id/837785
+# 
+# Note: Look for each GUID key, and check for the Compatibility Flags value;
+#       if the value is 0x400, the kill bit is set; a vulnerable system is 
+#       indicated by having IE version 6.x, and the kill bits NOT set (IE 7
+#       requires user interaction to download the ActiveX component
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package snapshot;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              version       => 20080725);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Check ActiveX comp kill bit; Access Snapshot";	
+}
+sub getDescr{}
+sub getRefs {"US-CERT Vuln Note 837785" => "http://www.kb.cert.org/vuls/id/837785"}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+my @guids = ("{F0E42D50-368C-11D0-AD81-00A0C90DC8D9}",
+      			 "{F0E42D60-368C-11D0-AD81-00A0C90DC8D9}",
+      			 "{F2175210-368C-11D0-AD81-00A0C90DC8D9}");
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching snapshot v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	
+	my $key_path = "Microsoft\\Internet Explorer";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("ActiveX Snapshot Vuln");
+		::rptMsg($key_path);
+		::rptMsg("");
+		my $ver;
+		eval {
+			$ver = $key->get_value("Version")->get_data();
+		};
+		if ($@) {
+			::rptMsg("IE Version not found.");
+		}
+		else {
+			::rptMsg("IE Version = ".$ver)
+		}
+		
+		::rptMsg("");
+		foreach my $guid (@guids) {
+			my $g;
+			eval {
+				$g = $key->get_subkey("ActiveX Compatibility\\".$guid);
+			};
+			if ($@) {
+				::rptMsg("$guid not found.");
+			}
+			else {
+				::rptMsg("GUID: $guid");
+				my $flag;
+				eval {
+					$flag = $g->get_value("Compatibility Flags")->get_data();
+				};
+				if ($@) {
+					::rptMsg("Compatibility Flags value not found.");
+				}
+				else {
+					my $str = sprintf "Compatibility Flags  0x%x",$flag;
+					::rptMsg($str); 
+				}
+			}
+			::rptMsg("");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/soft_run.pl b/thirdparty/rr/plugins/soft_run.pl
new file mode 100644
index 0000000000000000000000000000000000000000..1c5e7a6d526cabba2eb7d3a2954c217a8800f8fc
--- /dev/null
+++ b/thirdparty/rr/plugins/soft_run.pl
@@ -0,0 +1,97 @@
+#-----------------------------------------------------------
+# soft_run
+# Get contents of Run key from Software hive
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package soft_run;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              version       => 20080328);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Autostart - get Run key contents from Software hive";	
+}
+sub getDescr{}
+sub getRefs {
+	my %refs = ("Definition of the Run keys in the WinXP Registry" =>
+	            "http://support.microsoft.com/kb/314866");	
+	return %refs;
+}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching soft_run v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows\\CurrentVersion\\Run";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my %vals = getKeyValues($key);
+		if (scalar(keys %vals) > 0) {
+			foreach my $v (keys %vals) {
+				::rptMsg("\t".$v." -> ".$vals{$v});
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+		
+		my @sk = $key->get_list_of_subkeys();
+		if (scalar(@sk) > 0) {
+			foreach my $s (@sk) {
+				::rptMsg("");
+				::rptMsg($key_path."\\".$s->get_name());
+				::rptMsg("LastWrite Time ".gmtime($s->get_timestamp())." (UTC)");
+				my %vals = getKeyValues($s);
+				foreach my $v (keys %vals) {
+					::rptMsg("\t".$v." -> ".$vals{$v});
+				}
+			}
+		}
+		else {
+			::rptMsg("");
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+}
+
+sub getKeyValues {
+	my $key = shift;
+	my %vals;
+	
+	my @vk = $key->get_list_of_values();
+	if (scalar(@vk) > 0) {
+		foreach my $v (@vk) {
+			next if ($v->get_name() eq "" && $v->get_data() eq "");
+			$vals{$v->get_name()} = $v->get_data();
+		}
+	}
+	else {
+	
+	}
+	return %vals;
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/software b/thirdparty/rr/plugins/software
new file mode 100644
index 0000000000000000000000000000000000000000..144bfaf466cb66df4214d1e38fdab85c9f04a9a0
--- /dev/null
+++ b/thirdparty/rr/plugins/software
@@ -0,0 +1,36 @@
+#-------------------------------------
+# Software
+winver
+win_cv
+winnt_cv
+defbrowser
+ie_version
+banner
+bitbucket
+macaddr
+cmd_shell
+soft_run
+networkcards
+ssid
+appinitdlls
+bho
+shellexec
+imagefile
+port_dev
+userinit
+winlogon
+profilelist
+specaccts
+mrt
+svchost
+snapshot
+sfc
+uninstall
+installedcomp
+shelloverlay
+msis
+shellexec
+apppaths
+drwatson
+schedagent
+kb950582
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/specaccts.pl b/thirdparty/rr/plugins/specaccts.pl
new file mode 100644
index 0000000000000000000000000000000000000000..4933d865fa6de0e5abd8bc61c4e12af9149b33b5
--- /dev/null
+++ b/thirdparty/rr/plugins/specaccts.pl
@@ -0,0 +1,68 @@
+#-----------------------------------------------------------
+# specaccts.pl
+# Gets contents of SpecialAccounts\UserList key
+# 
+# History
+#   20100223 - created
+#
+# References
+#   http://www.microsoft.com/security/portal/Threat/Encyclopedia/
+#          Entry.aspx?Name=Trojan%3AWin32%2FStarter
+#
+#   http://www.microsoft.com/Security/portal/Threat/Encyclopedia/
+#          Entry.aspx?Name=TrojanSpy%3AWin32%2FUrsnif.gen!H&ThreatID=-2147343835
+#
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package specaccts;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100223);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Gets contents of SpecialAccounts\\UserList key";	
+}
+sub getDescr{}
+
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching specaccts v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\SpecialAccounts\\UserList";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my %apps;
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				::rptMsg(sprintf "%-20s 0x%x",$v->get_name(),$v->get_data());
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/sql_lastconnect.pl b/thirdparty/rr/plugins/sql_lastconnect.pl
new file mode 100644
index 0000000000000000000000000000000000000000..fb21951a75eff1d0405e787043306bb657cce2c3
--- /dev/null
+++ b/thirdparty/rr/plugins/sql_lastconnect.pl
@@ -0,0 +1,66 @@
+#-----------------------------------------------------------
+# sql_lastconnect.pl
+#
+# Per MS, Microsoft Data Access Components (MDAC) clients can attempt
+# to use multiple protocols based on a protocol ordering, which is 
+# listed in the SuperSocketNetLib\ProtocolOrder value.  Successful 
+# connection attempts (for SQL Server 2000) are cached in the LastConnect
+# key.
+#
+# References:
+#    http://support.microsoft.com/kb/273673/
+# 
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package sql_lastconnect;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090112);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "MDAC cache of successful connections";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching sql_lastconnect v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\MSSQLServer\\Client\\SuperSocketNetLib\\LastConnect";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("MDAC Cache of successful connections");
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $str = sprintf "%-15s  %-25s",$v->get_name(),$v->get_data();
+				::rptMsg($str);
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/ssid.pl b/thirdparty/rr/plugins/ssid.pl
new file mode 100644
index 0000000000000000000000000000000000000000..1e7714ae5695a968e10ba44ff277239128646c68
--- /dev/null
+++ b/thirdparty/rr/plugins/ssid.pl
@@ -0,0 +1,183 @@
+#-----------------------------------------------------------
+# ssid
+# Gets SSID and other info from WZCSVC key
+#
+#
+# Change History:
+#    20100301 - Updated References; removed dwCtlFlags being 
+#               printed; minor adjustments to formatting
+#    20091102 - added code to parse EAPOL values for SSIDs
+#    20090807 - updated code in accordance with WZC_WLAN_CONFIG 
+#               structure
+#
+# References
+#    http://msdn.microsoft.com/en-us/library/aa448338.aspx
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package ssid;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100301);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get WZCSVC SSID Info";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+my $error;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching ssid v.".$VERSION);
+# Get the NetworkCards values
+	my %nc;
+	if (%nc = getNetworkCards($hive)) {
+		
+	}
+	else {
+		::logMsg("Problem w/ SSIDs, getting NetworkCards: ".$error);
+		return;
+	}
+		
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Microsoft\\WZCSVC\\Parameters\\Interfaces";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("SSID");
+		::rptMsg($key_path);
+		::rptMsg("");
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				my $name = $s->get_name();
+				if (exists($nc{$name})) {
+					::rptMsg("NIC: ".$nc{$name}{descr});
+					::rptMsg("Key LastWrite: ".gmtime($s->get_timestamp())." UTC");
+					::rptMsg("");
+					my @vals = $s->get_list_of_values();
+					if (scalar(@vals) > 0) {
+						foreach my $v (@vals) {
+							my $n = $v->get_name();
+							if ($n =~ m/^Static#/) {
+								my $data = $v->get_data();								
+#								my $w = unpack("V",substr($data,0x04,0x04));
+#								printf "dwCtlFlags = 0x%x\n",$w;
+								
+								my $l = unpack("V",substr($data, 0x10, 0x04));
+								my $ssid = substr($data,0x14,$l);
+								
+								my $tm = uc(unpack("H*",substr($data,0x08,0x06)));
+								my @t = split(//,$tm);
+								my $mac = $t[0].$t[1]."-".$t[2].$t[3]."-".$t[4].$t[5]."-".$t[6].$t[7]."-".$t[8].$t[9]."-".$t[10].$t[11];
+								
+								my ($t1,$t2) = unpack("VV",substr($data,0x2B8,8));
+								my $t        = ::getTime($t1,$t2);
+								my $str = sprintf gmtime($t)." MAC: %-18s %-8s",$mac,$ssid;
+								::rptMsg($str);
+							}
+						}
+					}
+					else {
+						::rptMsg($name." has no values.");
+					}
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+	
+# Now, go to the EAPOL key, locate the appropriate subkeys and parse out
+# any available SSIDs	
+# EAPOL is Extensible Authentication Protocol over LAN
+	my $key_path = "Microsoft\\EAPOL\\Parameters\\Interfaces";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("");
+		::rptMsg($key_path);
+		::rptMsg("");
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				my $name = $s->get_name();
+				if (exists $nc{$name}) {
+					::rptMsg("NIC: ".$nc{$name}{descr});
+				}
+				else {
+					::rptMsg("NIC: ".$name);
+				}
+				::rptMsg("LastWrite time: ".gmtime($s->get_timestamp())." UTC");
+				
+				my @vals = $s->get_list_of_values();
+				my %eapol;
+				if (scalar(@vals) > 0) {
+					foreach my $v (@vals) {
+						$eapol{$v->get_name()} = parseEAPOLData($v->get_data());
+					}
+					foreach my $i (sort {$a <=> $b} keys %eapol) {
+						my $str = sprintf "%-3d  %s",$i,$eapol{$i};
+						::rptMsg($str);
+					}
+				}
+				::rptMsg("");
+			}
+		}
+		else {
+			::rtpMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+sub getNetworkCards {
+	my $hive = shift;
+	my %nc;
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				my $service = $s->get_value("ServiceName")->get_data();
+				$nc{$service}{descr} = $s->get_value("Description")->get_data();
+				$nc{$service}{lastwrite} = $s->get_timestamp();
+			}
+		}
+		else {
+			$error = $key_path." has no subkeys.";
+		}
+	}
+	else {
+		$error = $key_path." not found.";
+	}
+	return %nc;
+}
+
+sub parseEAPOLData {
+	my $data = shift;
+	my $size = unpack("V",substr($data,0x10,4));
+	return substr($data,0x14,$size);
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/startpage.pl b/thirdparty/rr/plugins/startpage.pl
new file mode 100644
index 0000000000000000000000000000000000000000..78dcc9e426c3901897dd35c6ae9cb50edf55476c
--- /dev/null
+++ b/thirdparty/rr/plugins/startpage.pl
@@ -0,0 +1,77 @@
+#-----------------------------------------------------------
+# startpage.pl
+# For Windows 7
+#
+# Change history
+#	  20100330 - created
+#
+# References
+#   
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package startpage;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100330);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of user's StartPage key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching startpage v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my $menu;
+		my $balloon;
+		
+		eval {
+			my $val = $key->get_value("StartMenu_Start_Time")->get_data();
+			my ($t0,$t1) = unpack("VV",$val);
+			$menu = ::getTime($t0,$t1);
+			::rptMsg("StartMenu_Start_Time   = ".gmtime($menu)." Z");
+		};
+		::rptMsg("Error: ".@$) if (@$);
+		
+		eval {
+			my $val = $key->get_value("StartMenu_Balloon_Time")->get_data();
+			my ($t0,$t1) = unpack("VV",$val);
+			$balloon = ::getTime($t0,$t1);
+			::rptMsg("StartMenu_Balloon_Time = ".gmtime($balloon)." Z");
+		};
+		::rptMsg("Error: ".@$) if (@$);
+		
+		
+		
+		
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/stillimage.pl b/thirdparty/rr/plugins/stillimage.pl
new file mode 100644
index 0000000000000000000000000000000000000000..aaf23600e4bf57e8488455bfc761cd056306a18d
--- /dev/null
+++ b/thirdparty/rr/plugins/stillimage.pl
@@ -0,0 +1,112 @@
+#-----------------------------------------------------------
+# stillimage.pl
+# Parses contents of Enum\USB key for web cam
+# 
+# History
+#   20100222 - created
+#
+# References
+#   http://msdn.microsoft.com/en-us/library/ms791870.aspx
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package stillimage;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100222);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get info on StillImage devices";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+my $reg;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	$reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+::logMsg("Launching stillimage v.".$VERSION);
+# Code for System file, getting CurrentControlSet
+	my $current;
+	my $ccs;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		return;
+	}
+	
+	my $key_path = $ccs."\\Control\\Class\\{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar @subkeys > 0) {
+			::rptMsg("");
+			foreach my $s (@subkeys) {
+				my $name = $s->get_name();
+				next unless ($name =~ m/\d\d/);
+				::rptMsg($name);
+				
+				eval {
+					my $desc = $s->get_value("DriverDesc")->get_data();
+					::rptMsg("  ".$desc);
+				};
+				
+				eval {
+					my $desc = $s->get_value("MatchingDeviceID")->get_data();
+					::rptMsg("  ".$desc);
+				};
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+
+# http://msdn.microsoft.com/en-us/library/ms791870.aspx
+# StillImage logging levels
+	my $key_path = $ccs."\\Control\\StillImage\\Logging";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("");
+		::rptMsg("StillImage Logging Level");
+		eval {
+			my $level = $key->get_subkey("STICLI")->get_value("Level")->get_data();
+			my $str = sprintf "  STICLI Logging Level = 0x%x",$level;
+			::rptMsg($str);
+		};
+		::rptMsg("STICLI Error: ".$@) if ($@);
+		
+		eval {
+			my $level = $key->get_subkey("STIMON")->get_value("Level")->get_data();
+			my $str = sprintf "  STIMON Logging Level = 0x%x",$level;
+			::rptMsg($str);
+		};
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/streammru.pl b/thirdparty/rr/plugins/streammru.pl
new file mode 100644
index 0000000000000000000000000000000000000000..0276cad0848e01ea9a9747e121fa1fbbec9a4e1a
--- /dev/null
+++ b/thirdparty/rr/plugins/streammru.pl
@@ -0,0 +1,64 @@
+#-----------------------------------------------------------
+# streammru.pl
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package streammru;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090205);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "streammru";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching streammru v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StreamMRU";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("");
+		::rptMsg($key_path);
+		::rptMsg("");
+		
+		my $data = $key->get_value("5")->get_data();
+		
+		my $drive = substr($data, 0x16,4);
+		::rptMsg("Drive = ".$drive);
+		::rptMsg("");
+		
+		my $size = substr($data, 0x2d, 1);
+		::rptMsg("Size of first object: ".unpack("c",$size)." bytes");
+		::rptMsg("");
+		
+		
+		
+		
+		
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/streams.pl b/thirdparty/rr/plugins/streams.pl
new file mode 100644
index 0000000000000000000000000000000000000000..e620c033dfa0864f482b24883ed63c096afae667
--- /dev/null
+++ b/thirdparty/rr/plugins/streams.pl
@@ -0,0 +1,63 @@
+#-----------------------------------------------------------
+# streams.pl
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package streams;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20081124);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Parse Streams and StreamsMRU entries";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching streams v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StreamMRU';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("streamMRU");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $i (0..10) {
+				my $data = $key->get_value($i)->get_data();
+				open(FH,">",$i);
+				binmode(FH);
+				print FH $data;
+				close(FH);		
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/svc.pl b/thirdparty/rr/plugins/svc.pl
new file mode 100644
index 0000000000000000000000000000000000000000..32332bf723412b6bbd402b339fd62f31eb0693a9
--- /dev/null
+++ b/thirdparty/rr/plugins/svc.pl
@@ -0,0 +1,149 @@
+#-----------------------------------------------------------
+# svc.pl
+# Plugin for Registry Ripper; Access System hive file to get the
+# services, display short format (hence "svc", shortened version
+# of service.pl plugin)
+# 
+# Change history
+#   20080610 - created
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package svc;
+#use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080610);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Lists services/drivers in Services key by LastWrite times (short format)";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+# Reference for types and start types:
+# http://msdn.microsoft.com/en-us/library/aa394420(VS.85).aspx
+my %types = (0x001 => "Kernel driver",
+             0x002 => "File system driver",
+             0x010 => "Own_Process",
+             0x020 => "Share_Process",
+             0x100 => "Interactive");
+
+my %starts = (0x00 => "Boot Start",
+              0x01 => "System Start",
+              0x02 => "Auto Start",
+              0x03 => "Manual",
+              0x04 => "Disabled");
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching svc v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+		my $s_path = $ccs."\\Services";
+		my $svc;
+		my %svcs;
+		if ($svc = $root_key->get_subkey($s_path)) {
+			::rptMsg($s_path);
+			::rptMsg(getShortDescr());
+			::rptMsg("");
+# Get all subkeys and sort based on LastWrite times
+			my @subkeys = $svc->get_list_of_subkeys();
+			if (scalar (@subkeys) > 0) {
+				foreach my $s (@subkeys) {
+					
+					my $type;
+					eval {
+						$type = $s->get_value("Type")->get_data();
+					};
+				
+				 	$name = $s->get_name();
+					my $display;
+					eval {
+						$display = $s->get_value("DisplayName")->get_data();
+					};
+					
+					my $image;
+					eval {
+						$image = $s->get_value("ImagePath")->get_data();
+					};
+					
+					my $start;
+					eval {
+						$start = $s->get_value("Start")->get_data();
+						if (exists $starts{$start}) {
+							$start = $starts{$start};
+						}
+					};
+					
+					my $object;
+					eval {
+						$object = $s->get_value("ObjectName")->get_data();
+					};
+					next if ($type == 0x001 || $type == 0x002);
+					my $str = $name.";".$display.";".$image.";".$type.";".$start.";".$object;
+					push(@{$svcs{$s->get_timestamp()}},$str) unless ($str eq "");
+				}
+			
+				foreach my $t (reverse sort {$a <=> $b} keys %svcs) {
+					::rptMsg(gmtime($t)."Z");
+					foreach my $item (@{$svcs{$t}}) {
+						my ($n,$d,$i,$t,$s,$o) = split(/;/,$item,6);
+						my $str = "  ".$n;
+						
+						if ($i eq "") {
+							if ($d eq "") {
+								
+							}
+							else {
+								$str = $str." (".$d.")";
+							}
+						}
+						else {
+							$str = $str." (".$i.")";
+						}
+						
+						$str = $str." [".$o."]" unless ($o eq "");
+						
+						::rptMsg($str);
+					}
+					::rptMsg("");
+				}
+				
+			}
+			else {
+				::rptMsg($s_path." has no subkeys.");
+				::logMsg("Error: ".$s_path." has no subkeys.");
+			}			
+		}
+		else {
+			::rptMsg($s_path." not found.");
+			::logMsg($s_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/svc2.pl b/thirdparty/rr/plugins/svc2.pl
new file mode 100644
index 0000000000000000000000000000000000000000..0a1237037100479ca2151125777b9ed1b2b17e39
--- /dev/null
+++ b/thirdparty/rr/plugins/svc2.pl
@@ -0,0 +1,148 @@
+#-----------------------------------------------------------
+# svc2.pl
+# Plugin for Registry Ripper; Access System hive file to get the
+# services, display short format (hence "svc", shortened version
+# of service.pl plugin); outputs info in .csv format
+# 
+# Change history
+#   20081129 - created
+# 
+# Ref:
+#   http://msdn.microsoft.com/en-us/library/aa394073(VS.85).aspx
+#
+# Analysis Tip: Several services keys have Parameters subkeys that point to
+#   the ServiceDll value; During intrusions, a service key may be added to 
+#   the system's Registry; using this module, send the output to .csv format
+#   and sort on column B to get the names to line up
+#
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package svc2;
+#use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20081129);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Lists Services key contents by LastWrite times (CSV)";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+my %types = (0x001 => "Kernel driver",
+             0x002 => "File system driver",
+             0x004 => "Adapter",
+             0x010 => "Own_Process",
+             0x020 => "Share_Process",
+             0x100 => "Interactive");
+
+my %starts = (0x00 => "Boot Start",
+              0x01 => "System Start",
+              0x02 => "Auto Start",
+              0x03 => "Manual",
+              0x04 => "Disabled");
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+#	::logMsg("Launching svc2 v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+		my $s_path = $ccs."\\Services";
+		my $svc;
+		my %svcs;
+		if ($svc = $root_key->get_subkey($s_path)) {
+#			::rptMsg($s_path);
+#			::rptMsg(getShortDescr());
+#			::rptMsg("");
+# Get all subkeys and sort based on LastWrite times
+			my @subkeys = $svc->get_list_of_subkeys();
+			if (scalar (@subkeys) > 0) {
+				foreach my $s (@subkeys) {
+					$name = $s->get_name();
+					my $display;
+					eval {
+						$display = $s->get_value("DisplayName")->get_data();
+# take commas out of the display name, replace w/ semi-colons
+						$display =~ s/,/;/g;
+					};
+					
+					my $type;
+					eval {
+						$type = $s->get_value("Type")->get_data();
+						$type = $types{$type} if (exists $types{$type});
+							
+					};
+
+					my $image;
+					eval {
+						$image = $s->get_value("ImagePath")->get_data();
+					};
+					
+					my $start;
+					eval {
+						$start = $s->get_value("Start")->get_data();
+						$start = $starts{$start} if (exists $starts{$start});
+					};
+					
+					my $object;
+					eval {
+						$object = $s->get_value("ObjectName")->get_data();
+					};
+					
+					my $str = $name."\|".$display."\|".$image."\|".$type."\|".$start."\|".$object;
+					push(@{$svcs{$s->get_timestamp()}},$str) unless ($str eq "");
+# Get ServiceDll value if there is one					
+					eval {
+						my $para = $s->get_subkey("Parameters");
+						my $dll = $para->get_value("ServiceDll")->get_data();
+						my $str = $name."\\Parameters\|\|".$dll."\|\|\|";
+						push(@{$svcs{$para->get_timestamp()}},$str);
+					};
+					
+				}
+			
+				foreach my $t (reverse sort {$a <=> $b} keys %svcs) {
+#					::rptMsg(gmtime($t)."Z");
+					foreach my $item (@{$svcs{$t}}) {
+						my ($n,$d,$i,$t2,$s,$o) = split(/\|/,$item,6);
+#						::rptMsg($t.",".$n.",".$d.",".$i.",".$t2.",".$s.",".$o);
+						::rptMsg(gmtime($t)."Z".",".$n.",".$d.",".$i.",".$t2.",".$s.",".$o);
+					}
+				}
+			}
+			else {
+				::rptMsg($s_path." has no subkeys.");
+				::logMsg("Error: ".$s_path." has no subkeys.");
+			}			
+		}
+		else {
+			::rptMsg($s_path." not found.");
+			::logMsg($s_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/svcdll.pl b/thirdparty/rr/plugins/svcdll.pl
new file mode 100644
index 0000000000000000000000000000000000000000..3cfbcd2f242d34de1d9028d4a94ce4e08d502d3d
--- /dev/null
+++ b/thirdparty/rr/plugins/svcdll.pl
@@ -0,0 +1,131 @@
+#-----------------------------------------------------------
+# svcdll.pl
+# 
+# Change history
+#   20091104 - created
+# 
+# Ref:
+#   http://msdn.microsoft.com/en-us/library/aa394073(VS.85).aspx
+#
+# Analysis Tip: Several services keys have Parameters subkeys that point to
+#   the ServiceDll value; During intrusions, a service key may be added to 
+#   the system's Registry; this module provides a quick look, displaying the
+#   Service names (in malware, sometimes random) and the ServiceDll value,
+#   sorted based on the LastWrite time of the <service name>\Parameters subkey.
+#
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package svcdll;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20091104);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Lists Services keys with ServiceDll values";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+#my %types = (0x001 => "Kernel driver",
+#             0x002 => "File system driver",
+#             0x004 => "Adapter",
+#             0x010 => "Own_Process",
+#             0x020 => "Share_Process",
+#             0x100 => "Interactive");
+
+#my %starts = (0x00 => "Boot Start",
+#              0x01 => "System Start",
+#              0x02 => "Auto Start",
+#              0x03 => "Manual",
+#              0x04 => "Disabled");
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching svcdll v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+		my $s_path = $ccs."\\Services";
+		my $svc;
+		my %svcs;
+		if ($svc = $root_key->get_subkey($s_path)) {
+
+# Get all subkeys and sort based on LastWrite times
+			my @subkeys = $svc->get_list_of_subkeys();
+			if (scalar (@subkeys) > 0) {
+				foreach my $s (@subkeys) {
+					my $name = $s->get_name();
+#					my $display;
+#					eval {
+#						$display = $s->get_value("DisplayName")->get_data();
+#					};
+					
+#					my $type;
+#					eval {
+#						$type = $s->get_value("Type")->get_data();
+#						$type = $types{$type} if (exists $types{$type});						
+#					};
+
+#					my $image;
+#					eval {
+#						$image = $s->get_value("ImagePath")->get_data();
+#					};
+					
+#					my $start;
+#					eval {
+#						$start = $s->get_value("Start")->get_data();
+#						$start = $starts{$start} if (exists $starts{$start});
+#					};
+					
+					my $dll;
+					eval {
+						$dll = $s->get_subkey("Parameters")->get_value("ServiceDll")->get_data();
+						my $str = $name." -> ".$dll;
+						push(@{$svcs{$s->get_timestamp()}},$str) unless ($str eq "");
+					};					
+				}
+			
+				foreach my $t (reverse sort {$a <=> $b} keys %svcs) {
+					::rptMsg(gmtime($t)."Z");
+					foreach my $item (@{$svcs{$t}}) {
+						::rptMsg("  ".$item);
+					}
+					::rptMsg("");
+				}
+			}
+			else {
+				::rptMsg($s_path." has no subkeys.");
+				::logMsg("Error: ".$s_path." has no subkeys.");
+			}			
+		}
+		else {
+			::rptMsg($s_path." not found.");
+			::logMsg($s_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/svchost.pl b/thirdparty/rr/plugins/svchost.pl
new file mode 100644
index 0000000000000000000000000000000000000000..481d08ca4628f6decb53edf36ed15b08382a12c0
--- /dev/null
+++ b/thirdparty/rr/plugins/svchost.pl
@@ -0,0 +1,74 @@
+#-----------------------------------------------------------
+# svchost
+# Plugin to get data from Security Center keys
+#
+# Change History:
+#   20100322 - created
+#
+# References:
+#   http://support.microsoft.com/kb/314056
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package svchost;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100322);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get entries from SvcHost key";	
+}
+sub getDescr{}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	my $infected = 0;
+	::logMsg("Launching secctr v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = 'Microsoft\Windows NT\CurrentVersion\SvcHost';
+	my $key;
+	::rptMsg("svchost");
+	::rptMsg("");
+	
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my @data = $v->get_data();
+				my $d;
+				if (scalar(@data) > 1) {
+					$d = join(',',@data);
+				}
+				else {
+					$d = $data[0];
+				}
+				my $str = sprintf "%-15s %-55s",$v->get_name(),$d;
+				::rptMsg($str);
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::rptMsg("");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/system b/thirdparty/rr/plugins/system
new file mode 100644
index 0000000000000000000000000000000000000000..366c10fc62b07d5dc2708c57e702577ad4d959c2
--- /dev/null
+++ b/thirdparty/rr/plugins/system
@@ -0,0 +1,36 @@
+#-------------------------------------
+# System
+compname
+xpedition
+producttype
+dllsearch
+termserv
+rdpport
+shutdown
+shutdowncount
+nolmhash
+timezone
+disablelastaccess
+eventlog
+auditfail
+crashcontrol
+kbdcrash
+pagefile
+hibernate
+mountdev
+routes
+network 
+nic_mst2
+nic
+nic2
+fw_config
+ide
+shares
+svc2
+svcdll
+imagedev
+legacy
+stillimage
+usbdevices
+usbstor
+devclass
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/taskman.pl b/thirdparty/rr/plugins/taskman.pl
new file mode 100644
index 0000000000000000000000000000000000000000..3a6b212a59db1ef0baa6cde8a6fd3ae3a8c30c75
--- /dev/null
+++ b/thirdparty/rr/plugins/taskman.pl
@@ -0,0 +1,61 @@
+#-----------------------------------------------------------
+# taskman.pl
+# Get Taskman value from Winlogon
+#
+# References
+#   http://www.geoffchappell.com/viewer.htm?doc=notes/windows/shell/explorer/
+#          taskman.htm&tx=3,5-7,12;4&ts=0,19
+#   http://technet.microsoft.com/en-us/library/cc957402.aspx
+#
+# Change History: 
+#   20091116 - created
+#   
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package taskman;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20091116);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Gets Taskman from HKLM\\..\\Winlogon";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching taskman v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\Winlogon";
+	if (my $key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		
+		eval {
+			::rptMsg("");
+			my $task = $key->get_value("Taskman")->get_data();
+			::rptMsg("Taskman value = ".$task);
+		};
+		if ($@) {
+		  ::rptMsg("Taskman value not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/termcert.pl b/thirdparty/rr/plugins/termcert.pl
new file mode 100644
index 0000000000000000000000000000000000000000..81e4b3750549b6a79514bc109304105388046c21
--- /dev/null
+++ b/thirdparty/rr/plugins/termcert.pl
@@ -0,0 +1,96 @@
+#-----------------------------------------------------------
+# termcert.pl
+# Plugin for Registry Ripper; 
+# 
+# Change history
+#   20110316 - created
+#   
+# copyright 2011 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package termcert;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20110316);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets Terminal Server certificate";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching termcert v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+		my $ts_path = $ccs."\\Services\\TermService\\Parameters";
+		my $ts;
+		if ($ts = $root_key->get_subkey($ts_path)) {
+			::rptMsg($ts_path);
+			::rptMsg("LastWrite Time ".gmtime($ts->get_timestamp())." (UTC)");
+			::rptMsg("");
+			
+			my $cert;
+			eval {
+				$cert = $ts->get_value("Certificate")->get_raw_data();
+				
+				printSector($cert);
+			};
+			::rptMsg("Certificate value not found.") if ($@);
+		}
+		else {
+			::rptMsg($ts_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+sub printSector {
+	my $data = shift;
+	my $len = length($data);
+	my $remaining = $len;
+	my $i = 0;
+	
+	while ($remaining > 0) {
+		my $seg1 = substr($data,$i * 16,16);
+		my @str1 = split(//,unpack("H*",$seg1));
+
+		my @s3;
+		foreach my $i (0..15) {
+			$s3[$i] = $str1[$i * 2].$str1[($i * 2) + 1];
+		}
+
+		my $h = join(' ',@s3);
+		my @s1 = unpack("A*",$seg1);
+		my $s2 = join('',@s1);
+		$s2 =~ s/\W/\./g;
+
+		::rptMsg(sprintf "%-50s %-20s",$h,$s2);
+		$i++;
+		$remaining -= 16;
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/termserv.pl b/thirdparty/rr/plugins/termserv.pl
new file mode 100644
index 0000000000000000000000000000000000000000..010e3aed5e9727f6605660ed1984a6c31c7e0a2f
--- /dev/null
+++ b/thirdparty/rr/plugins/termserv.pl
@@ -0,0 +1,137 @@
+#-----------------------------------------------------------
+# termserv.pl
+# Plugin for Registry Ripper; 
+# 
+# Change history
+#   20100713 - Updated to include additional values, based on references
+#   20100119 - updated
+#   20090727 - created
+#
+# References
+#   Change TS listening port number - http://support.microsoft.com/kb/187623
+#   Examining TS key - http://support.microsoft.com/kb/243215
+#   Win2K8 TS stops listening - http://support.microsoft.com/kb/954398
+#   XP/Win2K3 TSAdvertise value - http://support.microsoft.com/kb/281307
+#   AllowTSConnections value - http://support.microsoft.com/kb/305608
+#   TSEnabled value - http://support.microsoft.com/kb/222992
+#   TSUserEnabled value - http://support.microsoft.com/kb/238965
+#   
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package termserv;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100713);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets Terminal Server values from System hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching termserv v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+		my $ts_path = $ccs."\\Control\\Terminal Server";
+		my $ts;
+		if ($ts = $root_key->get_subkey($ts_path)) {
+			::rptMsg($ts_path);
+			::rptMsg("LastWrite Time ".gmtime($ts->get_timestamp())." (UTC)");
+			::rptMsg("");
+			::rptMsg("Reference: http://support.microsoft.com/kb/243215");
+			::rptMsg("");
+			
+			my $ver;
+			eval {
+				$ver = $ts->get_value("ProductVersion")->get_data();
+				::rptMsg("  ProductVersion = ".$ver);
+			};
+			::rptMsg("");
+			
+			my $fdeny;
+			eval {
+				$fdeny = $ts->get_value("fDenyTSConnections")->get_data();
+				::rptMsg("  fDenyTSConnections = ".$fdeny);
+				::rptMsg("  1 = connections denied");
+			};
+			::rptMsg("fDenyTSConnections value not found.") if ($@);
+			::rptMsg("");
+			
+			my $allow;
+			eval {
+				$allow = $ts->get_value("AllowTSConnections")->get_data();
+				::rptMsg("  AllowTSConnections = ".$allow);
+				::rptMsg("  Ref: http://support.microsoft.com/kb/305608");
+			};
+			::rptMsg("");
+			
+			my $ad;
+			eval {
+				$ad = $ts->get_value("TSAdvertise")->get_data();
+				::rptMsg("  TSAdvertise = ".$ad);
+				::rptMsg("  0 = disabled, 1 = enabled (advertise Terminal Services)");
+				::rptMsg("  Ref: http://support.microsoft.com/kb/281307");
+			};
+			::rptMsg("");
+			
+			my $enabled;
+			eval {
+				$enabled = $ts->get_value("TSEnabled")->get_data();
+				::rptMsg("  TSEnabled = ".$enabled);
+				::rptMsg("  0 = disabled, 1 = enabled (Terminal Services enabled)");
+				::rptMsg("  Ref: http://support.microsoft.com/kb/222992");
+			};
+			::rptMsg("");
+			
+			my $user;
+			eval {
+				$user = $ts->get_value("TSUserEnabled")->get_data();
+				::rptMsg("  TSUserEnabled = ".$user);
+				::rptMsg("  1 = All users logging in are automatically part of the");
+				::rptMsg("  built-in Terminal Server User group. 0 = No one is a");
+				::rptMsg("  member of the built-in group.");
+				::rptMsg("  Ref: http://support.microsoft.com/kb/238965");
+			};
+			::rptMsg("");
+			
+			my $help;
+			eval {
+				$help = $ts->get_value("fAllowToGetHelp")->get_data();
+				::rptMsg("  fAllowToGetHelp = ".$user);
+				::rptMsg("  1 = Users can request assistance from friend or a ");
+				::rptMsg("  support professional.");
+				::rptMsg("  Ref: http://www.pctools.com/guides/registry/detail/1213/");
+			};
+	
+		}
+		else {
+			::rptMsg($ts_path." not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/timezone.pl b/thirdparty/rr/plugins/timezone.pl
new file mode 100644
index 0000000000000000000000000000000000000000..fa3f38729d1f2c2424676b0658e7883efe9f836c
--- /dev/null
+++ b/thirdparty/rr/plugins/timezone.pl
@@ -0,0 +1,88 @@
+#-----------------------------------------------------------
+# timezone.pl
+# Plugin for Registry Ripper; Access System hive file to get the
+# contents of the TimeZoneInformation key
+# 
+# Change history
+#
+#
+# References
+#   http://support.microsoft.com/kb/102986
+#   http://support.microsoft.com/kb/207563
+#   
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package timezone;
+use strict;
+
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get TimeZoneInformation key contents";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching timezone v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+# First thing to do is get the ControlSet00x marked current...this is
+# going to be used over and over again in plugins that access the system
+# file
+	my $current;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		my $ccs = "ControlSet00".$current;
+		my $tz_path = $ccs."\\Control\\TimeZoneInformation";
+		my $tz;
+		if ($tz = $root_key->get_subkey($tz_path)) {
+			::rptMsg("TimeZoneInformation key");
+			::rptMsg($tz_path);
+			::rptMsg("LastWrite Time ".gmtime($tz->get_timestamp())." (UTC)");
+			my %tz_vals;
+			my @vals = $tz->get_list_of_values();
+			if (scalar(@vals) > 0) {
+				map{$tz_vals{$_->get_name()} = $_->get_data()}(@vals);
+				
+				::rptMsg("  DaylightName   -> ".$tz_vals{"DaylightName"});
+				::rptMsg("  StandardName   -> ".$tz_vals{"StandardName"});
+				
+				my $bias   = $tz_vals{"Bias"}/60;
+				my $atbias = $tz_vals{"ActiveTimeBias"}/60;
+				
+				::rptMsg("  Bias           -> ".$tz_vals{"Bias"}." (".$bias." hours)");
+				::rptMsg("  ActiveTimeBias -> ".$tz_vals{"ActiveTimeBias"}." (".$atbias." hours)");
+				
+			}
+			else {
+				::rptMsg($tz_path." has no values.");
+				::logMsg($tz_path." has no values.");
+			}
+		}
+		else {
+			::rptMsg($tz_path." could not be found.");
+			::logMsg($tz_path." could not be found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/tsclient.pl b/thirdparty/rr/plugins/tsclient.pl
new file mode 100644
index 0000000000000000000000000000000000000000..364c17bff0c66fa331393456b50b00141be618ba
--- /dev/null
+++ b/thirdparty/rr/plugins/tsclient.pl
@@ -0,0 +1,72 @@
+#-----------------------------------------------------------
+# tsclient.pl
+# Plugin for Registry Ripper
+#
+# Change history
+#
+#
+# References
+#   http://support.microsoft.com/kb/312169
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package tsclient;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 0,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Displays contents of user's Terminal Server Client\\Default key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching tsclient v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Microsoft\\Terminal Server Client\\Default';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("TSClient");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			my %mrus;
+			foreach my $v (@vals) {
+				my $val = $v->get_name();
+				my $data = $v->get_data();
+				my $tag = (split(/MRU/,$val))[1];
+				$mrus{$tag} = $val.":".$data;
+			}
+			foreach my $u (sort {$a <=> $b} keys %mrus) {
+				my ($val,$data) = split(/:/,$mrus{$u},2);
+				::rptMsg("  ".$val." -> ".$data);
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/typedpaths.pl b/thirdparty/rr/plugins/typedpaths.pl
new file mode 100644
index 0000000000000000000000000000000000000000..292f0370b0ad21b7141d01abc23c5ece8fbd28e7
--- /dev/null
+++ b/thirdparty/rr/plugins/typedpaths.pl
@@ -0,0 +1,69 @@
+#-----------------------------------------------------------
+# typedpaths.pl
+# For Windows 7, Desktop Address Bar History
+#
+# Change history
+#	  20100330 - created
+#
+# References
+#   
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package typedpaths;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100330);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of user's typedpaths key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching typedpaths v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\TypedPaths";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			my %paths;
+			foreach my $v (@vals) { 
+				my $name = $v->get_name();
+				$name =~ s/^url//;
+				my $data = $v->get_data();
+				$paths{$name} = $data;
+			}
+			foreach my $p (sort {$a <=> $b} keys %paths) {
+				::rptMsg(sprintf "%-8s %-30s","url".$p,$paths{$p});
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/typedurls.pl b/thirdparty/rr/plugins/typedurls.pl
new file mode 100644
index 0000000000000000000000000000000000000000..fbd6c194e9e28e8745434af7d7f08ac24f8ae237
--- /dev/null
+++ b/thirdparty/rr/plugins/typedurls.pl
@@ -0,0 +1,87 @@
+#! c:\perl\bin\perl.exe
+#-----------------------------------------------------------
+# typedurls.pl
+# Plugin for Registry Ripper, NTUSER.DAT edition - gets the 
+# TypedURLs values 
+#
+# Change history
+#
+#
+# References
+#   http://support.microsoft.com/kb/157729
+#   http://msdn2.microsoft.com/en-us/library/aa908115.aspx
+# 
+# Notes:  Reportedly, only the last 20 entries are maintained;
+#         Also, new entries aren't added to the key until the current
+#         instance of IE is terminated.
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package typedurls;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              osmask        => 22,
+              version       => 20080324);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Returns contents of user's TypedURLs key.";	
+}
+sub getDescr{}
+sub getRefs {
+	my %refs = ("IESample Registry Settings" => 
+	            "http://msdn2.microsoft.com/en-us/library/aa908115.aspx",
+	            "How to clear History entries in IE" =>
+	            "http://support.microsoft.com/kb/157729");
+	return %refs;	
+}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching typedurls v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	
+	my $key_path = 'Software\\Microsoft\\Internet Explorer\\TypedURLs';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("TypedURLs");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			my %urls;
+# Retrieve values and load into a hash for sorting			
+			foreach my $v (@vals) {
+				my $val = $v->get_name();
+				my $data = $v->get_data();
+				my $tag = (split(/url/,$val))[1];
+				$urls{$tag} = $val.":".$data;
+			}
+# Print sorted content to report file			
+			foreach my $u (sort {$a <=> $b} keys %urls) {
+				my ($val,$data) = split(/:/,$urls{$u},2);
+				::rptMsg("  ".$val." -> ".$data);
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/uninstall.pl b/thirdparty/rr/plugins/uninstall.pl
new file mode 100644
index 0000000000000000000000000000000000000000..71975fd38844d3deb8e6a32abf8a0bf19ab30a45
--- /dev/null
+++ b/thirdparty/rr/plugins/uninstall.pl
@@ -0,0 +1,89 @@
+#-----------------------------------------------------------
+# uninstall.pl
+# Gets contents of Uninstall key from Software hive; sorts 
+# display names based on key LastWrite time
+# 
+# References:
+#    http://support.microsoft.com/kb/247501
+#    http://support.microsoft.com/kb/314481
+#    http://msdn.microsoft.com/en-us/library/ms954376.aspx
+#
+# Change History:
+#    20100116 - Minor updates
+#    20090413 - Extract DisplayVersion info
+#    20090128 - Added references
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package uninstall;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100116);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Gets contents of Uninstall key from Software hive";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching uninstall v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Microsoft\\Windows\\CurrentVersion\\Uninstall';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("Uninstall");
+		::rptMsg($key_path);
+		::rptMsg("");
+		
+		my %uninst;
+		my @subkeys = $key->get_list_of_subkeys();
+	 	if (scalar(@subkeys) > 0) {
+	 		foreach my $s (@subkeys) {
+	 			my $lastwrite = $s->get_timestamp();
+	 			my $display;
+	 			eval {
+	 				$display = $s->get_value("DisplayName")->get_data();
+	 			};
+	 			$display = $s->get_name() if ($display eq "");
+	 			
+	 			my $ver;
+	 			eval {
+	 				$ver = $s->get_value("DisplayVersion")->get_data();
+	 			};
+	 			$display .= " v\.".$ver unless ($@);
+	 			
+	 			push(@{$uninst{$lastwrite}},$display);
+	 		}
+	 		foreach my $t (reverse sort {$a <=> $b} keys %uninst) {
+				::rptMsg(gmtime($t)." (UTC)");
+				foreach my $item (@{$uninst{$t}}) {
+					::rptMsg("\t$item");
+				}
+				::rptMsg("");
+			}
+	 	}
+	 	else {
+	 		::rptMsg($key_path." has no subkeys.");
+	 	}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/unreadmail.pl b/thirdparty/rr/plugins/unreadmail.pl
new file mode 100644
index 0000000000000000000000000000000000000000..5f6aadcf6d3ecae5fe04c445bd1c1b60d91f3223
--- /dev/null
+++ b/thirdparty/rr/plugins/unreadmail.pl
@@ -0,0 +1,89 @@
+#-----------------------------------------------------------
+# unreadmail.pl
+# 
+#
+# Change history
+#   20100218 - created
+#
+# References
+#    http://support.microsoft.com/kb/304148
+#    http://support.microsoft.com/kb/831403
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package unreadmail;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100218);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of Unreadmail key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	my %hist;
+	::logMsg("Launching unreadmail v.".$VERSION);
+	
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\UnreadMail';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		eval {
+			my $e = $key->get_value("MessageExpiryDays")->get_data();
+			::rptMsg("MessageExpiryDays  : ".$e);
+			::rptMsg("");
+		};
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar @subkeys > 0) {
+			::rptMsg("");
+			foreach my $s (@subkeys) {
+				::rptMsg($s->get_name());
+				::rptMsg("LastWrite Time ".gmtime($s->get_timestamp())." (UTC)");
+				eval {
+					my $m = $s->get_value("MessageCount")->get_data();
+					::rptMsg("  MessageCount: ".$m);
+				};
+				
+				eval {
+					my $a = $s->get_value("Application")->get_data();
+					::rptMsg("  Application : ".$a);
+				};
+				
+				eval {
+					my @t = unpack("VV",$s->get_value("TimeStamp")->get_data());
+					my $ts = ::getTime($t[0],$t[1]);
+					::rptMsg("  TimeStamp   : ".gmtime($ts)." (UTC)");
+				};
+				
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/urlzone.pl b/thirdparty/rr/plugins/urlzone.pl
new file mode 100644
index 0000000000000000000000000000000000000000..f48e82411f02d0962962e4eaedda7665a83dec1d
--- /dev/null
+++ b/thirdparty/rr/plugins/urlzone.pl
@@ -0,0 +1,96 @@
+#-----------------------------------------------------------
+# /root/bin/plugins/urlzone.pl
+# Plugin to detect URLZONE infection
+#
+# copyright 2009 Stefan Kelm (skelm@bfk.de)
+#-----------------------------------------------------------
+package urlzone;
+use strict;
+
+my %config = (hive          => "Software",
+             osmask        => 22,
+             hasShortDescr => 1,
+             hasDescr      => 0,
+             hasRefs       => 0,
+             version       => 20090526);
+
+sub getConfig{return %config}
+
+sub getShortDescr {return "URLZONE detection";}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+my $class = shift;
+my $hive = shift;
+::logMsg("Launching urlzone v.".$VERSION);
+my $reg = Parse::Win32Registry->new($hive);
+my $root_key = $reg->get_root_key;
+
+my $key_path = "Microsoft\\Windows\\CurrentVersion\\Internet Settings\\urlzone";
+my $key;
+if ($key = $root_key->get_subkey($key_path)) {
+	::rptMsg($key_path);
+	::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+	::rptMsg("");
+ 
+	my @subkeys = $key->get_list_of_subkeys();
+	if (scalar(@subkeys) > 0) {
+		foreach my $s (@subkeys) {
+			::rptMsg($key_path."\\".$s->get_name());
+			::rptMsg("LastWrite Time = ".gmtime($s->get_timestamp())." (UTC)");
+			eval {
+				my @vals = $s->get_list_of_values();
+				if (scalar(@vals) > 0) {
+					my %sns;
+					foreach my $v (@vals) {
+						$sns{$v->get_name()} = $v->get_data();
+					}
+					foreach my $i (keys %sns) {
+						::rptMsg("\t\t".$i." = ".$sns{$i});
+					}
+				}
+				else {
+# No values                                                    
+				}
+			};
+			::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+#		::logMsg($key_path." not found.");
+	}
+
+	my $key_path2 = "Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\userinit.exe";
+	my $key2;
+	if ($key2 = $root_key->get_subkey($key_path2)) {
+		::rptMsg($key_path2);
+		::rptMsg("LastWrite Time ".gmtime($key2->get_timestamp())." (UTC)");
+ 		::rptMsg("");
+		my $dbg;
+		eval {
+			$dbg = $key2->get_value("Debugger")->get_data();
+		};
+		if ($@) {
+			::rptMsg("Debugger value not found.");
+		}
+		else {
+			::rptMsg("Debugger = ".$dbg);
+		}
+		::rptMsg("");
+	}
+	else {
+		::rptMsg($key_path2." not found.");
+#		::logMsg($key_path2." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/usb.pl b/thirdparty/rr/plugins/usb.pl
new file mode 100644
index 0000000000000000000000000000000000000000..2a4c438c7cfa9226ebccacc826c650330bfcb326
--- /dev/null
+++ b/thirdparty/rr/plugins/usb.pl
@@ -0,0 +1,111 @@
+#-----------------------------------------------------------
+# usb
+# Similar to usbstor plugin, but prints output in .csv format;
+# also checks MountedDevices keys
+# 
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package usb;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080825);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get USB subkeys info; csv output";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+my $reg;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	$reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+	my $current;
+	my $ccs;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		return;
+	}
+	
+	my $name_path = $ccs."\\Control\\ComputerName\\ComputerName";
+	my $comp_name;
+	eval {
+		$comp_name = $root_key->get_subkey($name_path)->get_value("ComputerName")->get_data();
+	};
+	$comp_name = "Test" if ($@);
+	
+	my $key_path = $ccs."\\Enum\\USB";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				my $dev_class = $s->get_name();
+				my @sk = $s->get_list_of_subkeys();
+				if (scalar(@sk) > 0) {
+					foreach my $k (@sk) {
+						my $serial = $k->get_name();
+						my $sn_lw = $k->get_timestamp();
+						my $str = $comp_name.",".$dev_class.",".$serial.",".$sn_lw;
+						
+						my $loc;
+						eval {
+							$loc = $k->get_value("LocationInformation")->get_data();
+							$str .= ",".$loc;
+						};
+						$str .= ", " if ($@);
+						
+						
+						my $friendly;
+						eval {
+							$friendly = $k->get_value("FriendlyName")->get_data();
+							$str .= ",".$friendly;
+						};
+						$str .= ", " if ($@);
+
+						my $parent;
+						eval {
+							$parent = $k->get_value("ParentIdPrefix")->get_data();
+							$str .= ",".$parent;
+						};
+
+
+						::rptMsg($str);
+					}
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/usbdevices.pl b/thirdparty/rr/plugins/usbdevices.pl
new file mode 100644
index 0000000000000000000000000000000000000000..27f7ef8a29282c7fb7822181eeeb73d419435c87
--- /dev/null
+++ b/thirdparty/rr/plugins/usbdevices.pl
@@ -0,0 +1,108 @@
+#-----------------------------------------------------------
+# usbdevices.pl
+# Parses contents of Enum\USB key for web cam
+# 
+# History
+#   20100219 - created
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package usbdevices;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100219);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Parses Enum\\USB key for devices";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+my $reg;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	$reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+::logMsg("Launching usbdevices v.".$VERSION);
+# Code for System file, getting CurrentControlSet
+	my $current;
+	my $ccs;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		return;
+	}
+	
+	my $key_path = $ccs."\\Enum\\USB";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar @subkeys > 0) {
+			foreach my $s (@subkeys) {
+				my @sk = $s->get_list_of_subkeys();
+				if (scalar @sk > 0) {
+					foreach my $s2 (@sk) {
+						::rptMsg("");
+						eval {
+							my $desc = $s2->get_value("DeviceDesc")->get_data();
+							::rptMsg($desc." [".$s->get_name()."\\".$s2->get_name()."]");
+						};
+						
+						my $str;
+						eval {
+							my $class = $s2->get_value("Class")->get_data();
+							::rptMsg("  Class               : ".$class);
+						};
+						
+						eval {
+							my $serv = $s2->get_value("Service")->get_data();
+							::rptMsg("  Service             : ".$serv);
+						};
+						
+						eval {
+							my $serv = $s2->get_value("LocationInformation")->get_data();
+							::rptMsg("  Location Information: ".$serv);
+						};
+						
+						eval {
+							my $serv = $s2->get_value("Mfg")->get_data();
+							::rptMsg("  Mfg                 : ".$serv);
+						};
+
+#						eval {
+#							if ($s2->get_value("Class")->get_data() eq "Image") {
+#								::rptMsg("Possible webcam at ".$s->get_name()."\\".$s2->get_name());
+#							}
+#						};
+#						::rptMsg("Error: ".$@) if ($@);
+					}
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/usbstor.pl b/thirdparty/rr/plugins/usbstor.pl
new file mode 100644
index 0000000000000000000000000000000000000000..e0223805a459f564115ff8e379e55672bab23889
--- /dev/null
+++ b/thirdparty/rr/plugins/usbstor.pl
@@ -0,0 +1,91 @@
+#-----------------------------------------------------------
+# usbstor
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package usbstor;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080418);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get USBStor key info";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching usbstor v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+	my $current;
+	my $ccs;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		return;
+	}
+
+	my $key_path = $ccs."\\Enum\\USBStor";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("USBStor");
+		::rptMsg($key_path);
+		::rptMsg("");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				::rptMsg($s->get_name()." [".gmtime($s->get_timestamp())."]");
+				
+				my @sk = $s->get_list_of_subkeys();
+				if (scalar(@sk) > 0) {
+					foreach my $k (@sk) {
+						my $serial = $k->get_name();
+						::rptMsg("  S/N: ".$serial." [".gmtime($k->get_timestamp())."]");
+						my $friendly;
+						eval {
+							$friendly = $k->get_value("FriendlyName")->get_data();
+						};
+						::rptMsg("    FriendlyName  : ".$friendly) if ($friendly ne "");
+						my $parent;
+						eval {
+							$parent = $k->get_value("ParentIdPrefix")->get_data();
+						};
+						::rptMsg("    ParentIdPrefix: ".$parent) if ($parent ne "");
+					}
+				}
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/usbstor2.pl b/thirdparty/rr/plugins/usbstor2.pl
new file mode 100644
index 0000000000000000000000000000000000000000..b62283bb1c64fd1ab7d8d229784784a4f936bdd6
--- /dev/null
+++ b/thirdparty/rr/plugins/usbstor2.pl
@@ -0,0 +1,134 @@
+#-----------------------------------------------------------
+# usbstor2
+# Similar to usbstor plugin, but prints output in .csv format;
+# also checks MountedDevices keys
+# 
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package usbstor2;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080825);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get USBStor key info; csv output";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+my $reg;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	$reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+	my $current;
+	my $ccs;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		return;
+	}
+	
+	my $name_path = $ccs."\\Control\\ComputerName\\ComputerName";
+	my $comp_name;
+	eval {
+		$comp_name = $root_key->get_subkey($name_path)->get_value("ComputerName")->get_data();
+	};
+	$comp_name = "Test" if ($@);
+	
+	my $key_path = $ccs."\\Enum\\USBStor";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				my $dev_class = $s->get_name();
+				my @sk = $s->get_list_of_subkeys();
+				if (scalar(@sk) > 0) {
+					foreach my $k (@sk) {
+						my $serial = $k->get_name();
+						my $sn_lw = $k->get_timestamp();
+						my $str = $comp_name.",".$dev_class.",".$serial.",".$sn_lw;
+						
+						my $friendly;
+						eval {
+							$friendly = $k->get_value("FriendlyName")->get_data();
+							$str .= ",".$friendly;
+						};
+						$str .= ", " if ($@);
+
+						my $parent;
+						eval {
+							$parent = $k->get_value("ParentIdPrefix")->get_data();
+							$str .= ",".$parent;
+							
+							my $dev = checkMountedDevices($parent);
+							$str .= ",".$dev if ($dev);
+							
+						};
+
+
+						::rptMsg($str);
+					}
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+sub checkMountedDevices {
+	my $pip = shift;
+	my $root_key = $reg->get_root_key;
+	my $key_path = 'MountedDevices';
+	my $key;
+	my %md;
+	if ($key = $root_key->get_subkey($key_path)) {
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				next unless ($name =~ m/^\\DosDevices/);
+				my $data = $v->get_data();
+				if (length($data) > 12) {
+					$data =~ s/\00//g; 
+					return $name if (grep(/$pip/,$data));
+				}
+			}
+		}
+	}
+	else {
+		return undef;
+	}
+	return undef;
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/usbstor3.pl b/thirdparty/rr/plugins/usbstor3.pl
new file mode 100644
index 0000000000000000000000000000000000000000..52154548187dbd00b09cd25b5c2ff6d9a9b905e7
--- /dev/null
+++ b/thirdparty/rr/plugins/usbstor3.pl
@@ -0,0 +1,103 @@
+#-----------------------------------------------------------
+# usbstor3
+# Collects USBStor information, output in .csv
+#
+# History
+#   20100312 - created
+#
+#
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package usbstor3;
+use strict;
+
+my %config = (hive          => "System",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100312);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get USBStor key info";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching usbstor3 v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+# Code for System file, getting CurrentControlSet
+	my $current;
+	my $ccs;
+	my $key_path = 'Select';
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		$current = $key->get_value("Current")->get_data();
+		$ccs = "ControlSet00".$current;
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		return;
+	}
+
+	my $key_path = $ccs."\\Enum\\USBStor";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+#		::rptMsg("USBStor");
+#		::rptMsg($key_path);
+#		::rptMsg("");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+#				::rptMsg($s->get_name()." [".gmtime($s->get_timestamp())."]");
+				my $name1 = $s->get_name();
+				my $time1 = gmtime($s->get_timestamp());
+				
+				my @sk = $s->get_list_of_subkeys();
+				if (scalar(@sk) > 0) {
+					foreach my $k (@sk) {
+						my $serial = $k->get_name();
+#						::rptMsg("  S/N: ".$serial." [".gmtime($k->get_timestamp())."]");
+						my $str = $name1.",".$time1.",".$serial.",".gmtime($k->get_timestamp());
+						
+						my $friendly;
+						eval {
+							$friendly = $k->get_value("FriendlyName")->get_data();
+							$str .= ",".$friendly;
+						};
+						$str .= "," if ($@);
+#						::rptMsg("    FriendlyName  : ".$friendly) if ($friendly ne "");
+						my $parent;
+						eval {
+							$parent = $k->get_value("ParentIdPrefix")->get_data();
+							$str .= ",".$parent;
+						};
+						$str .= "," if ($@);
+#						::rptMsg("    ParentIdPrefix: ".$parent) if ($parent ne "");
+						::rptMsg($str);
+					}
+				}
+#				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/user_run.pl b/thirdparty/rr/plugins/user_run.pl
new file mode 100644
index 0000000000000000000000000000000000000000..f982cfde9a346240b13af26525de141cebb37e6f
--- /dev/null
+++ b/thirdparty/rr/plugins/user_run.pl
@@ -0,0 +1,102 @@
+#-----------------------------------------------------------
+# user_run
+# Get contents of Run key from Software hive
+#
+# References:
+#   http://msdn2.microsoft.com/en-us/library/aa376977.aspx
+#   http://support.microsoft.com/kb/170086
+#   
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package user_run;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              version       => 20080328);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Autostart - get Run key contents from NTUSER\.DAT hive";	
+}
+sub getDescr{}
+sub getRefs {
+	my %refs = ("Definition of the Run keys in the WinXP Registry" =>
+	            "http://support.microsoft.com/kb/314866");	
+	return %refs;
+}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching user_run v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Run";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my %vals = getKeyValues($key);
+		if (scalar(keys %vals) > 0) {
+			foreach my $v (keys %vals) {
+				::rptMsg("\t".$v." -> ".$vals{$v});
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+		
+		my @sk = $key->get_list_of_subkeys();
+		if (scalar(@sk) > 0) {
+			foreach my $s (@sk) {
+				::rptMsg("");
+				::rptMsg($key_path."\\".$s->get_name());
+				::rptMsg("LastWrite Time ".gmtime($s->get_timestamp())." (UTC)");
+				my %vals = getKeyValues($s);
+				foreach my $v (keys %vals) {
+					::rptMsg("\t".$v." -> ".$vals{$v});
+				}
+			}
+		}
+		else {
+			::rptMsg("");
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+}
+
+sub getKeyValues {
+	my $key = shift;
+	my %vals;
+	
+	my @vk = $key->get_list_of_values();
+	if (scalar(@vk) > 0) {
+		foreach my $v (@vk) {
+			next if ($v->get_name() eq "" && $v->get_data() eq "");
+			$vals{$v->get_name()} = $v->get_data();
+		}
+	}
+	else {
+	
+	}
+	return %vals;
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/user_win.pl b/thirdparty/rr/plugins/user_win.pl
new file mode 100644
index 0000000000000000000000000000000000000000..107c71d4be0c76e9d00e35acda5f3cc00c27d35c
--- /dev/null
+++ b/thirdparty/rr/plugins/user_win.pl
@@ -0,0 +1,60 @@
+#-----------------------------------------------------------
+# user_win.pl
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package user_win;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080415);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return " -- ";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching user_win v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		eval {
+			my $load = $key->get_value("load")->get_data();
+			::rptMsg("load value = ".$load);
+			::rptMsg("*Should be blank; anything listed gets run when the user logs in.");
+		};
+		
+		eval {
+			my $run = $key->get_value("run")->get_data();
+			::rptMsg("run value = ".$run);
+			::rptMsg("*Should be blank; anything listed gets run when the user logs in.");
+		};
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/userassist.pl b/thirdparty/rr/plugins/userassist.pl
new file mode 100644
index 0000000000000000000000000000000000000000..d523444e857540a194b4390b828c263ea31d6221
--- /dev/null
+++ b/thirdparty/rr/plugins/userassist.pl
@@ -0,0 +1,86 @@
+#! c:\perl\bin\perl.exe
+#-----------------------------------------------------------
+# userassist.pl
+# Plugin for Registry Ripper, NTUSER.DAT edition - gets the 
+# UserAssist values 
+#
+# Change history
+#  20080726 - added reference to help examiner understand Control
+#             Panel entries found in output
+#  20080301 - updated to include run count along with date
+#
+# 
+# 
+# copyright 2008 H. Carvey
+#-----------------------------------------------------------
+package userassist;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              osmask        => 22,
+              version       => 20080726);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Displays contents of UserAssist Active Desktop key";	
+}
+sub getDescr{}
+sub getRefs {"Description of Control Panel Files in XP" => "http://support.microsoft.com/kb/313808"}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching UserAssist (Active Desktop) v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\'.
+	               '{75048700-EF1F-11D0-9888-006097DEACF9}\\Count';
+	my $key;
+	my %ua;
+	my $hrzr = "HRZR";
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("UserAssist (Active Desktop)");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $value_name = $v->get_name();
+				my $data = $v->get_data();
+				if (length($data) == 16) {
+					my ($session,$count,$val1,$val2) = unpack("V*",$data);
+				 	if ($val2 != 0) {
+						my $time_value = ::getTime($val1,$val2);
+						if ($value_name =~ m/^$hrzr/) { 
+							$value_name =~ tr/N-ZA-Mn-za-m/A-Za-z/;
+						}
+						$count -= 5 if ($count > 5);
+						push(@{$ua{$time_value}},$value_name." (".$count.")");
+					}
+				}
+			}
+			foreach my $t (reverse sort {$a <=> $b} keys %ua) {
+				::rptMsg(gmtime($t)." (UTC)");
+				foreach my $item (@{$ua{$t}}) {
+					::rptMsg("\t$item");
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/userassist2.pl b/thirdparty/rr/plugins/userassist2.pl
new file mode 100644
index 0000000000000000000000000000000000000000..010b9899db0f77a7caf3f12fc226703fb81014e1
--- /dev/null
+++ b/thirdparty/rr/plugins/userassist2.pl
@@ -0,0 +1,125 @@
+#! c:\perl\bin\perl.exe
+#-----------------------------------------------------------
+# userassist2.pl
+# Plugin for Registry Ripper, NTUSER.DAT edition - gets the 
+# UserAssist values 
+#
+# Change history
+#  20100322 - Added CLSID list reference
+#  20100308 - created, based on original userassist.pl plugin
+#  
+# References
+#  Control Panel Applets - http://support.microsoft.com/kb/313808
+#  CLSIDs - http://www.autohotkey.com/docs/misc/CLSID-List.htm
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package userassist2;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100308);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Displays contents of UserAssist subkeys";	
+}
+sub getDescr{}
+sub getRefs {"Description of Control Panel Files in XP" => "http://support.microsoft.com/kb/313808"}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching userassist2 v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist";              
+	my $key;
+	
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("UserAssist");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				::rptMsg($s->get_name());
+				processKey($s);
+				::rptMsg("");
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+sub processKey {
+	my $ua = shift;
+	
+	my $key = $ua->get_subkey("Count");
+
+	my %ua;
+	my $hrzr = "HRZR";
+	
+	my @vals = $key->get_list_of_values();
+	if (scalar(@vals) > 0) {
+		foreach my $v (@vals) {
+			my $value_name = $v->get_name();
+			my $data = $v->get_data();
+
+# Windows XP/2003/Vista/2008
+			if (length($data) == 16) {
+				my ($session,$count,$val1,$val2) = unpack("V*",$data);
+			 	if ($val2 != 0) {
+					my $time_value = ::getTime($val1,$val2);
+					if ($value_name =~ m/^$hrzr/) { 
+						$value_name =~ tr/N-ZA-Mn-za-m/A-Za-z/;
+					}
+					$count -= 5 if ($count > 5);
+					push(@{$ua{$time_value}},$value_name." (".$count.")");
+				}
+			}
+# Windows 7				
+			elsif (length($data) == 72) { 
+				$value_name =~ tr/N-ZA-Mn-za-m/A-Za-z/;
+#				if (unpack("V",substr($data,0,4)) == 0) {	
+#					my $count = unpack("V",substr($data,4,4));
+#					my @t = unpack("VV",substr($data,60,8));
+#					next if ($t[0] == 0 && $t[1] == 0);
+#					my $time_val = ::getTime($t[0],$t[1]);	
+#					print "    .-> ".$time_val."\n";
+#					push(@{$ua{$time_val}},$value_name." (".$count.")");
+#				}
+				my $count = unpack("V",substr($data,4,4));
+				my @t = unpack("VV",substr($data,60,8));
+				next if ($t[0] == 0 && $t[1] == 0);
+				my $time_val = ::getTime($t[0],$t[1]);	
+				push(@{$ua{$time_val}},$value_name." (".$count.")");
+			}
+			else {
+# Nothing else to do
+			}
+		}
+		foreach my $t (reverse sort {$a <=> $b} keys %ua) {
+			::rptMsg(gmtime($t)." Z");
+			foreach my $i (@{$ua{$t}}) {
+				::rptMsg("  ".$i);
+			}
+		}
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/userassist_tln.pl b/thirdparty/rr/plugins/userassist_tln.pl
new file mode 100644
index 0000000000000000000000000000000000000000..ea87cb37872ebcbec1d7dbd6fa515a237edbfd80
--- /dev/null
+++ b/thirdparty/rr/plugins/userassist_tln.pl
@@ -0,0 +1,114 @@
+#! c:\perl\bin\perl.exe
+#-----------------------------------------------------------
+# userassist_tln.pl
+# Plugin for Registry Ripper, NTUSER.DAT edition - gets the 
+# UserAssist values 
+#
+# Change history
+#  20110516 - created, modified from userassist2.pl
+#  20100322 - Added CLSID list reference
+#  20100308 - created, based on original userassist.pl plugin
+#  
+# References
+#  Control Panel Applets - http://support.microsoft.com/kb/313808
+#  CLSIDs - http://www.autohotkey.com/docs/misc/CLSID-List.htm
+# 
+# copyright 2011 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package userassist_tln;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20110516);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Displays contents of UserAssist subkeys in TLN format";	
+}
+sub getDescr{}
+sub getRefs {"Description of Control Panel Files in XP" => "http://support.microsoft.com/kb/313808"}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching userassist_tln v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist";              
+	my $key;
+	
+	if ($key = $root_key->get_subkey($key_path)) {
+#		::rptMsg("UserAssist");
+#		::rptMsg($key_path);
+#		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+#		::rptMsg("");
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				::rptMsg($s->get_name());
+				processKey($s);
+				::rptMsg("");
+			}
+		}
+		else {
+			::logMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::logMsg($key_path." not found.");
+	}
+}
+
+sub processKey {
+	my $ua = shift;
+	my $key = $ua->get_subkey("Count");
+	my %ua;
+	my $hrzr = "HRZR";
+	my @vals = $key->get_list_of_values();
+	if (scalar(@vals) > 0) {
+		foreach my $v (@vals) {
+			my $value_name = $v->get_name();
+			my $data = $v->get_data();
+
+# Windows XP/2003/Vista/2008
+			if (length($data) == 16) {
+				my ($session,$count,$val1,$val2) = unpack("V*",$data);
+			 	if ($val2 != 0) {
+					my $time_value = ::getTime($val1,$val2);
+					if ($value_name =~ m/^$hrzr/) { 
+						$value_name =~ tr/N-ZA-Mn-za-m/A-Za-z/;
+					}
+					$count -= 5 if ($count > 5);
+					push(@{$ua{$time_value}},$value_name." (".$count.")");
+				}
+			}
+# Windows 7				
+			elsif (length($data) == 72) { 
+				$value_name =~ tr/N-ZA-Mn-za-m/A-Za-z/;
+				my $count = unpack("V",substr($data,4,4));
+				my @t = unpack("VV",substr($data,60,8));
+				next if ($t[0] == 0 && $t[1] == 0);
+				my $time_val = ::getTime($t[0],$t[1]);	
+				push(@{$ua{$time_val}},$value_name." (".$count.")");
+			}
+			else {
+# Nothing else to do
+			}
+		}
+		foreach my $t (reverse sort {$a <=> $b} keys %ua) {
+			foreach my $i (@{$ua{$t}}) {
+				::rptMsg($t."|REG|||UserAssist - ".$i);
+			}
+		}
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/userinit.pl b/thirdparty/rr/plugins/userinit.pl
new file mode 100644
index 0000000000000000000000000000000000000000..b6664b8626a06eb3c1c708765d85e6e35161e82f
--- /dev/null
+++ b/thirdparty/rr/plugins/userinit.pl
@@ -0,0 +1,63 @@
+#-----------------------------------------------------------
+# userinit
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package userinit;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 1,
+              version       => 20080328);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Gets UserInit value";	
+}
+sub getDescr{}
+sub getRefs {
+	my %refs = ("My Documents open at startup" => 
+	            "http://support.microsoft.com/kb/555294",
+	            "Userinit" => 
+	            "http://www.microsoft.com/technet/prodtechnol/windows2000serv/reskit/regentry/12330.mspx?mfr=true");
+	return %refs;
+}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching userinit v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\Winlogon";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my $ui;
+		eval {
+			$ui = $key->get_value("Userinit")->get_data();
+			::rptMsg("\tUserinit -> ".$ui);
+		};
+		::rptMsg("Error: ".$@) if ($@);
+		::rptMsg("");
+		::rptMsg("Per references, content should be %SystemDrive%\\system32\\userinit.exe,");
+		::rptMsg("");
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/userlocsvc.pl b/thirdparty/rr/plugins/userlocsvc.pl
new file mode 100644
index 0000000000000000000000000000000000000000..3974a036e1308e1bb025534f4c04d5c9d285790c
--- /dev/null
+++ b/thirdparty/rr/plugins/userlocsvc.pl
@@ -0,0 +1,62 @@
+#! c:\perl\bin\perl.exe
+#-----------------------------------------------------------
+# userlocsvc.pl
+# Get the contents of the Microsoft\User Location Service\Clients key
+# from the user's hive 
+#
+# Ref:
+#  http://support.microsoft.com/kb/196301
+#  
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package userlocsvc;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20090411);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Displays contents of User Location Service\\Client key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching UserLocSvc v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	my $key_path = 'Software\\Microsoft\\User Location Service\\Client';
+	my $key;
+	my %ua;
+	my $hrzr = "HRZR";
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $str = sprintf "%-15s %-30s",$v->get_name(),$v->get_data();
+				::rptMsg($str) if ($v->get_type() == 1);
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/virut.pl b/thirdparty/rr/plugins/virut.pl
new file mode 100644
index 0000000000000000000000000000000000000000..eed5fc2a60716d0dee381184c51e251da9caa262
--- /dev/null
+++ b/thirdparty/rr/plugins/virut.pl
@@ -0,0 +1,66 @@
+#-----------------------------------------------------------
+# virut.pl
+# Plugin to detect artifacts of a Virut infection
+# 
+# References:
+#   Symantec: http://www.symantec.com/security_response/
+#                    writeup.jsp?docid=2009-020411-2802-99&tabid=2
+# 
+#
+#
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package virut;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090218);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Detect Virut artifacts";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching virut v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows\\CurrentVersion\\Explorer";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my $update;
+		eval {
+			$update = $key->get_value("UpdateHost")->get_data();
+			::rptMsg("UpdateHost value detected!  Possible Virut infection!");
+		};
+		::rptMsg("UpdateHost value not found.") if ($@);
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	::rptMsg("");
+	::rptMsg("Also be sure to check the SYSTEM\\ControlSet00n\\Services\\SharedAccess\\");
+	::rptMsg("Parameters\\FirewallPolicy\\DomainProfile\\AuthorizedApplications\\List key");
+	::rptMsg("for exceptions added to the firewall; use the fw_config\.pl plugin.");
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/vista_bitbucket.pl b/thirdparty/rr/plugins/vista_bitbucket.pl
new file mode 100644
index 0000000000000000000000000000000000000000..6fa27c55a526302cb57d05b6afcea1bf6f3263ec
--- /dev/null
+++ b/thirdparty/rr/plugins/vista_bitbucket.pl
@@ -0,0 +1,88 @@
+#-----------------------------------------------------------
+# vista_bitbucket
+# BitBucket settings for Vista $Recylce.bin are maintained on a 
+# per-user, per-volume basis 
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package vista_bitbucket;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 192,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080420);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get BitBucket settings from Vista via NTUSER\.DAT";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching vista_bitbucket v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\BitBucket";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				::rptMsg($v->get_name()." : ".$v->get_data());
+			}
+			
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+		::rptMsg("");
+		
+		my @vols;
+		eval {
+			@vols = $key->get_subkey("Volume")->get_list_of_subkeys();
+		};
+		if ($@) {
+			::rptMsg("Could not access ".$key_path."\\Volume subkey.");
+			return;
+		}
+		
+		if (scalar(@vols) > 0) {
+			foreach my $v (@vols) {
+				::rptMsg($v->get_name()." [".gmtime($v->get_timestamp())."] (UTC)");
+				eval {
+					::rptMsg(sprintf "  %-15s %-3s","NukeOnDelete",$v->get_value("NukeOnDelete")->get_data());
+				};
+				
+				
+			}
+			
+		}
+		else {
+			::rptMsg($key_path."\\Volume key has no subkeys.");
+		}
+		
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/vista_comdlg32.pl b/thirdparty/rr/plugins/vista_comdlg32.pl
new file mode 100644
index 0000000000000000000000000000000000000000..d20b8fb89d10f0f79e8aac228c93b5cdd8772e75
--- /dev/null
+++ b/thirdparty/rr/plugins/vista_comdlg32.pl
@@ -0,0 +1,145 @@
+#-----------------------------------------------------------
+# vista_comdlg32.pl
+# Plugin for Registry Ripper 
+#
+# Change history
+#   20090821 - created
+#
+# References
+#  
+#   
+#		
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package vista_comdlg32;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20090821);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of Vista user's ComDlg32 key";
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching vista_comdlg32 v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+	::rptMsg("vista_comdlg32 v.".$VERSION);
+	::rptMsg("**All values listed in MRU order.");
+	
+# CIDSizeMRU	
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\CIDSizeMRU";
+	my $key;
+	my @vals;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my %lvmru;
+		my @mrulist;
+		@vals = $key->get_list_of_values();
+		
+		if (scalar(@vals) > 0) {
+# First, read in all of the values and the data
+			foreach my $v (@vals) {
+				$lvmru{$v->get_name()} = $v->get_data();
+			}
+# Then, remove the MRUList value
+			if (exists $lvmru{MRUListEx}) {
+				delete($lvmru{MRUListEx});
+				foreach my $m (keys %lvmru) {
+					my $file = parseStr($lvmru{$m});
+					my $str = sprintf "%-4s ".$file,$m;
+					::rptMsg("  ".$str);
+				}
+			}
+			else {
+				::rptMsg($key_path." does not have an MRUList value.");
+			}				
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+	::rptMsg("");
+	
+# LastVistedPidlMRU	
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU";
+	my $key;
+	my @vals;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my %lvmru;
+		my @mrulist;
+		@vals = $key->get_list_of_values();
+		
+		if (scalar(@vals) > 0) {
+# First, read in all of the values and the data
+			foreach my $v (@vals) {
+				$lvmru{$v->get_name()} = $v->get_data();
+			}
+# Then, remove the MRUList value
+			if (exists $lvmru{MRUListEx}) {
+				delete($lvmru{MRUListEx});
+				foreach my $m (keys %lvmru) {
+					my $file = parseStr($lvmru{$m});
+					my $str = sprintf "%-4s ".$file,$m;
+					::rptMsg("  ".$str);
+				}
+			}
+			else {
+				::rptMsg($key_path." does not have an MRUList value.");
+			}				
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+	::rptMsg("");
+	
+
+}	
+
+sub parseStr {
+	my $data = $_[0];
+	my $temp;
+	my $tag = 1;
+	my $ofs = 0;
+	
+	while ($tag) {
+		my $t = substr($data,$ofs,2);
+		if (unpack("v",$t) == 0x00) {
+			$tag = 0;
+		}
+		else {
+			$temp .= $t;
+			$ofs += 2;
+		}
+	}
+	$temp =~ s/\00//g;
+	return $temp;
+}
+1;		
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/vista_wireless.pl b/thirdparty/rr/plugins/vista_wireless.pl
new file mode 100644
index 0000000000000000000000000000000000000000..f6b74bcf7a8449f06b2f4e2e94233493dae20520
--- /dev/null
+++ b/thirdparty/rr/plugins/vista_wireless.pl
@@ -0,0 +1,80 @@
+#-----------------------------------------------------------
+# vista_wireless
+#
+# Get Wireless info from Vista systems
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package vista_wireless;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20090514);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get Vista Wireless Info";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+my $error;
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching vista_wireless v.".$VERSION);	
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Profiles";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("");
+		my @subkeys = $key->get_list_of_subkeys();
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				my $name = $s->get_name();
+				my $lastwrite = $s->get_timestamp();
+				
+				my $nametype;
+				eval {
+					$nametype = $s->get_value("NameType")->get_data();
+				};
+				if ($@) {
+					
+				}
+				else {
+					if ($nametype == 0x47) {
+						my $profilename;
+						my $descr;
+						eval {
+							::rptMsg("LastWrite = ".gmtime($lastwrite)." Z");
+							$profilename = $s->get_value("ProfileName")->get_data();
+							$descr       = $s->get_value("Description")->get_data();
+							::rptMsg("  ".$profilename." [".$descr."]");
+							
+						};
+					}
+				}
+				
+				
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/vncviewer.pl b/thirdparty/rr/plugins/vncviewer.pl
new file mode 100644
index 0000000000000000000000000000000000000000..82049c93bd748c2eec8d9479b05a8dd6ac337a63
--- /dev/null
+++ b/thirdparty/rr/plugins/vncviewer.pl
@@ -0,0 +1,68 @@
+#-----------------------------------------------------------
+# vncviewer
+#
+#
+#-----------------------------------------------------------
+package vncviewer;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080325);
+              
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get VNCViewer system list";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching vncviewer v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Software\\ORL\\VNCviewer\\MRU";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("VNCViewer\\MRU");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			my %vnc;
+			foreach my $v (@vals) {
+				$vnc{$v->get_name()} = $v->get_data();
+			}
+			my $ind;
+			if (exists $vnc{'index'}) {
+				$ind = $vnc{'index'};
+				delete $vnc{'index'};
+			}
+			
+			::rptMsg("Index = ".$ind);
+			my @i = split(//,$ind);
+			foreach my $i (@i) {
+				::rptMsg("  ".$i." -> ".$vnc{$i});
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg($key_path." has no values.");	
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/wallpaper.pl b/thirdparty/rr/plugins/wallpaper.pl
new file mode 100644
index 0000000000000000000000000000000000000000..2d930cb0b1c08abeb88276fa49d70852ca49c19e
--- /dev/null
+++ b/thirdparty/rr/plugins/wallpaper.pl
@@ -0,0 +1,90 @@
+#-----------------------------------------------------------
+# wallpaper.pl
+#
+# Wallpaper MRU 
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package wallpaper;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 200800810);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Parses Wallpaper MRU Entries";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching wallpaper v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Wallpaper\\MRU";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("wallpaper");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my %wp;
+		my @mrulist;
+		
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (sort @vals) {
+				my $name = $v->get_name();
+				if ($name =~ m/^\d/) {
+					my $data = $v->get_data();
+					my $str = getStringValue($data);
+					$wp{$name} = $str;
+				}
+				elsif ($name =~ m/^MRUList/) {
+					@mrulist = unpack("V*",$v->get_data());
+				}
+				else {
+# nothing to do					
+				}
+			}
+			foreach my $m (@mrulist) {
+				next if ($m == 0xffffffff);
+				::rptMsg($m." -> ".$wp{$m});
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+#-----------------------------------------------------------
+# getStringValue() - given a binary data type w/ a Unicode 
+# string at the beginning, delimited by \x00\x00, return an ASCII
+# string
+#-----------------------------------------------------------
+sub getStringValue {
+	my $bin = shift;
+	my $str = (split(/\00\00/,$bin,2))[0];
+	$str =~ s/\00//g;
+	return $str;
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/win7_ua.pl b/thirdparty/rr/plugins/win7_ua.pl
new file mode 100644
index 0000000000000000000000000000000000000000..be2ea1afa8c083f27f1ee90bcec60918f1b9ad76
--- /dev/null
+++ b/thirdparty/rr/plugins/win7_ua.pl
@@ -0,0 +1,140 @@
+#-----------------------------------------------------------
+# win7_ua.pl
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package win7_ua;
+use strict;
+my $vignerekey = "BWHQNKTEZYFSLMRGXADUJOPIVC";
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20090121);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get Win7 UserAssist data";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching win7_ua v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my @subkeys = $key->get_list_of_subkeys();
+		
+		if (scalar(@subkeys) > 0) {
+			foreach my $s (@subkeys) {
+				print $s->get_name()."\n";
+				
+				my @vals = $s->get_subkey("Count")->get_list_of_values();
+				if (scalar(@vals) > 0) {
+					foreach my $v (@vals) {
+						my $name = decrypt_string($v->get_name(),$vignerekey);
+						my $data = $v->get_data();
+						::rptMsg("  ".$name);
+						if (length($data) == 72) {
+							my %vals = parseData($data);
+							::rptMsg("    Counter 1 = ".$vals{counter1});
+							::rptMsg("    Counter 2 = ".$vals{counter2});
+							::rptMsg("    Runtime   = ".$vals{runtime}." ms");
+							::rptMsg("    Last Run  = ".$vals{lastrun});
+							::rptMsg("    MRU       = ".$vals{mru});
+						}
+					}
+					
+				}
+				else {
+					::rptMsg($key_path."\\".$s->get_name()." has no values.");
+				}
+			}
+		}
+		else {
+			::rptMsg($key_path." has no subkeys.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+1;
+
+sub decrypt_string{
+# decrypts a full string of ciphertext, given the ciphertext and the key.
+# returns the plaintext string.
+	my ($ciphertext, $key) = @_;
+  my $plaintext;
+  my @plain;
+  
+  $key = $key x (length($ciphertext) / length($key) + 1);
+  
+  my @cipherletters = split(//,$ciphertext);
+  foreach my $i (0..(scalar(@cipherletters) - 1)) {
+#  	print "Cipher letter => ".$cipherletters[$i]."\n";
+  	if ($cipherletters[$i] =~ m/\w/ && !($cipherletters[$i] =~ m/\d/)) {
+#  		print "Decrypting ".$cipherletters[$i]." with ".(substr($key,$i,1))."\n";
+  		$plain[$i] = decrypt_letter($cipherletters[$i], (substr($key,$i,1)));
+  	}
+  	else {
+  		$plain[$i] = $cipherletters[$i];
+  	}
+  }
+  
+#	for( my $i=0; $i<length($ciphertext); $i++ ){
+#		$plaintext .= decrypt_letter((substr($ciphertext,$i,1)), (substr($key,$i,1)));
+#  }
+	$plaintext = join('',@plain);
+  return $plaintext;
+}
+
+sub decrypt_letter{
+# decrypts a single letter of ciphertext, given the ciphertext
+# letter and the key to use for that letter's position.
+# The key is the first letter of the row to look in.
+	my ($cipher, $row) = @_;
+	my $plain;
+	my $upper = 0;
+	$upper = 1 if (ord($cipher) >= 65 && ord($cipher) <= 90);
+		
+# in row n, plaintext is ciphertext - n, mod 26.
+	$row    = ord(lc($row))    - ord('a');    # enable mod 26
+	$cipher = ord(lc($cipher)) - ord('a');    # enable mod 26
+	$plain  = ($cipher - $row) % 26;
+	$plain  = chr($plain + ord('a'));
+	
+	$plain = uc($plain) if ($upper == 1);
+  return $plain;
+}
+
+sub parseData {
+	my $data = shift;
+	my %vals;
+	
+	$vals{counter1} = unpack("V",substr($data,4,4));
+	$vals{counter2} = unpack("V",substr($data,8,4));
+	$vals{runtime}  = unpack("V",substr($data,12,4));
+	my @a = unpack("VV",substr($data,60,8));
+	my $t = ::getTime($a[0],$a[1]);
+	($t == 0) ? ($vals{lastrun} = 0) : ($vals{lastrun} = gmtime($t));
+	
+	$vals{mru}  = unpack("V",substr($data,68,4));
+	return %vals;
+	
+}
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/win_cv.pl b/thirdparty/rr/plugins/win_cv.pl
new file mode 100644
index 0000000000000000000000000000000000000000..977eeb7920990489f76201b7e004ef4f74226f63
--- /dev/null
+++ b/thirdparty/rr/plugins/win_cv.pl
@@ -0,0 +1,85 @@
+#-----------------------------------------------------------
+# win_cv.pl
+# Get and display the contents of the Windows\CurrentVersion key
+# Output sorted based on length of data
+#
+# Change History:
+# 20080609: added translation of InstallDate time
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package win_cv;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20090312);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get & display the contents of the Windows\\CurrentVersion key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching win_cv v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Microsoft\\Windows\\CurrentVersion";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my %cv;
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				my $data = $v->get_data();
+				my $len  = length($data);
+				next if ($name eq "");
+				if ($v->get_type() == 3) {
+					$data = _translateBinary($data);
+				}
+				push(@{$cv{$len}},$name." : ".$data);
+			}
+			foreach my $t (sort {$a <=> $b} keys %cv) {
+				foreach my $item (@{$cv{$t}}) {
+					::rptMsg("  $item");
+				}
+			}	
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg($key_path." has no values");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+
+sub _translateBinary {
+	my $str = unpack("H*",$_[0]);
+	my $len = length($str);
+	my @nstr = split(//,$str,$len);
+	my @list = ();
+	foreach (0..($len/2)) {
+		push(@list,$nstr[$_*2].$nstr[($_*2)+1]);
+	}
+	return join(' ',@list);
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/winlogon.pl b/thirdparty/rr/plugins/winlogon.pl
new file mode 100644
index 0000000000000000000000000000000000000000..6808f3e27860bf89c8eb56ded505a2a9b6273848
--- /dev/null
+++ b/thirdparty/rr/plugins/winlogon.pl
@@ -0,0 +1,98 @@
+#-----------------------------------------------------------
+# WinLogon
+# Get values from WinLogon key
+# 
+# History
+#    20100219 - Updated output to better present some data
+#    20080415 - created
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package winlogon;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20100219);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get values from the WinLogon key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching winlogon v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion\\Winlogon";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			my %wl;
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				my $data = $v->get_data();
+				my $len  = length($data);
+				next if ($name eq "");
+				if ($v->get_type() == 3 && $name ne "DCacheUpdate") {
+					$data = _translateBinary($data);
+				}
+				
+				$data = sprintf "0x%x",$data if ($name eq "SfcQuota");
+				if ($name eq "DCacheUpdate") {
+					my @v = unpack("VV",$data);
+					$data = gmtime(::getTime($v[0],$v[1]));
+				}
+				
+				push(@{$wl{$len}},$name." = ".$data);
+			}
+			
+			foreach my $t (sort {$a <=> $b} keys %wl) {
+				foreach my $item (@{$wl{$t}}) {
+					::rptMsg("  $item");
+				}
+			}	
+			
+			::rptMsg("");
+			::rptMsg("Analysis Tips: The UserInit and Shell values are executed when a user logs on.");
+			
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+}
+
+sub _translateBinary {
+	my $str = unpack("H*",$_[0]);
+	my $len = length($str);
+	my @nstr = split(//,$str,$len);
+	my @list = ();
+	foreach (0..($len/2)) {
+		push(@list,$nstr[$_*2].$nstr[($_*2)+1]);
+	}
+	return join(' ',@list);
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/winlogon_u.pl b/thirdparty/rr/plugins/winlogon_u.pl
new file mode 100644
index 0000000000000000000000000000000000000000..f2355efe83974a9a2f8b48bb7e24d4a9e0c7ff1e
--- /dev/null
+++ b/thirdparty/rr/plugins/winlogon_u.pl
@@ -0,0 +1,90 @@
+#-----------------------------------------------------------
+# winlogon_u
+# Get values from user's WinLogon key
+#
+# Change History:
+#   20091021 - created
+#
+# References:
+#   http://support.microsoft.com/kb/119941
+#
+# copyright 2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package winlogon_u;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20091021);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get values from the user's WinLogon key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching winlogon_u v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			my %wl;
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				my $data = $v->get_data();
+				my $len  = length($data);
+				next if ($name eq "");
+				if ($v->get_type() == 3) {
+					$data = _translateBinary($data);
+				}
+				push(@{$wl{$len}},$name." = ".$data);
+			}
+			
+			foreach my $t (sort {$a <=> $b} keys %wl) {
+				foreach my $item (@{$wl{$t}}) {
+					::rptMsg("  $item");
+				}
+			}	
+			
+			::rptMsg("");
+			::rptMsg("Analysis Tip: Existence of RunGrpConv = 1 value may indicate that the");
+			::rptMsg("              system had been infected with Bredolab (Symantec).");
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+sub _translateBinary {
+	my $str = unpack("H*",$_[0]);
+	my $len = length($str);
+	my @nstr = split(//,$str,$len);
+	my @list = ();
+	foreach (0..($len/2)) {
+		push(@list,$nstr[$_*2].$nstr[($_*2)+1]);
+	}
+	return join(' ',@list);
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/winnt_cv.pl b/thirdparty/rr/plugins/winnt_cv.pl
new file mode 100644
index 0000000000000000000000000000000000000000..537ced5ca8082ead4cf02bf01992ca241c4fd652
--- /dev/null
+++ b/thirdparty/rr/plugins/winnt_cv.pl
@@ -0,0 +1,87 @@
+#-----------------------------------------------------------
+# winnt_cv.pl
+# Get and display the contents of the Windows\CurrentVersion key
+# Output sorted based on length of data
+#
+# Change History:
+# 20080609: added translation of InstallDate time
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package winnt_cv;
+use strict;
+
+my %config = (hive          => "Software",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080609);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get & display the contents of the Windows NT\\CurrentVersion key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching winnt_cv v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("WinNT_CV");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		my %cv;
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				my $data = $v->get_data();
+				$data = gmtime($data)." (UTC)" if ($name eq "InstallDate");
+				my $len  = length($data);
+				next if ($name eq "");
+				if ($v->get_type() == 3) {
+					$data = _translateBinary($data);
+				}
+				push(@{$cv{$len}},$name." : ".$data);
+			}
+			foreach my $t (sort {$a <=> $b} keys %cv) {
+				foreach my $item (@{$cv{$t}}) {
+					::rptMsg("  $item");
+				}
+			}	
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+			::logMsg($key_path." has no values");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+
+
+sub _translateBinary {
+	my $str = unpack("H*",$_[0]);
+	my $len = length($str);
+	my @nstr = split(//,$str,$len);
+	my @list = ();
+	foreach (0..($len/2)) {
+		push(@list,$nstr[$_*2].$nstr[($_*2)+1]);
+	}
+	return join(' ',@list);
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/winrar.pl b/thirdparty/rr/plugins/winrar.pl
new file mode 100644
index 0000000000000000000000000000000000000000..f66f06ff65910226c35a331391f1636ab53daea9
--- /dev/null
+++ b/thirdparty/rr/plugins/winrar.pl
@@ -0,0 +1,66 @@
+#-----------------------------------------------------------
+# winrar.pl
+# Get WinRAR\ArcHistory entries
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package winrar;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20080819);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get WinRAR\\ArcHistory entries";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching winrar v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\WinRAR\\ArcHistory";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("WinRAR");
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		::rptMsg("");
+		
+		my %arc;
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			foreach my $v (@vals) {
+				$arc{$v->get_name()} = $v->get_data();
+			}
+			
+			foreach (sort keys %arc) {
+				::rptMsg($_." -> ".$arc{$_});
+			}
+			
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/winver.pl b/thirdparty/rr/plugins/winver.pl
new file mode 100644
index 0000000000000000000000000000000000000000..d59262e5963f9e9be25c6f9445926743413eec48
--- /dev/null
+++ b/thirdparty/rr/plugins/winver.pl
@@ -0,0 +1,107 @@
+#-----------------------------------------------------------
+# winver.pl
+#
+# copyright 2008-2009 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package winver;
+use strict;
+
+my %config = (hive          => "Software",
+              osmask        => 22,
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              version       => 20081210);
+
+sub getConfig{return %config}
+
+sub getShortDescr {
+	return "Get Windows version";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching winver v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Microsoft\\Windows NT\\CurrentVersion";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+#		::rptMsg("{name}");
+#		::rptMsg($key_path);
+#		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		
+		my $prod;
+		eval {
+			$prod = $key->get_value("ProductName")->get_data();
+		};
+		if ($@) {
+#			::rptMsg("ProductName value not found.");
+		}
+		else {
+			::rptMsg("ProductName = ".$prod);
+		}
+		
+		my $csd;
+		eval {
+			$csd = $key->get_value("CSDVersion")->get_data();
+		};
+		if ($@) {
+#			::rptMsg("CSDVersion value not found.");
+		}
+		else {
+			::rptMsg("CSDVersion  = ".$csd);
+		}
+		
+		
+		my $build;
+		eval {
+			$build = $key->get_value("BuildName")->get_data();
+		};
+		if ($@) {
+#			::rptMsg("BuildName value not found.");
+		}
+		else {
+			::rptMsg("BuildName = ".$build);
+		}
+		
+		my $buildex;
+		eval {
+			$buildex = $key->get_value("BuildNameEx")->get_data();
+		};
+		if ($@) {
+#			::rptMsg("BuildName value not found.");
+		}
+		else {
+			::rptMsg("BuildNameEx = ".$buildex);
+		}
+		
+		
+		my $install;
+		eval {
+			$install = $key->get_value("InstallDate")->get_data();
+		};
+		if ($@) {
+#			::rptMsg("InstallDate value not found.");
+		}
+		else {
+			::rptMsg("InstallDate = ".gmtime($install));
+		}
+		
+		
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+	
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/winzip.pl b/thirdparty/rr/plugins/winzip.pl
new file mode 100644
index 0000000000000000000000000000000000000000..7fa815250bb94c231bf21e664193315dc5640b1e
--- /dev/null
+++ b/thirdparty/rr/plugins/winzip.pl
@@ -0,0 +1,89 @@
+#-----------------------------------------------------------
+# WinZip
+#
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+package winzip;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20080325);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Get WinZip extract and filemenu values";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	::logMsg("Launching WinZip v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	my $key_path = "Software\\Nico Mak Computing\\WinZip";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg("WinZip");
+		::rptMsg($key_path);
+		::rptMsg("");
+		my @subkeys = $key->get_list_of_subkeys();
+		my %sk;
+		foreach my $s (@subkeys) {
+			$sk{$s->get_name()} = $s;
+		}
+		
+		if (exists $sk{'extract'}) {
+			my $tag = "extract";
+			::rptMsg($key_path."\\extract  [".gmtime($sk{'extract'}->get_timestamp)."]");
+			my @vals = $sk{'extract'}->get_list_of_values();
+			my %ext;
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				my $num = $name;
+				$num =~ s/^$tag//;
+				$ext{$num} = $v->get_data();
+			}
+			foreach my $e (sort {$a <=> $b} keys %ext) {
+				::rptMsg("  extract".$e." -> ".$ext{$e});
+			}
+			::rptMsg("");
+		}
+		else {
+			::rptMsg("extract key not found.");
+		}
+		
+		if (exists $sk{'filemenu'}) {
+			my $tag = "filemenu";
+			::rptMsg($key_path."\\filemenu  [".gmtime($sk{'extract'}->get_timestamp)."]");
+			my @vals = $sk{'filemenu'}->get_list_of_values();
+			my %ext;
+			foreach my $v (@vals) {
+				my $name = $v->get_name();
+				my $num = $name;
+				$num =~ s/^$tag//;
+				$ext{$num} = $v->get_data();
+			}
+			foreach my $e (sort {$a <=> $b} keys %ext) {
+				::rptMsg("  filemenu".$e." -> ".$ext{$e});
+			}
+		}
+		else {
+			::rptMsg("filemenu key not found.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+		::logMsg($key_path." not found.");
+	}
+}
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/wordwheelquery.pl b/thirdparty/rr/plugins/wordwheelquery.pl
new file mode 100644
index 0000000000000000000000000000000000000000..10a2eba1cffed2b673d44660e93eb24064a64b0b
--- /dev/null
+++ b/thirdparty/rr/plugins/wordwheelquery.pl
@@ -0,0 +1,79 @@
+#-----------------------------------------------------------
+# wordwheelquery.pl
+# For Windows 7
+#
+# Change history
+#	  20100330 - created
+#
+# References
+#   http://www.winhelponline.com/blog/clear-file-search-mru-history-windows-7/
+# 
+# copyright 2010 Quantum Analytics Research, LLC
+#-----------------------------------------------------------
+package wordwheelquery;
+use strict;
+
+my %config = (hive          => "NTUSER\.DAT",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20100330);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Gets contents of user's WordWheelQuery key";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $ntuser = shift;
+	::logMsg("Launching wordwheelquery v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($ntuser);
+	my $root_key = $reg->get_root_key;
+
+	my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\WordWheelQuery";
+	my $key;
+	if ($key = $root_key->get_subkey($key_path)) {
+		::rptMsg($key_path);
+		::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
+		my @vals = $key->get_list_of_values();
+		if (scalar(@vals) > 0) {
+			my @list;
+			my %wwq;
+			foreach my $v (@vals) { 
+				my $name = $v->get_name();
+				if ($name eq "MRUListEx") {
+					@list = unpack("V*",$v->get_data());
+					pop(@list) if ($list[scalar(@list) - 1] == 0xffffffff);
+				}
+				else {
+					my $data = $v->get_data();
+					$data =~ s/\00//g;
+					$wwq{$name} = $data;
+				}
+			}
+# list searches in MRUListEx order
+			::rptMsg("");
+			::rptMsg("Searches listed in MRUListEx order");
+			::rptMsg("");			
+			foreach my $l (@list) {
+				::rptMsg(sprintf "%-4d %-30s",$l,$wwq{$l});
+			}
+		}
+		else {
+			::rptMsg($key_path." has no values.");
+		}
+	}
+	else {
+		::rptMsg($key_path." not found.");
+	}
+}
+
+1;
\ No newline at end of file
diff --git a/thirdparty/rr/plugins/xpedition.pl b/thirdparty/rr/plugins/xpedition.pl
new file mode 100644
index 0000000000000000000000000000000000000000..f3a5d35914d4c8e700425768feb78179807a6255
--- /dev/null
+++ b/thirdparty/rr/plugins/xpedition.pl
@@ -0,0 +1,60 @@
+#-----------------------------------------------------------
+# xpedition.pl
+# Determine the edition of XP (MediaCenter, TabletPC)
+#
+# History
+#
+# References
+#   http://windowsitpro.com/article/articleid/94531/
+#      how-can-a-script-determine-if-windows-xp-tablet-pc-edition-is-installed.html
+#   http://unasked.com/question/view/id/119610
+#
+# copyright 2009 H. Carvey
+#-----------------------------------------------------------
+package xpedition;
+use strict;
+my %config = (hive          => "System",
+              hasShortDescr => 1,
+              hasDescr      => 0,
+              hasRefs       => 0,
+              osmask        => 22,
+              version       => 20090727);
+
+sub getConfig{return %config}
+sub getShortDescr {
+	return "Queries System hive for XP Edition info";	
+}
+sub getDescr{}
+sub getRefs {}
+sub getHive {return $config{hive};}
+sub getVersion {return $config{version};}
+
+my $VERSION = getVersion();
+
+sub pluginmain {
+	my $class = shift;
+	my $hive = shift;
+	my $key;
+	my $edition = 0;
+	
+	::logMsg("Launching xpedition v.".$VERSION);
+	my $reg = Parse::Win32Registry->new($hive);
+	my $root_key = $reg->get_root_key;
+	::rptMsg("xpedition v.".$VERSION);
+	eval {
+		$key = $root_key->get_subkey("WPA\\MediaCenter")->get_value("Installed")->get_data();
+		if ($key == 1) {
+			::rptMsg("MediaCenter Edition"); 
+			$edition = 1;
+		}
+	};
+	
+	eval {
+		$key = $root_key->get_subkey("WPA\\TabletPC")->get_value("Installed")->get_data();
+		if ($key == 1) {
+			::rptMsg("TabletPC Edition"); 
+			$edition = 1;
+		}
+	};	
+}
+1
\ No newline at end of file
diff --git a/thirdparty/rr/rip.exe b/thirdparty/rr/rip.exe
new file mode 100644
index 0000000000000000000000000000000000000000..6ecc7fec59702edf1ada8030897db99fdfe27e45
Binary files /dev/null and b/thirdparty/rr/rip.exe differ
diff --git a/thirdparty/rr/rip.pl b/thirdparty/rr/rip.pl
new file mode 100644
index 0000000000000000000000000000000000000000..6c561436870248d5bb4a9f17da7222abd3c3da70
--- /dev/null
+++ b/thirdparty/rr/rip.pl
@@ -0,0 +1,292 @@
+#! c:\perl\bin\perl.exe
+#-------------------------------------------------------------------------
+# Rip - RegRipper, CLI version
+# Use this utility to run a plugins file or a single plugin against a Reg
+# hive file.
+# 
+# Output goes to STDOUT
+# Usage: see "_syntax()" function
+#
+# Change History
+#   20110516 - added -s & -u options for TLN support
+#   20090102 - updated code for relative path to plugins dir
+#   20080419 - added '-g' switch (experimental)
+#   20080412 - added '-c' switch
+#
+# copyright 2011 Quantum Analytics Research, LLC
+#-------------------------------------------------------------------------
+use strict;
+use Parse::Win32Registry qw(:REG_);
+use Getopt::Long;
+
+# Included to permit compiling via Perl2Exe
+#perl2exe_include "Parse/Win32Registry.pm";
+#perl2exe_include "Parse/Win32Registry/Key.pm";
+#perl2exe_include "Parse/Win32Registry/Entry.pm";
+#perl2exe_include "Parse/Win32Registry/Value.pm";
+#perl2exe_include "Parse/Win32Registry/File.pm";
+#perl2exe_include "Parse/Win32Registry/Win95/File.pm";
+#perl2exe_include "Parse/Win32Registry/Win95/Key.pm";
+#perl2exe_include "Encode/Unicode.pm";
+
+my %config;
+Getopt::Long::Configure("prefix_pattern=(-|\/)");
+GetOptions(\%config,qw(reg|r=s file|f=s csv|c guess|g user|u=s sys|s=s plugin|p=s list|l help|?|h));
+
+# Code updated 20090102
+my @path;
+my $str = $0;
+($^O eq "MSWin32") ? (@path = split(/\\/,$0))
+                   : (@path = split(/\//,$0));
+$str =~ s/($path[scalar(@path) - 1])//;
+my $plugindir = $str."plugins/";
+#print "Plugins Dir = ".$plugindir."\n";
+# End code update
+my $VERSION = "20090102";
+
+if ($config{help} || !%config) {
+	_syntax();
+	exit;
+}
+
+#-------------------------------------------------------------
+# 
+#-------------------------------------------------------------
+if ($config{list}) {
+	my @plugins;
+	opendir(DIR,$plugindir) || die "Could not open $plugindir: $!\n";
+	@plugins = readdir(DIR);
+	closedir(DIR);
+
+	my $count = 1; 
+	print "Plugin,Version,Hive,Description\n" if ($config{csv});
+	foreach my $p (@plugins) {
+		next unless ($p =~ m/\.pl$/);
+		my $pkg = (split(/\./,$p,2))[0];
+		$p = $plugindir.$p;
+		eval {
+			require $p;
+			my $hive    = $pkg->getHive();
+			my $version = $pkg->getVersion();
+			my $descr   = $pkg->getShortDescr();
+			if ($config{csv}) {
+				print $pkg.",".$version.",".$hive.",".$descr."\n";
+			}
+			else {
+				print $count.". ".$pkg." v.".$version." [".$hive."]\n";
+#				printf "%-20s %-10s %-10s\n",$pkg,$version,$hive;
+				print  "   - ".$descr."\n\n";
+				$count++;
+			}
+		};
+		print "Error: $@\n" if ($@);
+	}
+	exit;
+}
+
+#-------------------------------------------------------------
+# 
+#-------------------------------------------------------------
+if ($config{file}) {
+# First, check that a hive file was identified, and that the path is
+# correct
+	my $hive = $config{reg};
+	die "You must enter a hive file path/name.\n" if ($hive eq "");
+	die $hive." not found.\n" unless (-e $hive);
+	
+	my %plugins = parsePluginsFile($config{file});
+	if (%plugins) {
+		logMsg("Parsed Plugins file.");
+	}
+	else {
+		logMsg("Plugins file not parsed.");
+		exit;
+	}
+	foreach my $i (sort {$a <=> $b} keys %plugins) {
+		eval {
+			require "plugins\\".$plugins{$i}."\.pl";
+			$plugins{$i}->pluginmain($hive);
+		};
+		if ($@) {
+			logMsg("Error in ".$plugins{$i}.": ".$@);
+		}
+		logMsg($plugins{$i}." complete.");
+		rptMsg("-" x 40);
+	}
+}
+
+#-------------------------------------------------------------
+# 
+#-------------------------------------------------------------
+if ($config{reg} && $config{guess}) {
+# Attempt to guess which kind of hive we have
+	my $hive = $config{reg};
+	die "You must enter a hive file path/name.\n" if ($hive eq "");
+	die $hive." not found.\n" unless (-e $hive);
+	
+	my $reg;
+	my $root_key;
+	my %guess;
+	eval {
+		$reg = Parse::Win32Registry->new($hive);
+	  $root_key = $reg->get_root_key;
+	};
+	::rptMsg($config{reg}." may not be a valid hive.") if ($@);
+	
+# Check for SAM
+	eval {
+		$guess{sam} = 1 if (my $key = $root_key->get_subkey("SAM\\Domains\\Account\\Users"));
+	};
+# Check for Software	
+	eval {
+		$guess{software} = 1 if ($root_key->get_subkey("Microsoft\\Windows\\CurrentVersion") &&
+				$root_key->get_subkey("Microsoft\\Windows NT\\CurrentVersion"));
+	};
+
+# Check for System	
+	eval {
+		$guess{system} = 1 if ($root_key->get_subkey("MountedDevices") &&
+				$root_key->get_subkey("Select"));
+	};
+	
+# Check for Security	
+	eval {
+		$guess{security} = 1 if ($root_key->get_subkey("Policy\\Accounts") &&
+				$root_key->get_subkey("Policy\\PolAdtEv"));
+	};
+# Check for NTUSER.DAT	
+	eval {
+		$guess{ntuser} = 1 if ($root_key->get_subkey("Software\\Microsoft\\Windows\\CurrentVersion"));
+		
+	};	
+	
+	foreach my $g (keys %guess) {
+		::rptMsg(sprintf "%-8s = %-2s",$g,$guess{$g});
+	}
+}
+
+#-------------------------------------------------------------
+# 
+#-------------------------------------------------------------
+if ($config{plugin}) {
+# First, check that a hive file was identified, and that the path is
+# correct
+	my $hive = $config{reg};
+	die "You must enter a hive file path/name.\n" if ($hive eq "");
+	die $hive." not found.\n" unless (-e $hive);	
+		
+# check to see if the plugin exists
+	my $plugin = $config{plugin};
+	my $pluginfile = $plugindir.$config{plugin}."\.pl";
+	die $pluginfile." not found.\n" unless (-e $pluginfile);
+	
+	eval {
+		require $pluginfile;
+		$plugin->pluginmain($hive);
+	};
+	if ($@) {
+		logMsg("Error in ".$pluginfile.": ".$@);
+	}	
+}
+
+sub _syntax {
+	print<< "EOT";
+Rip v.$VERSION - CLI RegRipper tool	
+Rip [-r Reg hive file] [-f plugin file] [-p plugin module] [-l] [-h]
+Parse Windows Registry files, using either a single module, or a plugins file.
+All plugins must be located in the \"plugins\" directory; default plugins file 
+used if no other filename given is \"plugins\\plugins\"\.
+
+  -r Reg hive file...Registry hive file to parse
+  -g ................Guess the hive file (experimental)
+  -f [plugin file]...use the plugin file (default: plugins\\plugins)
+  -p plugin module...use only this module
+  -l ................list all plugins
+  -c ................Output list in CSV format (use with -l)
+  -s system name.....Server name (TLN support)
+  -u username........User name (TLN support)
+  -h.................Help (print this information)
+  
+Ex: C:\\>rr -r c:\\case\\system -f system
+    C:\\>rr -r c:\\case\\ntuser.dat -p userassist
+    C:\\>rr -l -c
+
+All output goes to STDOUT; use redirection (ie, > or >>) to output to a file\.
+  
+copyright 2011 Quantum Analytics Research, LLC
+EOT
+}
+
+#-------------------------------------------------------------
+# 
+#-------------------------------------------------------------
+sub logMsg {
+	print STDERR $_[0]."\n";
+}
+
+#-------------------------------------------------------------
+# 
+#-------------------------------------------------------------
+sub rptMsg {
+	binmode STDOUT,":utf8";
+	if ($config{sys} || $config{user}) {
+		my @vals = split(/\|/,$_[0],5);
+		my $str = $vals[0]."|".$vals[1]."|".$config{sys}."|".$config{user}."|".$vals[4];
+		print $str."\n";
+	}
+	else {
+		print $_[0]."\n";
+	}
+}
+
+#-------------------------------------------------------------
+# parsePluginsFile()
+# Parse the plugins file and get a list of plugins
+#-------------------------------------------------------------
+sub parsePluginsFile {
+	my $file = $_[0];
+	my %plugins;
+# Parse a file containing a list of plugins
+# Future versions of this tool may allow for the analyst to 
+# choose different plugins files	
+	my $pluginfile = $plugindir.$file;
+	if (-e $pluginfile) {
+		open(FH,"<",$pluginfile);
+		my $count = 1;
+		while(<FH>) {
+			chomp;
+			next if ($_ =~ m/^#/ || $_ =~ m/^\s+$/);
+#			next unless ($_ =~ m/\.pl$/);
+			next if ($_ eq "");
+			$_ =~ s/^\s+//;
+			$_ =~ s/\s+$//;
+			$plugins{$count++} = $_; 
+		}
+		close(FH);
+		return %plugins;
+	}
+	else {
+		return undef;
+	}
+}
+
+#-------------------------------------------------------------
+# getTime()
+# Translate FILETIME object (2 DWORDS) to Unix time, to be passed
+# to gmtime() or localtime()
+#-------------------------------------------------------------
+sub getTime($$) {
+	my $lo = shift;
+	my $hi = shift;
+	my $t;
+
+	if ($lo == 0 && $hi == 0) {
+		$t = 0;
+	} else {
+		$lo -= 0xd53e8000;
+		$hi -= 0x019db1de;
+		$t = int($hi*429.4967296 + $lo/1e7);
+	};
+	$t = 0 if ($t < 0);
+	return $t;
+}
\ No newline at end of file
diff --git a/thirdparty/rr/rr.exe b/thirdparty/rr/rr.exe
new file mode 100644
index 0000000000000000000000000000000000000000..0a89f5b83cb5a9c6f00f7db15e233de2cc0abc64
Binary files /dev/null and b/thirdparty/rr/rr.exe differ
diff --git a/thirdparty/rr/rr.pl b/thirdparty/rr/rr.pl
new file mode 100644
index 0000000000000000000000000000000000000000..397e486b4f6898f9b7b9f407270b48fc47b01113
--- /dev/null
+++ b/thirdparty/rr/rr.pl
@@ -0,0 +1,441 @@
+#! c:\perl\bin\perl.exe
+#-----------------------------------------------------------
+# Registry Ripper
+# Parse a Registry hive file for data pertinent to an investigation
+#
+# Adv version...provides the basic functionality.  All plugins 
+# can be used with both the basic version and the full-featured 
+# version
+#
+# Change History:
+#  20081111 - Updated code in setUpEnv() to parse the file paths for 
+#             output files (log, etc) so that they paths were handled
+#             properly; updated Perl2Exe include statements to support
+#             Parse::Win32Registry 0.40
+#  20080512 - Consolidated Basic and Advanced versions into a single
+#             track
+#  20080429 - Fixed issue with output report and log files having the
+#             same (.log) file extension
+#  20080422 - Added ComboBox to choose plugins file
+#  20080414 - updated code to check for a selected hive file; set 
+#             default plugin file to "ntuser" if none selected; check
+#             for plugins file with no plugins or all plugins commented
+#             out; keep track of plugins w/ hard errors generated via 
+#             this GUI.
+#  20080412 - added listbox; populate with list of plugin files
+#             from plugin dir
+#           - Log file now based on report file name and location
+#  20080226 - added eval{} to wrap require pragma in go_Click() 
+#  
+#
+# Functionality: 
+#   - plugins file is selectable
+# 
+# copyright 2008 H. Carvey, keydet89@yahoo.com
+#-----------------------------------------------------------
+#use strict;
+use Win32::GUI();
+use Parse::Win32Registry qw(:REG_);
+
+# Included to permit compiling via Perl2Exe
+#perl2exe_include "Parse/Win32Registry.pm";
+#perl2exe_include "Parse/Win32Registry/Key.pm";
+#perl2exe_include "Parse/Win32Registry/Entry.pm";
+#perl2exe_include "Parse/Win32Registry/Value.pm";
+#perl2exe_include "Parse/Win32Registry/File.pm";
+#perl2exe_include "Parse/Win32Registry/Win95/File.pm";
+#perl2exe_include "Parse/Win32Registry/Win95/Key.pm";
+#perl2exe_include "Encode/Unicode.pm";
+#-----------------------------------------------------------
+# Global variables
+#-----------------------------------------------------------
+my $VERSION = "2\.02";
+my %env; 
+
+#-----------------------------------------------------------
+# GUI
+#-----------------------------------------------------------
+# create our menu
+my $menu = Win32::GUI::MakeMenu(
+		"&File"                => "File",
+		" > O&pen..."          => { -name => "Open"},
+		" > -"                 => 0,
+    " > E&xit"             => { -name => "Exit", -onClick => sub {exit 1;}},
+    "&Help"                => "Help",
+    " > &About"            => { -name => "About", -onClick => \&RR_OnAbout},
+);
+
+# Create Main Window
+my $main = new Win32::GUI::Window (
+    -name     => "Main",
+    -title    => "Registry Ripper, v.".$VERSION,
+    -pos      => [200, 200],
+# Format: [width, height]
+    -maxsize  => [500, 420],
+    -size     => [500, 420],
+    -menu     => $menu,
+    -dialogui => 1,
+) or die "Could not create a new Window: $!\n";
+
+$main->AddLabel(
+    -text   => "Hive File:",
+    -left   => 20,
+    -top    => 10);
+    
+my $ntuserfile = $main->AddTextfield(
+    -name     => "ntuserdat",
+    -tabstop  => 1,
+    -left     => 100,
+    -top      => 10,
+    -width    => 250,
+    -height   => 22,
+    -tabstop  => 1,
+    -foreground => "#000000",
+    -background => "#FFFFFF");
+
+my $browse1 = $main->AddButton(
+		-name => 'browse1',
+		-left => 375,
+		-top  => 10,
+		-width => 50,
+		-height => 22,
+		-tabstop  => 1,
+		-text => "Browse");
+
+$main->AddLabel(
+    -text   => "Report File:",
+    -left   => 20,
+    -top    => 50);
+    
+my $rptfile = $main->AddTextfield(
+    -name     => "rptfile",
+    -tabstop  => 1,
+    -left     => 100,
+    -top      => 50,
+    -width    => 250,
+    -height   => 22,
+    -tabstop  => 1,
+    -foreground => "#000000",
+    -background => "#FFFFFF");
+
+my $browse2 = $main->AddButton(
+		-name => 'browse2',
+		-left => 375,
+		-top  => 50,
+		-width => 50,
+		-height => 22,
+		-tabstop  => 1,
+		-text => "Browse");
+
+$main->AddLabel(
+    -text   => "Plugin File:",
+    -left   => 20,
+    -top    => 90);
+
+# http://perl-win32-gui.sourceforge.net/cgi-bin/docs.cgi?doc=combobox
+my $combo = $main->AddCombobox(
+ -name   => "Combobox",
+# -dropdown => 1,
+ -dropdownlist => 1,
+ -top    => 90,
+ -left   => 100,
+ -width  => 120,
+ -height => 110,
+ -tabstop=> 1,
+ );
+
+my $testlabel = $main->AddLabel(
+	-text => "",
+	-name => "TestLabel",
+	-pos => [10,140],
+	-size => [445,160],
+	-frame => etched,
+	-sunken => 1
+);
+
+my $report = $main->AddTextfield(
+    -name      => "Report",
+    -pos       => [20,150],
+    -size      => [425,140],
+    -multiline => 1,
+    -vscroll   => 1,
+    -autohscroll => 1,
+    -autovscroll => 1,
+    -keepselection => 1 ,
+    -tabstop => 1,
+);
+
+my $go = $main->AddButton(
+		-name => 'go',
+		-left => 320,
+		-top  => 310,
+		-width => 50,
+		-height => 25,
+		-tabstop => 1,
+		-text => "Rip It");
+		
+$main->AddButton(
+		-name => 'close',
+		-left => 390,
+		-top  => 310,
+		-width => 50,
+		-height => 25,
+		-tabstop => 1,
+		-text => "Close");
+
+my $status = new Win32::GUI::StatusBar($main,
+		-text  => "Registry Ripper v.".$VERSION." opened.",
+);
+
+populatePluginsList();
+$combo->Text("<Select>");
+$status->Text("Plugins List Populated.");
+
+$main->Show();
+Win32::GUI::Dialog();
+#-----------------------------------------------------------
+sub Open_Click {
+	\&browse1_Click();	
+}
+
+sub browse1_Click {
+  # Open a file
+  my $file = Win32::GUI::GetOpenFileName(
+                   -owner  => $main,
+                   -title  => "Open a hive file",
+                   -filter => ['All files' => '*.*',],
+                   );
+  if (-e $file) {
+  	 $ntuserfile->Text($file);
+
+  } elsif (Win32::GUI::CommDlgExtendedError()) {
+     $main->MessageBox ("ERROR : ".Win32::GUI::CommDlgExtendedError(),
+                        "GetOpenFileName Error");
+  }
+  0;
+}
+
+sub browse2_Click {
+  # Open a file
+  my $file = Win32::GUI::GetSaveFileName(
+                   -owner  => $main,
+                   -title  => "Save a report file",
+                   -filter => [
+                       'Report file (*.txt)' => '*.txt',
+                       'All files' => '*.*',
+                    ],
+                   );
+  if ($file) {
+  	$file = $file."\.txt" unless ($file =~ m/\.\w+$/i);
+  	$rptfile->Text($file);
+
+  } elsif (Win32::GUI::CommDlgExtendedError()) {
+     $main->MessageBox ("ERROR : ".Win32::GUI::CommDlgExtendedError(),
+                        "GetOpenFileName Error");
+  }
+  0;
+}
+
+sub go_Click {	
+# Set up the environment
+	setUpEnv();
+	if ($env{ntuser} eq "") {
+		Win32::GUI::MessageBox($main,$ENV{USERNAME}.", you did not select a hive file.\r\n",
+		                       "Doh!!",16);
+		return;
+	}
+# Get the selected item from the Plugins file listbox
+# only allows for single selections at this time; defaults to ntuser
+# if none selected
+	my $pluginfile = $combo->GetLBText($combo->GetCurSel());
+	$pluginfile = "ntuser" if ($pluginfile eq "");
+	$report->Append("Logging to ".$env{logfile}."\r\n");
+	$report->Append("Using plugins file ".$pluginfile."\r\n");
+	logMsg("Log opened.");
+	logMsg("File: ".$env{ntuser});
+	logMsg("Environment set up.");
+	my %plugins = parsePluginsFile($pluginfile);
+	logMsg("Parsed Plugins file ".$pluginfile);
+	if (scalar(keys %plugins) == 0) {
+		Win32::GUI::MessageBox($main,$ENV{USERNAME}.", the plugins file has no plugins!!.\r\n",
+		                       "Doh!!",16);
+		return;
+	}
+	my $err_cnt = 0;
+	foreach my $i (sort {$a <=> $b} keys %plugins) {
+		eval {
+			require "plugins\\".$plugins{$i}."\.pl";
+			$plugins{$i}->pluginmain($env{ntuser});
+		};
+		if ($@) {
+			$err_cnt++;
+			logMsg("Error in ".$plugins{$i}.": ".$@);
+		}
+		
+		$report->Append($plugins{$i}."...Done.\r\n");
+		$status->Text($plugins{$i}." completed.");
+		
+		Win32::GUI::DoEvents();
+		logMsg($err_cnt." plugins completed with errors.");
+		logMsg($plugins{$i}." complete.");
+		rptMsg("-" x 40);
+	}
+	$report->Append($err_cnt." plugins completed with errors.\r\n");
+	$status->Text("Done.");
+}
+
+sub close_Click {
+	exit 1;
+}
+
+sub Combobox_CloseUp {
+	$status->Text("Plugin File = ".$combo->GetLBText($combo->GetCurSel()));
+	
+}
+
+
+# About box
+sub RR_OnAbout {
+  my $self = shift;
+
+  $self->MessageBox(
+     "Registry Ripper, v.".$VERSION."\r\n".
+     "Parses Registry hive (NTUSER\.DAT, System, etc.) files, placing pertinent info in a report\r\n".
+     "file in a readable manner.\r\n".
+     "Copyright 2008 H\. Carvey, keydet89\@yahoo\.com",
+     "About...",
+     MB_ICONINFORMATION | MB_OK,
+  );
+  0;
+}
+#-----------------------------------------------------------
+
+#-----------------------------------------------------------
+sub setUpEnv {
+	$env{ntuser} = $ntuserfile->Text();
+	$env{rptfile} = $rptfile->Text();
+# Ensure that the report file has a .txt extension if none was given
+	$env{rptfile} = $env{rptfile}."\.txt" unless ($env{rptfile} =~ m/\.\w+$/i);
+	$rptfile->Text($env{rptfile});
+	
+	my @path = split(/\\/,$env{rptfile});
+	my $last = scalar(@path) - 1;
+	my @f = split(/\./,$path[$last]);
+	my $ext = $f[scalar(@f) - 1];
+	
+# Assemble path to log file	
+	$f[scalar(@f) - 1] = "log";
+	$path[$last] = join('.',@f);
+	print join('\\',@path)."\n";
+	$env{logfile} = join('\\',@path);
+
+# Use the above code to set up the path to the Timeline
+# (.tln) file	
+# Assemble path to log file	
+#	$f[scalar(@f) - 1] = "tln";
+#	$path[$last] = join('.',@f);
+#	print join('\\',@path)."\n";
+#	$env{tlnfile} = join('\\',@path);
+
+}
+
+#-----------------------------------------------------------
+# get a list of plugins files from the plugins dir
+#-----------------------------------------------------------
+sub getPluginsFiles {
+	my @pluginfiles;
+	opendir(DIR,"plugins");
+	my @files = readdir(DIR);
+	close(DIR);
+	
+	foreach my $f (@files) {
+		next if ($f =~ m/^\./);
+		next if ($f =~ m/\.pl$/);
+		push(@pluginfiles,$f);
+	}
+	return @pluginfiles;
+}
+
+#-----------------------------------------------------------
+# populate the list of plugins files
+#-----------------------------------------------------------
+sub populatePluginsList {
+	my @files = getPluginsFiles();
+	foreach my $f (@files) {
+		$combo->InsertItem($f);
+	}
+}
+
+#-----------------------------------------------------------
+# 
+#-----------------------------------------------------------
+sub parsePluginsFile {
+	my $file = $_[0];
+	my %plugins;
+# Parse a file containing a list of plugins
+# Future versions of this tool may allow for the analyst to 
+# choose different plugins files	
+	my $pluginfile = "plugins\\".$file;
+	if (-e $pluginfile) {
+		open(FH,"<",$pluginfile);
+		my $count = 1;
+		while(<FH>) {
+			chomp;
+			next if ($_ =~ m/^#/ || $_ =~ m/^\s+$/);
+#			next unless ($_ =~ m/\.pl$/);
+			next if ($_ eq "");
+			$_ =~ s/^\s+//;
+			$_ =~ s/\s+$//;
+			$plugins{$count++} = $_; 
+		}
+		close(FH);
+		$status->Text("Plugin file parsed and loaded.");
+		return %plugins;
+	}
+	else {
+		$report->Append($pluginfile." not found.\r\n");
+		return undef;
+	}
+}
+
+sub logMsg {
+	open(FH,">>",$env{logfile});
+	print FH localtime(time).": ".$_[0]."\n";
+	close(FH);
+}
+
+sub rptMsg {
+	open(FH,">>",$env{rptfile});
+	binmode FH,":utf8";
+	print FH $_[0]."\n";
+	close(FH);
+}
+
+# sub tlnMsg {
+# Need to set the format for the pipe-delimited line to be
+# written in the TSK TimeMachine format
+#		open(FH,">>",$env{tlnfile});
+#		print FH $_[0]."\n";
+#		close(FH);
+#}
+
+#-------------------------------------------------------------
+# getTime()
+# Translate FILETIME object (2 DWORDS) to Unix time, to be passed
+# to gmtime() or localtime()
+#-------------------------------------------------------------
+sub getTime($$) {
+	my $lo = shift;
+	my $hi = shift;
+	my $t;
+
+	if ($lo == 0 && $hi == 0) {
+		$t = 0;
+	} else {
+		$lo -= 0xd53e8000;
+		$hi -= 0x019db1de;
+		$t = int($hi*429.4967296 + $lo/1e7);
+	};
+	$t = 0 if ($t < 0);
+	return $t;
+}
\ No newline at end of file
diff --git a/trove/build.xml b/trove/build.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c68221af25518aeab80cd3de949b7325d7966e63
--- /dev/null
+++ b/trove/build.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="org.gnu.trove" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project org.gnu.trove.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
diff --git a/trove/manifest.mf b/trove/manifest.mf
new file mode 100644
index 0000000000000000000000000000000000000000..7eb568c522efa25ce9a137b2173772ca8618af9d
--- /dev/null
+++ b/trove/manifest.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: org.gnu.trove
+OpenIDE-Module-Localizing-Bundle: org/gnu/trove/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
diff --git a/trove/nbproject/build-impl.xml b/trove/nbproject/build-impl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c8725838c80373a22c2f7b6ccf494e9c86f06020
--- /dev/null
+++ b/trove/nbproject/build-impl.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="org.gnu.trove-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>
diff --git a/trove/nbproject/genfiles.properties b/trove/nbproject/genfiles.properties
new file mode 100644
index 0000000000000000000000000000000000000000..b15062e889cbd0460be9a5cd42b60d5a147d7680
--- /dev/null
+++ b/trove/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=f46defa5
+build.xml.script.CRC32=9f9a492d
+build.xml.stylesheet.CRC32=a56c6a5b@1.46.1
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=f46defa5
+nbproject/build-impl.xml.script.CRC32=62e537b6
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.46.1
diff --git a/trove/nbproject/platform.properties b/trove/nbproject/platform.properties
new file mode 100644
index 0000000000000000000000000000000000000000..38ecd5a92ebea2c14710d0595bdd2d6df0bafcf4
--- /dev/null
+++ b/trove/nbproject/platform.properties
@@ -0,0 +1,99 @@
+cluster.path=\
+    ${nbplatform.active.dir}/java:\
+    ${nbplatform.active.dir}/platform
+disabled.modules=\
+    org.apache.tools.ant.module,\
+    org.netbeans.api.debugger.jpda,\
+    org.netbeans.api.java,\
+    org.netbeans.libs.cglib,\
+    org.netbeans.libs.javacapi,\
+    org.netbeans.libs.javacimpl,\
+    org.netbeans.libs.jsr223,\
+    org.netbeans.libs.springframework,\
+    org.netbeans.modules.ant.browsetask,\
+    org.netbeans.modules.ant.debugger,\
+    org.netbeans.modules.ant.freeform,\
+    org.netbeans.modules.ant.grammar,\
+    org.netbeans.modules.ant.kit,\
+    org.netbeans.modules.beans,\
+    org.netbeans.modules.classfile,\
+    org.netbeans.modules.dbschema,\
+    org.netbeans.modules.debugger.jpda,\
+    org.netbeans.modules.debugger.jpda.ant,\
+    org.netbeans.modules.debugger.jpda.projects,\
+    org.netbeans.modules.debugger.jpda.ui,\
+    org.netbeans.modules.form,\
+    org.netbeans.modules.form.j2ee,\
+    org.netbeans.modules.form.kit,\
+    org.netbeans.modules.hibernate,\
+    org.netbeans.modules.hibernatelib,\
+    org.netbeans.modules.hudson.ant,\
+    org.netbeans.modules.hudson.maven,\
+    org.netbeans.modules.i18n,\
+    org.netbeans.modules.i18n.form,\
+    org.netbeans.modules.j2ee.core.utilities,\
+    org.netbeans.modules.j2ee.eclipselink,\
+    org.netbeans.modules.j2ee.eclipselinkmodelgen,\
+    org.netbeans.modules.j2ee.jpa.refactoring,\
+    org.netbeans.modules.j2ee.jpa.verification,\
+    org.netbeans.modules.j2ee.metadata,\
+    org.netbeans.modules.j2ee.metadata.model.support,\
+    org.netbeans.modules.j2ee.persistence,\
+    org.netbeans.modules.j2ee.persistence.kit,\
+    org.netbeans.modules.j2ee.persistenceapi,\
+    org.netbeans.modules.j2ee.toplinklib,\
+    org.netbeans.modules.java.api.common,\
+    org.netbeans.modules.java.debug,\
+    org.netbeans.modules.java.editor,\
+    org.netbeans.modules.java.editor.lib,\
+    org.netbeans.modules.java.examples,\
+    org.netbeans.modules.java.freeform,\
+    org.netbeans.modules.java.guards,\
+    org.netbeans.modules.java.helpset,\
+    org.netbeans.modules.java.hints,\
+    org.netbeans.modules.java.hints.processor,\
+    org.netbeans.modules.java.j2seplatform,\
+    org.netbeans.modules.java.j2seproject,\
+    org.netbeans.modules.java.kit,\
+    org.netbeans.modules.java.lexer,\
+    org.netbeans.modules.java.navigation,\
+    org.netbeans.modules.java.platform,\
+    org.netbeans.modules.java.preprocessorbridge,\
+    org.netbeans.modules.java.project,\
+    org.netbeans.modules.java.source,\
+    org.netbeans.modules.java.source.ant,\
+    org.netbeans.modules.java.sourceui,\
+    org.netbeans.modules.javadoc,\
+    org.netbeans.modules.javawebstart,\
+    org.netbeans.modules.jellytools,\
+    org.netbeans.modules.jellytools.java,\
+    org.netbeans.modules.junit,\
+    org.netbeans.modules.maven,\
+    org.netbeans.modules.maven.coverage,\
+    org.netbeans.modules.maven.embedder,\
+    org.netbeans.modules.maven.grammar,\
+    org.netbeans.modules.maven.graph,\
+    org.netbeans.modules.maven.hints,\
+    org.netbeans.modules.maven.indexer,\
+    org.netbeans.modules.maven.junit,\
+    org.netbeans.modules.maven.kit,\
+    org.netbeans.modules.maven.model,\
+    org.netbeans.modules.maven.osgi,\
+    org.netbeans.modules.maven.persistence,\
+    org.netbeans.modules.maven.repository,\
+    org.netbeans.modules.maven.search,\
+    org.netbeans.modules.maven.spring,\
+    org.netbeans.modules.projectimport.eclipse.core,\
+    org.netbeans.modules.projectimport.eclipse.j2se,\
+    org.netbeans.modules.refactoring.java,\
+    org.netbeans.modules.spellchecker.bindings.java,\
+    org.netbeans.modules.spring.beans,\
+    org.netbeans.modules.swingapp,\
+    org.netbeans.modules.websvc.jaxws21,\
+    org.netbeans.modules.websvc.jaxws21api,\
+    org.netbeans.modules.websvc.saas.codegen.java,\
+    org.netbeans.modules.xml.jaxb,\
+    org.netbeans.modules.xml.tools.java,\
+    org.openide.compat,\
+    org.openide.util.enumerations
+nbplatform.active=default
diff --git a/trove/nbproject/project.properties b/trove/nbproject/project.properties
new file mode 100644
index 0000000000000000000000000000000000000000..c4a287af7f9698f4a4fe857e05578adf9aefacbf
--- /dev/null
+++ b/trove/nbproject/project.properties
@@ -0,0 +1 @@
+is.autoload=true
diff --git a/trove/nbproject/project.xml b/trove/nbproject/project.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4813201efdd2f5c1b73ebf95a8a784e21b2331c2
--- /dev/null
+++ b/trove/nbproject/project.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>org.gnu.trove</code-name-base>
+            <suite-component/>
+            <module-dependencies/>
+            <public-packages>
+                <package>gnu.trove</package>
+                <package>gnu.trove.decorator</package>
+                <package>gnu.trove.function</package>
+                <package>gnu.trove.impl</package>
+                <package>gnu.trove.impl.hash</package>
+                <package>gnu.trove.impl.sync</package>
+                <package>gnu.trove.impl.unmodifiable</package>
+                <package>gnu.trove.iterator</package>
+                <package>gnu.trove.iterator.hash</package>
+                <package>gnu.trove.list</package>
+                <package>gnu.trove.list.array</package>
+                <package>gnu.trove.list.linked</package>
+                <package>gnu.trove.map</package>
+                <package>gnu.trove.map.custom_hash</package>
+                <package>gnu.trove.map.hash</package>
+                <package>gnu.trove.procedure</package>
+                <package>gnu.trove.procedure.array</package>
+                <package>gnu.trove.queue</package>
+                <package>gnu.trove.set</package>
+                <package>gnu.trove.set.hash</package>
+                <package>gnu.trove.stack</package>
+                <package>gnu.trove.stack.array</package>
+                <package>gnu.trove.strategy</package>
+            </public-packages>
+            <class-path-extension>
+                <runtime-relative-path>ext/trove-3.0.2.jar</runtime-relative-path>
+                <binary-origin>release/modules/ext/trove-3.0.2.jar</binary-origin>
+            </class-path-extension>
+        </data>
+    </configuration>
+</project>
diff --git a/trove/nbproject/suite.properties b/trove/nbproject/suite.properties
new file mode 100644
index 0000000000000000000000000000000000000000..29d7cc9bd6fdd81453543cdf1bcf1dab301e3a92
--- /dev/null
+++ b/trove/nbproject/suite.properties
@@ -0,0 +1 @@
+suite.dir=${basedir}/..
diff --git a/trove/release/modules/ext/trove-3.0.2.jar b/trove/release/modules/ext/trove-3.0.2.jar
new file mode 100644
index 0000000000000000000000000000000000000000..12fb57681f8ca343350c8f43f1a8c007045936ec
Binary files /dev/null and b/trove/release/modules/ext/trove-3.0.2.jar differ
diff --git a/trove/src/org/gnu/trove/Bundle.properties b/trove/src/org/gnu/trove/Bundle.properties
new file mode 100644
index 0000000000000000000000000000000000000000..c6178bf414c9ddddd3a94dd39851bc5d76b01f68
--- /dev/null
+++ b/trove/src/org/gnu/trove/Bundle.properties
@@ -0,0 +1 @@
+OpenIDE-Module-Name=trove