Merge branch 'develop' of https://github.com/sleuthkit/autopsy into 6305-UpdateDiscoveryUI

This commit is contained in:
William Schaefer 2020-05-21 10:41:33 -04:00
commit 53eff40214
119 changed files with 16108 additions and 1035 deletions

View File

@ -90,6 +90,7 @@ public interface AutopsyService {
private final Case theCase; private final Case theCase;
private final ProgressIndicator progressIndicator; private final ProgressIndicator progressIndicator;
private volatile boolean cancelRequested; private volatile boolean cancelRequested;
private final boolean isNewCase;
/** /**
* Constructs the context for the creation/opening/upgrading of * Constructs the context for the creation/opening/upgrading of
@ -100,9 +101,23 @@ public interface AutopsyService {
* case-level resources * case-level resources
*/ */
public CaseContext(Case theCase, ProgressIndicator progressIndicator) { public CaseContext(Case theCase, ProgressIndicator progressIndicator) {
this(theCase, progressIndicator, false);
}
/**
* Constructs the context for the creation/opening/upgrading of
* case-level resources by a service.
*
* @param theCase The case.
* @param progressIndicator A progress indicator for the opening of the
* case-level resources.
* @param isNewCase True if theCase is a new case.
*/
public CaseContext(Case theCase, ProgressIndicator progressIndicator, boolean isNewCase) {
this.theCase = theCase; this.theCase = theCase;
this.progressIndicator = progressIndicator; this.progressIndicator = progressIndicator;
this.cancelRequested = false; this.cancelRequested = false;
this.isNewCase = isNewCase;
} }
/** /**
@ -145,6 +160,16 @@ public interface AutopsyService {
public boolean cancelRequested() { public boolean cancelRequested() {
return this.cancelRequested; return this.cancelRequested;
} }
/**
* Indicates whether or the case is a new case in the process of being
* created.
*
* @return True if it is a new case.
*/
public boolean isNewCase() {
return this.isNewCase;
}
} }
/** /**

View File

@ -132,7 +132,6 @@ class AddImageTask implements Runnable {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
List<Content> newDataSources = new ArrayList<>(); List<Content> newDataSources = new ArrayList<>();
try { try {
currentCase.getSleuthkitCase().acquireSingleUserCaseWriteLock();
synchronized (tskAddImageProcessLock) { synchronized (tskAddImageProcessLock) {
if (!tskAddImageProcessStopped) { if (!tskAddImageProcessStopped) {
tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true, ignoreFatOrphanFiles, imageWriterPath); tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true, ignoreFatOrphanFiles, imageWriterPath);
@ -147,7 +146,6 @@ class AddImageTask implements Runnable {
commitOrRevertAddImageProcess(currentCase, errorMessages, newDataSources); commitOrRevertAddImageProcess(currentCase, errorMessages, newDataSources);
progressMonitor.setProgress(100); progressMonitor.setProgress(100);
} finally { } finally {
currentCase.getSleuthkitCase().releaseSingleUserCaseWriteLock();
DataSourceProcessorCallback.DataSourceProcessorResult result; DataSourceProcessorCallback.DataSourceProcessorResult result;
if (criticalErrorOccurred) { if (criticalErrorOccurred) {
result = DataSourceProcessorResult.CRITICAL_ERRORS; result = DataSourceProcessorResult.CRITICAL_ERRORS;

View File

@ -1958,7 +1958,7 @@ public class Case {
checkForCancellation(); checkForCancellation();
openCaseLevelServices(progressIndicator); openCaseLevelServices(progressIndicator);
checkForCancellation(); checkForCancellation();
openAppServiceCaseResources(progressIndicator); openAppServiceCaseResources(progressIndicator, true);
checkForCancellation(); checkForCancellation();
openCommunicationChannels(progressIndicator); openCommunicationChannels(progressIndicator);
return null; return null;
@ -2007,7 +2007,7 @@ public class Case {
checkForCancellation(); checkForCancellation();
openCaseLevelServices(progressIndicator); openCaseLevelServices(progressIndicator);
checkForCancellation(); checkForCancellation();
openAppServiceCaseResources(progressIndicator); openAppServiceCaseResources(progressIndicator, false);
checkForCancellation(); checkForCancellation();
openCommunicationChannels(progressIndicator); openCommunicationChannels(progressIndicator);
checkForCancellation(); checkForCancellation();
@ -2518,7 +2518,7 @@ public class Case {
"# {0} - service name", "Case.serviceOpenCaseResourcesProgressIndicator.cancellingMessage=Cancelling opening case resources by {0}...", "# {0} - service name", "Case.serviceOpenCaseResourcesProgressIndicator.cancellingMessage=Cancelling opening case resources by {0}...",
"# {0} - service name", "Case.servicesException.notificationTitle={0} Error" "# {0} - service name", "Case.servicesException.notificationTitle={0} Error"
}) })
private void openAppServiceCaseResources(ProgressIndicator progressIndicator) throws CaseActionException { private void openAppServiceCaseResources(ProgressIndicator progressIndicator, boolean isNewCase) throws CaseActionException {
/* /*
* Each service gets its own independently cancellable/interruptible * Each service gets its own independently cancellable/interruptible
* task, running in a named thread managed by an executor service, with * task, running in a named thread managed by an executor service, with
@ -2550,7 +2550,7 @@ public class Case {
appServiceProgressIndicator = new LoggingProgressIndicator(); appServiceProgressIndicator = new LoggingProgressIndicator();
} }
appServiceProgressIndicator.start(Bundle.Case_progressMessage_preparing()); appServiceProgressIndicator.start(Bundle.Case_progressMessage_preparing());
AutopsyService.CaseContext context = new AutopsyService.CaseContext(this, appServiceProgressIndicator); AutopsyService.CaseContext context = new AutopsyService.CaseContext(this, appServiceProgressIndicator, isNewCase);
String threadNameSuffix = service.getServiceName().replaceAll("[ ]", "-"); //NON-NLS String threadNameSuffix = service.getServiceName().replaceAll("[ ]", "-"); //NON-NLS
threadNameSuffix = threadNameSuffix.toLowerCase(); threadNameSuffix = threadNameSuffix.toLowerCase();
TaskThreadFactory threadFactory = new TaskThreadFactory(String.format(CASE_RESOURCES_THREAD_NAME, threadNameSuffix)); TaskThreadFactory threadFactory = new TaskThreadFactory(String.format(CASE_RESOURCES_THREAD_NAME, threadNameSuffix));

View File

@ -57,11 +57,11 @@ final class TagNameDefinition implements Comparable<TagNameDefinition> {
private static final String TAG_SETTING_VERSION_KEY = "CustomTagNameVersion"; private static final String TAG_SETTING_VERSION_KEY = "CustomTagNameVersion";
private static final int TAG_SETTINGS_VERSION = 1; private static final int TAG_SETTINGS_VERSION = 1;
private static final String CATEGORY_ONE_NAME = "CAT-1: Child Exploitation (Illegal)"; private static final String CATEGORY_ONE_NAME = "Child Exploitation (Illegal)";
private static final String CATEGORY_TWO_NAME = "CAT-2: Child Exploitation (Non-Illegal/Age Difficult)"; private static final String CATEGORY_TWO_NAME = "Child Exploitation (Non-Illegal/Age Difficult)";
private static final String CATEGORY_THREE_NAME = "CAT-3: CGI/Animation (Child Exploitive)"; private static final String CATEGORY_THREE_NAME = "CGI/Animation (Child Exploitive)";
private static final String CATEGORY_FOUR_NAME = "CAT-4: Exemplar/Comparison (Internal Use Only)"; private static final String CATEGORY_FOUR_NAME = "Exemplar/Comparison (Internal Use Only)";
private static final String CATEGORY_FIVE_NAME = "CAT-5: Non-pertinent"; private static final String CATEGORY_FIVE_NAME = "Non-pertinent";
private final String displayName; private final String displayName;
private final String description; private final String description;
@ -70,6 +70,7 @@ final class TagNameDefinition implements Comparable<TagNameDefinition> {
private static final Map<String, TagNameDefinition> STANDARD_TAGS_DEFINITIONS = new HashMap<>(); private static final Map<String, TagNameDefinition> STANDARD_TAGS_DEFINITIONS = new HashMap<>();
private static final Map<String, TagNameDefinition> PROJECT_VIC_TAG_DEFINITIONS = new HashMap<>(); private static final Map<String, TagNameDefinition> PROJECT_VIC_TAG_DEFINITIONS = new HashMap<>();
private static final List<String> OLD_CATEGORY_TAG_NAMES = new ArrayList<>();
static { static {
STANDARD_TAGS_DEFINITIONS.put(Bundle.TagNameDefinition_predefTagNames_bookmark_text(), new TagNameDefinition(Bundle.TagNameDefinition_predefTagNames_bookmark_text(), "", TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN)); STANDARD_TAGS_DEFINITIONS.put(Bundle.TagNameDefinition_predefTagNames_bookmark_text(), new TagNameDefinition(Bundle.TagNameDefinition_predefTagNames_bookmark_text(), "", TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN));
@ -81,6 +82,14 @@ final class TagNameDefinition implements Comparable<TagNameDefinition> {
PROJECT_VIC_TAG_DEFINITIONS.put(CATEGORY_THREE_NAME, new TagNameDefinition(CATEGORY_THREE_NAME, "", TagName.HTML_COLOR.YELLOW, TskData.FileKnown.BAD)); PROJECT_VIC_TAG_DEFINITIONS.put(CATEGORY_THREE_NAME, new TagNameDefinition(CATEGORY_THREE_NAME, "", TagName.HTML_COLOR.YELLOW, TskData.FileKnown.BAD));
PROJECT_VIC_TAG_DEFINITIONS.put(CATEGORY_FOUR_NAME, new TagNameDefinition(CATEGORY_FOUR_NAME, "", TagName.HTML_COLOR.PURPLE, TskData.FileKnown.UNKNOWN)); PROJECT_VIC_TAG_DEFINITIONS.put(CATEGORY_FOUR_NAME, new TagNameDefinition(CATEGORY_FOUR_NAME, "", TagName.HTML_COLOR.PURPLE, TskData.FileKnown.UNKNOWN));
PROJECT_VIC_TAG_DEFINITIONS.put(CATEGORY_FIVE_NAME, new TagNameDefinition(CATEGORY_FIVE_NAME, "", TagName.HTML_COLOR.FUCHSIA, TskData.FileKnown.UNKNOWN)); PROJECT_VIC_TAG_DEFINITIONS.put(CATEGORY_FIVE_NAME, new TagNameDefinition(CATEGORY_FIVE_NAME, "", TagName.HTML_COLOR.FUCHSIA, TskData.FileKnown.UNKNOWN));
OLD_CATEGORY_TAG_NAMES.add("CAT-1: " + CATEGORY_ONE_NAME);
OLD_CATEGORY_TAG_NAMES.add("CAT-2: " + CATEGORY_TWO_NAME);
OLD_CATEGORY_TAG_NAMES.add("CAT-3: " + CATEGORY_THREE_NAME);
OLD_CATEGORY_TAG_NAMES.add("CAT-4: " + CATEGORY_FOUR_NAME);
OLD_CATEGORY_TAG_NAMES.add("CAT-5: " + CATEGORY_FIVE_NAME);
OLD_CATEGORY_TAG_NAMES.add("CAT-0: Uncategorized");
} }
/** /**
@ -115,6 +124,33 @@ final class TagNameDefinition implements Comparable<TagNameDefinition> {
return strList; return strList;
} }
/**
* Returns the bookmark tag display string.
*
* @return
*/
static String getBookmarkDisplayString() {
return Bundle.TagNameDefinition_predefTagNames_bookmark_text();
}
/**
* Returns the Follow Up tag display string.
*
* @return
*/
static String getFollowUpDisplayString() {
return Bundle.TagNameDefinition_predefTagNames_followUp_text();
}
/**
* Returns the Notable tag display string.
*
* @return
*/
static String getNotableDisplayString() {
return Bundle.TagNameDefinition_predefTagNames_notableItem_text();
}
/** /**
* Gets the display name for the tag name. * Gets the display name for the tag name.
* *
@ -300,6 +336,7 @@ final class TagNameDefinition implements Comparable<TagNameDefinition> {
if (version == null) { if (version == null) {
String tagsProperty = ModuleSettings.getConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY); String tagsProperty = ModuleSettings.getConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY);
if (tagsProperty == null || tagsProperty.isEmpty()) { if (tagsProperty == null || tagsProperty.isEmpty()) {
ModuleSettings.setConfigSetting(TAGS_SETTINGS_NAME, TAG_SETTING_VERSION_KEY, Integer.toString(TAG_SETTINGS_VERSION));
return; return;
} }
@ -339,7 +376,8 @@ final class TagNameDefinition implements Comparable<TagNameDefinition> {
List<String> tagStrings = new ArrayList<>(); List<String> tagStrings = new ArrayList<>();
List<String> standardTags = getStandardTagNames(); List<String> standardTags = getStandardTagNames();
for (TagNameDefinition def : definitions) { for (TagNameDefinition def : definitions) {
if (!standardTags.contains(def.getDisplayName())) { if (!standardTags.contains(def.getDisplayName()) &&
!OLD_CATEGORY_TAG_NAMES.contains(def.getDisplayName())) {
tagStrings.add(def.toSettingsFormat()); tagStrings.add(def.toSettingsFormat());
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2018 Basis Technology Corp. * Copyright 2011-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -55,7 +55,7 @@ public class TagsManager implements Closeable {
private static final Logger LOGGER = Logger.getLogger(TagsManager.class.getName()); private static final Logger LOGGER = Logger.getLogger(TagsManager.class.getName());
private final SleuthkitCase caseDb; private final SleuthkitCase caseDb;
static String DEFAULT_TAG_SET_NAME = "Project VIC (United States)"; private static String DEFAULT_TAG_SET_NAME = "Project VIC";
static { static {
@ -184,7 +184,62 @@ public class TagsManager implements Closeable {
* @return list of predefined tag names * @return list of predefined tag names
*/ */
public static List<String> getStandardTagNames() { public static List<String> getStandardTagNames() {
return TagNameDefinition.getStandardTagNames(); List<String> tagList = new ArrayList<>();
for (TagNameDefinition tagNameDef : TagNameDefinition.getStandardTagNameDefinitions()) {
tagList.add(tagNameDef.getDisplayName());
}
try {
List<TagSet> tagSetList = Case.getCurrentCaseThrows().getSleuthkitCase().getTaggingManager().getTagSets();
for (TagSet tagSet : tagSetList) {
if (tagSet.getName().equals(DEFAULT_TAG_SET_NAME)) {
for (TagName tagName : tagSet.getTagNames()) {
tagList.add(tagName.getDisplayName());
}
}
}
} catch (NoCurrentCaseException | TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Failed to get Project VIC tags from the database.", ex);
}
return tagList;
}
/**
* Returns the name of the Category TagSet.
*
* @return Name of category TagSet.
*/
public static String getCategoryTagSetName() {
return DEFAULT_TAG_SET_NAME;
}
/**
* Returns the bookmark tag display string.
*
* @return
*/
public static String getBookmarkDisplayString() {
return TagNameDefinition.getBookmarkDisplayString();
}
/**
* Returns the Follow Up tag display string.
*
* @return
*/
public static String getFollowUpDisplayString() {
return TagNameDefinition.getFollowUpDisplayString();
}
/**
* Returns the Notable tag display string.
*
* @return
*/
public static String getNotableDisplayString() {
return TagNameDefinition.getNotableDisplayString();
} }
/** /**

View File

@ -147,7 +147,6 @@ final class AddRawImageTask implements Runnable {
} }
imageFilePaths.add(imageFilePath); imageFilePaths.add(imageFilePath);
try { try {
caseDatabase.acquireSingleUserCaseWriteLock();
/* /*
* Get Image that will be added to case * Get Image that will be added to case
*/ */
@ -187,9 +186,6 @@ final class AddRawImageTask implements Runnable {
errorMessages.add(errorMessage); errorMessages.add(errorMessage);
logger.log(Level.SEVERE, errorMessage, ex); logger.log(Level.SEVERE, errorMessage, ex);
criticalErrorOccurred = true; criticalErrorOccurred = true;
} finally {
caseDatabase.releaseSingleUserCaseWriteLock();
} }
} }
} }

View File

@ -116,8 +116,6 @@ class AddMultipleImagesTask implements Runnable {
* Try to add the input image files as images. * Try to add the input image files as images.
*/ */
List<String> corruptedImageFilePaths = new ArrayList<>(); List<String> corruptedImageFilePaths = new ArrayList<>();
try {
currentCase.getSleuthkitCase().acquireSingleUserCaseWriteLock();
progressMonitor.setIndeterminate(true); progressMonitor.setIndeterminate(true);
for (String imageFilePath : imageFilePaths) { for (String imageFilePath : imageFilePaths) {
synchronized (tskAddImageProcessLock) { synchronized (tskAddImageProcessLock) {
@ -138,9 +136,6 @@ class AddMultipleImagesTask implements Runnable {
} }
} }
} }
} finally {
currentCase.getSleuthkitCase().releaseSingleUserCaseWriteLock();
}
/* /*
* Try to add any input image files that did not have file systems as a * Try to add any input image files that did not have file systems as a
@ -153,8 +148,6 @@ class AddMultipleImagesTask implements Runnable {
try { try {
progressMonitor.setProgressText(Bundle.AddMultipleImagesTask_addingFileAsLogicalFile(corruptedImageFilePaths.toString())); progressMonitor.setProgressText(Bundle.AddMultipleImagesTask_addingFileAsLogicalFile(corruptedImageFilePaths.toString()));
caseDatabase.acquireSingleUserCaseWriteLock();
Image dataSource = caseDatabase.addImageInfo(0, corruptedImageFilePaths, timeZone); Image dataSource = caseDatabase.addImageInfo(0, corruptedImageFilePaths, timeZone);
newDataSources.add(dataSource); newDataSources.add(dataSource);
List<TskFileRange> fileRanges = new ArrayList<>(); List<TskFileRange> fileRanges = new ArrayList<>();
@ -177,8 +170,6 @@ class AddMultipleImagesTask implements Runnable {
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
errorMessages.add(Bundle.AddMultipleImagesTask_errorAddingImgWithoutFileSystem(deviceId, ex.getLocalizedMessage())); errorMessages.add(Bundle.AddMultipleImagesTask_errorAddingImgWithoutFileSystem(deviceId, ex.getLocalizedMessage()));
criticalErrorOccurred = true; criticalErrorOccurred = true;
} finally {
caseDatabase.releaseSingleUserCaseWriteLock();
} }
} }

View File

@ -146,8 +146,7 @@ final class AddMemoryImageTask implements Runnable {
progressMonitor.setProgressText(Bundle.AddMemoryImageTask_progressMessage_addingImageFile( memoryImagePath)); progressMonitor.setProgressText(Bundle.AddMemoryImageTask_progressMessage_addingImageFile( memoryImagePath));
SleuthkitCase caseDatabase = Case.getCurrentCaseThrows().getSleuthkitCase(); SleuthkitCase caseDatabase = Case.getCurrentCaseThrows().getSleuthkitCase();
caseDatabase.acquireSingleUserCaseWriteLock();
try {
/* /*
* Verify the memory image file exists. * Verify the memory image file exists.
*/ */
@ -166,10 +165,6 @@ final class AddMemoryImageTask implements Runnable {
*/ */
Image dataSource = caseDatabase.addImageInfo(0, new ArrayList<>(Arrays.asList(memoryImagePath)), timeZone); Image dataSource = caseDatabase.addImageInfo(0, new ArrayList<>(Arrays.asList(memoryImagePath)), timeZone);
return dataSource; return dataSource;
} finally {
caseDatabase.releaseSingleUserCaseWriteLock();
}
} }
/** /**

View File

@ -57,6 +57,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.casemodule.events.DataSourceDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceDeletedEvent;
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
import org.sleuthkit.autopsy.coreutils.History; import org.sleuthkit.autopsy.coreutils.History;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined;
@ -74,6 +75,7 @@ import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisEvent; import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisEvent;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector.FileTypeDetectorInitException;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
@ -109,8 +111,6 @@ public final class ImageGalleryController {
Case.Events.DATA_SOURCE_DELETED Case.Events.DATA_SOURCE_DELETED
); );
private static final String CATEGORY_TAG_SET_PREFIX = "Project VIC";
/* /*
* There is an image gallery controller per case. It is created during the * There is an image gallery controller per case. It is created during the
* opening of case resources and destroyed during the closing of case * opening of case resources and destroyed during the closing of case
@ -737,7 +737,7 @@ public final class ImageGalleryController {
List<TagSet> tagSetList = getCaseDatabase().getTaggingManager().getTagSets(); List<TagSet> tagSetList = getCaseDatabase().getTaggingManager().getTagSets();
if (tagSetList != null && !tagSetList.isEmpty()) { if (tagSetList != null && !tagSetList.isEmpty()) {
for (TagSet set : tagSetList) { for (TagSet set : tagSetList) {
if (set.getName().startsWith(CATEGORY_TAG_SET_PREFIX)) { if (set.getName().equals(TagsManager.getCategoryTagSetName())) {
return set; return set;
} }
} }

View File

@ -82,7 +82,6 @@ public class CategorizeAction extends Action {
this.tagName = tagName; this.tagName = tagName;
setGraphic(getGraphic(tagName)); setGraphic(getGraphic(tagName));
setEventHandler(actionEvent -> addCatToFiles(selectedFileIDs)); setEventHandler(actionEvent -> addCatToFiles(selectedFileIDs));
setAccelerator(new KeyCodeCombination(KeyCode.getKeyCode(getCategoryNumberFromTagName(tagName))));
} }
static public Menu getCategoriesMenu(ImageGalleryController controller) { static public Menu getCategoriesMenu(ImageGalleryController controller) {
@ -94,16 +93,6 @@ public class CategorizeAction extends Action {
controller.queueDBTask(new CategorizeDrawableFileTask(ids, tagName, createUndo)); controller.queueDBTask(new CategorizeDrawableFileTask(ids, tagName, createUndo));
} }
private String getCategoryNumberFromTagName(TagName tagName) {
String displayName = tagName.getDisplayName();
if (displayName.contains("CAT")) {
String[] split = displayName.split(":");
split = split[0].split("-");
return split[1];
}
return "";
}
/** /**
* Instances of this class implement a context menu user interface for * Instances of this class implement a context menu user interface for
* selecting a category * selecting a category

View File

@ -13,6 +13,4 @@ DrawableAttribute.name=Name
DrawableAttribute.path=Path DrawableAttribute.path=Path
DrawableAttribute.tags=Tags DrawableAttribute.tags=Tags
DrawableAttribute.width=Width DrawableAttribute.width=Width
DrawableTagsManager.bookMark=Bookmark
DrawableTagsManager.followUp=Follow Up
VideoFile.getMedia.progress=writing temporary file to disk VideoFile.getMedia.progress=writing temporary file to disk

View File

@ -38,7 +38,6 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent.DeletedContentTagInfo; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent.DeletedContentTagInfo;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TagName;
@ -62,9 +61,7 @@ public class CategoryManager {
private static final Logger LOGGER = Logger.getLogger(CategoryManager.class.getName()); private static final Logger LOGGER = Logger.getLogger(CategoryManager.class.getName());
/** /**
* the DrawableDB that backs the category counts cache. The counts are * the DrawableDB that backs the category counts cache.
* initialized from this, and the counting of CAT-0 is always delegated to
* this db.
*/ */
private final DrawableDB drawableDb; private final DrawableDB drawableDb;

View File

@ -29,7 +29,6 @@ import javafx.scene.Node;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.casemodule.services.TagsManager;
@ -44,8 +43,6 @@ import org.sleuthkit.datamodel.TskCoreException;
* Manages Tags, Tagging, and the relationship between Categories and Tags in * Manages Tags, Tagging, and the relationship between Categories and Tags in
* the autopsy Db. Delegates some work to the backing autopsy TagsManager. * the autopsy Db. Delegates some work to the backing autopsy TagsManager.
*/ */
@NbBundle.Messages({"DrawableTagsManager.followUp=Follow Up",
"DrawableTagsManager.bookMark=Bookmark"})
public final class DrawableTagsManager { public final class DrawableTagsManager {
private static final Logger logger = Logger.getLogger(DrawableTagsManager.class.getName()); private static final Logger logger = Logger.getLogger(DrawableTagsManager.class.getName());
@ -78,8 +75,8 @@ public final class DrawableTagsManager {
public DrawableTagsManager(ImageGalleryController controller) throws TskCoreException { public DrawableTagsManager(ImageGalleryController controller) throws TskCoreException {
this.autopsyTagsManager = controller.getCase().getServices().getTagsManager(); this.autopsyTagsManager = controller.getCase().getServices().getTagsManager();
followUpTagName = getTagName(Bundle.DrawableTagsManager_followUp()); followUpTagName = getTagName(TagsManager.getFollowUpDisplayString());
bookmarkTagName = getTagName(Bundle.DrawableTagsManager_bookMark()); bookmarkTagName = getTagName(TagsManager.getBookmarkDisplayString());
this.controller = controller; this.controller = controller;
compareByDisplayName = new Comparator<TagName>() { compareByDisplayName = new Comparator<TagName>() {

View File

@ -1497,11 +1497,11 @@ class ExtractRegistry extends Extract {
line = line.trim(); line = line.trim();
// Reading to the SECTION DIVIDER to get next section of records to process. Dates appear to have // Reading to the SECTION DIVIDER to get next section of records to process. Dates appear to have
// multiple spaces in them that makes it harder to parse so next section will be easier to parse // multiple spaces in them that makes it harder to parse so next section will be easier to parse
while (!line.contains(SECTION_DIVIDER)) { while (!line.contains(SECTION_DIVIDER) && !line.contains("MSOffice version not found.")) {
line = reader.readLine(); line = reader.readLine();
} }
line = reader.readLine(); line = reader.readLine();
while (!line.contains(SECTION_DIVIDER)) { while (!line.contains(SECTION_DIVIDER) && !line.contains("MSOffice version not found.")) {
// record has the following format // record has the following format
// 1294283922|REG|||OfficeDocs2010 - F:\Windows_time_Rules_xp.doc // 1294283922|REG|||OfficeDocs2010 - F:\Windows_time_Rules_xp.doc
String tokens[] = line.split("\\|"); String tokens[] = line.split("\\|");
@ -1551,7 +1551,7 @@ class ExtractRegistry extends Extract {
line = line.trim(); line = line.trim();
usedTime = Long.valueOf(0); usedTime = Long.valueOf(0);
if (!line.contains("**") && !line.contains("----------") && !line.contains("LastWrite") if (!line.contains("**") && !line.contains("----------") && !line.contains("LastWrite")
&& !line.contains(SECTION_DIVIDER) && !line.isEmpty()) { && !line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains("TrustRecords")) {
// Columns are // Columns are
// Date : <File Name>/<Website> // Date : <File Name>/<Website>
// Split line on " : " which is the record delimiter between position and file // Split line on " : " which is the record delimiter between position and file

1119
thirdparty/rr-full/Base.pm vendored Normal file

File diff suppressed because it is too large Load Diff

355
thirdparty/rr-full/File.pm vendored Normal file
View File

@ -0,0 +1,355 @@
package Parse::Win32Registry::WinNT::File;
use strict;
use warnings;
use base qw(Parse::Win32Registry::File);
use Carp;
use Encode;
use File::Basename;
use Parse::Win32Registry::Base qw(:all);
use Parse::Win32Registry::WinNT::Key;
use constant REGF_HEADER_LENGTH => 0x200;
use constant OFFSET_TO_FIRST_HBIN => 0x1000;
sub new {
my $class = shift;
my $filename = shift or croak "No filename specified";
open my $fh, '<', $filename or croak "Unable to open '$filename': $!";
# 0x00 dword = 'regf' signature
# 0x04 dword = seq1
# 0x08 dword = seq2
# 0x0c qword = timestamp
# 0x14 dword = major version
# 0x18 dword = minor version
# 0x1c dword = type (0 = registry file, 1 = log file)
# 0x20 dword = (1)
# 0x24 dword = offset to root key
# 0x28 dword = total length of all hbins (excludes header)
# 0x2c dword = (1)
# 0x30 = embedded filename
# Extracted offsets are always relative to first hbin
my $bytes_read = sysread($fh, my $regf_header, REGF_HEADER_LENGTH);
if ($bytes_read != REGF_HEADER_LENGTH) {
warnf('Could not read registry file header');
return;
}
my ($regf_sig,
$seq1,
$seq2,
$timestamp,
$major_version,
$minor_version,
$type,
$offset_to_root_key,
$total_hbin_length,
$embedded_filename,
$reorg_timestamp,
) = unpack('a4VVa8VVVx4VVx4a64x56a8', $regf_header);
# Updated 20200219
#----------------------------------------------------------------------------
$bytes_read = sysread($fh, my $re_org, 8, 168);
if ($bytes_read != 8) {
warnf('Could not read re_org timestamp');
return;
}
#----------------------------------------------------------------------------
$offset_to_root_key += OFFSET_TO_FIRST_HBIN;
if ($regf_sig ne 'regf') {
warnf('Invalid registry file signature');
return;
}
$embedded_filename = unpack('Z*', decode('UCS-2LE', $embedded_filename));
# The header checksum is the xor of the first 127 dwords.
# The checksum is stored in the 128th dword, at offset 0x1fc (508).
my $checksum = 0;
foreach my $x (unpack('V127', $regf_header)) {
$checksum ^= $x;
}
my $embedded_checksum = unpack('x508V', $regf_header);
if ($checksum != $embedded_checksum) {
warnf('Invalid checksum for registry file header');
}
my $self = {};
$self->{_filehandle} = $fh;
$self->{_filename} = $filename;
$self->{_length} = (stat $fh)[7];
$self->{_offset_to_root_key} = $offset_to_root_key;
$self->{_timestamp} = unpack_windows_time($timestamp);
#----------------------------------------------------------------------------
$self->{_reorg_timestamp} = unpack_windows_time($reorg_timestamp);
#----------------------------------------------------------------------------
$self->{_embedded_filename} = $embedded_filename;
$self->{_seq1} = $seq1;
$self->{_seq2} = $seq2;
$self->{_version} = "$major_version.$minor_version";
$self->{_type} = $type;
$self->{_total_hbin_length} = $total_hbin_length;
$self->{_embedded_checksum} = $embedded_checksum;
$self->{_security_cache} = {}; # comment out to disable cache
bless $self, $class;
return $self;
}
sub get_root_key {
my $self = shift;
my $offset_to_root_key = $self->{_offset_to_root_key};
my $root_key = Parse::Win32Registry::WinNT::Key->new($self,
$offset_to_root_key);
return $root_key;
}
sub get_virtual_root_key {
my $self = shift;
my $fake_root = shift;
my $root_key = $self->get_root_key;
return if !defined $root_key;
if (!defined $fake_root) {
# guess virtual root from filename
my $filename = basename $self->{_filename};
if ($filename =~ /NTUSER/i) {
$fake_root = 'HKEY_CURRENT_USER';
}
elsif ($filename =~ /USRCLASS/i) {
$fake_root = 'HKEY_CLASSES_ROOT';
}
elsif ($filename =~ /SOFTWARE/i) {
$fake_root = 'HKEY_LOCAL_MACHINE\SOFTWARE';
}
elsif ($filename =~ /SYSTEM/i) {
$fake_root = 'HKEY_LOCAL_MACHINE\SYSTEM';
}
elsif ($filename =~ /SAM/i) {
$fake_root = 'HKEY_LOCAL_MACHINE\SAM';
}
elsif ($filename =~ /SECURITY/i) {
$fake_root = 'HKEY_LOCAL_MACHINE\SECURITY';
}
else {
$fake_root = 'HKEY_UNKNOWN';
}
}
$root_key->{_name} = $fake_root;
$root_key->{_key_path} = $fake_root;
return $root_key;
}
sub get_timestamp {
my $self = shift;
return $self->{_timestamp};
}
sub get_timestamp_as_string {
my $self = shift;
return iso8601($self->{_timestamp});
}
# Added 20200219
#---------------------------------------------------------
sub get_version {
my $self = shift;
return $self->{_version};
}
sub get_reorg_timestamp {
my $self = shift;
return $self->{_reorg_timestamp};
}
sub get_seq1 {
my $self = shift;
return $self->{_seq1};
}
sub get_seq2 {
my $self = shift;
return $self->{_seq2};
}
sub is_dirty {
my $self = shift;
if ($self->{_seq1} == $self->{_seq2}) {
return 0;
}
else {
return 1;
}
}
sub get_type {
my $self = shift;
if ($self->{_type} == 0) {
return "Registry file";
}
elsif ($self->{_type} == 1) {
return "Log file";
}
else {
return "Unknown (".$self->{_type}.")";
}
}
#---------------------------------------------------------
sub get_embedded_filename {
my $self = shift;
return $self->{_embedded_filename};
}
sub get_block_iterator {
my $self = shift;
my $offset_to_next_hbin = OFFSET_TO_FIRST_HBIN;
my $end_of_file = $self->{_length};
return Parse::Win32Registry::Iterator->new(sub {
if ($offset_to_next_hbin > $end_of_file) {
return; # no more hbins
}
if (my $hbin = Parse::Win32Registry::WinNT::Hbin->new($self,
$offset_to_next_hbin))
{
return unless $hbin->get_length > 0;
$offset_to_next_hbin += $hbin->get_length;
return $hbin;
}
else {
return; # no more hbins
}
});
}
*get_hbin_iterator = \&get_block_iterator;
sub _dump_security_cache {
my $self = shift;
if (defined(my $cache = $self->{_security_cache})) {
foreach my $offset (sort { $a <=> $b } keys %$cache) {
my $security = $cache->{$offset};
printf '0x%x %s\n', $offset, $security->as_string;
}
}
}
package Parse::Win32Registry::WinNT::Hbin;
use strict;
use warnings;
use base qw(Parse::Win32Registry::Entry);
use Carp;
use Parse::Win32Registry::Base qw(:all);
use Parse::Win32Registry::WinNT::Entry;
use constant HBIN_HEADER_LENGTH => 0x20;
sub new {
my $class = shift;
my $regfile = shift;
my $offset = shift;
croak 'Missing registry file' if !defined $regfile;
croak 'Missing offset' if !defined $offset;
my $fh = $regfile->get_filehandle;
# 0x00 dword = 'hbin' signature
# 0x04 dword = offset from first hbin to this hbin
# 0x08 dword = length of this hbin / relative offset to next hbin
# 0x14 qword = timestamp (first hbin only)
# Extracted offsets are always relative to first hbin
sysseek($fh, $offset, 0);
my $bytes_read = sysread($fh, my $hbin_header, HBIN_HEADER_LENGTH);
if ($bytes_read != HBIN_HEADER_LENGTH) {
return;
}
my ($sig,
$offset_to_hbin,
$length,
$timestamp) = unpack('a4VVx8a8x4', $hbin_header);
if ($sig ne 'hbin') {
return;
}
my $self = {};
$self->{_regfile} = $regfile;
$self->{_offset} = $offset;
$self->{_length} = $length;
$self->{_header_length} = HBIN_HEADER_LENGTH;
$self->{_allocated} = 1;
$self->{_tag} = $sig;
$self->{_timestamp} = unpack_windows_time($timestamp);
bless $self, $class;
return $self;
}
sub get_timestamp {
my $self = shift;
return $self->{_timestamp};
}
sub get_timestamp_as_string {
my $self = shift;
return iso8601($self->{_timestamp});
}
sub get_entry_iterator {
my $self = shift;
my $regfile = $self->{_regfile};
my $offset = $self->{_offset};
my $length = $self->{_length};
my $offset_to_next_entry = $offset + HBIN_HEADER_LENGTH;
my $end_of_hbin = $offset + $length;
return Parse::Win32Registry::Iterator->new(sub {
if ($offset_to_next_entry >= $end_of_hbin) {
return; # no more entries
}
if (my $entry = Parse::Win32Registry::WinNT::Entry->new($regfile,
$offset_to_next_entry))
{
return unless $entry->get_length > 0;
$offset_to_next_entry += $entry->get_length;
return $entry;
}
else {
return; # no more entries
}
});
}
1;

464
thirdparty/rr-full/Key.pm vendored Normal file
View File

@ -0,0 +1,464 @@
package Parse::Win32Registry::WinNT::Key;
use strict;
use warnings;
use base qw(Parse::Win32Registry::Key);
use Carp;
use Encode;
use Parse::Win32Registry::Base qw(:all);
use Parse::Win32Registry::WinNT::Value;
use Parse::Win32Registry::WinNT::Security;
use constant NK_HEADER_LENGTH => 0x50;
use constant OFFSET_TO_FIRST_HBIN => 0x1000;
sub new {
my $class = shift;
my $regfile = shift;
my $offset = shift; # offset to nk record relative to start of file
my $parent_key_path = shift; # parent key path (optional)
croak 'Missing registry file' if !defined $regfile;
croak 'Missing offset' if !defined $offset;
my $fh = $regfile->get_filehandle;
# 0x00 dword = key length (negative = allocated)
# 0x04 word = 'nk' signature
# 0x06 word = flags
# 0x08 qword = timestamp
# 0x10
# 0x14 dword = offset to parent
# 0x18 dword = number of subkeys
# 0x1c
# 0x20 dword = offset to subkey list (lf, lh, ri, li)
# 0x24
# 0x28 dword = number of values
# 0x2c dword = offset to value list
# 0x30 dword = offset to security
# 0x34 dword = offset to class name
# 0x38 dword = max subkey name length
# 0x3c dword = max class name length
# 0x40 dword = max value name length
# 0x44 dword = max value data length
# 0x48
# 0x4c word = key name length
# 0x4e word = class name length
# 0x50 = key name [for key name length bytes]
# Extracted offsets are always relative to first hbin
sysseek($fh, $offset, 0);
my $bytes_read = sysread($fh, my $nk_header, NK_HEADER_LENGTH);
if ($bytes_read != NK_HEADER_LENGTH) {
warnf('Could not read key at 0x%x', $offset);
return;
}
my ($length,
$sig,
$flags,
$timestamp,
# added 20190127
$access_bits,
$offset_to_parent,
$num_subkeys,
$offset_to_subkey_list,
$num_values,
$offset_to_value_list,
$offset_to_security,
$offset_to_class_name,
$largest_subkey_name_length,
$name_length,
$class_name_length,
# added 20190127
) = unpack('Va2va8VVVx4Vx4VVVVVx16vv', $nk_header);
# ) = unpack('Va2va8x4VVx4Vx4VVVVx20vv', $nk_header);
$offset_to_parent += OFFSET_TO_FIRST_HBIN
if $offset_to_parent != 0xffffffff;
$offset_to_subkey_list += OFFSET_TO_FIRST_HBIN
if $offset_to_subkey_list != 0xffffffff;
$offset_to_value_list += OFFSET_TO_FIRST_HBIN
if $offset_to_value_list != 0xffffffff;
$offset_to_security += OFFSET_TO_FIRST_HBIN
if $offset_to_security != 0xffffffff;
$offset_to_class_name += OFFSET_TO_FIRST_HBIN
if $offset_to_class_name != 0xffffffff;
my $allocated = 0;
if ($length > 0x7fffffff) {
$allocated = 1;
$length = (0xffffffff - $length) + 1;
}
# allocated should be true
if ($length < NK_HEADER_LENGTH) {
warnf('Invalid value entry length at 0x%x', $offset);
return;
}
if ($sig ne 'nk') {
warnf('Invalid signature for key at 0x%x', $offset);
return;
}
$bytes_read = sysread($fh, my $name, $name_length);
if ($bytes_read != $name_length) {
warnf('Could not read name for key at 0x%x', $offset);
return;
}
if ($flags & 0x20) {
$name = decode($Parse::Win32Registry::Base::CODEPAGE, $name);
}
else {
$name = decode('UCS-2LE', $name);
}
my $key_path = (defined $parent_key_path)
? "$parent_key_path\\$name"
: "$name";
my $class_name;
if ($offset_to_class_name != 0xffffffff) {
sysseek($fh, $offset_to_class_name + 4, 0);
$bytes_read = sysread($fh, $class_name, $class_name_length);
if ($bytes_read != $class_name_length) {
warnf('Could not read class name at 0x%x', $offset_to_class_name);
$class_name = undef;
}
else {
$class_name = decode('UCS-2LE', $class_name);
}
}
my $self = {};
$self->{_regfile} = $regfile;
$self->{_offset} = $offset;
$self->{_length} = $length;
$self->{_allocated} = $allocated;
$self->{_tag} = $sig;
$self->{_name} = $name;
$self->{_name_length} = $name_length;
$self->{_key_path} = $key_path;
$self->{_flags} = $flags;
$self->{_offset_to_parent} = $offset_to_parent;
$self->{_num_subkeys} = $num_subkeys;
$self->{_offset_to_subkey_list} = $offset_to_subkey_list;
$self->{_num_values} = $num_values;
$self->{_offset_to_value_list} = $offset_to_value_list;
$self->{_timestamp} = unpack_windows_time($timestamp);
# added 20190127
$self->{_access_bits} = $access_bits;
$self->{_largest_subkey_name_length} = $largest_subkey_name_length;
$self->{_offset_to_security} = $offset_to_security;
$self->{_offset_to_class_name} = $offset_to_class_name;
$self->{_class_name_length} = $class_name_length;
$self->{_class_name} = $class_name;
bless $self, $class;
return $self;
}
sub get_timestamp {
my $self = shift;
return $self->{_timestamp};
}
sub get_timestamp_as_string {
my $self = shift;
return iso8601($self->get_timestamp);
}
# added 20190127
sub get_access_bits {
my $self = shift;
return $self->{_access_bits};
}
sub get_largest_subkey_name_length {
my $self = shift;
return $self->{_largest_subkey_name_length};
}
sub get_class_name {
my $self = shift;
return $self->{_class_name};
}
sub is_root {
my $self = shift;
my $flags = $self->{_flags};
return $flags & 4 || $flags & 8;
}
sub get_parent {
my $self = shift;
my $regfile = $self->{_regfile};
my $offset_to_parent = $self->{_offset_to_parent};
my $key_path = $self->{_key_path};
return if $self->is_root;
my $grandparent_key_path;
my @keys = split /\\/, $key_path, -1;
if (@keys > 2) {
$grandparent_key_path = join('\\', @keys[0..$#keys-2]);
}
return Parse::Win32Registry::WinNT::Key->new($regfile,
$offset_to_parent,
$grandparent_key_path);
}
sub get_security {
my $self = shift;
my $regfile = $self->{_regfile};
my $offset_to_security = $self->{_offset_to_security};
my $key_path = $self->{_key_path};
if ($offset_to_security == 0xffffffff) {
return;
}
return Parse::Win32Registry::WinNT::Security->new($regfile,
$offset_to_security,
$key_path);
}
sub as_string {
my $self = shift;
my $string = $self->get_path . ' [' . $self->get_timestamp_as_string . ']';
return $string;
}
sub parse_info {
my $self = shift;
my $info = sprintf '0x%x nk len=0x%x alloc=%d "%s" par=0x%x keys=%d,0x%x vals=%d,0x%x sec=0x%x class=0x%x',
$self->{_offset},
$self->{_length},
$self->{_allocated},
$self->{_name},
$self->{_offset_to_parent},
$self->{_num_subkeys}, $self->{_offset_to_subkey_list},
$self->{_num_values}, $self->{_offset_to_value_list},
$self->{_offset_to_security},
$self->{_offset_to_class_name};
if (defined $self->{_class_name}) {
$info .= sprintf ',len=0x%x', $self->{_class_name_length};
}
return $info;
}
sub _get_offsets_to_subkeys {
my $self = shift;
# Offset is passed as a parameter for recursive lists such as 'ri'
my $offset_to_subkey_list = shift || $self->{_offset_to_subkey_list};
my $regfile = $self->{_regfile};
my $fh = $regfile->get_filehandle;
return if $offset_to_subkey_list == 0xffffffff
|| $self->{_num_subkeys} == 0;
sysseek($fh, $offset_to_subkey_list, 0);
my $bytes_read = sysread($fh, my $subkey_list_header, 8);
if ($bytes_read != 8) {
warnf('Could not read subkey list header at 0x%x',
$offset_to_subkey_list);
return;
}
# 0x00 dword = subkey list length (negative = allocated)
# 0x04 word = 'lf' signature
# 0x06 word = number of entries
# 0x08 dword = offset to 1st subkey
# 0x0c dword = first four characters of the key name
# 0x10 dword = offset to 2nd subkey
# 0x14 dword = first four characters of the key name
# ...
# 0x00 dword = subkey list length (negative = allocated)
# 0x04 word = 'lh' signature
# 0x06 word = number of entries
# 0x08 dword = offset to 1st subkey
# 0x0c dword = hash of the key name
# 0x10 dword = offset to 2nd subkey
# 0x14 dword = hash of the key name
# ...
# 0x00 dword = subkey list length (negative = allocated)
# 0x04 word = 'ri' signature
# 0x06 word = number of entries in ri list
# 0x08 dword = offset to 1st lf/lh/li list
# 0x0c dword = offset to 2nd lf/lh/li list
# 0x10 dword = offset to 3rd lf/lh/li list
# ...
# 0x00 dword = subkey list length (negative = allocated)
# 0x04 word = 'li' signature
# 0x06 word = number of entries in li list
# 0x08 dword = offset to 1st subkey
# 0x0c dword = offset to 2nd subkey
# ...
# Extracted offsets are always relative to first hbin
my @offsets_to_subkeys = ();
my ($length,
$sig,
$num_entries,
) = unpack('Va2v', $subkey_list_header);
my $subkey_list_length;
if ($sig eq 'lf' || $sig eq 'lh') {
$subkey_list_length = 2 * 4 * $num_entries;
}
elsif ($sig eq 'ri' || $sig eq 'li') {
$subkey_list_length = 4 * $num_entries;
}
else {
warnf('Invalid signature for subkey list at 0x%x',
$offset_to_subkey_list);
return;
}
$bytes_read = sysread($fh, my $subkey_list, $subkey_list_length);
if ($bytes_read != $subkey_list_length) {
warnf('Could not read subkey list at 0x%x',
$offset_to_subkey_list);
return;
}
if ($sig eq 'lf') {
foreach my $offset (unpack("(Vx4)$num_entries", $subkey_list)) {
push @offsets_to_subkeys, OFFSET_TO_FIRST_HBIN + $offset;
}
}
elsif ($sig eq 'lh') {
foreach my $offset (unpack("(Vx4)$num_entries", $subkey_list)) {
push @offsets_to_subkeys, OFFSET_TO_FIRST_HBIN + $offset;
}
}
elsif ($sig eq 'ri') {
foreach my $offset (unpack("V$num_entries", $subkey_list)) {
my $offsets_ref =
$self->_get_offsets_to_subkeys(OFFSET_TO_FIRST_HBIN + $offset);
if (defined $offsets_ref && ref $offsets_ref eq 'ARRAY') {
push @offsets_to_subkeys, @{ $offsets_ref };
}
}
}
elsif ($sig eq 'li') {
foreach my $offset (unpack("V$num_entries", $subkey_list)) {
push @offsets_to_subkeys, OFFSET_TO_FIRST_HBIN + $offset;
}
}
return \@offsets_to_subkeys;
}
sub get_subkey_iterator {
my $self = shift;
my $regfile = $self->{_regfile};
my $key_path = $self->{_key_path};
my @offsets_to_subkeys = ();
if ($self->{_num_subkeys} > 0) {
my $offsets_to_subkeys_ref = $self->_get_offsets_to_subkeys;
if (defined $offsets_to_subkeys_ref) {
@offsets_to_subkeys = @{$self->_get_offsets_to_subkeys};
}
}
return Parse::Win32Registry::Iterator->new(sub {
while (defined(my $offset_to_subkey = shift @offsets_to_subkeys)) {
my $subkey = Parse::Win32Registry::WinNT::Key->new($regfile,
$offset_to_subkey, $key_path);
if (defined $subkey) {
return $subkey;
}
}
return; # no more offsets to subkeys
});
}
sub _get_offsets_to_values {
my $self = shift;
my $regfile = $self->{_regfile};
my $fh = $regfile->get_filehandle;
my $offset_to_value_list = $self->{_offset_to_value_list};
my $num_values = $self->{_num_values};
return if $num_values == 0;
# Actually, this could probably just fall through
# as unpack("x4V0", ...) would return an empty array.
my @offsets_to_values = ();
# 0x00 dword = value list length (negative = allocated)
# 0x04 dword = 1st offset
# 0x08 dword = 2nd offset
# ...
# Extracted offsets are always relative to first hbin
sysseek($fh, $offset_to_value_list, 0);
my $value_list_length = 0x4 + $num_values * 4;
my $bytes_read = sysread($fh, my $value_list, $value_list_length);
if ($bytes_read != $value_list_length) {
warnf("Could not read value list at 0x%x",
$offset_to_value_list);
return;
}
foreach my $offset (unpack("x4V$num_values", $value_list)) {
push @offsets_to_values, OFFSET_TO_FIRST_HBIN + $offset;
}
return \@offsets_to_values;
}
sub get_value_iterator {
my $self = shift;
my $regfile = $self->{_regfile};
my $key_path = $self->{_key_path};
my @offsets_to_values = ();
if ($self->{_num_values} > 0) {
my $offsets_to_values_ref = $self->_get_offsets_to_values;
if (defined $offsets_to_values_ref) {
@offsets_to_values = @{$self->_get_offsets_to_values};
}
}
return Parse::Win32Registry::Iterator->new(sub {
while (defined(my $offset_to_value = shift @offsets_to_values)) {
my $value = Parse::Win32Registry::WinNT::Value->new($regfile,
$offset_to_value);
if (defined $value) {
return $value;
}
}
return; # no more offsets to values
});
}
1;

51
thirdparty/rr-full/README.md vendored Normal file
View File

@ -0,0 +1,51 @@
RegRipper2.8
============
RegRipper version 2.8
This is the GitHub repository for RegRipper version 2.8
Note: This tool does NOT automatically process hive transaction logs. If you need
to incorporate data from hive transaction logs into your analysis, consider merging
the data via Maxim Suhanov's yarp + registryFlush.py, or via Eric Zimmerman's rla.exe.
Updates 20200220
- Added warning that tool does not automatically process Registry hive transaction logs
- Added check for dirty hives
- Modified C:\Perl\site\lib\Parse\Win32Registry\WinNT\File.pm
- if you're using the Perl version of this tool (Linux, Mac) be sure to copy File.pm
from the repository and replace the appropriate file
Updates 20200104
- Fixed issue with processing of key LastWrite times
- Modified C:\Perl\site\lib\Parse\Win32Registry\WinNT\Base.pm
- if you're using the Perl version of this tool (Linux, Mac) be sure to copy Base.pm
from the repository and replace the appropriate file
Updates 20190128
- added Time::Local module
- this allows plugins to be written that parse string-based date/time stamps, converting
them to epochs (for timelining, etc.)
- modified C:\Perl\site\lib\Parse\Win32Registry\WinNT\Key.pm
- extract access_bits and largest_subkey_name_length values from Key node structure
- call 'get_access_bits()', 'get_largest_subkey_name_length()' to retrieve the values for parsing/display
- IAW https://github.com/msuhanov/regf/blob/master/Windows%20registry%20file%20format%20specification.md
Note: The modifications to Key.pm are 'compiled' into the EXE versions of RegRipper. In order to fully take
advantage of them with the .pl versions:
- got to \Perl\site\lib\Parse\Win32Registry\WinNT\
- rename Key.pm to Key_old.pm
- copy Key.pm from this distro to the folder
Updates 20200104
Based on how key LastWrite times were being converted from FILETIME objects to Unix epoch format, the function
appears to have 'broke' as of 1 Jan 2020. As such, I modified/fixed the code, and have updated the compiled
EXEs for the tools. I've also provided an updated Base.pm file, with instructions below as to how to update
your local copy of the file.
- Navigate to the \site\lib\Parse\Win32Registry\ folder in your Perl installation, and remove any restrictions
or attributes from Base.pm (i.e., 'attrib -r Base.pm')
- Rename Base.pm to Base_old.pm
- Copy the Base.pm from this repository
=======

22
thirdparty/rr-full/license.md vendored Normal file
View File

@ -0,0 +1,22 @@
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This project is licensed under terms of the MIT License -
https://opensource.org/licenses/MIT
See also:
https://en.wikipedia.org/wiki/MIT_License
Questions, comments, etc., can be sent to keydet89 at yahoo dot com.

View File

@ -1,12 +1,22 @@
This software is released AS-IS, with no statements or guarantees as to Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
its effectiveness or stability. While it shouldn't cause any problems associated documentation files (the "Software"), to deal in the Software without restriction, including
whatsoever with your system, there's always the chance that someone may find without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
a way to blame a system crash or loss of data on software like this...you've copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to
been warned! the following conditions:
This software is released under the GNU Public License - The above copyright notice and this permission notice shall be included in all copies or substantial
http://www.gnu.org/copyleft/gpl.html portions of the Software.
Specifically, GPL v2.0: http://www.gnu.org/licenses/gpl-2.0.html THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This project is licensed under terms of the MIT License -
https://opensource.org/licenses/MIT
See also:
https://en.wikipedia.org/wiki/MIT_License
Questions, comments, etc., can be sent to keydet89 at yahoo dot com. Questions, comments, etc., can be sent to keydet89 at yahoo dot com.

View File

@ -1,17 +1,10 @@
# 20161213 *ALL* Plugins that apply on any HIVES, alphabetical order
baseline baseline
del del
del_tln
fileless fileless
findexes findexes
installedcomp
installer
malware malware
null null
regtime regtime
regtime_tln
rlo rlo
sizes sizes
uninstall slack
uninstall_tln
wallpaper

View File

@ -1,2 +1 @@
#20161213 *ALL* Plugins that apply on any amcache, alphabetical order
amcache amcache

View File

@ -2,6 +2,7 @@
# amcache.pl # amcache.pl
# #
# Change history # Change history
# 20180311 - updated to support newer version files, albeit without parsing devices
# 20170315 - added output for Product Name and File Description values # 20170315 - added output for Product Name and File Description values
# 20160818 - added check for value 17 # 20160818 - added check for value 17
# 20131218 - fixed bug computing compile time # 20131218 - fixed bug computing compile time
@ -9,9 +10,10 @@
# 20131204 - created # 20131204 - created
# #
# References # References
# https://binaryforay.blogspot.com/2017/10/amcache-still-rules-everything-around.html
# http://www.swiftforensics.com/2013/12/amcachehve-in-windows-8-goldmine-for.html # http://www.swiftforensics.com/2013/12/amcachehve-in-windows-8-goldmine-for.html
# #
# Copyright (c) 2017 QAR, LLC # Copyright (c) 2018 QAR, LLC
# Author: H. Carvey, keydet89@yahoo.com # Author: H. Carvey, keydet89@yahoo.com
#----------------------------------------------------------- #-----------------------------------------------------------
package amcache; package amcache;
@ -23,7 +25,7 @@ my %config = (hive => "amcache",
hasRefs => 1, hasRefs => 1,
osmask => 22, osmask => 22,
category => "program execution", category => "program execution",
version => 20170315); version => 20180311);
my $VERSION = getVersion(); my $VERSION = getVersion();
# Functions # # Functions #
@ -40,27 +42,119 @@ sub pluginmain {
my $class = shift; my $class = shift;
my $hive = shift; my $hive = shift;
# Initialize #
::logMsg("Launching amcache v.".$VERSION); ::logMsg("Launching amcache v.".$VERSION);
::rptMsg("amcache v.".$VERSION); ::rptMsg("amcache v.".$VERSION);
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); ::rptMsg("(".$config{hive}.") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive); my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key; my $root_key = $reg->get_root_key;
my $key; my $key;
my @sk1;
my @sk;
my (@t,$gt);
my $key_path = 'Root\\File'; # Newer version Amcache.hve files
::rptMsg("***Files***"); # Devices not parsed at this time
my $key_path = 'Root\\InventoryApplicationFile';
if ($key = $root_key->get_subkey($key_path)) { if ($key = $root_key->get_subkey($key_path)) {
parseInventoryApplicationFile($key);
@sk1 = $key->get_list_of_subkeys(); }
else {
::rptMsg($key_path." not found.");
}
::rptMsg("");
my $key_path = 'Root\\InventoryApplication';
if ($key = $root_key->get_subkey($key_path)) {
parseInventoryApplication($key);
}
else {
::rptMsg($key_path." not found.");
}
::rptMsg("");
# Older version AmCache.hve files
# Root\Files subkey
my $key_path = 'Root\\File';
if ($key = $root_key->get_subkey($key_path)) {
parseFile($key);
}
else {
::rptMsg($key_path." not found.");
}
::rptMsg("");
# Root\Programs subkey
$key_path = 'Root\\Programs';
if ($key = $root_key->get_subkey($key_path)) {
parsePrograms($key);
}
else {
::rptMsg($key_path." not found.");
}
}
sub parseInventoryApplicationFile {
my $key = shift;
::rptMsg("***InventoryApplicationFile***");
my @sk = $key->get_list_of_subkeys();
if (scalar(@sk) > 0) {
foreach my $s (@sk) {
my $lw = $s->get_timestamp();
my $path;
eval {
$path = $s->get_value("LowerCaseLongPath")->get_data();
};
my $hash;
eval {
$hash = $s->get_value("FileID")->get_data();
$hash =~ s/^0000//;
};
::rptMsg($path." LastWrite: ".gmtime($lw));
::rptMsg("Hash: ".$hash);
::rptMsg("");
}
}
else {
}
}
sub parseInventoryApplication {
my $key = shift;
my @sk = $key->get_list_of_subkeys();
if (scalar(@sk) > 0) {
foreach my $s (@sk) {
my $lw = $s->get_timestamp();
my $name;
eval {
$name = $s->get_value("Name")->get_data();
};
my $version;
eval {
$version = "v.".$s->get_value("Version")->get_data();
};
::rptMsg(gmtime($lw)." - ".$name." ".$version);
}
}
else {
}
}
sub parseFile {
my $key = shift;
::rptMsg("***Files***");
my (@t,$gt);
my @sk1 = $key->get_list_of_subkeys();
foreach my $s1 (@sk1) { foreach my $s1 (@sk1) {
# Volume GUIDs # Volume GUIDs
::rptMsg($s1->get_name()); ::rptMsg($s1->get_name());
@sk = $s1->get_list_of_subkeys(); my @sk = $s1->get_list_of_subkeys();
if (scalar(@sk) > 0) { if (scalar(@sk) > 0) {
foreach my $s (@sk) { foreach my $s (@sk) {
::rptMsg("File Reference: ".$s->get_name()); ::rptMsg("File Reference: ".$s->get_name());
@ -121,16 +215,14 @@ sub pluginmain {
# ::rptMsg("Key ".$s1->get_name()." has no subkeys."); # ::rptMsg("Key ".$s1->get_name()." has no subkeys.");
} }
} }
}
else { }
::rptMsg($key_path." not found.");
}
# Root\Programs subkey # Root\Programs subkey
$key_path = 'Root\\Programs'; sub parsePrograms {
my $key = shift;
::rptMsg("***Programs***"); ::rptMsg("***Programs***");
if ($key = $root_key->get_subkey($key_path)) { my @sk1 = $key->get_list_of_subkeys();
@sk1 = $key->get_list_of_subkeys();
if (scalar(@sk1) > 0) { if (scalar(@sk1) > 0) {
foreach my $s1 (@sk1) { foreach my $s1 (@sk1) {
my $str; my $str;
@ -151,10 +243,7 @@ sub pluginmain {
::rptMsg(""); ::rptMsg("");
} }
} }
}
else {
::rptMsg($key_path." not found.");
}
} }
1; 1;

View File

@ -2,12 +2,18 @@
# amcache_tln.pl # amcache_tln.pl
# #
# Change history # Change history
# 20170315 - created # 20180311 - updated to support newer version files, albeit without parsing devices
# 20170315 - added output for Product Name and File Description values
# 20160818 - added check for value 17
# 20131218 - fixed bug computing compile time
# 20131213 - updated
# 20131204 - created
# #
# References # References
# https://binaryforay.blogspot.com/2017/10/amcache-still-rules-everything-around.html
# http://www.swiftforensics.com/2013/12/amcachehve-in-windows-8-goldmine-for.html # http://www.swiftforensics.com/2013/12/amcachehve-in-windows-8-goldmine-for.html
# #
# Copyright (c) 2017 QAR, LLC # Copyright (c) 2018 QAR, LLC
# Author: H. Carvey, keydet89@yahoo.com # Author: H. Carvey, keydet89@yahoo.com
#----------------------------------------------------------- #-----------------------------------------------------------
package amcache_tln; package amcache_tln;
@ -19,7 +25,7 @@ my %config = (hive => "amcache",
hasRefs => 1, hasRefs => 1,
osmask => 22, osmask => 22,
category => "program execution", category => "program execution",
version => 20170315); version => 20180311);
my $VERSION = getVersion(); my $VERSION = getVersion();
# Functions # # Functions #
@ -28,7 +34,7 @@ sub getHive {return $config{hive};}
sub getVersion {return $config{version};} sub getVersion {return $config{version};}
sub getDescr {} sub getDescr {}
sub getShortDescr { sub getShortDescr {
return "Parse AmCache\.hve file, TLN format"; return "Parse AmCache\.hve file";
} }
sub getRefs {} sub getRefs {}
@ -36,27 +42,108 @@ sub pluginmain {
my $class = shift; my $class = shift;
my $hive = shift; my $hive = shift;
# Initialize #
::logMsg("Launching amcache_tln v.".$VERSION); ::logMsg("Launching amcache_tln v.".$VERSION);
# ::rptMsg("amcache v.".$VERSION); # ::rptMsg("amcache v.".$VERSION);
# ::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # ::rptMsg("(".$config{hive}.") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive); my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key; my $root_key = $reg->get_root_key;
my $key; my $key;
my @sk1;
my @sk;
my (@t,$gt);
my $key_path = 'Root\\File'; # Newer version Amcache.hve files
# ::rptMsg("***Files***"); # Devices not parsed at this time
my $key_path = 'Root\\InventoryApplicationFile';
if ($key = $root_key->get_subkey($key_path)) { if ($key = $root_key->get_subkey($key_path)) {
parseInventoryApplicationFile($key);
@sk1 = $key->get_list_of_subkeys(); }
else {
# ::rptMsg($key_path." not found.");
}
# ::rptMsg("");
# my $key_path = 'Root\\InventoryApplication';
# if ($key = $root_key->get_subkey($key_path)) {
# parseInventoryApplication($key);
#
# }
# else {
# ::rptMsg($key_path." not found.");
# }
# ::rptMsg("");
# Older version AmCache.hve files
# Root\Files subkey
my $key_path = 'Root\\File';
if ($key = $root_key->get_subkey($key_path)) {
parseFile($key);
}
else {
# ::rptMsg($key_path." not found.");
}
# ::rptMsg("");
}
sub parseInventoryApplicationFile {
my $key = shift;
# ::rptMsg("***InventoryApplicationFile***");
my @sk = $key->get_list_of_subkeys();
if (scalar(@sk) > 0) {
foreach my $s (@sk) {
my $lw = $s->get_timestamp();
my $path;
eval {
$path = $s->get_value("LowerCaseLongPath")->get_data();
};
my $hash;
eval {
$hash = $s->get_value("FileID")->get_data();
$hash =~ s/^0000//;
};
::rptMsg($lw."|AmCache|||Key LastWrite - ".$path." (".$hash.")");
}
}
else {
}
}
sub parseInventoryApplication {
my $key = shift;
my @sk = $key->get_list_of_subkeys();
if (scalar(@sk) > 0) {
foreach my $s (@sk) {
my $lw = $s->get_timestamp();
my $name;
eval {
$name = $s->get_value("Name")->get_data();
};
my $version;
eval {
$version = "v.".$s->get_value("Version")->get_data();
};
::rptMsg(gmtime($lw)." - ".$name." ".$version);
}
}
else {
}
}
sub parseFile {
my $key = shift;
# ::rptMsg("***Files***");
my (@t,$gt);
my @sk1 = $key->get_list_of_subkeys();
foreach my $s1 (@sk1) { foreach my $s1 (@sk1) {
# Volume GUIDs # Volume GUIDs
::rptMsg($s1->get_name()); ::rptMsg($s1->get_name());
my @sk = $s1->get_list_of_subkeys();
@sk = $s1->get_list_of_subkeys();
if (scalar(@sk) > 0) { if (scalar(@sk) > 0) {
foreach my $s (@sk) { foreach my $s (@sk) {
my $fileref = $s->get_name(); my $fileref = $s->get_name();
@ -66,7 +153,6 @@ sub pluginmain {
eval { eval {
$fileref = $fileref.":".$s->get_value("15")->get_data(); $fileref = $fileref.":".$s->get_value("15")->get_data();
}; };
::rptMsg($lw."|AmCache|||Key LastWrite - ".$fileref); ::rptMsg($lw."|AmCache|||Key LastWrite - ".$fileref);
# get last mod./creation times # get last mod./creation times
@ -108,8 +194,39 @@ sub pluginmain {
} }
} }
else {
# ::rptMsg("Key ".$s1->get_name()." has no subkeys.");
}
}
}
# Root\Programs subkey
sub parsePrograms {
my $key = shift;
# ::rptMsg("***Programs***");
my @sk1 = $key->get_list_of_subkeys();
if (scalar(@sk1) > 0) {
foreach my $s1 (@sk1) {
my $str;
$str = "Name : ".$s1->get_value("0")->get_data();
eval {
$str .= " v\.".$s1->get_value("1")->get_data();
};
::rptMsg($str);
eval {
::rptMsg("Category : ".$s1->get_value("6")->get_data());
};
eval {
::rptMsg("UnInstall : ".$s1->get_value("7")->get_data());
};
# ::rptMsg("");
} }
} }
} }
1; 1;

67
thirdparty/rr-full/plugins/angelfire.pl vendored Normal file
View File

@ -0,0 +1,67 @@
#-----------------------------------------------------------
# angelfire.pl
#
# History:
# 20170831 - created
#
# References:
# https://wikileaks.org/vault7/document/Angelfire-2_0-UserGuide/Angelfire-2_0-UserGuide.pdf
#
#
# copyright 2017 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package angelfire;
use strict;
my %config = (hive => "System",
hivemask => 4,
output => "report",
category => "malware",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 31, #XP - Win7
version => 20170831);
sub getConfig{return %config}
sub getShortDescr {
return "Detects AngelFire";
}
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 angelfire v.".$VERSION);
::rptMsg("angelfire v.".$VERSION); # banner
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
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 $af_path = $ccs."\\Control\\Windows\\SystemLookup";
my $af;
if ($af = $root_key->get_subkey($af_path)) {
::rptMsg("AngelFire found.");
::rptMsg("Path: ".$af_path);
}
else {
::rptMsg("AngelFire not found.");
}
}
}
1;

62
thirdparty/rr-full/plugins/appassoc.pl vendored Normal file
View File

@ -0,0 +1,62 @@
#-----------------------------------------------------------
# appassoc.pl
#
# Change history
# 20190513 - created
#
# References
# https://twitter.com/EricRZimmerman/status/916422135987474433
#
# copyright 2017 H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package appassoc;
use strict;
my %config = (hive => "NTUSER\.DAT",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20190513);
sub getConfig{return %config}
sub getShortDescr {
return "Gets contents of user's ApplicationAssociationToasts 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 appassoc v.".$VERSION);
::rptMsg("appassoc v.".$VERSION); # banner
::rptMsg("- ".getShortDescr()."\n"); # banner
my $reg = Parse::Win32Registry->new($ntuser);
my $root_key = $reg->get_root_key;
my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\ApplicationAssociationToasts';
my $key;
if ($key = $root_key->get_subkey($key_path)) {
my @vals = $key->get_list_of_values();
if (scalar(@vals) > 0) {
::rptMsg("LastWrite: ".gmtime($key->get_timestamp()));
::rptMsg("");
foreach my $v (@vals) {
::rptMsg($v->get_name());
}
}
else {
::rptMsg($key_path." has no values.");
}
}
else {
::rptMsg($key_path." not found.");
}
}
1;

View File

@ -2,6 +2,8 @@
# appcompatcache.pl # appcompatcache.pl
# #
# History: # History:
# 20190112 - updated parsing for Win8.1
# 20180311 - updated for more recent version of Win10/Win2016
# 20160528 - updated code to not de-dup entries based on filename # 20160528 - updated code to not de-dup entries based on filename
# 20160217 - updated to correctly support Win10 # 20160217 - updated to correctly support Win10
# 20150611 - mod'd for Kevin Pagano # 20150611 - mod'd for Kevin Pagano
@ -42,7 +44,7 @@ my %config = (hive => "System",
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
osmask => 31, #XP - Win7 osmask => 31, #XP - Win7
version => 20160528); version => 20190112);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
@ -120,12 +122,18 @@ sub pluginmain {
# probe($app_data); # probe($app_data);
} }
elsif ($sig == 0x30) { elsif ($sig == 0x0) {
# possible win 8.1 system
appWin81($app_data);
# print $app_data;
}
elsif ($sig == 0x30 || $sig == 0x34) {
# Windows 10 system # Windows 10 system
appWin10($app_data); appWin10($app_data);
} }
else { else {
::rptMsg(sprintf "Unknown signature: 0x%x",$sig); ::rptMsg(sprintf "Unknown signature: 0x%x",$sig);
# probe($app_data);
} }
# this is where we print out the files # this is where we print out the files
foreach my $f (keys %files) { foreach my $f (keys %files) {
@ -328,6 +336,38 @@ sub appWin8 {
} }
} }
#-----------------------------------------------------------
# appWin81()
#
#-----------------------------------------------------------
sub appWin81 {
my $data = shift;
my $len = length($data);
my ($tag, $sz, $t0, $t1, $name, $name_len);
my $ct = 0;
# my $ofs = unpack("V",substr($data,0,4));
my $ofs = 0x80;
while ($ofs < $len) {
$tag = substr($data,$ofs,4);
last unless (defined $tag);
if ($tag eq "10ts") {
$sz = unpack("V",substr($data,$ofs + 0x08,4));
$name_len = unpack("v",substr($data,$ofs + 0x0c,2));
my $name = substr($data,$ofs + 0x0e,$name_len);
$name =~ s/\00//g;
# ($t0,$t1) = unpack("VV",substr($data,$ofs + 0x03 + $name_len,8));
($t0,$t1) = unpack("VV",substr($data,$ofs + 0x0e + $name_len + 0x0a,8));
$files{$ct}{filename} = $name;
$files{$ct}{modtime} = ::getTime($t0,$t1);
$ct++;
$ofs += ($sz + 0x0c);
}
}
}
#----------------------------------------------------------- #-----------------------------------------------------------
# appWin10() # appWin10()
# Ref: http://binaryforay.blogspot.com/2015/04/appcompatcache-changes-in-windows-10.html # Ref: http://binaryforay.blogspot.com/2015/04/appcompatcache-changes-in-windows-10.html
@ -337,11 +377,11 @@ sub appWin10 {
my $len = length($data); my $len = length($data);
my ($tag, $sz, $t0, $t1, $name, $name_len); my ($tag, $sz, $t0, $t1, $name, $name_len);
my $ct = 0; my $ct = 0;
my $ofs = 0x30; my $ofs = unpack("V",substr($data,0,4));
# my $ofs = 0x30;
while ($ofs < $len) { while ($ofs < $len) {
$tag = substr($data,$ofs,4); $tag = substr($data,$ofs,4);
last unless (defined $tag);
if ($tag eq "10ts") { if ($tag eq "10ts") {
$sz = unpack("V",substr($data,$ofs + 0x08,4)); $sz = unpack("V",substr($data,$ofs + 0x08,4));

View File

@ -2,6 +2,8 @@
# appcompatcache_tln.pl # appcompatcache_tln.pl
# #
# History: # History:
# 20190112 - updated parsing for Win8.1
# 20180311 - updated for more recent version of Win10/Win2016
# 20160528 - updated code to not de-dup entries based on filename # 20160528 - updated code to not de-dup entries based on filename
# 20160217 - updated to correctly support Win10 # 20160217 - updated to correctly support Win10
# 20150611 - mod'd for Kevin Pagano # 20150611 - mod'd for Kevin Pagano
@ -42,7 +44,7 @@ my %config = (hive => "System",
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
osmask => 31, #XP - Win7 osmask => 31, #XP - Win7
version => 20160528); version => 20190112);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
@ -120,7 +122,10 @@ sub pluginmain {
# probe($app_data); # probe($app_data);
} }
elsif ($sig == 0x30) { elsif ($sig == 0x0) {
appWin81($app_data);
}
elsif ($sig == 0x30 || $sig == 0x34) {
# Windows 10 system # Windows 10 system
appWin10($app_data); appWin10($app_data);
} }
@ -323,6 +328,39 @@ sub appWin8 {
} }
} }
#-----------------------------------------------------------
# appWin81()
#
#-----------------------------------------------------------
sub appWin81 {
my $data = shift;
my $len = length($data);
my ($tag, $sz, $t0, $t1, $name, $name_len);
my $ct = 0;
# my $ofs = unpack("V",substr($data,0,4));
my $ofs = 0x80;
while ($ofs < $len) {
$tag = substr($data,$ofs,4);
last unless (defined $tag);
if ($tag eq "10ts") {
$sz = unpack("V",substr($data,$ofs + 0x08,4));
$name_len = unpack("v",substr($data,$ofs + 0x0c,2));
my $name = substr($data,$ofs + 0x0e,$name_len);
$name =~ s/\00//g;
# ($t0,$t1) = unpack("VV",substr($data,$ofs + 0x03 + $name_len,8));
($t0,$t1) = unpack("VV",substr($data,$ofs + 0x0e + $name_len + 0x0a,8));
$files{$ct}{filename} = $name;
$files{$ct}{modtime} = ::getTime($t0,$t1);
$ct++;
$ofs += ($sz + 0x0c);
}
}
}
#----------------------------------------------------------- #-----------------------------------------------------------
# appWin10() # appWin10()
# Ref: http://binaryforay.blogspot.com/2015/04/appcompatcache-changes-in-windows-10.html # Ref: http://binaryforay.blogspot.com/2015/04/appcompatcache-changes-in-windows-10.html
@ -332,11 +370,11 @@ sub appWin10 {
my $len = length($data); my $len = length($data);
my ($tag, $sz, $t0, $t1, $name, $name_len); my ($tag, $sz, $t0, $t1, $name, $name_len);
my $ct = 0; my $ct = 0;
my $ofs = 0x30; my $ofs = unpack("V",substr($data,0,4));
# my $ofs = 0x30;
while ($ofs < $len) { while ($ofs < $len) {
$tag = substr($data,$ofs,4); $tag = substr($data,$ofs,4);
last unless (defined $tag);
if ($tag eq "10ts") { if ($tag eq "10ts") {
$sz = unpack("V",substr($data,$ofs + 0x08,4)); $sz = unpack("V",substr($data,$ofs + 0x08,4));

79
thirdparty/rr-full/plugins/appkeys.pl vendored Normal file
View File

@ -0,0 +1,79 @@
#-----------------------------------------------------------
# appkeys.pl
#
#
# Change history
# 20180920 - created
#
# References
# http://www.hexacorn.com/blog/2018/07/06/beyond-good-ol-run-key-part-80/
# http://blog.airbuscybersecurity.com/post/2015/06/Latest-improvements-in-PlugX
# https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-appcommand
#
# Copyright (c) 2018 QAR, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package appkeys;
use strict;
my %config = (hive => "NTUSER\.DAT, Software",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
category => "persistence",
version => 20180920);
my $VERSION = getVersion();
sub getConfig {return %config}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
sub getDescr {}
sub getShortDescr {
return "Extracts AppKeys entries.";
}
sub getRefs {}
sub pluginmain {
my $class = shift;
my $hive = shift;
::logMsg("Launching appkeys v.".$VERSION);
::rptMsg("appkeys v.".$VERSION);
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key;
my @paths = ("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AppKey",
"Microsoft\\Windows\\CurrentVersion\\Explorer\\AppKey");
foreach my $key_path (@paths) {
if ($key = $root_key->get_subkey($key_path)) {
::rptMsg($key_path);
my $lw = $key->get_timestamp();
my @sk = $key->get_list_of_subkeys();
if (scalar @sk > 0) {
foreach my $s (@sk) {
::rptMsg("Subkey Name: ".$s->get_name()." LastWrite: ".gmtime($s->get_timestamp()));
eval {
my $shell = $s->get_value("ShellExecute")->get_data();
::rptMsg(" ShellExecute value: ".$shell);
};
eval {
my $assoc = $s->get_value("Association")->get_data();
::rptMsg(" Association value: ".$assoc);
};
}
}
else {
::rptMsg($key_path." has no subkeys.");
}
}
}
}
1;

View File

@ -0,0 +1,78 @@
#-----------------------------------------------------------
# appkeys_tln.pl
#
# Change history
# 20180920 - created
#
# References
# http://www.hexacorn.com/blog/2018/07/06/beyond-good-ol-run-key-part-80/
# http://blog.airbuscybersecurity.com/post/2015/06/Latest-improvements-in-PlugX
# https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-appcommand
#
# Copyright (c) 2018 QAR, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package appkeys_tln;
use strict;
my %config = (hive => "NTUSER\.DAT, Software",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
category => "persistence",
version => 20180920);
my $VERSION = getVersion();
sub getConfig {return %config}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
sub getDescr {}
sub getShortDescr {
return "Extracts AppKeys entries.";
}
sub getRefs {}
sub pluginmain {
my $class = shift;
my $hive = shift;
# ::logMsg("Launching appkeys v.".$VERSION);
# ::rptMsg("appkeys v.".$VERSION);
# ::rptMsg("(".$config{hive}.") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key;
my @paths = ("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AppKey",
"Microsoft\\Windows\\CurrentVersion\\Explorer\\AppKey");
foreach my $key_path (@paths) {
if ($key = $root_key->get_subkey($key_path)) {
# ::rptMsg($key_path);
my $lw = $key->get_timestamp();
my @sk = $key->get_list_of_subkeys();
if (scalar @sk > 0) {
foreach my $s (@sk) {
my $name = $s->get_name();
my $sk_lw = $s->get_timestamp();
eval {
my $shell = $s->get_value("ShellExecute")->get_data();
::rptMsg($sk_lw."|AppKeys|||AppKey\\".$name." LastWrite - ShellExecute Value: ".$shell);
};
eval {
my $assoc = $s->get_value("Association")->get_data();
::rptMsg($sk_lw."|AppKeys|||AppKey\\".$name." LastWrite - Association Value: ".$assoc);
};
}
}
else {
# ::rptMsg($key_path." has no subkeys.");
}
}
}
}
1;

View File

@ -3,17 +3,22 @@
# Plugin to extract file association data from the Software hive file # Plugin to extract file association data from the Software hive file
# Can take considerable time to run; recommend running it via rip.exe # Can take considerable time to run; recommend running it via rip.exe
# #
# History
# 20180117 - updated, based on input from Jean, jean.crush@hotmail.fr
# 20080815 - created
#
#
# copyright 2008 H. Carvey, keydet89@yahoo.com # copyright 2008 H. Carvey, keydet89@yahoo.com
#----------------------------------------------------------- #-----------------------------------------------------------
package assoc; package assoc;
use strict; use strict;
my %config = (hive => "Software", my %config = (hive => "Software,USRCLASS",
osmask => 22, osmask => 22,
hasShortDescr => 1, hasShortDescr => 1,
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
version => 20080815); version => 20180117);
sub getConfig{return %config} sub getConfig{return %config}
@ -36,8 +41,9 @@ sub pluginmain {
my $reg = Parse::Win32Registry->new($hive); my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key; my $root_key = $reg->get_root_key;
my $key_path = "Classes"; my @paths = ("Classes","Classes\\Wow6432Node","Wow6432Node");
my $key; my $key;
foreach my $key_path (@paths) {
if ($key = $root_key->get_subkey($key_path)) { if ($key = $root_key->get_subkey($key_path)) {
::rptMsg("assoc"); ::rptMsg("assoc");
::rptMsg($key_path); ::rptMsg($key_path);
@ -80,10 +86,6 @@ sub pluginmain {
::rptMsg($key_path." has no subkeys."); ::rptMsg($key_path." has no subkeys.");
} }
} }
else {
::rptMsg($key_path." not found.");
::logMsg($key_path." not found.");
} }
} }
1; 1;

View File

@ -4,6 +4,7 @@
# *Works for Win7 and Win10 at the moment # *Works for Win7 and Win10 at the moment
# #
# History # History
# 20190510 - updated; Win2016
# 20151202 - created # 20151202 - created
# #
# Ref: # Ref:
@ -24,7 +25,7 @@ my %config = (hive => "Security",
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
osmask => 22, osmask => 22,
version => 20151202); version => 20190510);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
@ -71,9 +72,15 @@ sub pluginmain {
@policy = processWin10($data) @policy = processWin10($data)
} }
elsif (length($data) == 138 && $id == 0x78) { elsif (length($data) == 138 && $id == 0x78) {
::rptMsg("Possible Win7/Win2008");
@policy = processWin7($data); @policy = processWin7($data);
} }
elsif (length($data) == 0x96 && $id == 0x84) {
::rptMsg("Possible Win10(1607+)/Win2016");
@policy = processWin2016($data);
}
else { else {
::rptMsg(sprintf "Data Length: 0x%x",length($data));
my @d = printData($data); my @d = printData($data);
foreach (0..(scalar(@d) - 1)) { foreach (0..(scalar(@d) - 1)) {
::rptMsg($d[$_]); ::rptMsg($d[$_]);
@ -213,6 +220,71 @@ sub processWin7 {
return @win; return @win;
} }
sub processWin2016 {
my $data = shift;
my @win = ("System:Security State Change;".unpack("v",substr($data,0x0c,2)),
"System:Security System Extension;".unpack("v",substr($data,0x0e,2)),
"System:System Integrity;".unpack("v",substr($data,0x10,2)),
"System:IPsec Driver;".unpack("v",substr($data,0x12,2)),
"System:Other System Events;".unpack("v",substr($data,0x14,2)),
"Logon/Logoff:Logon;".unpack("v",substr($data,0x16,2)),
"Logon/Logoff:Logoff;".unpack("v",substr($data,0x18,2)),
"Logon/Logoff:Account Lockout;".unpack("v",substr($data,0x1a,2)),
"Logon/Logoff:IPsec Main Mode;".unpack("v",substr($data,0x1c,2)),
"Logon/Logoff:Special Logon;".unpack("v",substr($data,0x1e,2)),
"Logon/Logoff:IPsec Quick Mode;".unpack("v",substr($data,0x20,2)),
"Logon/Logoff:IPsec Extended Mode;".unpack("v",substr($data,0x22,2)),
"Logon/Logoff:Other Logon/Logoff Events;".unpack("v",substr($data,0x24,2)),
"Logon/Logoff:Network Policy Server;".unpack("v",substr($data,0x26,2)),
"Logon/Logoff:User/Device Claims;".unpack("v",substr($data,0x28,2)),
"Logon/Logoff:Group Membership;".unpack("v",substr($data,0x2a,2)),
"Object Access:File System;".unpack("v",substr($data,0x2c,2)),
"Object Access:Registry;".unpack("v",substr($data,0x2e,2)),
"Object Access:Kernel Object;".unpack("v",substr($data,0x30,2)),
"Object Access:SAM;".unpack("v",substr($data,0x32,2)),
"Object Access:Other Object Access Events;".unpack("v",substr($data,0x34,2)),
"Object Access:Certification Services;".unpack("v",substr($data,0x36,2)),
"Object Access:Application Generated;".unpack("v",substr($data,0x38,2)),
"Object Access:Handle Manipulation;".unpack("v",substr($data,0x3a,2)),
"Object Access:File Share;".unpack("v",substr($data,0x3c,2)),
"Object Access:Filtering Platform Packet Drop;".unpack("v",substr($data,0x3e,2)),
"Object Access:Filtering Platform Connection;".unpack("v",substr($data,0x40,2)),
"Object Access:Detailed File Share;".unpack("v",substr($data,0x42,2)),
"Object Access:Removable Storage;".unpack("v",substr($data,0x44,2)),
"Object Access:Central Policy Staging;".unpack("v",substr($data,0x46,2)),
"Privilege Use:Sensitive Privilege Use;".unpack("v",substr($data,0x48,2)),
"Privilege Use:Non Sensitive Privilege Use;".unpack("v",substr($data,0x4a,2)),
"Privilege Use:Other Privilege Use Events;".unpack("v",substr($data,0x4c,2)),
"Detailed Tracking:Process Creation;".unpack("v",substr($data,0x4e,2)),
"Detailed Tracking:Process Termination;".unpack("v",substr($data,0x50,2)),
"Detailed Tracking:DPAPI Activity;".unpack("v",substr($data,0x52,2)),
"Detailed Tracking:RPC Events;".unpack("v",substr($data,0x54,2)),
"Detailed Tracking:Plug and Play Events;".unpack("v",substr($data,0x56,2)),
"Detailed Tracking:Token Right Adjusted Events;".unpack("v",substr($data,0x58,2)),
"Policy Change:Audit Policy Change;".unpack("v",substr($data,0x5a,2)),
"Policy Change:Authentication Policy Change;".unpack("v",substr($data,0x5c,2)),
"Policy Change:Authorization Policy Change;".unpack("v",substr($data,0x5e,2)),
"Policy Change:MPSSVC Rule-Level Policy Change;".unpack("v",substr($data,0x60,2)),
"Policy Change:Filtering Platform Policy Change;".unpack("v",substr($data,0x62,2)),
"Policy Change:Other Policy Change Events;".unpack("v",substr($data,0x64,2)),
"Account Management:User Account Management;".unpack("v",substr($data,0x66,2)),
"Account Management:Computer Account Management;".unpack("v",substr($data,0x68,2)),
"Account Management:Security Group Management;".unpack("v",substr($data,0x6a,2)),
"Account Management:Distribution Group Management;".unpack("v",substr($data,0x6c,2)),
"Account Management:Application Group Management;".unpack("v",substr($data,0x6e,2)),
"Account Management:Other Account Management Events;".unpack("v",substr($data,0x70,2)),
"DS Access:Directory Service Access;".unpack("v",substr($data,0x72,2)),
"DS Access:Directory Service Changes;".unpack("v",substr($data,0x74,2)),
"DS Access:Directory Service Replication;".unpack("v",substr($data,0x76,2)),
"DS Access:Detailed Directory Service Replication;".unpack("v",substr($data,0x78,2)),
"Account Logon:Credential Validation;".unpack("v",substr($data,0x7a,2)),
"Account Logon:Kerberos Service Ticket Operations;".unpack("v",substr($data,0x7c,2)),
"Account Logon:Other Account Logon Events;".unpack("v",substr($data,0x73,2)),
"Account Logon:Kerberos Authentication Service;".unpack("v",substr($data,0x80,2)));
# The rest of the data is apparently footer
return @win;
}
#----------------------------------------------------------- #-----------------------------------------------------------
# printData() # printData()
# subroutine used primarily for debugging; takes an arbitrary # subroutine used primarily for debugging; takes an arbitrary

106
thirdparty/rr-full/plugins/bam.pl vendored Normal file
View File

@ -0,0 +1,106 @@
#-----------------------------------------------------------
# bam.pl
#
# History:
# 20180225 - created
#
# References:
# from Phill Moore via Twitter: https://padawan-4n6.hatenablog.com/entry/2018/02/22/131110
# https://twitter.com/aionescu/status/891172221971910661?lang=en
# http://batcmd.com/windows/10/services/bam/
#
#
# copyright 2018 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package bam;
use strict;
my %config = (hive => "System",
hivemask => 4,
output => "report",
category => "Program Execution",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 31, #XP - Win7
version => 20180225);
sub getConfig{return %config}
sub getShortDescr {
return "Parse files from System hive BAM Services";
}
sub getDescr{}
sub getRefs {}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
my $VERSION = getVersion();
my %files;
my $str = "";
sub pluginmain {
my $class = shift;
my $hive = shift;
::logMsg("Launching bam v.".$VERSION);
::rptMsg("bam v.".$VERSION); # banner
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
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 $bam_path = $ccs."\\Services\\bam\\UserSettings";
my $bam;
if ($bam = $root_key->get_subkey($bam_path)) {
my @sk = $bam->get_list_of_subkeys();
if (scalar(@sk) > 0) {
foreach my $s (@sk) {
processKey($s);
}
}
}
else {
::rptMsg($bam_path." not found.");
}
}
else {
::rptMsg($key_path." not found.");
}
}
sub processKey {
my $key = shift;
my ($t,$count);
my @values = $key->get_list_of_values();
foreach (@values) {
$count = 1 if ($_->get_type() == 3);
}
if (scalar(@values) > 0 && $count == 1) {
::rptMsg($key->get_name());
foreach my $v (@values) {
my $name = $v->get_name();
if ($v->get_type() == 3) {
my ($t0,$t1) = unpack("VV",substr($v->get_data(),0,8));
$t = ::getTime($t0,$t1);
::rptMsg(" ".gmtime($t)." - ".$name);
}
}
::rptMsg("");
}
}
1;

99
thirdparty/rr-full/plugins/bam_tln.pl vendored Normal file
View File

@ -0,0 +1,99 @@
#-----------------------------------------------------------
# bam_tln.pl
#
# History:
# 20180225 - created
#
# References:
# from Phill Moore via Twitter: https://padawan-4n6.hatenablog.com/entry/2018/02/22/131110
# https://twitter.com/aionescu/status/891172221971910661?lang=en
# http://batcmd.com/windows/10/services/bam/
#
#
# copyright 2018 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package bam_tln;
use strict;
my %config = (hive => "System",
hivemask => 4,
output => "tln",
category => "Program Execution",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 31, #XP - Win7
version => 20180225);
sub getConfig{return %config}
sub getShortDescr {
return "Parse files from System hive BAM Services";
}
sub getDescr{}
sub getRefs {}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
my $VERSION = getVersion();
my %files;
my $str = "";
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,$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 $bam_path = $ccs."\\Services\\bam\\UserSettings";
my $bam;
if ($bam = $root_key->get_subkey($bam_path)) {
my @sk = $bam->get_list_of_subkeys();
if (scalar(@sk) > 0) {
foreach my $s (@sk) {
processKey($s);
}
}
}
else {
# ::rptMsg($bam_path." not found.");
}
}
else {
# ::rptMsg($key_path." not found.");
}
}
sub processKey {
my $key = shift;
my ($t,$count);
my @values = $key->get_list_of_values();
foreach (@values) {
$count = 1 if ($_->get_type() == 3);
}
if (scalar(@values) > 0 && $count == 1) {
foreach my $v (@values) {
my $name = $v->get_name();
if ($v->get_type() == 3) {
my ($t0,$t1) = unpack("VV",substr($v->get_data(),0,8));
$t = ::getTime($t0,$t1);
::rptMsg($t."|BAM|||".$name." (".$key->get_name().")");
}
}
}
}
1;

View File

@ -5,12 +5,13 @@
# other locations) # other locations)
# #
# Change history # Change history
# 20130115 - created # 20180705 - updated to support Win10, per data provided by Micah Jones
# 20170129 - added support for http://www.hexacorn.com/blog/2017/01/29/beyond-good-ol-run-key-part-59/ # 20170129 - added support for http://www.hexacorn.com/blog/2017/01/29/beyond-good-ol-run-key-part-59/
# 20130115 - created
# #
# Category: # Category:
# #
# copyright 2017 Quantum Analytics Research, LLC # copyright 2018 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com # Author: H. Carvey, keydet89@yahoo.com
#----------------------------------------------------------- #-----------------------------------------------------------
package bthport; package bthport;
@ -21,7 +22,7 @@ my %config = (hive => "System",
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
osmask => 22, osmask => 22,
version => 20170129); version => 20180705);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
@ -67,22 +68,21 @@ sub pluginmain {
# Note: Need to get VID and PID values for translation and mapping # Note: Need to get VID and PID values for translation and mapping
my $devname; my $devname;
eval { eval {
# May need to work on parsing the binary "Name" value data into an actual name... my $n = $s->get_value("Name")->get_data();
my @str1 = split(//,unpack("H*",$s->get_value("Name")->get_data())); ::rptMsg("Name : ".$n);
my @s3;
my $str;
foreach my $i (0..((scalar(@str1)/2) - 1)) {
$s3[$i] = $str1[$i * 2].$str1[($i * 2) + 1];
if (hex($s3[$i]) > 0x1f && hex($s3[$i]) < 0x7f) {
$str .= chr(hex($s3[$i]));
}
else {
$str .= " ";
}
}
::rptMsg("Device Name: ".$str);
}; };
eval {
my ($t0,$t1) = unpack("VV",$s->get_value("LastSeen")->get_data());
::rptMsg("LastSeen : ".gmtime(::getTime($t0,$t1))." Z");
};
eval {
my ($t0,$t1) = unpack("VV",$s->get_value("LastConnected")->get_data());
::rptMsg("LastConnected : ".gmtime(::getTime($t0,$t1))." Z");
};
::rptMsg("");
} }
} }
else { else {
@ -92,7 +92,7 @@ sub pluginmain {
else { else {
::rptMsg($cn_path." not found."); ::rptMsg($cn_path." not found.");
} }
::rptMsg("");
my $rs_path = $ccs."\\services\\BTHPORT\\Parameters\\Radio Support"; my $rs_path = $ccs."\\services\\BTHPORT\\Parameters\\Radio Support";
my $rs; my $rs;
if ($rs = $root_key->get_subkey($rs_path)) { if ($rs = $root_key->get_subkey($rs_path)) {

View File

@ -0,0 +1,90 @@
#-----------------------------------------------------------
# bthport_tln.pl
# Get BlueTooth device information from the Registry; assumes
# MS drivers (other drivers, such as BroadComm, will be found in
# other locations)
#
# Change history
# 20180705 - updated to support Win10, per data provided by Micah Jones
# 20170129 - added support for http://www.hexacorn.com/blog/2017/01/29/beyond-good-ol-run-key-part-59/
# 20130115 - created
#
# Category:
#
# copyright 2018 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package bthport_tln;
use strict;
my %config = (hive => "System",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20180705);
sub getConfig{return %config}
sub getShortDescr {
return "Gets Bluetooth-connected devices from System hive; TLN output";
}
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 bthport_tln v.".$VERSION);
# ::rptMsg("bthport v.".$VERSION); # banner
# ::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
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."\\services\\BTHPORT\\Parameters\\Devices";
my $cn;
if ($cn = $root_key->get_subkey($cn_path)) {
my @sk = $cn->get_list_of_subkeys();
if (scalar(@sk) > 0) {
foreach my $s (@sk) {
my $uniq = $s->get_name();
my $devname;
eval {
$devname = $s->get_value("Name")->get_data();
};
eval {
my ($t0,$t1) = unpack("VV",$s->get_value("LastSeen")->get_data());
::rptMsg(::getTime($t0,$t1)."|REG|||BlueTooth Device ".$devname." (Unique ID: ".$uniq.") LastSeen");
};
eval {
my ($t0,$t1) = unpack("VV",$s->get_value("LastConnected")->get_data());
::rptMsg(::getTime($t0,$t1)."|REG|||BlueTooth Device ".$devname." (Unique ID: ".$uniq.") LastConnected");
};
}
}
else {
# ::rptMsg($cn_path." has no subkeys.");
}
}
else {
# ::rptMsg($cn_path." not found.");
}
}
}
1;

View File

@ -4,13 +4,19 @@
# Can take considerable time to run; recommend running it via rip.exe # Can take considerable time to run; recommend running it via rip.exe
# #
# History # History
# 20180823 - minor code fix
# 20180819 - updated to incorporate check for "TreatAs" value; code rewrite
# 20180319 - fixed minor code issue
# 20180117 - updated based on input from Jean, jean.crush@hotmail.fr
# 20130603 - added alert functionality # 20130603 - added alert functionality
# 20100227 - created # 20100227 - created
# #
# References # References
# http://msdn.microsoft.com/en-us/library/ms724475%28VS.85%29.aspx # http://msdn.microsoft.com/en-us/library/ms724475%28VS.85%29.aspx
# https://docs.microsoft.com/en-us/windows/desktop/com/treatas
# #
# copyright 2010, Quantum Analytics Research, LLC # #copyright 2010, Quantum Analytics Research, LLC
# copyright 2018, Quantum Analytics Research, LLC
#----------------------------------------------------------- #-----------------------------------------------------------
package clsid; package clsid;
use strict; use strict;
@ -20,7 +26,7 @@ my %config = (hive => "Software",
hasShortDescr => 1, hasShortDescr => 1,
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
version => 20130603); version => 20180823);
sub getConfig{return %config} sub getConfig{return %config}
@ -44,7 +50,9 @@ sub pluginmain {
my $reg = Parse::Win32Registry->new($hive); my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key; my $root_key = $reg->get_root_key;
my $key_path = "Classes\\CLSID"; # my $key_path = "Classes\\CLSID";
my @paths = ("Classes\\CLSID","Classes\\Wow6432Node\\CLSID");
foreach my $key_path (@paths) {
my $key; my $key;
if ($key = $root_key->get_subkey($key_path)) { if ($key = $root_key->get_subkey($key_path)) {
::rptMsg($key_path); ::rptMsg($key_path);
@ -57,26 +65,25 @@ sub pluginmain {
foreach my $s (@sk) { foreach my $s (@sk) {
my $name = $s->get_name(); my $name = $s->get_name();
my $n;
eval { eval {
my $n = $s->get_value("")->get_data(); $n = $s->get_value("")->get_data();
$name .= " ".$n unless ($n eq ""); $name .= " ".$n unless ($n eq "");
}; };
eval { ::rptMsg($name);
my $path = $s->get_subkey("InprocServer32")->get_value("")->get_data(); ::rptMsg(" LastWrite: ".gmtime($s->get_timestamp())." Z");
alertCheckPath($path);
alertCheckADS($path);
eval {
my $proc = $s->get_subkey("InprocServer32")->get_value("")->get_data();
::rptMsg(" InprocServer32: ".$proc);
}; };
push(@{$clsid{$s->get_timestamp()}},$name); eval {
} my $treat = $s->get_subkey("TreatAs")->get_value("")->get_data();
::rptMsg(" TreatAs: ".$treat);
foreach my $t (reverse sort {$a <=> $b} keys %clsid) { };
::rptMsg(gmtime($t)." Z"); ::rptMsg("");
foreach my $item (@{$clsid{$t}}) {
::rptMsg(" ".$item);
}
} }
} }
else { else {
@ -86,31 +93,8 @@ sub pluginmain {
else { else {
::rptMsg($key_path." not found."); ::rptMsg($key_path." not found.");
} }
}
#-----------------------------------------------------------
# alertCheckPath()
#-----------------------------------------------------------
sub alertCheckPath {
my $path = shift;
$path = lc($path);
my @alerts = ("recycle","globalroot","temp","system volume information","appdata",
"application data");
foreach my $a (@alerts) {
if (grep(/$a/,$path)) {
::alertMsg("ALERT: clsid: ".$a." found in path: ".$path);
}
} }
} }
#-----------------------------------------------------------
# alertCheckADS()
#-----------------------------------------------------------
sub alertCheckADS {
my $path = shift;
my @list = split(/\\/,$path);
my $last = $list[scalar(@list) - 1];
::alertMsg("ALERT: clsid: Poss. ADS found in path: ".$path) if grep(/:/,$last);
}
1; 1;

94
thirdparty/rr-full/plugins/clsid_tln.pl vendored Normal file
View File

@ -0,0 +1,94 @@
#-----------------------------------------------------------
# clsid_tln.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
# 20180823 - minor code fix
# 20180820 - created
#
# References
# http://msdn.microsoft.com/en-us/library/ms724475%28VS.85%29.aspx
# https://docs.microsoft.com/en-us/windows/desktop/com/treatas
#
# #copyright 2010, Quantum Analytics Research, LLC
# copyright 2018, Quantum Analytics Research, LLC
#-----------------------------------------------------------
package clsid_tln;
use strict;
my %config = (hive => "Software",
osmask => 22,
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
version => 20180823);
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);
# ::rptMsg("clsid v.".$VERSION); # banner
# ::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
# my $key_path = "Classes\\CLSID";
my @paths = ("Classes\\CLSID","Classes\\Wow6432Node\\CLSID");
foreach my $key_path (@paths) {
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 ($descr,$ts,$proc,$treat);
$descr = $s->get_name();
$ts = $s->get_timestamp();
eval {
my $n = $s->get_value("")->get_data();
$descr .= " ".$n unless ($n eq "");
};
eval {
my $proc = $s->get_subkey("InprocServer32")->get_value("")->get_data();
$descr .= " InprocServer32: ".$proc;
};
eval {
my $treat = $s->get_subkey("TreatAs")->get_value("")->get_data();
$descr .= " TreatAs: ".$treat;
};
::rptMsg($ts."|CLSID|||".$descr);
}
}
else {
# ::rptMsg($key_path." has no subkeys.");
}
}
else {
# ::rptMsg($key_path." not found.");
}
}
}
1;

View File

@ -3,10 +3,12 @@
# Checks key for files to autostart from cmd.exe # Checks key for files to autostart from cmd.exe
# #
# Change History # Change History
# 20190223 - added reference
# 20130425 - added alertMsg() functionality # 20130425 - added alertMsg() functionality
# 20130115 - created # 20130115 - created
# #
# References: # References:
# https://unit42.paloaltonetworks.com/new-babyshark-malware-targets-u-s-national-security-think-tanks/
# #
# Category: autostart,malware,programexecution # Category: autostart,malware,programexecution
# #
@ -21,12 +23,12 @@ my %config = (hive => "NTUSER\.DAT",
hasShortDescr => 1, hasShortDescr => 1,
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
version => 20130425); version => 20190223);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
return "Autostart - get Command Processor\\AutoRun value from NTUSER.DAT hive"; return "Autostart - get Command Processor\\AutoRun value from NTUSER\.DAT hive";
} }
sub getDescr{} sub getDescr{}
sub getRefs {} sub getRefs {}

View File

@ -3,6 +3,8 @@
# Plugin for Registry Ripper # Plugin for Registry Ripper
# #
# Change history # Change history
# 20180702 - update to parseGUID function
# 20180627 - updated to address Win10, per input from Geoff Rempel
# 20121005 - updated to address shell item type 0x3A # 20121005 - updated to address shell item type 0x3A
# 20121005 - updated to parse shell item ID lists # 20121005 - updated to parse shell item ID lists
# 20100409 - updated to include Vista and above # 20100409 - updated to include Vista and above
@ -14,7 +16,7 @@
# Win2000 - http://support.microsoft.com/kb/319958 # Win2000 - http://support.microsoft.com/kb/319958
# XP - http://support.microsoft.com/kb/322948/EN-US/ # XP - http://support.microsoft.com/kb/322948/EN-US/
# #
# copyright 2012 Quantum Analytics Research, LLC # copyright 2018 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com # Author: H. Carvey, keydet89@yahoo.com
#----------------------------------------------------------- #-----------------------------------------------------------
package comdlg32; package comdlg32;
@ -26,7 +28,7 @@ my %config = (hive => "NTUSER\.DAT",
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
osmask => 22, osmask => 22,
version => 20121008); version => 20180702);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
@ -39,6 +41,50 @@ sub getVersion {return $config{version};}
my $VERSION = getVersion(); my $VERSION = getVersion();
my %folder_types = ("{724ef170-a42d-4fef-9f26-b60e846fba4f}" => "Administrative Tools",
"{d0384e7d-bac3-4797-8f14-cba229b392b5}" => "Common Administrative Tools",
"{de974d24-d9c6-4d3e-bf91-f4455120b917}" => "Common Files",
"{c1bae2d0-10df-4334-bedd-7aa20b227a9d}" => "Common OEM Links",
"{5399e694-6ce5-4d6c-8fce-1d8870fdcba0}" => "Control Panel",
"{1ac14e77-02e7-4e5d-b744-2eb1ae5198b7}" => "CSIDL_SYSTEM",
"{b4bfcc3a-db2c-424c-b029-7fe99a87c641}" => "Desktop",
"{7b0db17d-9cd2-4a93-9733-46cc89022e7c}" => "Documents Library",
"{a8cdff1c-4878-43be-b5fd-f8091c1c60d0}" => "Documents",
"{fdd39ad0-238f-46af-adb4-6c85480369c7}" => "Documents",
"{374de290-123f-4565-9164-39c4925e467b}" => "Downloads",
"{de61d971-5ebc-4f02-a3a9-6c82895e5c04}" => "Get Programs",
"{a305ce99-f527-492b-8b1a-7e76fa98d6e4}" => "Installed Updates",
"{871c5380-42a0-1069-a2ea-08002b30309d}" => "Internet Explorer (Homepage)",
"{031e4825-7b94-4dc3-b131-e946b44c8dd5}" => "Libraries",
"{2112ab0a-c86a-4ffe-a368-0de96e47012e}" => "Music",
"{1cf1260c-4dd0-4ebb-811f-33c572699fde}" => "Music",
"{4bd8d571-6d19-48d3-be97-422220080e43}" => "Music",
"{20d04fe0-3aea-1069-a2d8-08002b30309d}" => "My Computer",
"{450d8fba-ad25-11d0-98a8-0800361b1103}" => "My Documents",
"{ed228fdf-9ea8-4870-83b1-96b02cfe0d52}" => "My Games",
"{208d2c60-3aea-1069-a2d7-08002b30309d}" => "My Network Places",
"{f02c1a0d-be21-4350-88b0-7367fc96ef3c}" => "Network",
"{3add1653-eb32-4cb0-bbd7-dfa0abb5acca}" => "Pictures",
"{33e28130-4e1e-4676-835a-98395c3bc3bb}" => "Pictures",
"{a990ae9f-a03b-4e80-94bc-9912d7504104}" => "Pictures",
"{7c5a40ef-a0fb-4bfc-874a-c0f2e0b9fa8e}" => "Program Files (x86)",
"{905e63b6-c1bf-494e-b29c-65b732d3d21a}" => "Program Files",
"{df7266ac-9274-4867-8d55-3bd661de872d}" => "Programs and Features",
"{3214fab5-9757-4298-bb61-92a9deaa44ff}" => "Public Music",
"{b6ebfb86-6907-413c-9af7-4fc2abf07cc5}" => "Public Pictures",
"{2400183a-6185-49fb-a2d8-4a392a602ba3}" => "Public Videos",
"{4336a54d-38b-4685-ab02-99bb52d3fb8b}" => "Public",
"{491e922f-5643-4af4-a7eb-4e7a138d8174}" => "Public",
"{dfdf76a2-c82a-4d63-906a-5644ac457385}" => "Public",
"{645ff040-5081-101b-9f08-00aa002f954e}" => "Recycle Bin",
"{d65231b0-b2f1-4857-a4ce-a8e7c6ea7d27}" => "System32 (x86)",
"{9e52ab10-f80d-49df-acb8-4330f5687855}" => "Temporary Burn Folder",
"{f3ce0f7c-4901-4acc-8648-d5d44b04ef8f}" => "Users Files",
"{59031a47-3f72-44a7-89c5-5595fe6b30ee}" => "Users",
"{a0953c92-50dc-43bf-be83-3742fed03c9c}" => "Videos",
"{b5947d7f-b489-4fde-9e77-23780cc610d1}" => "Virtual Machines",
"{f38bf404-1d43-42f2-9305-67de0b28fc23}" => "Windows");
sub pluginmain { sub pluginmain {
my $class = shift; my $class = shift;
my $ntuser = shift; my $ntuser = shift;
@ -128,9 +174,9 @@ sub parseLastVisitedMRU {
@mrulist = split(//,$lvmru{MRUList}); @mrulist = split(//,$lvmru{MRUList});
delete($lvmru{MRUList}); delete($lvmru{MRUList});
foreach my $m (@mrulist) { foreach my $m (@mrulist) {
my ($file,$dir) = split(/\x00\x00/,$lvmru{$m},2); my ($file,$dir) = split(/\00\00/,$lvmru{$m},2);
$file =~ s/\x00//g; $file =~ s/\00//g;
$dir =~ s/\x00//g; $dir =~ s/\00//g;
::rptMsg(" ".$m." -> EXE: ".$file); ::rptMsg(" ".$m." -> EXE: ".$file);
::rptMsg(" -> Last Dir: ".$dir); ::rptMsg(" -> Last Dir: ".$dir);
} }
@ -213,8 +259,8 @@ sub parseCIDSizeMRU {
delete $mru{0xffffffff}; delete $mru{0xffffffff};
foreach my $m (sort {$a <=> $b} keys %mru) { foreach my $m (sort {$a <=> $b} keys %mru) {
# my $file = parseStr($mru{$m}); # my $file = parseStr($mru{$m});
my $file = (split(/\x00\x00/,$mru{$m},2))[0]; my $file = (split(/\00\00/,$mru{$m},2))[0];
$file =~ s/\x00//g; $file =~ s/\00//g;
::rptMsg(" ".$file); ::rptMsg(" ".$file);
} }
} }
@ -251,18 +297,18 @@ sub parseFirstFolder {
delete $mru{0xffffffff}; delete $mru{0xffffffff};
foreach my $m (sort {$a <=> $b} keys %mru) { foreach my $m (sort {$a <=> $b} keys %mru) {
# my $file = parseStr($mru{$m}); # my $file = parseStr($mru{$m});
my @files = split(/\x00\x00/,$mru{$m}); my @files = split(/\00\00/,$mru{$m});
if (scalar(@files) == 0) { if (scalar(@files) == 0) {
::rptMsg(" No files listed."); ::rptMsg(" No files listed.");
} }
elsif (scalar(@files) == 1) { elsif (scalar(@files) == 1) {
$files[0] =~ s/\x00//g; $files[0] =~ s/\00//g;
::rptMsg(" ".$files[0]); ::rptMsg(" ".$files[0]);
} }
elsif (scalar(@files) > 1) { elsif (scalar(@files) > 1) {
my @files2; my @files2;
foreach my $file (@files) { foreach my $file (@files) {
$file =~ s/\x00//g; $file =~ s/\00//g;
push(@files2,$file); push(@files2,$file);
} }
::rptMsg(" ".join(' ',@files2)); ::rptMsg(" ".join(' ',@files2));
@ -305,9 +351,9 @@ sub parseLastVisitedPidlMRU {
delete $mru{0xffffffff}; delete $mru{0xffffffff};
foreach my $m (sort {$a <=> $b} keys %mru) { foreach my $m (sort {$a <=> $b} keys %mru) {
my ($file,$shell) = split(/\x00\x00/,$mru{$m},2); my ($file,$shell) = split(/\00\00/,$mru{$m},2);
$file =~ s/\x00//g; $file =~ s/\00//g;
$shell =~ s/^\x00//; $shell =~ s/^\00//;
my $str = parseShellItem($shell); my $str = parseShellItem($shell);
::rptMsg(" ".$file." - ".$str); ::rptMsg(" ".$file." - ".$str);
} }
@ -398,6 +444,11 @@ sub parseShellItem {
%item = parseSystemFolderEntry($dat); %item = parseSystemFolderEntry($dat);
$str .= "\\".$item{name}; $str .= "\\".$item{name};
} }
elsif ($type == 0x2E) {
# probe($dat);
%item = parseDeviceEntry($dat);
$str .= "\\".$item{name};
}
elsif ($type == 0x2F) { elsif ($type == 0x2F) {
# Volume (Drive Letter) # Volume (Drive Letter)
%item = parseDriveEntry($dat); %item = parseDriveEntry($dat);
@ -476,7 +527,17 @@ sub parseGUID {
my $d3 = unpack("v",substr($data,6,2)); my $d3 = unpack("v",substr($data,6,2));
my $d4 = unpack("H*",substr($data,8,2)); my $d4 = unpack("H*",substr($data,8,2));
my $d5 = unpack("H*",substr($data,10,6)); my $d5 = unpack("H*",substr($data,10,6));
return sprintf "{%08x-%x-%x-$d4-$d5}",$d1,$d2,$d3; # ---- Added 20180627, updated 20180702
my $guid = sprintf "{%08x-%04x-%04x-$d4-$d5}",$d1,$d2,$d3;
if (exists $folder_types{$guid}) {
return "CLSID_".$folder_types{$guid};
}
else {
return $guid;
}
# return sprintf "{%08x-%x-%x-$d4-$d5}",$d1,$d2,$d3;
} }
#----------------------------------------------------------- #-----------------------------------------------------------
@ -498,7 +559,7 @@ sub parseNetworkEntry {
my %item = (); my %item = ();
$item{type} = unpack("C",substr($data,2,1)); $item{type} = unpack("C",substr($data,2,1));
my @n = split(/\x00/,substr($data,4,length($data) - 4)); my @n = split(/\00/,substr($data,4,length($data) - 4));
$item{name} = $n[0]; $item{name} = $n[0];
$item{name} =~ s/^\W//; $item{name} =~ s/^\W//;
return %item; return %item;
@ -538,7 +599,7 @@ sub parseFolderEntry {
($item{mtime_str},$item{mtime}) = convertDOSDate($m[0],$m[1]); ($item{mtime_str},$item{mtime}) = convertDOSDate($m[0],$m[1]);
# Need to read in short name; nul-term ASCII # Need to read in short name; nul-term ASCII
# $item{shortname} = (split(/\x00/,substr($data,12,length($data) - 12),2))[0]; # $item{shortname} = (split(/\00/,substr($data,12,length($data) - 12),2))[0];
$ofs_shortname = $ofs_mdate + 6; $ofs_shortname = $ofs_mdate + 6;
my $tag = 1; my $tag = 1;
my $cnt = 0; my $cnt = 0;
@ -546,7 +607,7 @@ sub parseFolderEntry {
while($tag) { while($tag) {
my $s = substr($data,$ofs_shortname + $cnt,1); my $s = substr($data,$ofs_shortname + $cnt,1);
return %item unless (defined $s); return %item unless (defined $s);
if ($s =~ m/\x00/ && ((($cnt + 1) % 2) == 0)) { if ($s =~ m/\00/ && ((($cnt + 1) % 2) == 0)) {
$tag = 0; $tag = 0;
} }
else { else {
@ -554,12 +615,12 @@ sub parseFolderEntry {
$cnt++; $cnt++;
} }
} }
# $str =~ s/\x00//g; # $str =~ s/\00//g;
my $shortname = $str; my $shortname = $str;
my $ofs = $ofs_shortname + $cnt + 1; my $ofs = $ofs_shortname + $cnt + 1;
# Read progressively, 1 byte at a time, looking for 0xbeef # Read progressively, 1 byte at a time, looking for 0xbeef
$tag = 1; my $tag = 1;
$cnt = 0; my $cnt = 0;
while ($tag) { while ($tag) {
my $s = substr($data,$ofs + $cnt,2); my $s = substr($data,$ofs + $cnt,2);
return %item unless (defined $s); return %item unless (defined $s);
@ -577,10 +638,10 @@ sub parseFolderEntry {
$ofs = $ofs + $cnt + 2; $ofs = $ofs + $cnt + 2;
@m = unpack("vv",substr($data,$ofs,4)); my @m = unpack("vv",substr($data,$ofs,4));
($item{ctime_str},$item{ctime}) = convertDOSDate($m[0],$m[1]); ($item{ctime_str},$item{ctime}) = convertDOSDate($m[0],$m[1]);
$ofs += 4; $ofs += 4;
@m = unpack("vv",substr($data,$ofs,4)); my @m = unpack("vv",substr($data,$ofs,4));
($item{atime_str},$item{atime}) = convertDOSDate($m[0],$m[1]); ($item{atime_str},$item{atime}) = convertDOSDate($m[0],$m[1]);
$ofs += 4; $ofs += 4;
@ -594,15 +655,19 @@ sub parseFolderEntry {
elsif ($item{extver} == 0x08) { elsif ($item{extver} == 0x08) {
$jmp = 26; $jmp = 26;
} }
# Updated for Windows 10
elsif ($item{extver} == 0x09) {
$jmp = 30;
}
else {} else {}
$ofs += $jmp; $ofs += $jmp;
# ::rptMsg(sprintf " Offset: 0x%x",$ofs); # ::rptMsg(sprintf " Offset: 0x%x",$ofs);
$str = substr($data,$ofs,length($data) - $ofs); my $str = substr($data,$ofs,length($data) - $ofs);
my $longname = (split(/\x00\x00/,$str,2))[0]; my $longname = (split(/\00\00/,$str,2))[0];
$longname =~ s/\x00//g; $longname =~ s/\00//g;
if ($longname ne "") { if ($longname ne "") {
$item{name} = $longname; $item{name} = $longname;
@ -613,6 +678,61 @@ sub parseFolderEntry {
return %item; return %item;
} }
#-----------------------------------------------------------
#
#-----------------------------------------------------------
sub parseDeviceEntry {
my $data = shift;
my %item = ();
my $ofs = unpack("v",substr($data,4,2));
my $tag = unpack("V",substr($data,6,4));
#-----------------------------------------------------
# DEBUG
# ::rptMsg("parseDeviceEntry, tag = ".$tag);
#-----------------------------------------------------
if ($tag == 0) {
my $guid1 = parseGUID(substr($data,$ofs + 6,16));
my $guid2 = parseGUID(substr($data,$ofs + 6 + 16,16));
$item{name} = $guid1."\\".$guid2
}
elsif ($tag == 2) {
$item{name} = substr($data,0x0a,($ofs + 6) - 0x0a);
$item{name} =~ s/\00//g;
}
else {
my $ver = unpack("C",substr($data,9,1));
my $idx = unpack("C",substr($data,3,1));
if ($idx == 0x80) {
$item{name} = parseGUID(substr($data,4,16));
}
# Version 3 = XP
elsif ($ver == 3) {
my $guid1 = parseGUID(substr($data,$ofs + 6,16));
my $guid2 = parseGUID(substr($data,$ofs + 6 + 16,16));
$item{name} = $guid1."\\".$guid2
}
# Version 8 = Win7
elsif ($ver == 8) {
my $userlen = unpack("V",substr($data,30,4));
my $devlen = unpack("V",substr($data,34,4));
my $user = substr($data,0x28,$userlen * 2);
$user =~ s/\00//g;
my $dev = substr($data,0x28 + ($userlen * 2),$devlen * 2);
$dev =~ s/\00//g;
$item{name} = $user;
}
# Version unknown
else {
$item{name} = "Device Entry - Unknown Version";
}
}
return %item;
}
#----------------------------------------------------------- #-----------------------------------------------------------
# convertDOSDate() # convertDOSDate()
# subroutine to convert 4 bytes of binary data into a human- # subroutine to convert 4 bytes of binary data into a human-

105
thirdparty/rr-full/plugins/dafupnp.pl vendored Normal file
View File

@ -0,0 +1,105 @@
#-----------------------------------------------------------
# dafupnp.pl
#
# Description:
# Parses Device Association Framework (DAF) for Universal Plug and Play
# (UPnP) data. DAFUPnP is used to stream media across a network.
#
# History:
# 20180705 - updated, code tweaks
# 20180628 - Created
#
#
# Author: M. Jones, mictjon@gmail.com
#-----------------------------------------------------------
package dafupnp;
use strict;
my %config = (hive => "System",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20180705);
my $VERSION = getVersion();
sub getConfig{return %config}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
sub getShortDescr {
return "Parses data from networked media streaming devices";
}
sub getDescr{}
sub getRefs {};
sub pluginmain {
my $class = shift;
my $hive = shift;
::logMsg("Launching dafupnp v.".$VERSION);
::rptMsg("dafupnp v.".$VERSION); # banner
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
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;
}
else {
::rptMsg($key_path." not found.");
return;
}
$key_path = $ccs."\\Enum\\SWD\\DAFUPnPProvider";
if ($key = $root_key->get_subkey($key_path)) {
my @subkeys = $key->get_list_of_subkeys();
if (scalar @subkeys > 0) {
foreach my $s (@subkeys) {
::rptMsg($s->get_name());
my ($desc,$comid,$hid,$loc,$mfg,$fname);
eval {
$desc = $s->get_value("DeviceDesc")->get_data();
::rptMsg("DeviceDesc : ".$desc);
};
eval {
$comid = $s->get_value("CompatibleIDs")->get_data();
::rptMsg("CompatibleID : ".$comid);
};
eval {
$hid = $s->get_value("HardwareID")->get_data();
::rptMsg("HardwareID : ".$hid);
};
eval {
$loc = $s->get_value("LocationInformation")->get_data();
::rptMsg("LocationInformation : ".$loc);
};
eval {
$mfg = $s->get_value("Mfg")->get_data();
::rptMsg("MFG : ".$mfg);
};
eval {
$fname = $s->get_value("FriendlyName")->get_data();
::rptMsg("FriendlyName : ".$fname);
};
::rptMsg("");
}
}
else {
::rptMsg($key_path." has no subkeys.");
}
}
else {
::rptMsg($key_path." not found.");
}
}
1;

View File

@ -4,13 +4,15 @@
# #
# #
# Change history # Change history
# 20190506 - updated
# 20140807 - created # 20140807 - created
# #
# References: # References:
# https://metacpan.org/pod/Parse::Win32Registry
# https://github.com/msuhanov/regf/blob/master/Windows%20registry%20file%20format%20specification.md
# #
# #
# # copyright 2019 QAR, LLC
# copyright 2014 QAR, LLC
# Author: H. Carvey # Author: H. Carvey
#----------------------------------------------------------- #-----------------------------------------------------------
package del; package del;
@ -22,7 +24,7 @@ my %config = (hive => "All",
hasRefs => 0, hasRefs => 0,
osmask => 22, osmask => 22,
category => "deleted", category => "deleted",
version => 20140807); version => 20190506);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
@ -35,6 +37,19 @@ sub getVersion {return $config{version};}
my $VERSION = getVersion(); my $VERSION = getVersion();
my %data_types = (0 => "REG_NONE",
1 => "REG_SZ",
2 => "REG_EXPAND_SZ",
3 => "REG_BINARY",
4 => "REG_DWORD",
5 => "REG_DWORD_BIG_ENDIAN",
6 => "REG_LINK",
7 => "REG_MULTI_SZ",
8 => "REG_RESOURCE_LIST",
9 => "REG_FULL_RESOURCE_DESCRIPTOR",
10 => "REG_RESOURCE_REQUIREMENTS_LIST",
11 => "REG_QWORD");
my %regkeys; my %regkeys;
sub pluginmain { sub pluginmain {
@ -50,32 +65,90 @@ sub pluginmain {
next if $entry->is_allocated; next if $entry->is_allocated;
# printf "0x%x ", $entry->get_offset; # printf "0x%x ", $entry->get_offset;
# print $entry->unparsed()."\n"; # print $entry->unparsed()."\n";
my $tag = $entry->get_tag(); my $data = $entry->get_raw_bytes();
my $str = $entry->as_string(); my $len = length($data);
next if ($str eq "(unidentified entry)"); next if ($len <= 8);
::rptMsg("------------- Deleted Data ------------");
if ($tag eq "vk") { # Value node header is 20 bytes, w/o name string
::rptMsg("Value: ".$str); # Key node header is 76 bytes, w/o name string
if ($len >= 20) {
my $cursor = 0;
while ($cursor < $len) {
if (unpack("v",substr($data,$cursor,2)) == 0x6b76) {
# ::rptMsg("Value node found at ".$cursor);
parseValueNode($data,$cursor);
$cursor += 0x12;
}
elsif (unpack("v",substr($data,$cursor,2)) == 0x6b6e) {
# ::rptMsg("Key node found at ".$cursor);
parseKeyNode($data,$cursor);
$cursor += 0x4a;
}
else {
$cursor++;
}
} }
elsif ($tag eq "nk") {
if ($entry->get_length() > 15) {
my ($t0,$t1) = unpack("VV",substr($entry->get_raw_bytes(),8,16));
my $lw = ::getTime($t0,$t1);
::rptMsg("Key: ".parseDelKeyName($str)." LW: ".gmtime($lw)." Z");
} }
} ::rptMsg($entry->unparsed());
else {}
} }
} }
sub parseDelKeyName { sub parseValueNode {
my $str = shift; my $data = shift;
my $name_str = (split(/\s\[/,$str))[0]; my $ofs = shift;
my @list = split(/\\/,$name_str);
shift(@list); my $name_len = unpack("v",substr($data,$ofs + 0x02,2));
return join('\\',@list); my $data_len = unpack("V",substr($data,$ofs + 0x04,4));
my $data_ofs = unpack("V",substr($data,$ofs + 0x08,4));
my $data_type = unpack("V",substr($data,$ofs + 0x0c,4));
my $data_flag = unpack("v",substr($data,$ofs + 0x10,2));
my $name;
if (($ofs + 0x14 + $name_len) <= length($data)) {
$name = substr($data,$ofs + 0x14,$name_len);
::rptMsg("Value Name: ".$name);
::rptMsg(sprintf "Data Length: 0x%x Data Offset: 0x%x Data Type: ".$data_types{$data_type},$data_len,$data_ofs);
}
} }
sub parseKeyNode {
my $data = shift;
my $ofs = shift;
my $len = length($data);
if ($len > 75 && $ofs >= 4) {
my $size = unpack("i",substr($data,$ofs - 4,4));
$size = ($size * -1) if ($size < 0);
# ::rptMsg("Key node size = ".$size);
my $type = unpack("v",substr($data,$ofs + 0x02,2));
# ::rptMsg(sprintf "Node Type = 0x%x",$type);
my ($t1,$t2) = unpack("VV",substr($data,$ofs + 0x04,8));
my $lw = ::getTime($t1,$t2);
# ::rptMsg("Key LastWrite time = ".gmtime($lw)." UTC");
my $parent_ofs = unpack("V",substr($data,$ofs + 0x10,4));
my $sk = unpack("V",substr($data,$ofs + 0x14,4));
# ::rptMsg("Number of subkeys: ".$sk);
my $vals = unpack("V",substr($data,$ofs + 0x24,4));
# ::rptMsg("Number of values: ".$vals);
my $len_name = unpack("V",substr($data,$ofs + 0x48,4));
# print "Name Length: ".$len_name."\n";
my $name;
if (($ofs + 0x4c + $len_name) <= $len) {
$name = substr($data,$ofs + 0x4c,$len_name);
::rptMsg("Key name: ".$name);
}
::rptMsg("Key LastWrite time = ".gmtime($lw)." UTC");
::rptMsg(sprintf "Offset to parent: 0x%x",$parent_ofs);
}
}
1; 1;

View File

@ -4,13 +4,15 @@
# #
# #
# Change history # Change history
# 20190506 - updated
# 20140807 - created # 20140807 - created
# #
# References: # References:
# https://metacpan.org/pod/Parse::Win32Registry
# https://github.com/msuhanov/regf/blob/master/Windows%20registry%20file%20format%20specification.md
# #
# #
# # copyright 2019 QAR, LLC
# copyright 2014 QAR, LLC
# Author: H. Carvey # Author: H. Carvey
#----------------------------------------------------------- #-----------------------------------------------------------
package del_tln; package del_tln;
@ -22,7 +24,7 @@ my %config = (hive => "All",
hasRefs => 0, hasRefs => 0,
osmask => 22, osmask => 22,
category => "deleted", category => "deleted",
version => 20140807); version => 20190506);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
@ -41,9 +43,8 @@ sub pluginmain {
my $class = shift; my $class = shift;
my $file = shift; my $file = shift;
my $reg = Parse::Win32Registry->new($file); my $reg = Parse::Win32Registry->new($file);
my $root_key = $reg->get_root_key; ::logMsg("Launching del_tln v.".$VERSION);
# ::logMsg("Launching del v.".$VERSION); # ::rptMsg("del_tln v.".$VERSION); # banner
# ::rptMsg("del v.".$VERSION); # banner
# ::rptMsg("(".getHive().") ".getShortDescr()."\n"); # banner # ::rptMsg("(".getHive().") ".getShortDescr()."\n"); # banner
my $entry_iter = $reg->get_entry_iterator; my $entry_iter = $reg->get_entry_iterator;
@ -51,28 +52,63 @@ sub pluginmain {
next if $entry->is_allocated; next if $entry->is_allocated;
# printf "0x%x ", $entry->get_offset; # printf "0x%x ", $entry->get_offset;
# print $entry->unparsed()."\n"; # print $entry->unparsed()."\n";
my $tag = $entry->get_tag(); my $data = $entry->get_raw_bytes();
my $str = $entry->as_string(); my $len = length($data);
next if ($str eq "(unidentified entry)"); next if ($len <= 8);
# Key node header is 76 bytes, w/o name string
if ($tag eq "nk") { if ($len >= 20) {
if ($entry->get_length() > 15) { my $cursor = 0;
my ($t0,$t1) = unpack("VV",substr($entry->get_raw_bytes(),8,16)); while ($cursor < $len) {
my $lw = ::getTime($t0,$t1); if (unpack("v",substr($data,$cursor,2)) == 0x6b6e) {
::rptMsg($lw."|REG|||[Deleted key]: ".parseDelKeyName($str)); # ::rptMsg("Key node found at ".$cursor);
parseKeyNode($data,$cursor);
$cursor += 0x4a;
}
else {
$cursor++;
} }
} }
else {}
}
# ::rptMsg($entry->unparsed());
} }
} }
sub parseDelKeyName { sub parseKeyNode {
my $str = shift; my $data = shift;
my $name_str = (split(/\s\[/,$str))[0]; my $ofs = shift;
my @list = split(/\\/,$name_str); my $len = length($data);
shift(@list);
return join('\\',@list); if ($len > 75 && $ofs >= 4) {
my $size = unpack("i",substr($data,$ofs - 4,4));
$size = ($size * -1) if ($size < 0);
# ::rptMsg("Key node size = ".$size);
my $type = unpack("v",substr($data,$ofs + 0x02,2));
# ::rptMsg(sprintf "Node Type = 0x%x",$type);
my ($t1,$t2) = unpack("VV",substr($data,$ofs + 0x04,8));
my $lw = ::getTime($t1,$t2);
# ::rptMsg("Key LastWrite time = ".gmtime($lw)." UTC");
my $parent_ofs = unpack("V",substr($data,$ofs + 0x10,4));
my $sk = unpack("V",substr($data,$ofs + 0x14,4));
# ::rptMsg("Number of subkeys: ".$sk);
my $vals = unpack("V",substr($data,$ofs + 0x24,4));
# ::rptMsg("Number of values: ".$vals);
my $len_name = unpack("V",substr($data,$ofs + 0x48,4));
# print "Name Length: ".$len_name."\n";
my $name;
if (($ofs + 0x4c + $len_name) <= $len) {
$name = substr($data,$ofs + 0x4c,$len_name);
}
::rptMsg($lw."|||| Deleted key: ".$name);
}
} }
1; 1;

View File

@ -1,7 +1,14 @@
#----------------------------------------------------------- #-----------------------------------------------------------
# disablelastaccess.pl # disablelastaccess.pl
# #
# History:
# 20181207 - updated for Win10 v.1803 (Maxim, David Cohen)
# 20090118 -
#
# References: # References:
# https://twitter.com/errno_fail/status/1070838120545955840
# https://dfir.ru/2018/12/08/the-last-access-updates-are-almost-back/
# https://www.hecfblog.com/2018/12/daily-blog-557-changes-in.html
# http://support.microsoft.com/kb/555041 # http://support.microsoft.com/kb/555041
# http://support.microsoft.com/kb/894372 # http://support.microsoft.com/kb/894372
# #
@ -15,10 +22,15 @@ my %config = (hive => "System",
hasShortDescr => 1, hasShortDescr => 1,
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
version => 20090118); version => 20181207);
sub getConfig{return %config} sub getConfig{return %config}
my %dla = (0x80000000 => "(User Managed, Updates Enabled)",
0x80000001 => "(User Managed, Updates Disabled)",
0x80000002 => "(System Managed, Updates Enabled)",
0x80000003 => "(System Managed, Updates Disabled)");
sub getShortDescr { sub getShortDescr {
return "Get NTFSDisableLastAccessUpdate value"; return "Get NTFSDisableLastAccessUpdate value";
} }
@ -48,7 +60,8 @@ sub pluginmain {
$ccs = "ControlSet00".$current; $ccs = "ControlSet00".$current;
} }
$key_path = $ccs."\\Control\\FileSystem"; my $key_path = $ccs."\\Control\\FileSystem";
my $key;
if ($key = $root_key->get_subkey($key_path)) { if ($key = $root_key->get_subkey($key_path)) {
::rptMsg("NtfsDisableLastAccessUpdate"); ::rptMsg("NtfsDisableLastAccessUpdate");
::rptMsg($key_path); ::rptMsg($key_path);
@ -57,8 +70,19 @@ sub pluginmain {
if (scalar(@vals) > 0) { if (scalar(@vals) > 0) {
foreach my $v (@vals) { foreach my $v (@vals) {
if ($v->get_name() eq "NtfsDisableLastAccessUpdate") { if ($v->get_name() eq "NtfsDisableLastAccessUpdate") {
::rptMsg("NtfsDisableLastAccessUpdate = ".$v->get_data()); my $dat = $v->get_data();
::rptMsg(sprintf "NtfsDisableLastAccessUpdate = 0x%08x",$dat);
$found = 1; $found = 1;
if ($dat > 1) {
::rptMsg($dla{$dat});
eval {
my $thresh = $key->get_value("NtfsLastAccessUpdatePolicyVolumeSizeThreshold")->get_data();
::rptMsg(sprintf "NtfsLastAccessUpdatePolicyVolumeSizeThreshold value = 0x%08x",$thresh);
};
}
} }
} }
::rptMsg("NtfsDisableLastAccessUpdate value not found.") if ($found == 0); ::rptMsg("NtfsDisableLastAccessUpdate value not found.") if ($found == 0);

102
thirdparty/rr-full/plugins/disablemru.pl vendored Normal file
View File

@ -0,0 +1,102 @@
#-----------------------------------------------------------
# disablemru.pl
#
# Change history
# 20180807 - created
#
# References
# *Provided in the code
#
# copyright 2018 H. Carvey
#-----------------------------------------------------------
package disablemru;
use strict;
my %config = (hive => "NTUSER\.DAT",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20180807);
sub getConfig{return %config}
sub getShortDescr {
return "Checks settings disabling user's MRUs";
}
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 disablemru v.".$VERSION);
::rptMsg("disablemru v.".$VERSION); # banner
::rptMsg("- ".getShortDescr()."\n"); # banner
my $reg = Parse::Win32Registry->new($ntuser);
my $root_key = $reg->get_root_key;
# Windows 10 JumpLists
# https://winaero.com/blog/disable-jump-lists-windows-10/
my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced';
my $key;
if ($key = $root_key->get_subkey($key_path)) {
eval {
my $start = $key->get_value("Start_TrackDocs")->get_data();
};
}
else {
::rptMsg($key_path." not found.");
}
# https://answers.microsoft.com/en-us/windows/forum/windows_xp-security/how-do-i-disable-most-recent-used-list-in-run/dab29225-4222-4412-8bc3-0516cee65a78
$key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Comdlg32';
if ($key = $root_key->get_subkey($key_path)) {
eval {
my $file = $key->get_value("NoFileMRU")->get_data();
if ($file == 1) {
::rptMsg("NoFileMRU = 1; Recording for Comdlg32 disabled");
}
};
}
else {
::rptMsg($key_path." not found.");
}
# http://systemmanager.ru/win2k_regestry.en/92853.htm
$key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer';
if ($key = $root_key->get_subkey($key_path)) {
my $mru;
eval {
$mru = $key->get_value("NoRecentDocsMenu")->get_data();
if ($mru == 1) {
::rptMsg("NoRecentDocsMenu = 1; No Documents menu in Start menu");
}
};
eval {
$mru = $key->get_value("ClearRecentDocsOnExit")->get_data();
if ($mru == 1) {
::rptMsg("ClearRecentDocsOnExit = 1; RecentDocs cleared on exit");
}
};
eval {
$mru = $key->get_value("NoRecentDocsHistory")->get_data();
if ($mru == 1) {
::rptMsg("NoRecentDocsHistory = 1; No RecentDocs history");
}
};
}
else {
::rptMsg($key_path." not found.");
}
}
1;

67
thirdparty/rr-full/plugins/eraser.pl vendored Normal file
View File

@ -0,0 +1,67 @@
#-----------------------------------------------------------
# eraser.pl
# Gets Eraser User Settings
#
# Change history
# 20180708 - Created (based on ccleaner.pl plugin)
#
# References
#
# Author: Hadar Yudovich <@hadar0x>
#-----------------------------------------------------------
package eraser;
use strict;
my %config = (hive => "NTUSER\.DAT",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20180708);
sub getConfig{return %config}
sub getShortDescr {
return "Gets User's Eraser Settings";
}
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 Eraser v.".$VERSION);
::rptMsg("Eraser v.".$VERSION);
::rptMsg("(".getHive().") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive); # creates a Win32Registry object
my $root_key = $reg->get_root_key;
my $key_path = "Software\\Eraser\\Eraser 6";
my $key;
if ($key = $root_key->get_subkey($key_path)) {
::rptMsg($key_path);
::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
::rptMsg("");
my %eraserkeys;
my @eraservals = $key->get_list_of_values();
if (scalar(@eraservals) > 0) {
foreach my $val (@eraservals) {
$eraserkeys{$val->get_name()} = $val->get_data();
}
foreach my $keyval (sort keys %eraserkeys) {
::rptMsg($keyval." -> ".$eraserkeys{$keyval});
}
}
else {
::rptMsg($key_path." has no values.");
}
}
else {
::rptMsg($key_path." does not exist.");
}
::rptMsg("");
}
1;

View File

@ -0,0 +1,60 @@
#-----------------------------------------------------------
# execpolicy
#
# Change history:
# 20180618 - created
#
# Ref:
# https://blogs.technet.microsoft.com/operationsguy/2011/04/21/remotely-tweak-powershell-execution-policies-without-powershell-remoting/
#
# copyright 2018 QAR,LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package execpolicy;
use strict;
my %config = (hive => "Software",
category => "config",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20180618);
sub getConfig{return %config}
sub getShortDescr {
return "Gets PowerShell Execution Policy";
}
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;
::rptMsg("Launching execpolicy v.".$VERSION);
::rptMsg("execpolicy v.".$VERSION); # banner
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
my $key_path = ('Microsoft\\PowerShell\\1\\ShellIds\\Microsoft.Powershell');
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key;
if ($key = $root_key->get_subkey($key_path)) {
my $policy = "";
eval {
$policy = $key->get_value("ExecutionPolicy")->get_data();
};
if ($policy eq "") {
::rptMsg("ExecutionPolicy value not found.")
}
else {
::rptMsg("ExecutionPolicy = ".$policy);
}
}
}
1;

View File

@ -17,7 +17,7 @@
package ie_zones; package ie_zones;
use strict; use strict;
my %config = (hive => "NTUSER\.DAT;Software", my %config = (hive => "NTUSER\.DAT,Software",
hasShortDescr => 1, hasShortDescr => 1,
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,

View File

@ -5,8 +5,10 @@
# http://msdn2.microsoft.com/en-us/library/a329t4ed(VS\.80)\.aspx # http://msdn2.microsoft.com/en-us/library/a329t4ed(VS\.80)\.aspx
# CWDIllegalInDllSearch: http://support.microsoft.com/kb/2264107 # CWDIllegalInDllSearch: http://support.microsoft.com/kb/2264107
# http://carnal0wnage.attackresearch.com/2012/04/privilege-escalation-via-sticky-keys.html # http://carnal0wnage.attackresearch.com/2012/04/privilege-escalation-via-sticky-keys.html
# 'Auto' value - https://docs.microsoft.com/en-us/windows/desktop/debug/configuring-automatic-debugging
# #
# Change history: # Change history:
# 20190511 - added search for 'auto' value
# 20131007 - added Carnal0wnage reference # 20131007 - added Carnal0wnage reference
# 20130425 - added alertMsg() functionality # 20130425 - added alertMsg() functionality
# 20130410 - added Wow6432Node support # 20130410 - added Wow6432Node support
@ -23,7 +25,7 @@ my %config = (hive => "Software",
hasRefs => 0, hasRefs => 0,
osmask => 22, osmask => 22,
category => "malware", category => "malware",
version => 20131007); version => 20190511);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
@ -76,6 +78,11 @@ sub pluginmain {
eval { eval {
$dllsearch = $s->get_value("CWDIllegalInDllSearch")->get_data(); $dllsearch = $s->get_value("CWDIllegalInDllSearch")->get_data();
}; };
# 20190511 - added search for 'auto' value
eval {
$debug{$name}{auto} = $s->get_value("Auto")->get_data();
};
# If the eval{} throws an error, it's b/c the Debugger value isn't # 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 # found within the key, so we don't need to do anything w/ the error
if ($dllsearch ne "") { if ($dllsearch ne "") {
@ -88,7 +95,7 @@ sub pluginmain {
foreach my $d (keys %debug) { foreach my $d (keys %debug) {
::rptMsg($d." LastWrite: ".gmtime($debug{$d}{lastwrite})); ::rptMsg($d." LastWrite: ".gmtime($debug{$d}{lastwrite}));
::rptMsg(" Debugger : ".$debug{$d}{debug}) if (exists $debug{$d}{debug}); ::rptMsg(" Debugger : ".$debug{$d}{debug}) if (exists $debug{$d}{debug});
::alertMsg("Alert: imagefile: Debugger value found : ".$debug{$d}{debug}) if (exists $debug{$d}{debug}); ::rptMsg(" Auto : ".$debug{$d}{auto}) if (exists $debug{$d}{auto});
::rptMsg(" CWDIllegalInDllSearch: ".$debug{$d}{dllsearch}) if (exists $debug{$d}{dllsearch}); ::rptMsg(" CWDIllegalInDllSearch: ".$debug{$d}{dllsearch}) if (exists $debug{$d}{dllsearch});
} }
} }

211
thirdparty/rr-full/plugins/imgburn1.pl vendored Normal file
View File

@ -0,0 +1,211 @@
#-----------------------------------------------------------
# imgburn1.pl
#
# Gets user's ImgBurn recent files and configured paths
#
# History
# 20180630 - created
#
# References
# http://forum.imgburn.com/index.php?/forum/4-guides/
#
#
# copyright 2018 Michael Godfrey mgodfrey [at] gmail.com
#-----------------------------------------------------------
package imgburn1;
use strict;
my %config =
(
hive => "NTUSER\.DAT",
hasShortDescr => 0,
hasDescr => 1,
hasRefs => 1,
osmask => 29,
version => 20180630
);
sub getConfig {return %config;}
sub getDescr {return "Gets user's ImgBurn MRU files and paths from NTUSER";}
sub getRefs {return "n/a";}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
my $VERSION = getVersion();
sub pluginmain {
my $class = shift;
my $hive = shift;
::logMsg("Launching imgburn1 v.".$VERSION);
::rptMsg('imgburn1 v'.$VERSION.' ('.getDescr().")");
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key_path = 'Software\\ImgBurn';
my $key;
if ($key = $root_key->get_subkey($key_path)) {
::rptMsg($key_path);
::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
::rptMsg("");
my $id;
eval {
$id = $key->get_value("InstallDirectory")->get_data();
};
if ($@) {
::rptMsg("InstallDirectory value not found.");
}
else {
::rptMsg("InstallDirectory = ".$id);
}
my $bq;
eval {
$bq = $key->get_value("IBQ_MRUFile")->get_data();
};
if ($@) {
::rptMsg("IBQ_MRUFile value not found.");
}
else {
::rptMsg("IBQ_MRUFile = ".$bq);
}
my $rf;
eval {
$rf = $key->get_value("ISOREAD_RecentFiles_Destination")->get_data();
};
if ($@) {
::rptMsg("ISOREAD_RecentFiles_Destination value not found.");
}
else {
::rptMsg("ISOREAD_RecentFiles_Destination = ".$rf);
}
my $rs;
eval {
$rs = $key->get_value("ISOWRITE_RecentFiles_Source")->get_data();
};
if ($@) {
::rptMsg("ISOWRITE_RecentFiles_Source value not found.");
}
else {
::rptMsg("ISOWRITE_RecentFiles_Source = ".$rs);
}
my $sf;
eval {
$sf = $key->get_value("ISOBUILD_MRUSourceFolder")->get_data();
};
if ($@) {
::rptMsg("ISOBUILD_MRUSourceFolder value not found.");
}
else {
::rptMsg("ISOBUILD_MRUSourceFolder = ".$sf);
}
my $fs;
eval {
$fs = $key->get_value("ISOBUILD_RecentFiles_Source")->get_data();
};
if ($@) {
::rptMsg("ISOBUILD_RecentFiles_Source value not found.");
}
else {
::rptMsg("ISOBUILD_RecentFiles_Source = ".$fs);
}
my $fd;
eval {
$fd = $key->get_value("ISOBUILD_RecentFiles_Destination")->get_data();
};
if ($@) {
::rptMsg("ISOBUILD_RecentFiles_Destination value not found.");
}
else {
::rptMsg("ISOBUILD_RecentFiles_Destination = ".$fd);
}
my $fd;
eval {
$fd = $key->get_value("ISOBUILD_Recentfolders_Destination")->get_data();
};
if ($@) {
::rptMsg("ISOBUILD_RecentFolders_Destination value not found.");
}
else {
::rptMsg("ISOBUILD_RecentFolders_Destination = ".$fd);
}
my $if;
eval {
$if = $key->get_value("FILELOCATIONS_ImageFiles")->get_data();
};
if ($@) {
::rptMsg("FILELOCATIONS_ImageFiles value not found.");
}
else {
::rptMsg("FILELOCATIONS_ImageFiles = ".$if);
}
my $lf;
eval {
$lf = $key->get_value("FILELOCATIONS_LogFiles")->get_data();
};
if ($@) {
::rptMsg("FILELOCATIONS_LogFiles value not found.");
}
else {
::rptMsg("FILELOCATIONS_LogFiles = ".$lf);
}
my $pf;
eval {
$pf = $key->get_value("FILELOCATIONS_ProjectFiles")->get_data();
};
if ($@) {
::rptMsg("FILELOCATIONS_ProjectFiles value not found.");
}
else {
::rptMsg("FILELOCATIONS_ProjectFiles = ".$pf);
}
my $qf;
eval {
$qf = $key->get_value("FILELOCATIONS_QueueFiles")->get_data();
};
if ($@) {
::rptMsg("FILELOCATIONS_QueueFiles value not found.");
}
else {
::rptMsg("FILELOCATIONS_QueueFiles = ".$qf);
}
}
else {
::rptMsg($key_path." not found.");
}
}
1;

View File

@ -225,6 +225,7 @@ sub parseFolderItem {
my $str = ""; my $str = "";
while($tag) { while($tag) {
my $s = substr($data,$ofs_shortname + $cnt,1); my $s = substr($data,$ofs_shortname + $cnt,1);
return %item unless (defined $s);
if ($s =~ m/\x00/ && ((($cnt + 1) % 2) == 0)) { if ($s =~ m/\x00/ && ((($cnt + 1) % 2) == 0)) {
$tag = 0; $tag = 0;
} }
@ -240,7 +241,9 @@ sub parseFolderItem {
$tag = 1; $tag = 1;
$cnt = 0; $cnt = 0;
while ($tag) { while ($tag) {
if (unpack("v",substr($data,$ofs + $cnt,2)) == 0xbeef) { my $s = substr($data,$ofs + $cnt,2);
return %item unless (defined $s);
if (unpack("v",$s) == 0xbeef) {
$tag = 0; $tag = 0;
} }
else { else {

View File

@ -0,0 +1,68 @@
#-----------------------------------------------------------
# jumplistdata.pl
#
#
# Change history
# 20180611 - created (per request submitted by John McCash)
#
# References
# https://twitter.com/sv2hui/status/1005763370186891269
#
# copyright 2018 QAR, LLC
# author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package jumplistdata;
use strict;
my %config = (hive => "NTUSER\.DAT",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20180611);
sub getConfig{return %config}
sub getShortDescr {
return "Gets contents of user's JumpListData 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 jumplistdata v.".$VERSION);
::rptMsg("jumplistdata v.".$VERSION);
::rptMsg("- ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($ntuser);
my $root_key = $reg->get_root_key;
my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Search\\JumpListData';
my $key;
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();
my @t = unpack("VV",$v->get_data());
my $w = ::getTime($t[0],$t[1]);
::rptMsg(gmtime($w)." UTC $name");
}
}
else {
::rptMsg($key_path." has no values.");
}
}
else {
::rptMsg($key_path." not found.");
}
}
1;

View File

@ -2,12 +2,14 @@
# knowndev.pl # knowndev.pl
# #
# History # History
# 20190714 - updated
# 20140414 - created # 20140414 - created
# #
# Registry entries created by devices that support device stage # Registry entries created by devices that support device stage
# Reference: http://nicoleibrahim.com/part-4-usb-device-research-usb-first-insert-results/ # Reference: http://nicoleibrahim.com/part-4-usb-device-research-usb-first-insert-results/
# #
# Author: Jasmine Chua, babymagic06@gmail.com # Author: Jasmine Chua, babymagic06@gmail.com
# updates: QAR, LLC (H. Carvey, keydet89@yahoo.com)
#----------------------------------------------------------------------------------------- #-----------------------------------------------------------------------------------------
package knowndev; package knowndev;
use strict; use strict;
@ -17,7 +19,7 @@ my %config = (hive => "NTUSER\.DAT",
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
osmask => 22, osmask => 22,
version => 20140414); version => 20190714);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
@ -50,39 +52,14 @@ sub pluginmain {
if (scalar @subkeys > 0) { if (scalar @subkeys > 0) {
foreach my $s (@subkeys) { foreach my $s (@subkeys) {
my $name = $s->get_name(); my $name = $s->get_name();
if ($name =~ m/_COMP/) { my $lw = gmtime($s->get_timestamp());
my $m = (split(/#/,$name,3))[1]; ::rptMsg($name." ".$lw." Z");
my $device = (split(/&/,$m,3))[0];
my $model = (split(/&/,$m,3))[1];
my $label;
my $icon;
eval { eval {
$label = $s->get_value('Label')->get_data(); my $label = $s->get_value("Label")->get_data();
$icon = $s->get_value('Icon')->get_data(); ::rptMsg("Label: ".$label);
}; };
my $time = gmtime($s->get_timestamp()); ::rptMsg("");
::rptMsg("Device: ".$device);
::rptMsg("Model: ".$model);
::rptMsg("Label: ".$label) unless ($@);
::rptMsg("Icon: ".$icon) unless ($@);
::rptMsg("LastWrite Time: ".$time." (UTC)\n");
}
elsif ($name =~ m/_USB/) {
my $vidpid = (split(/#/,$name,3))[1];
my $serial = (split(/#/,$name,3))[2];
my $label;
my $icon;
eval {
$label = $s->get_value('Label')->get_data();
$icon = $s->get_value('Icon')->get_data();
};
my $time = gmtime($s->get_timestamp());
::rptMsg("VID&PID: ".$vidpid);
::rptMsg("Serial: ".$serial);
::rptMsg("Label: ".$label) unless ($@);
::rptMsg("Icon: ".$icon) unless ($@);
::rptMsg("LastWrite Time: ".$time." (UTC)\n");
}
} }
} }
else { else {

View File

@ -6,9 +6,10 @@
# #
# #
# History: # History:
# 20180614 - Updated by Michael Godfrey
# 20160531 - created # 20160531 - created
# #
# copyright 2016 Quantum Analytics Research, LLC # copyright 2018 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com # Author: H. Carvey, keydet89@yahoo.com
#----------------------------------------------------------- #-----------------------------------------------------------
package lastloggedon; package lastloggedon;
@ -62,6 +63,11 @@ sub pluginmain {
my $lastsamuser = $key->get_value("LastLoggedOnSAMUser")->get_data(); my $lastsamuser = $key->get_value("LastLoggedOnSAMUser")->get_data();
::rptMsg("LastLoggedOnSAMUser = ".$lastsamuser); ::rptMsg("LastLoggedOnSAMUser = ".$lastsamuser);
}; };
# Added by Michael Godfrey
eval {
my $lastsamuserSID = $key->get_value("LastLoggedOnUserSID")->get_data();
::rptMsg("LastLoggedOnUserSID = ".$lastsamuserSID);
}
} }
else { else {
::rptMsg($key_path." not found."); ::rptMsg($key_path." not found.");

View File

@ -0,0 +1,82 @@
#-----------------------------------------------------------
# LogonStats
#
# Change history
# 20180128 - created
#
# References
# https://twitter.com/jasonshale/status/623081308722475009
#
# copyright 2018 H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package logonstats;
use strict;
my %config = (hive => "NTUSER\.DAT",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20180128);
sub getConfig{return %config}
sub getShortDescr {
return "Gets contents of user's LogonStats 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 logonstats v.".$VERSION);
::rptMsg("logonstats v.".$VERSION); # banner
::rptMsg("- ".getShortDescr()."\n"); # banner
my $reg = Parse::Win32Registry->new($ntuser);
my $root_key = $reg->get_root_key;
my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\LogonStats';
my $key;
if ($key = $root_key->get_subkey($key_path)) {
eval {
my $flt = $key->get_value("FirstLogonTime")->get_data();
my $str = convertSystemTime($flt);
::rptMsg("FirstLogonTime: ".$str);
};
eval {
my $oc = $key->get_value("FirstLogonTimeOnCurrentInstallation")->get_data();
my $i = convertSystemTime($oc);
::rptMsg("FirstLogonTimeOnCurrentInstallation: ".$i);
};
}
else {
::rptMsg($key_path." not found.");
}
}
#-----------------------------------------------------------
# convertSystemTime()
# Converts 128-bit SYSTEMTIME object to readable format
#-----------------------------------------------------------
sub convertSystemTime {
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;

View File

@ -4,18 +4,22 @@
# The plugin will determine which one its in and use the appropriate # The plugin will determine which one its in and use the appropriate
# code # code
# #
# History:
# 20190506 - updated
# 20090118 - created
# #
# copyright 2008 H. Carvey, keydet89@yahoo.com # copyright 2019, QAR, LLC
# Author: H. Carvey, keydet89@yahoo.com
#----------------------------------------------------------- #-----------------------------------------------------------
package macaddr; package macaddr;
use strict; use strict;
my %config = (hive => "Software", my %config = (hive => "System,Software",
osmask => 22, osmask => 22,
hasShortDescr => 1, hasShortDescr => 1,
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
version => 20090118); version => 20190506);
sub getConfig{return %config} sub getConfig{return %config}
@ -61,6 +65,7 @@ sub pluginmain {
eval { eval {
$na = $key->get_subkey($name)->get_value("NetworkAddress")->get_data(); $na = $key->get_subkey($name)->get_value("NetworkAddress")->get_data();
::rptMsg(" ".$name.": NetworkAddress = ".$na); ::rptMsg(" ".$name.": NetworkAddress = ".$na);
::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
$found = 1; $found = 1;
}; };
} }

View File

@ -8,6 +8,9 @@
# <included inline> # <included inline>
# #
# Change history: # Change history:
# 20190527 - updates
# 20190107 - added remote UAC bypass check
# 20180702 - added values to check for MS Defender being disabled
# 20161210 - added WebRoot check # 20161210 - added WebRoot check
# 20160615 - added new Sofacy persistence # 20160615 - added new Sofacy persistence
# 20160412 - added Ramdo checks # 20160412 - added Ramdo checks
@ -19,7 +22,7 @@
# 20151008 - added keys # 20151008 - added keys
# 20150828 - created # 20150828 - created
# #
# copyright 2015 Quantum Analytics Research, LLC # copyright 2018 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com # Author: H. Carvey, keydet89@yahoo.com
#----------------------------------------------------------- #-----------------------------------------------------------
package malware; package malware;
@ -31,7 +34,7 @@ my %config = (hive => "All",
hasRefs => 0, hasRefs => 0,
osmask => 22, osmask => 22,
category => "malware", category => "malware",
version => 20161210); version => 20190527);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
@ -102,9 +105,29 @@ sub pluginmain {
} }
}; };
# Added 20190527
# https://www.praetorian.com/blog/mitigating-mimikatz-wdigest-cleartext-credential-theft?edition=2019
eval {
$key_path = "Control\\SecurityProviders\\WDigest";
if ($key = $root_key->get_subkey($key_path)){
my $ulc = $key->get_value("UseLogonCredential")->get_data();
::rptMsg(" UseLogonCredential value = ".$ulc);
}
};
# Software Hive # Software Hive
# Added 20190527
# https://www.stigviewer.com/stig/windows_7/2013-03-14/finding/V-3470
eval {
$key_path = "Policies\\Microsoft\\Windows NT\\Terminal Services\\";
if ($key = $root_key->get_subkey($key_path)) {
my $fallow = $key->get_value("fAllowUnsolicited")->get_data();
::rptMsg(" fAllowUnsolicited value = ".$fallow);
}
};
# Check for several PlugX variants # Check for several PlugX variants
# http://www.symantec.com/security_response/earthlink_writeup.jsp?docid=2013-112101-0135-99 # http://www.symantec.com/security_response/earthlink_writeup.jsp?docid=2013-112101-0135-99
# http://www.trendmicro.com/vinfo/us/threat-encyclopedia/malware/PLUGX # http://www.trendmicro.com/vinfo/us/threat-encyclopedia/malware/PLUGX
@ -307,6 +330,45 @@ sub pluginmain {
} }
}; };
# https://www.ghacks.net/2015/10/25/how-to-disable-windows-defender-in-windows-10-permanently/
eval {
$key_path = "Policies\\Microsoft\\Windows Defender";
if ($key = $root_key->get_subkey($key_path)) {
my $dis = $key->get_value("DisableAntiSpyware")->get_data();
if ($dis == 1) {
::rptMsg($key_path);
::rptMsg("LastWrite Time : ".gmtime($key->get_timestamp())." UTC");
::rptMsg("DisableAntiSpyware value = 1");
}
}
};
eval {
$key_path = "Policies\\Microsoft\\Windows Defender\\Real-Time Protection";
if ($key = $root_key->get_subkey($key_path)) {
my $dis = $key->get_value("DisableRealtimeMonitoring")->get_data();
if ($dis == 1) {
::rptMsg($key_path);
::rptMsg("LastWrite Time : ".gmtime($key->get_timestamp())." UTC");
::rptMsg("DisableRealtimeMonitoring value = 1");
}
}
};
# Remote UAC bypass
# https://support.microsoft.com/en-us/help/951016/description-of-user-account-control-and-remote-restrictions-in-windows
eval {
$key_path = "Microsoft\\Windows\\CurrentVersion\\Policies\\System";
if ($key = $root_key->get_subkey($key_path)) {
my $uac = $key->get_value("LocalAccountTokenFilterPolicy")->get_data();
if ($uac == 1) {
::rptMsg($key_path);
::rptMsg("LastWrite Time : ".gmtime($key->get_timestamp())." UTC");
::rptMsg("LocalAccountTokenFilterPolicy value = 1; remote UAC bypass");
}
}
};
# NTUSER.DAT/USRCLASS.DAT # NTUSER.DAT/USRCLASS.DAT
# Possible PlugX # Possible PlugX

View File

@ -0,0 +1,147 @@
#-----------------------------------------------------------
# msedge_win10.pl
# Plugin for RegRipper
#
# Parses Microsoft Edge (Windows App) key:
# -USRCLASS.DAT\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppContainer\Storage\microsoft.microsoftedge_8wekyb3d8bbwe\MicrosoftEdge\TypedURLs
# -USRCLASS.DAT\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppContainer\Storage\microsoft.microsoftedge_8wekyb3d8bbwe\MicrosoftEdge\TypedURLsTime
# -USRCLASS.DAT\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppContainer\Storage\microsoft.microsoftedge_8wekyb3d8bbwe\MicrosoftEdge\TypedURLsVisitCount
#
# On a live machine, the key path is found under HKEY_CLASSES_ROOT
#
# The script code is based on:
# - adoberdr.pl/landesk.pl by H. Carvey
# - iexplore.pl by E. Rye esten@ryezone.net
# http://www.ryezone.net/regripper-and-internet-explorer-1
#
# Change history
# 20180610 - First release
#
# References
# http://digitalforensicsurvivalpodcast.com/2017/04/11/dfsp-060-browsing-on-the-edge/
# https://forensenellanebbia.blogspot.com/2018/06/usrclassdat-stores-more-history-than.html
#
# copyright 2018 Gabriele Zambelli <forensenellanebbia@gmail.com> | Twitter: @gazambelli
#-----------------------------------------------------------
package msedge_win10;
use strict;
my %config = (hive => "USRCLASS\.DAT",
osmask => 22,
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
version => 20180610);
sub getShortDescr { return "Get values from the user's Microsoft Edge Windows App key"; }
sub getDescr {}
sub getRefs {}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
my $VERSION = getVersion();
my (@ts,$d);
my @arr;
sub pluginmain {
my $class = shift;
my $hive = shift;
::rptMsg("msedge_win10 v.".$VERSION);
::rptMsg("(".getHive().") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
# First, let's find out is Microsoft Edge was used to type any URL
my $version;
my $tag = 0;
my @globalitems = ();
my $key_path = "Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppContainer\\Storage\\microsoft.microsoftedge_8wekyb3d8bbwe\\MicrosoftEdge\\TypedURLsVisitCount";
my $key = $root_key->get_subkey($key_path);
if (defined($key)) {
$tag = 1;
}
else {
::rptMsg($key_path." not found.");
}
#TypedURLs
if ($tag) {
my $key_path = "Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppContainer\\Storage\\microsoft.microsoftedge_8wekyb3d8bbwe\\MicrosoftEdge\\TypedURLs";
my $key;
if ($key = $root_key->get_subkey($key_path)) {
my %vals = getKeyValues($key);
foreach my $v (keys %vals) {
push @arr,($v." (TypedURLs) -> ".$vals{$v});
}
}
else {
::rptMsg("");
::rptMsg($key_path." has no subkeys.");
}
}
#TypedURLsTime
if ($tag) {
my $key_path = "Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppContainer\\Storage\\microsoft.microsoftedge_8wekyb3d8bbwe\\MicrosoftEdge\\TypedURLsTime";
my $key;
if ($key = $root_key->get_subkey($key_path)) {
my %vals = getKeyValues($key);
foreach my $v (keys %vals) {
@ts = unpack("VV",$key->get_value($v)->get_data());
push @arr, ($v." (TypedURLsTime) -> ".gmtime(::getTime($ts[0],$ts[1]))." (UTC)");
}
}
else {
::rptMsg("");
::rptMsg($key_path." has no subkeys.");
}
}
#TypedURLsVisitCount
if ($tag) {
my $key_path = "Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppContainer\\Storage\\microsoft.microsoftedge_8wekyb3d8bbwe\\MicrosoftEdge\\TypedURLsVisitCount";
my $key;
if ($key = $root_key->get_subkey($key_path)) {
my %vals = getKeyValues($key);
foreach my $v (keys %vals) {
push @arr, ($v." (TypedURLsVisitCount) -> ".$vals{$v}."\r\n");
}
}
else {
::rptMsg("");
::rptMsg($key_path." has no subkeys.");
}
}
if (scalar(@arr) > 0) {
#sort items in the array
::rptMsg("|-- \\Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppContainer\\Storage\\microsoft.microsoftedge_8wekyb3d8bbwe");
::rptMsg("|----- \\MicrosoftEdge\\TypedURLs");
::rptMsg("|----- \\MicrosoftEdge\\TypedURLsTime");
::rptMsg("|----- \\MicrosoftEdge\\TypedURLsVisitCount");
::rptMsg("");
foreach my $i (sort @arr){
::rptMsg($i);
}
}
}
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;

View File

@ -0,0 +1,82 @@
#-----------------------------------------------------------
# mzthunderbird.pl
# Gets Thunderbird profile data
#
# Change history
# 20180712 - created
#
# References
# https://www.thunderbird.net/en-US/
#
# Author: M. Jones, mictjon@gmail.com
#-----------------------------------------------------------
package mzthunderbird;
use strict;
my %config = (hive => "NTUSER\.DAT",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20180712);
sub getConfig{return %config}
sub getShortDescr {
return "Gets Thunderbird profile data";
}
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 mzthunderbird v.".$VERSION);
::rptMsg("mzthunderbird v.".$VERSION); # banner
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
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("Thunderbird Email Addresses");
::rptMsg($key_path);
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 ($app,$msgct,$ts);
eval {
$app = $s->get_value("Application")->get_data();
::rptMsg(" Application: ".$app);
};
eval {
$msgct = $s->get_value("MessageCount")->get_data();
::rptMsg(" MessageCount: ".$msgct);
};
eval {
my ($t0,$t1) = unpack("VV",$s->get_value("TimeStamp")->get_data());
my $t = ::getTime($t0,$t1);
::rptMsg(" TimeStamp: ".gmtime($t));
};
::rptMsg("");
}
}
else {
::rptMsg($key_path." has no subkeys.");
}
}
else {
::rptMsg($key_path." not found.");
}
}
1;

365
thirdparty/rr-full/plugins/nation.pl vendored Normal file
View File

@ -0,0 +1,365 @@
#-----------------------------------------------------------
# nation.pl
# Region Information
# Get Geo Nation information from the NTUSER.DAT hive file
#
# Written By:
# Fahad Alzaabi
# falzaab@masonlive.gmu.edu
# George Mason University,CFRS 763
#-----------------------------------------------------------
package nation;
use strict;
my %config = (hive => "ntuser.dat",
osmask => 22,
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
version => 20091116);
sub getConfig{return %config}
sub getShortDescr {
return "Gets region information from HKCU";
}
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 nation v.".$VERSION);
::rptMsg("nation v.".$VERSION);
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key_path = "Control Panel\\International\\Geo";
my $key;
if ($key = $root_key->get_subkey($key_path)) {
::rptMsg("Nation Information Check");
::rptMsg($key_path);
::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
::rptMsg("");
my $nation = $key->get_value("Nation")->get_data();
::rptMsg("The Region value is : ".$nation);
::rptMsg("The Country Is: Antigua and Barbuda") if ($nation == 2);
::rptMsg("The Country Is: Afghanistan") if ($nation == 3);
::rptMsg("The Country Is: Algeria") if ($nation == 4);
::rptMsg("The Country Is: Azerbaijan") if ($nation == 5);
::rptMsg("The Country Is: Albania") if ($nation == 6);
::rptMsg("The Country Is: Armenia") if ($nation == 7);
::rptMsg("The Country Is: Andorra") if ($nation == 8);
::rptMsg("The Country Is: Angola") if ($nation == 9);
::rptMsg("The Country Is: American Samoa") if ($nation == 10);
::rptMsg("The Country Is: Argentina") if ($nation == 11);
::rptMsg("The Country Is: Australia") if ($nation == 12);
::rptMsg("The Country Is: Austria") if ($nation == 14);
::rptMsg("The Country Is: Bahrain") if ($nation == 17);
::rptMsg("The Country Is: Barbados") if ($nation == 18);
::rptMsg("The Country Is: Botswana") if ($nation == 19);
::rptMsg("The Country Is: Bermuda") if ($nation == 20);
::rptMsg("The Country Is: Belgium") if ($nation == 21);
::rptMsg("The Country Is: Bahamas The") if ($nation == 22);
::rptMsg("The Country Is: Bangladesh") if ($nation == 23);
::rptMsg("The Country Is: Belize") if ($nation == 24);
::rptMsg("The Country Is: Bosnia and Herzegovina") if ($nation == 25);
::rptMsg("The Country Is: Bolivia") if ($nation == 26);
::rptMsg("The Country Is: Myanmar") if ($nation == 27);
::rptMsg("The Country Is: Benin") if ($nation == 28);
::rptMsg("The Country Is: Belarus") if ($nation == 29);
::rptMsg("The Country Is: Solomon Islands") if ($nation == 30);
::rptMsg("The Country Is: Brazil") if ($nation == 32);
::rptMsg("The Country Is: Bhutan") if ($nation == 34);
::rptMsg("The Country Is: Bulgaria") if ($nation == 35);
::rptMsg("The Country Is: Brunei") if ($nation == 37);
::rptMsg("The Country Is: Burundi") if ($nation == 38);
::rptMsg("The Country Is: Canada") if ($nation == 39);
::rptMsg("The Country Is: Cambodia") if ($nation == 40);
::rptMsg("The Country Is: Chad") if ($nation == 41);
::rptMsg("The Country Is: Sri Lanka") if ($nation == 42);
::rptMsg("The Country Is: Congo") if ($nation == 43);
::rptMsg("The Country Is: Congo (DRC)") if ($nation == 44);
::rptMsg("The Country Is: China") if ($nation == 45);
::rptMsg("The Country Is: Chile") if ($nation == 46);
::rptMsg("The Country Is: Cameroon") if ($nation == 49);
::rptMsg("The Country Is: Comoros") if ($nation == 50);
::rptMsg("The Country Is: Colombia") if ($nation == 51);
::rptMsg("The Country Is: Costa Rica") if ($nation == 54);
::rptMsg("The Country Is: Central African Republic") if ($nation == 55);
::rptMsg("The Country Is: Cuba") if ($nation == 56);
::rptMsg("The Country Is: Cabo Verde") if ($nation == 57);
::rptMsg("The Country Is: Cyprus") if ($nation == 59);
::rptMsg("The Country Is: Denmark") if ($nation == 61);
::rptMsg("The Country Is: Djibouti") if ($nation == 62);
::rptMsg("The Country Is: Dominica") if ($nation == 63);
::rptMsg("The Country Is: Dominican Republic") if ($nation == 65);
::rptMsg("The Country Is: Ecuador") if ($nation == 66);
::rptMsg("The Country Is: Egypt") if ($nation == 67);
::rptMsg("The Country Is: Ireland") if ($nation == 68);
::rptMsg("The Country Is: Equatorial Guinea") if ($nation == 69);
::rptMsg("The Country Is: Estonia") if ($nation == 70);
::rptMsg("The Country Is: Eritrea") if ($nation == 71);
::rptMsg("The Country Is: El Salvador") if ($nation == 72);
::rptMsg("The Country Is: Ethiopia") if ($nation == 73);
::rptMsg("The Country Is: Czech Republic") if ($nation == 75);
::rptMsg("The Country Is: Finland") if ($nation == 77);
::rptMsg("The Country Is: Fiji") if ($nation == 78);
::rptMsg("The Country Is: Micronesia") if ($nation == 80);
::rptMsg("The Country Is: Faroe Islands") if ($nation == 81);
::rptMsg("The Country Is: France") if ($nation == 84);
::rptMsg("The Country Is: Gambia") if ($nation == 86);
::rptMsg("The Country Is: Gabon") if ($nation == 87);
::rptMsg("The Country Is: Georgia") if ($nation == 88);
::rptMsg("The Country Is: Ghana") if ($nation == 89);
::rptMsg("The Country Is: Gibraltar") if ($nation == 90);
::rptMsg("The Country Is: Grenada") if ($nation == 91);
::rptMsg("The Country Is: Greenland") if ($nation == 93);
::rptMsg("The Country Is: Germany") if ($nation == 94);
::rptMsg("The Country Is: Greece") if ($nation == 98);
::rptMsg("The Country Is: Guatemala") if ($nation == 99);
::rptMsg("The Country Is: Guinea") if ($nation == 100);
::rptMsg("The Country Is: Guyana") if ($nation == 101);
::rptMsg("The Country Is: Haiti") if ($nation == 103);
::rptMsg("The Country Is: Hong Kong ") if ($nation == 104);
::rptMsg("The Country Is: Honduras") if ($nation == 106);
::rptMsg("The Country Is: Croatia") if ($nation == 108);
::rptMsg("The Country Is: Hungary") if ($nation == 109);
::rptMsg("The Country Is: Iceland") if ($nation == 110);
::rptMsg("The Country Is: Indonesia") if ($nation == 111);
::rptMsg("The Country Is: India") if ($nation == 113);
::rptMsg("The Country Is: British Indian Ocean Territory") if ($nation == 114);
::rptMsg("The Country Is: Iran") if ($nation == 116);
::rptMsg("The Country Is: Israel") if ($nation == 117);
::rptMsg("The Country Is: Italy") if ($nation == 118);
::rptMsg("The Country Is: Côte dIvoire") if ($nation == 119);
::rptMsg("The Country Is: Iraq") if ($nation == 121);
::rptMsg("The Country Is: Japan") if ($nation == 122);
::rptMsg("The Country Is: Jamaica") if ($nation == 124);
::rptMsg("The Country Is: Jan Mayen") if ($nation == 125);
::rptMsg("The Country Is: Jordan") if ($nation == 126);
::rptMsg("The Country Is: Johnston Atoll") if ($nation == 127);
::rptMsg("The Country Is: Kenya") if ($nation == 129);
::rptMsg("The Country Is: Kyrgyzstan") if ($nation == 130);
::rptMsg("The Country Is: North Korea") if ($nation == 131);
::rptMsg("The Country Is: Kiribati") if ($nation == 133);
::rptMsg("The Country Is: Korea") if ($nation == 134);
::rptMsg("The Country Is: Kuwait") if ($nation == 136);
::rptMsg("The Country Is: Kazakhstan") if ($nation == 137);
::rptMsg("The Country Is: Laos") if ($nation == 138);
::rptMsg("The Country Is: Lebanon") if ($nation == 139);
::rptMsg("The Country Is: Latvia") if ($nation == 140);
::rptMsg("The Country Is: Lithuania") if ($nation == 141);
::rptMsg("The Country Is: Liberia") if ($nation == 142);
::rptMsg("The Country Is: Slovakia") if ($nation == 143);
::rptMsg("The Country Is: Liechtenstein") if ($nation == 145);
::rptMsg("The Country Is: Lesotho") if ($nation == 146);
::rptMsg("The Country Is: Luxembourg") if ($nation == 147);
::rptMsg("The Country Is: Libya") if ($nation == 148);
::rptMsg("The Country Is: Madagascar") if ($nation == 149);
::rptMsg("The Country Is: Macao") if ($nation == 151);
::rptMsg("The Country Is: Moldova") if ($nation == 152);
::rptMsg("The Country Is: Mongolia") if ($nation == 154);
::rptMsg("The Country Is: Malawi") if ($nation == 156);
::rptMsg("The Country Is: Mali") if ($nation == 157);
::rptMsg("The Country Is: Monaco") if ($nation == 158);
::rptMsg("The Country Is: Morocco") if ($nation == 159);
::rptMsg("The Country Is: Mauritius") if ($nation == 160);
::rptMsg("The Country Is: Mauritania") if ($nation == 162);
::rptMsg("The Country Is: Malta") if ($nation == 163);
::rptMsg("The Country Is: Oman") if ($nation == 164);
::rptMsg("The Country Is: Maldives") if ($nation == 165);
::rptMsg("The Country Is: Mexico") if ($nation == 166);
::rptMsg("The Country Is: Malaysia") if ($nation == 167);
::rptMsg("The Country Is: Mozambique") if ($nation == 168);
::rptMsg("The Country Is: Niger") if ($nation == 173);
::rptMsg("The Country Is: Vanuatu") if ($nation == 174);
::rptMsg("The Country Is: Nigeria") if ($nation == 175);
::rptMsg("The Country Is: Netherlands") if ($nation == 176);
::rptMsg("The Country Is: Norway") if ($nation == 177);
::rptMsg("The Country Is: Nepal") if ($nation == 178);
::rptMsg("The Country Is: Nauru") if ($nation == 180);
::rptMsg("The Country Is: Suriname") if ($nation == 181);
::rptMsg("The Country Is: Nicaragua") if ($nation == 182);
::rptMsg("The Country Is: New Zealand") if ($nation == 183);
::rptMsg("The Country Is: Palestinian Authority") if ($nation == 184);
::rptMsg("The Country Is: Paraguay") if ($nation == 185);
::rptMsg("The Country Is: Peru") if ($nation == 187);
::rptMsg("The Country Is: Pakistan") if ($nation == 190);
::rptMsg("The Country Is: Poland") if ($nation == 191);
::rptMsg("The Country Is: Panama") if ($nation == 192);
::rptMsg("The Country Is: Portugal") if ($nation == 193);
::rptMsg("The Country Is: Papua New Guinea") if ($nation == 194);
::rptMsg("The Country Is: Palau") if ($nation == 195);
::rptMsg("The Country Is: Guinea-Bissau") if ($nation == 196);
::rptMsg("The Country Is: Qatar") if ($nation == 197);
::rptMsg("The Country Is: Réunion") if ($nation == 198);
::rptMsg("The Country Is: Marshall Islands") if ($nation == 199);
::rptMsg("The Country Is: Romania") if ($nation == 200);
::rptMsg("The Country Is: Philippines") if ($nation == 201);
::rptMsg("The Country Is: Puerto Rico") if ($nation == 202);
::rptMsg("The Country Is: Russia") if ($nation == 203);
::rptMsg("The Country Is: Rwanda") if ($nation == 204);
::rptMsg("The Country Is: Saudi Arabia") if ($nation == 205);
::rptMsg("The Country Is: Saint Pierre and Miquelon") if ($nation == 206);
::rptMsg("The Country Is: Saint Kitts and Nevis") if ($nation == 207);
::rptMsg("The Country Is: Seychelles") if ($nation == 208);
::rptMsg("The Country Is: South Africa") if ($nation == 209);
::rptMsg("The Country Is: Senegal") if ($nation == 210);
::rptMsg("The Country Is: Slovenia") if ($nation == 212);
::rptMsg("The Country Is: Sierra Leone") if ($nation == 213);
::rptMsg("The Country Is: San Marino") if ($nation == 214);
::rptMsg("The Country Is: Singapore") if ($nation == 215);
::rptMsg("The Country Is: Somalia") if ($nation == 216);
::rptMsg("The Country Is: Spain") if ($nation == 217);
::rptMsg("The Country Is: Saint Lucia") if ($nation == 218);
::rptMsg("The Country Is: Sudan") if ($nation == 219);
::rptMsg("The Country Is: Svalbard") if ($nation == 220);
::rptMsg("The Country Is: Sweden") if ($nation == 221);
::rptMsg("The Country Is: Syria") if ($nation == 222);
::rptMsg("The Country Is: Switzerland") if ($nation == 223);
::rptMsg("The Country Is: United Arab Emirates") if ($nation == 224);
::rptMsg("The Country Is: Trinidad and Tobago") if ($nation == 225);
::rptMsg("The Country Is: Thailand") if ($nation == 227);
::rptMsg("The Country Is: Tajikistan") if ($nation == 228);
::rptMsg("The Country Is: Tonga") if ($nation == 231);
::rptMsg("The Country Is: Togo") if ($nation == 232);
::rptMsg("The Country Is: São Tomé and Príncipe") if ($nation == 233);
::rptMsg("The Country Is: Tunisia") if ($nation == 234);
::rptMsg("The Country Is: Turkey") if ($nation == 235);
::rptMsg("The Country Is: Tuvalu") if ($nation == 236);
::rptMsg("The Country Is: Taiwan") if ($nation == 237);
::rptMsg("The Country Is: Turkmenistan") if ($nation == 238);
::rptMsg("The Country Is: Tanzania") if ($nation == 239);
::rptMsg("The Country Is: Uganda") if ($nation == 240);
::rptMsg("The Country Is: Ukraine") if ($nation == 241);
::rptMsg("The Country Is: United Kingdom") if ($nation == 242);
::rptMsg("The Country Is: United States") if ($nation == 244);
::rptMsg("The Country Is: Burkina Faso") if ($nation == 245);
::rptMsg("The Country Is: Uruguay") if ($nation == 246);
::rptMsg("The Country Is: Uzbekistan") if ($nation == 247);
::rptMsg("The Country Is: Saint Vincent and the Grenadines") if ($nation == 248);
::rptMsg("The Country Is: Venezuela") if ($nation == 249);
::rptMsg("The Country Is: Vietnam") if ($nation == 251);
::rptMsg("The Country Is: U.S. Virgin Islands") if ($nation == 252);
::rptMsg("The Country Is: Vatican City") if ($nation == 253);
::rptMsg("The Country Is: Namibia") if ($nation == 254);
::rptMsg("The Country Is: Wake Island") if ($nation == 258);
::rptMsg("The Country Is: Samoa") if ($nation == 259);
::rptMsg("The Country Is: Swaziland") if ($nation == 260);
::rptMsg("The Country Is: Yemen") if ($nation == 261);
::rptMsg("The Country Is: Zambia") if ($nation == 263);
::rptMsg("The Country Is: Zimbabwe") if ($nation == 264);
::rptMsg("The Country Is: Serbia and Montenegro (Former)") if ($nation == 269);
::rptMsg("The Country Is: Montenegro") if ($nation == 270);
::rptMsg("The Country Is: Serbia") if ($nation == 271);
::rptMsg("The Country Is: Curaçao") if ($nation == 273);
::rptMsg("The Country Is: Anguilla") if ($nation == 300);
::rptMsg("The Country Is: South Sudan") if ($nation == 276);
::rptMsg("The Country Is: Antarctica") if ($nation == 301);
::rptMsg("The Country Is: Aruba") if ($nation == 302);
::rptMsg("The Country Is: Ascension Island") if ($nation == 303);
::rptMsg("The Country Is: Ashmore and Cartier Islands") if ($nation == 304);
::rptMsg("The Country Is: Baker sland") if ($nation == 305);
::rptMsg("The Country Is: Bouvet Island") if ($nation == 306);
::rptMsg("The Country Is: Cayman Islands") if ($nation == 307);
::rptMsg("The Country Is: Channel Islands") if ($nation == 308);
::rptMsg("The Country Is: Christmas Island") if ($nation == 309);
::rptMsg("The Country Is: Clipperton Island") if ($nation == 310);
::rptMsg("The Country Is: Cocos (Keeling) Islands") if ($nation == 311);
::rptMsg("The Country Is: Cook Islands") if ($nation == 312);
::rptMsg("The Country Is: Coral Sea Islands") if ($nation == 313);
::rptMsg("The Country Is: Diego Garcia") if ($nation == 314);
::rptMsg("The Country Is: Falkland Islands") if ($nation == 315);
::rptMsg("The Country Is: French Guiana") if ($nation == 317);
::rptMsg("The Country Is: French Polynesia") if ($nation == 318);
::rptMsg("The Country Is: French Southern Territories") if ($nation == 319);
::rptMsg("The Country Is: Guadeloupe") if ($nation == 321);
::rptMsg("The Country Is: Guam") if ($nation == 322);
::rptMsg("The Country Is: Guantanamo Bay") if ($nation == 323);
::rptMsg("The Country Is: Guernsey") if ($nation == 324);
::rptMsg("The Country Is: Heard Island and Mcdonald Islands") if ($nation == 325);
::rptMsg("The Country Is: Howland Island") if ($nation == 326);
::rptMsg("The Country Is: Jarvis Island") if ($nation == 327);
::rptMsg("The Country Is: Jersey") if ($nation == 328);
::rptMsg("The Country Is: Kingman Reef") if ($nation == 329);
::rptMsg("The Country Is: Martinique") if ($nation == 330);
::rptMsg("The Country Is: Mayotte") if ($nation == 331);
::rptMsg("The Country Is: Montserrat") if ($nation == 332);
::rptMsg("The Country Is: Netherlands Antilles (Former)") if ($nation == 333);
::rptMsg("The Country Is: New Caledonia") if ($nation == 334);
::rptMsg("The Country Is: Niue") if ($nation == 335);
::rptMsg("The Country Is: Norfolk Island") if ($nation == 336);
::rptMsg("The Country Is: Northern Mariana Islands") if ($nation == 337);
::rptMsg("The Country Is: Palmyra Atoll") if ($nation == 338);
::rptMsg("The Country Is: Pitcairn Islands") if ($nation == 339);
::rptMsg("The Country Is: Rota Island") if ($nation == 340);
::rptMsg("The Country Is: Saipan") if ($nation == 341);
::rptMsg("The Country Is: South Georgia and the South Sandwich Islands") if ($nation == 342);
::rptMsg("The Country Is: St Helena Ascension and Tristan da Cunha") if ($nation == 343);
::rptMsg("The Country Is: Tinian Island") if ($nation == 346);
::rptMsg("The Country Is: Tokelau") if ($nation == 347);
::rptMsg("The Country Is: Tristan da Cunha") if ($nation == 348);
::rptMsg("The Country Is: Turks and Caicos Islands") if ($nation == 349);
::rptMsg("The Country Is: British Virgin Islands") if ($nation == 351);
::rptMsg("The Country Is: Wallis and Futuna") if ($nation == 352);
::rptMsg("The Country Is: Africa") if ($nation == 742);
::rptMsg("The Country Is: Asia") if ($nation == 2129);
::rptMsg("The Country Is: Europe") if ($nation == 10541);
::rptMsg("The Country Is: Isle of Man") if ($nation == 15126);
::rptMsg("The Country Is: Macedonia") if ($nation == 19618);
::rptMsg("The Country Is: Melanesia") if ($nation == 20900);
::rptMsg("The Country Is: Micronesia") if ($nation == 21206);
::rptMsg("The Country Is: Midway Islands") if ($nation == 21242);
::rptMsg("The Country Is: Northern America") if ($nation == 23581);
::rptMsg("The Country Is: Polynesia") if ($nation == 26286);
::rptMsg("The Country Is: Central America") if ($nation == 27082);
::rptMsg("The Country Is: Oceania") if ($nation == 27114);
::rptMsg("The Country Is: Sint Maarten") if ($nation == 30967);
::rptMsg("The Country Is: South America") if ($nation == 31396);
::rptMsg("The Country Is: Saint Martin") if ($nation == 31706);
::rptMsg("The Country Is: World") if ($nation == 39070);
::rptMsg("The Country Is: Western Africa") if ($nation == 42483);
::rptMsg("The Country Is: Middle Africa") if ($nation == 42484);
::rptMsg("The Country Is: Northern Africa") if ($nation == 42487);
::rptMsg("The Country Is: Central Asia") if ($nation == 47590);
::rptMsg("The Country Is: South-Eastern Asia") if ($nation == 47599);
::rptMsg("The Country Is: Eastern Asia") if ($nation == 47600);
::rptMsg("The Country Is: Eastern Africa") if ($nation == 47603);
::rptMsg("The Country Is: Eastern Europe") if ($nation == 47609);
::rptMsg("The Country Is: Southern Europe") if ($nation == 47610);
::rptMsg("The Country Is: Middle East") if ($nation == 47611);
::rptMsg("The Country Is: Southern Asia") if ($nation == 47614);
::rptMsg("The Country Is: Timor-Leste") if ($nation == 7299303);
::rptMsg("The Country Is: Kosovo") if ($nation == 9914689);
::rptMsg("The Country Is: Americas") if ($nation == 10026358);
::rptMsg("The Country Is: Åland Islands") if ($nation == 10028789);
::rptMsg("The Country Is: Caribbean") if ($nation == 10039880);
::rptMsg("The Country Is: Northern Europe") if ($nation == 10039882);
::rptMsg("The Country Is: Southern Africa") if ($nation == 10039883);
::rptMsg("The Country Is: Western Europe") if ($nation == 10210824);
::rptMsg("The Country Is: Australia and New Zealand") if ($nation == 10210825);
::rptMsg("The Country Is: Saint Barthélemy") if ($nation == 161832015);
::rptMsg("The Country Is: U.S. Minor Outlying Islands") if ($nation == 161832256);
::rptMsg("The Country Is: Latin America and the Caribbean") if ($nation == 161832257);
::rptMsg("The Country Is: Bonaire Saint Eustatius and Saba") if ($nation == 161832258);
::rptMsg("For more information please visit the link below:");
::rptMsg("https://msdn.microsoft.com/en-us/library/aa723531.aspx");
}
else {
::rptMsg($key_path." not found.");
}
::rptMsg("");
}
1;

92
thirdparty/rr-full/plugins/netlogon.pl vendored Normal file
View File

@ -0,0 +1,92 @@
#-----------------------------------------------------------
# netlogon.pl
#
#
# History:
# 20190223 - created
#
# References:
# https://support.microsoft.com/en-us/help/154501/how-to-disable-automatic-machine-account-password-changes
#
# copyright 2019 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package netlogon;
use strict;
my %config = (hive => "System",
hivemask => 4,
output => "report",
category => "System Config",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 31,
version => 20190223);
sub getConfig{return %config}
sub getShortDescr {
return "Parse values for machine account password changes";
}
sub getDescr{}
sub getRefs {}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
my $VERSION = getVersion();
my @vals;
my $name;
my $data;
my $type;
sub pluginmain {
my $class = shift;
my $hive = shift;
::logMsg("Launching netlogon v.".$VERSION);
::rptMsg("netlogon v.".$VERSION);
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my @sets = ();
my @subkeys = ();
if (@subkeys = $root_key->get_list_of_subkeys()) {
foreach my $s (@subkeys) {
my $name = $s->get_name();
push(@sets,$name) if ($name =~ m/^ControlSet/);
}
}
my $set;
foreach $set (@sets) {
::rptMsg("*** ".$set." ***");
my $key_path = $set."\\services\\NetLogon\\Parameters";
my $key;
if ($key = $root_key->get_subkey($key_path)) {
# ::rptMsg("LastWrite Time: ".gmtime($key->get_timestamp())." Z");
@vals = $key->get_list_of_values();
if (scalar @vals > 0) {
foreach my $v (@vals) {
$name = $v->get_name();
$data = $v->get_data();
$type = $v->get_type();
if ($type == 4) {
::rptMsg(sprintf "%-35s 0x%04x",$name,$data);
}
else {
::rptMsg(sprintf "%-35s $data",$name);
}
}
}
else {
# no values
}
}
else {
::rptMsg($key_path." not found.");
}
::rptMsg("");
}
}
1;

View File

@ -4,11 +4,15 @@
# #
# References # References
# http://www.adaptforward.com/2016/09/using-netshell-to-execute-evil-dlls-and-persist-on-a-host/ # http://www.adaptforward.com/2016/09/using-netshell-to-execute-evil-dlls-and-persist-on-a-host/
# https://attack.mitre.org/techniques/T1128/
# https://htmlpreview.github.io/?https://github.com/MatthewDemaske/blogbackup/blob/master/netshell.html
# #
# Change history # Change history
# 20190316 - updated references
# 20160926 - created # 20160926 - created
# #
# Copyright 2016 QAR, LLC # Copyright 2019 QAR, LLC
# Author: H. Carvey, keydet89@yahoo.com
#----------------------------------------------------------- #-----------------------------------------------------------
package netsh; package netsh;
use strict; use strict;
@ -18,7 +22,7 @@ my %config = (hive => "Software",
hasShortDescr => 1, hasShortDescr => 1,
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
version => 20160926); version => 20190316);
sub getConfig{return %config} sub getConfig{return %config}
@ -45,12 +49,13 @@ sub pluginmain {
if ($key = $root_key->get_subkey($key_path)) { if ($key = $root_key->get_subkey($key_path)) {
::rptMsg($key_path); ::rptMsg($key_path);
::rptMsg("LastWrite: ".gmtime($key->get_timestamp())." Z"); ::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
::rptMsg("");
my @vals = $key->get_list_of_values(); my @vals = $key->get_list_of_values();
if (scalar(@vals) > 0) { if (scalar @vals > 0) {
::rptMsg("");
::rptMsg(sprintf "%-15s %-25s","Name","DLL Name");
foreach my $v (@vals) { foreach my $v (@vals) {
::rptMsg(sprintf "%-15s %-30s",$v->get_name(),$v->get_data()); ::rptMsg(sprintf "%-15s %-25s",$v->get_name(),$v->get_data());
} }
} }
} }

View File

@ -5,6 +5,7 @@
# #
# #
# Change History: # Change History:
# 20190128 - Added Nla\Wireless data
# 20150812 - updated to include Nla\Cache data # 20150812 - updated to include Nla\Cache data
# 20120917 - updated to include NameType value # 20120917 - updated to include NameType value
# 20090812 - updated code to parse DateCreated and DateLastConnected # 20090812 - updated code to parse DateCreated and DateLastConnected
@ -24,7 +25,7 @@ my %config = (hive => "Software",
hasShortDescr => 1, hasShortDescr => 1,
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
version => 20150812); version => 20190128);
sub getConfig{return %config} sub getConfig{return %config}
@ -125,7 +126,7 @@ sub pluginmain {
foreach my $n (keys %nl) { foreach my $n (keys %nl) {
my $str = sprintf "%-15s Gateway Mac: ".$nl{$n}{DefaultGatewayMac},$nl{$n}{ProfileName}; my $str = sprintf "%-15s Gateway Mac: ".$nl{$n}{DefaultGatewayMac},$nl{$n}{ProfileName};
::rptMsg($nl{$n}{ProfileName}); ::rptMsg($nl{$n}{ProfileName});
::rptMsg(" Key LastWrite : ".gmtime($nl{$n}{LastWrite})." Z"); # ::rptMsg(" Key LastWrite : ".gmtime($nl{$n}{LastWrite})." Z");
::rptMsg(" DateLastConnected: ".$nl{$n}{DateLastConnected}); ::rptMsg(" DateLastConnected: ".$nl{$n}{DateLastConnected});
::rptMsg(" DateCreated : ".$nl{$n}{DateCreated}); ::rptMsg(" DateCreated : ".$nl{$n}{DateCreated});
::rptMsg(" DefaultGatewayMac: ".$nl{$n}{DefaultGatewayMac}); ::rptMsg(" DefaultGatewayMac: ".$nl{$n}{DefaultGatewayMac});
@ -147,9 +148,30 @@ sub pluginmain {
if ($key = $root_key->get_subkey($key_path)) { if ($key = $root_key->get_subkey($key_path)) {
my @subkeys = $key->get_list_of_subkeys(); my @subkeys = $key->get_list_of_subkeys();
if (scalar(@subkeys) > 0) { if (scalar(@subkeys) > 0) {
::rptMsg(sprintf "%-26s %-30s","Date","Domain/IP"); # ::rptMsg(sprintf "%-26s %-30s","Date","Domain/IP");
::rptMsg(sprintf "%-30s","Domain/IP");
foreach my $s (@subkeys) { foreach my $s (@subkeys) {
::rptMsg(sprintf "%-26s %-30s",gmtime($s->get_timestamp())." Z",$s->get_name()); # ::rptMsg(sprintf "%-26s %-30s",gmtime($s->get_timestamp())." Z",$s->get_name());
::rptMsg(sprintf "%-30s",$s->get_name());
}
}
}
::rptMsg("");
# Added 20190128 - Nla\Wireless data
$key_path = $base_path."\\Nla\\Wireless";
if ($key = $root_key->get_subkey($key_path)) {
my @subkeys = $key->get_list_of_subkeys();
if (scalar(@subkeys) > 0) {
::rptMsg("");
::rptMsg("Nla\\Wireless");
foreach my $s (@subkeys) {
my $str = $s->get_value("")->get_data();
my @list = unpack("(A2)*", $str);
my @chars = map {chr hex} @list;
my $new_str = join('',@chars);
::rptMsg($new_str);
} }
} }
} }

View File

@ -1,29 +1,27 @@
# 20161213 *ALL* Plugins that apply on NTUSER hive, alphabetical order
acmru acmru
adoberdr adoberdr
ahaha
aim aim
aports aports
appassoc
appcompatflags appcompatflags
appkeys
applets applets
applets_tln
appspecific appspecific
ares ares
arpcache arpcache
attachmgr attachmgr
attachmgr_tln
autoendtasks autoendtasks
autorun autorun
bitbucket_user bitbucket_user
brisv brisv
cached cached
cached_tln
cain cain
ccleaner ccleaner
cdstaginginfo cdstaginginfo
clampi clampi
clampitm clampitm
cmdproc cmdproc
cmdproc_tln
comdlg32 comdlg32
compdesc compdesc
controlpanel controlpanel
@ -32,10 +30,13 @@ cpldontload
ddo ddo
decaf decaf
dependency_walker dependency_walker
disablemru
domains domains
environment environment
eraser
fileexts fileexts
filehistory filehistory
foxitrdr
gthist gthist
gtwhitelist gtwhitelist
haven_and_hearth haven_and_hearth
@ -44,31 +45,32 @@ iejava
ie_main ie_main
ie_settings ie_settings
ie_zones ie_zones
imgburn1
internet_explorer_cu internet_explorer_cu
internet_settings_cu internet_settings_cu
itempos itempos
javafx javafx
jumplistdata
kankan kankan
knowndev knowndev
latentbot latentbot
listsoft listsoft
liveContactsGUID liveContactsGUID
load load
logonstats
logonusername logonusername
menuorder menuorder
mixer mixer
mixer_tln
mmc mmc
mmc_tln
mmo mmo
mndmru mndmru
mndmru_tln
mp2 mp2
mp3 mp3
mpmru mpmru
mspaper mspaper
muicache muicache
muicache_tln mzthunderbird
nation
nero nero
netassist netassist
ntusernetwork ntusernetwork
@ -79,7 +81,6 @@ officedocs2010_tln
oisc oisc
olsearch olsearch
osversion osversion
osversion_tln
outlook outlook
outlook2 outlook2
policies_u policies_u
@ -88,20 +89,24 @@ printers
privoxy privoxy
profiler profiler
proxysettings proxysettings
pslogging
publishingwizard publishingwizard
putty putty
putty_sessions
rdphint rdphint
reading_locations reading_locations
realplayer6 realplayer6
realvnc realvnc
recentapps
recentdocs recentdocs
recentdocs_tln recentdocs_timeline
reveton reveton
rootkit_revealer rootkit_revealer
runmru runmru
runmru_tln searchscopes
sevenzip sevenzip
shc shc
shellactivities
shellbags_xp shellbags_xp
shellfolders shellfolders
skype skype
@ -111,25 +116,20 @@ startmenuinternetapps_cu
startpage startpage
startup startup
sysinternals sysinternals
sysinternals_tln thunderbirdinstalled
trustrecords trustrecords
trustrecords_tln
tsclient tsclient
tsclient_tln
typedpaths typedpaths
typedpaths_tln
typedurls typedurls
typedurlstime typedurlstime
typedurlstime_tln uninstall
typedurls_tln
unreadmail unreadmail
urun_tln
userassist userassist
userassist_tln
userinfo userinfo
userlocsvc userlocsvc
user_run user_run
user_win user_win
utorrent
vawtrak vawtrak
vista_bitbucket vista_bitbucket
vmplayer vmplayer
@ -141,7 +141,6 @@ warcraft3
winlogon_u winlogon_u
winrar winrar
winrar2 winrar2
winrar_tln
winscp winscp
winscp_sessions winscp_sessions
winvnc winvnc

View File

@ -0,0 +1,191 @@
#-----------------------------------------------------------
# photos_win10.pl
# Plugin for RegRipper
#
# Parses Microsoft Photos (Windows App) key:
# - USRCLASS.DAT\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\SystemAppData\Microsoft.Windows.Photos_8wekyb3d8bbwe
#
# On a live machine, the key path is:
# - HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\SystemAppData\Microsoft.Windows.Photos_8wekyb3d8bbwe
#
# The script was tested on Windows 10 against:
# - Microsoft.Windows.Photos_2017.37071.16410.0_x64__8wekyb3d8bbwe
# - Microsoft.Windows.Photos_2018.18022.15810.1000_x64__8wekyb3d8bbwe
#
# The script code is based on:
# - adoberdr.pl/landesk.pl/photos.pl by H. Carvey
# - iexplore.pl by E. Rye esten@ryezone.net
# http://www.ryezone.net/regripper-and-internet-explorer-1
#
# Change history
# 20180610 - First release
#
# To Dos
# Extract value name "Link"
#
# References
# https://forensenellanebbia.blogspot.com/2018/06/usrclassdat-stores-more-history-than.html
# https://df-stream.com/2013/03/windows-8-tracking-opened-photos/
#
# copyright 2018 Gabriele Zambelli <forensenellanebbia@gmail.com> | Twitter: @gazambelli
#-----------------------------------------------------------
package photos_win10;
use strict;
my %config = (hive => "USRCLASS\.DAT",
osmask => 22,
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
version => 20180610);
sub getShortDescr { return "Get values from the user's Microsoft Photos Windows App key"; }
sub getDescr {}
sub getRefs {}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
my $VERSION = getVersion();
my (@ts,$d);
sub pluginmain {
my $class = shift;
my $hive = shift;
::rptMsg("photos_win10 v.".$VERSION);
::rptMsg("(".getHive().") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
# First, let's find out which version of Microsoft Photos is installed
my $version;
my $tag = 0;
my @globalitems = ();
my $key_path = "Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppModel\\SystemAppData\\Microsoft.Windows.Photos_8wekyb3d8bbwe\\Schemas";
my $key = $root_key->get_subkey($key_path);
if (defined($key)) {
my %vals = getKeyValues($key);
foreach my $v (keys %vals) {
if ($v =~ m/^PackageFullName/) {
#Version of Microsoft Photos App
::rptMsg($key_path);
::rptMsg(" PackageFullName => ".($vals{$v}));
$tag = 1;
}
}
}
else {
::rptMsg($key_path." not found.");
}
#Print SubKey, Last Write Time, Viewed Picture
if ($tag) {
my $key_path = "Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppModel\\SystemAppData\\Microsoft.Windows.Photos_8wekyb3d8bbwe\\PersistedStorageItemTable\\ManagedByApp";
my $key;
if ($key = $root_key->get_subkey($key_path)) {
my %vals = getKeyValues($key);
if (scalar(keys %vals) > 0) {
foreach my $v (keys %vals) {
::rptMsg("\t".$v." -> ".$vals{$v});
}
}
my @sk = $key->get_list_of_subkeys();
if (scalar(@sk) > 0) {
::rptMsg("");
::rptMsg($key_path);
foreach my $s (@sk) {
::rptMsg("");
::rptMsg(" ".$s->get_name());
::rptMsg(" KeyLastWrite : ".gmtime($s->get_timestamp())." (UTC)");
my %vals = getKeyValues($s);
foreach my $v (keys %vals) {
if ($v =~ m/^Metadata/) {
#Metadata contains the path to the viewed picture
::rptMsg(" Metadata : ".$vals{$v});
}
if ($v =~ m/^LastUpdatedTime/) {
#LastUpdatedTime
@ts = unpack("VV",$s->get_value($v)->get_data());
::rptMsg(" LastUpdatedTime: ".gmtime(::getTime($ts[0],$ts[1]))." (UTC)");
}
}
}
}
else {
::rptMsg("");
::rptMsg($key_path." has no subkeys.");
}
}
else {
::rptMsg($key_path." not found.");
::logMsg($key_path." not found.");
}
}
#Print Viewed Picture | Write Time
if ($tag) {
my $key_path = "Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppModel\\SystemAppData\\Microsoft.Windows.Photos_8wekyb3d8bbwe\\PersistedStorageItemTable\\ManagedByApp";
my $key;
if ($key = $root_key->get_subkey($key_path)) {
my %vals = getKeyValues($key);
my @sk = $key->get_list_of_subkeys();
if (scalar(@sk) > 0) {
::rptMsg("");
::rptMsg("");
::rptMsg("## Microsoft Photos (Windows App): Recent Files ## (Tab-separated values)");
::rptMsg("");
my @sitems; #create new array for sorted items
foreach my $s (@sk) {
my %vals = getKeyValues($s);
foreach my $v (keys %vals) {
if ($v =~ m/^Metadata/) {
if ($vals{$v} =~ m/^. /) { #find single character followed by a space at the beginning of the string
my $sd; #single digit
$sd = substr($vals{$v},0,1);
$vals{$v} =~ s/^. / $sd /g; #change from "^\. " to "^ \. ", Microsoft Photos 2018 prepends a number in front of the path
push @sitems, ($vals{$v}."\t".gmtime($s->get_timestamp()));
}
elsif ($vals{$v} =~ m/^.. /) { #find two characters followed by a space at the beginning of the string
push @sitems, ($vals{$v}."\t".gmtime($s->get_timestamp()));
}
else {
::rptMsg($vals{$v}."\t KeyLastWrite: ".gmtime($s->get_timestamp())." (UTC)");
}
}
}
}
if (scalar(@sitems) > 0) {
#sort alphabetically the items in the array
::rptMsg("Metadata\tKeyLastWrite (UTC)"); #print header row
foreach my $item (sort @sitems){
::rptMsg($item);
}
}
}
::rptMsg("");
}
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;

108
thirdparty/rr-full/plugins/pslogging.pl vendored Normal file
View File

@ -0,0 +1,108 @@
#-----------------------------------------------------------
# pslogging.pl
#
#
# Change history
# 20181209 - created
#
# References
# https://getadmx.com/?Category=Windows_10_2016&Policy=Microsoft.Policies.PowerShell::EnableTranscripting
#
#
# Copyright (c) 2018 QAR, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package pslogging;
use strict;
# Declarations #
my %config = (hive => "NTUSER\.DAT, Software",
hasShortDescr => 0,
hasDescr => 1,
hasRefs => 0,
osmask => 22,
category => "config settings",
version => 20181209);
my $VERSION = getVersion();
# Functions #
sub getConfig {return %config}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
sub getDescr {}
sub getShortDescr {
return "Extracts PowerShell logging settings";
}
sub getRefs {}
sub pluginmain {
# Declarations #
my $class = shift;
my $hive = shift;
# Initialize #
::logMsg("Launching pslogging v.".$VERSION);
::rptMsg("pslogging v.".$VERSION);
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key;
my @paths = ("Software\\Policies\\Microsoft\\Windows\\PowerShell",
"Policies\\Microsoft\\Windows\\PowerShell");
foreach my $key_path (@paths) {
if ($key = $root_key->get_subkey($key_path)) {
# Execution Policy
eval {
my $e_s = $key->get_value("EnableScripts")->get_data();
::rptMsg(" EnableScripts = ".$e_s);
};
eval {
my $e_p = $key->get_value("ExecutionPolicy")->get_data();
::rptMsg(" ExecutionPolicy = ".$e_p);
};
# Module Logging
eval {
my $ml = $key->get_subkey("ModuleLogging")->get_value("EnableModuleLogging")->get_data();
::rptMsg(" ModuleLogging, EnableModuleLogging = ".$ml);
};
# ScriptBlock Logging
eval {
my $sbl = $key->get_subkey("ScriptBlockLogging")->get_value("EnableScriptBlockLogging")->get_data();
::rptMsg(" ScriptBlockLogging, EnableScriptBlockLogging = ".$sbl);
};
eval {
my $sbil = $key->get_subkey("ScriptBlockLogging")->get_value("EnableScriptBlockInvocationLogging")->get_data();
::rptMsg(" ScriptBlockLogging, EnableScriptBlockInvocationLogging = ".$sbil);
};
# Transcription
eval {
my $t_enable = $key->get_subkey("Transcription")->get_value("EnableTranscripting")->get_data();
::rptMsg(" Transcription, EnableTranscripting = ".$t_enable);
};
eval {
my $t_out = $key->get_subkey("Transcription")->get_value("OutputDirectory")->get_data();
::rptMsg(" Transcription, OutputDirectory = ".$t_out);
};
eval {
my $t_eih = $key->get_subkey("Transcription")->get_value("EnableInvocationHeader")->get_data();
::rptMsg(" Transcription, EnableInvocationHeader = ".$t_eih);
};
}
else {
::rptMsg($key_path." not found.");
}
}
}
1;

View File

@ -7,7 +7,7 @@
package rdphint; package rdphint;
use strict; use strict;
my %config = (hive => "NTUSER", my %config = (hive => "NTUSER\.DAT",
osmask => 22, osmask => 22,
hasShortDescr => 1, hasShortDescr => 1,
hasDescr => 0, hasDescr => 0,

View File

@ -4,6 +4,7 @@
# #
# Change history # Change history
# 20140130 - created # 20140130 - created
# 20190211 - added "paragraphID" int to hex conversion
# #
# References # References
# http://dfstream.blogspot.com/2014/01/ms-word-2013-reading-locations.html # http://dfstream.blogspot.com/2014/01/ms-word-2013-reading-locations.html
@ -66,7 +67,9 @@ sub pluginmain {
eval { eval {
my $p = $s->get_value("Position")->get_data(); my $p = $s->get_value("Position")->get_data();
::rptMsg("Position: ".$p); my @ps = split(' ', $p);
my $paraid = sprintf("%X", $ps[0]);
::rptMsg("Position: ".$p." (ParagraphID: ".$paraid.")");
}; };
::rptMsg(""); ::rptMsg("");
} }

View File

@ -0,0 +1,83 @@
#-----------------------------------------------------------
# recentapps.pl
#
# Change history
# 20171013 - created
#
# References
# https://twitter.com/EricRZimmerman/status/916422135987474433
#
# copyright 2017 H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package recentapps;
use strict;
my %config = (hive => "NTUSER\.DAT",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20171013);
sub getConfig{return %config}
sub getShortDescr {
return "Gets contents of user's RecentApps 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 recentapps v.".$VERSION);
::rptMsg("recentapps v.".$VERSION); # banner
::rptMsg("- ".getShortDescr()."\n"); # banner
my $reg = Parse::Win32Registry->new($ntuser);
my $root_key = $reg->get_root_key;
my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Search\\RecentApps';
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) {
eval {
::rptMsg("AppId : ".$s->get_value("AppId")->get_data());
my ($t1,$t2) = unpack("VV",$s->get_value("LastAccessedTime")->get_data());
my $lat = ::getTime($t1,$t2);
::rptMsg("LastAccessedTime: ".gmtime($lat)." UTC");
::rptMsg("LaunchCount : ".$s->get_value("LaunchCount")->get_data());
};
if (my $r = $s->get_subkey("RecentItems")) {
::rptMsg("::RecentItems::");
my @subkeys2 = $s->get_subkey("RecentItems")->get_list_of_subkeys();
if (scalar(@subkeys2 > 0)) {
foreach my $r (@subkeys2) {
eval {
::rptMsg(" Path : ".$r->get_value("Path")->get_data());
my ($l1,$l2) = unpack("VV",$r->get_value("LastAccessedTime")->get_data());
my $l = ::getTime($l1,$l2);
::rptMsg(" LastAccessedTime: ".gmtime($l)." UTC");
::rptMsg("");
};
}
}
}
::rptMsg("");
}
}
else {
::rptMsg($key_path." has no subkeys.");
}
}
else {
::rptMsg($key_path." not found.");
}
}
1;

View File

@ -0,0 +1,86 @@
#-----------------------------------------------------------
# recentapps_tln.pl
#
# Change history
# 20190513 - updated timestamp issue
# 20171013 - created
#
# References
# https://twitter.com/EricRZimmerman/status/916422135987474433
#
# copyright 2017 H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package recentapps_tln;
use strict;
my %config = (hive => "NTUSER\.DAT",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20190513);
sub getConfig{return %config}
sub getShortDescr {
return "Gets contents of user's RecentApps 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 recentapps_tln v.".$VERSION);
my $reg = Parse::Win32Registry->new($ntuser);
my $root_key = $reg->get_root_key;
my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Search\\RecentApps';
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 $appid;
eval {
my ($t1,$t2) = unpack("VV",$s->get_value("LastAccessedTime")->get_data());
my $lat = ::getTime($t1,$t2);
$appid = $s->get_value("AppId")->get_data();
my $launchcount = $s->get_value("LaunchCount")->get_data();
::rptMsg($lat."|REG|||".$appid." (".$launchcount.")");
};
if (my $r = $s->get_subkey("RecentItems")) {
my @subkeys2 = $s->get_subkey("RecentItems")->get_list_of_subkeys();
if (scalar(@subkeys2 > 0)) {
foreach my $r (@subkeys2) {
eval {
my $path = $r->get_value("Path")->get_data();
my ($l1,$l2) = unpack("VV",$r->get_value("LastAccessedTime")->get_data());
my $l = ::getTime($l1,$l2);
# Update to plugin
# If the LastAccessedTime for a RecentItem entry is 0, get the key LastWrite time instead
if ($l == 0) {
$l = $r->get_timestamp();
}
::rptMsg($l."|REG|||".$appid." RecentItem: ".$path);
};
}
}
}
}
}
else {
::rptMsg($key_path." has no subkeys.");
}
}
else {
::rptMsg($key_path." not found.");
}
}
1;

View File

@ -0,0 +1,94 @@
#------------------------------------
# revouninstall.pl
# Plugin for Registry Ripper, NTUSER.DAT - gets the information regarding the
# Revo Unistaller Pro application
#
# Change History:
# 20200329 - Initial Development
#
# References
#
#
# Copyright 2020 Tiago Sousa tsousahs@gmail.com
# ------------------------------------
package revouninstaller;
use strict;
my %config = (hive => "NTUSER\.DAT",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20200329);
sub getConfig { return %config }
sub getShortDescr {
return "Gets the information regarding revo unistaller execution";
}
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("Lauching revounistall v.".$VERSION);
::rptMsg("revounistall v.".$VERSION);
::rptMsg("(".getHive().") ".getShortDescr()."\n" );
my $reg = Parse::Win32Registry->new($ntuser);
my $root_key = $reg->get_root_key;
# Browser Run
my @key_paths = (
"Software\\VS Revo Group\\Revo Uninstaller Pro\\TrackCleaner\\Browsers",
"Software\\VS Revo Group\\Revo Uninstaller Pro\\TrackCleaner\\Windows",
"Software\\VS Revo Group\\Revo Uninstaller Pro\\TrackCleaner\\MSOffice",
"Software\\VS Revo Group\\Revo Uninstaller Pro\\Uninstaller\\AppBar",
"Software\\VS Revo Group\\Revo Uninstaller Pro\\Uninstaller"
);
my $key;
my @vals;
my @list_of_browsers;
# Inside the browser key it may have separate sub keys for specific browsers
$key = $root_key->get_subkey( @key_paths[0] );
@list_of_browsers = $key->get_list_of_subkeys();
foreach $key (@list_of_browsers) {
push(@key_paths,$key_paths[0]."\\".$key->get_name());
}
# Remove the Browser key. it's not really needed anymore
shift(@key_paths);
foreach my $key_path (@key_paths) {
$key = $root_key->get_subkey( $key_path );
::rptMsg("\n\nName:".$key->get_name());
::rptMsg("Last Write Time: ".gmtime($key->get_timestamp())." (UTC)\n");
my @vals = $key->get_list_of_values();
foreach my $v (@vals) {
if ($v->get_data() eq 1) {
::rptMsg($v->get_name()." : Enabled");
} elsif ($v->get_data() eq 0){
::rptMsg($v->get_name()." : Disabled");
} else {
::rptMsg($v->get_name()." : ".$v->get_data());
}
}
}
}

85
thirdparty/rr-full/plugins/runonceex.pl vendored Normal file
View File

@ -0,0 +1,85 @@
#-----------------------------------------------------------
# runonceex
#
# Change history:
# 20190716 - created
#
# Ref:
# https://oddvar.moe/2018/03/21/persistence-using-runonceex-hidden-from-autoruns-exe/
#
# copyright 2019 QAR,LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package runonceex;
use strict;
my %config = (hive => "Software",
category => "autostart",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20190716);
sub getConfig{return %config}
sub getShortDescr {
return "Gets contents of RunOnceEx 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;
::rptMsg("Launching runonceex v.".$VERSION);
::rptMsg("runonceex v.".$VERSION); # banner
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
my $key_path = ('Microsoft\\Windows\\CurrentVersion\\RunOnceEx');
::rptMsg("RunOnceEx");
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key;
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) {
::rptMsg($s->get_name());
::rptMsg("LastWrite Time ".gmtime($s->get_timestamp())." (UTC)");
# Gets values and data
my @vals = $s->get_list_of_values();
if (scalar(@vals) > 0) {
foreach my $v (@vals) {
::rptMsg($v->get_name()." -> ".$v->get_data());
}
}
::rptMsg("");
# Check for Depend key
if (my $dep = $s->get_subkey("Depend")) {
my @vals2 = $dep->get_list_of_values();
if (scalar(@vals2) > 0) {
foreach my $v2 (@vals2) {
::rptMsg($v2->get_name()." -> ".$v2->get_data());
}
}
}
}
}
else {
::rptMsg($key_path." has no subkeys.");
}
}
else {
::rptMsg($key_path." not found.");
}
}
1;

View File

@ -1,3 +1 @@
# 20161213 *ALL* Plugins that apply on SAM hive, alphabetical order
samparse samparse
samparse_tln

69
thirdparty/rr-full/plugins/sbs.pl vendored Normal file
View File

@ -0,0 +1,69 @@
#-----------------------------------------------------------
# sbs
#
#
# References
# http://www.hexacorn.com/blog/2017/12/29/beyond-good-ol-run-key-part-69/
#
# History:
# 20180101 - created
#
# copyright 2018 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package sbs;
use strict;
my %config = (hive => "Software",
osmask => 22,
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
version => 20180101);
sub getConfig{return %config}
sub getShortDescr {
return "Gets PreferExternalManifest value";
}
sub getDescr{}
sub getRefs {
my %refs = ();
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 sbs v.".$VERSION);
::rptMsg("sbs v.".$VERSION); # banner
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
# used a list of values to address the need for parsing the App Paths key
# in the Wow6432Node key, if it exists.
my @paths = ("Microsoft\\Windows\\CurrentVersion\\SideBySide",
"Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\SideBySide");
foreach my $key_path (@paths) {
my $key;
if ($key = $root_key->get_subkey($key_path)) {
::rptMsg("SBS");
::rptMsg($key_path);
::rptMsg("");
my $sbs;
eval {
$sbs = $key->get_value("SideBySide")->get_data();
::rptMsg("SideBySide = ".$sbs);
};
::rptMsg("SideBySide value not found.") if ($@);
}
}
}
1;

View File

@ -0,0 +1,73 @@
#-----------------------------------------------------------
# searchscopes.pl
# Plugin for Registry Ripper, NTUSER.DAT edition - gets the
# ACMru values
#
# Change history
# 20180406 - created (per request submitted by John McCash)
#
# References
# https://www.online-tech-tips.com/internet-explorer-tips/change-default-search-engine-ie/
#
# copyright 2018 QAR, LLC
# author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package searchscopes;
use strict;
my %config = (hive => "NTUSER\.DAT",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20180406);
sub getConfig{return %config}
sub getShortDescr {
return "Gets contents of user's SearchScopes 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 searchscopes v.".$VERSION);
::rptMsg("searchscopes v.".$VERSION); # banner
::rptMsg("- ".getShortDescr()."\n"); # banner
my $reg = Parse::Win32Registry->new($ntuser);
my $root_key = $reg->get_root_key;
my $key_path = 'Software\\Microsoft\\Internet Explorer\\SearchScopes';
my $key;
if ($key = $root_key->get_subkey($key_path)) {
::rptMsg("SearchScopes");
::rptMsg($key_path);
::rptMsg("DefaultScope: ".$key->get_value("DefaultScope")->get_data());
::rptMsg("");
# ::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)]");
eval {
::rptMsg ("DisplayName: ".$s->get_value("DisplayName")->get_data());
};
::rptMsg("");
}
}
else {
::rptMsg($key_path." has no subkeys.");
}
}
else {
::rptMsg($key_path." not found.");
}
}
1;

View File

@ -1,8 +1,5 @@
# 20161213 *ALL* Plugins that apply on SECURITY hive, alphabetical order
auditpol auditpol
auditpol_xp auditpol_xp
lsasecrets lsasecrets
polacdms polacdms
secrets secrets
secrets_tln
securityproviders

View File

@ -3,8 +3,14 @@
# This key may have something to do with the Start Menu Cache - nothing # This key may have something to do with the Start Menu Cache - nothing
# definitive yet. # definitive yet.
# #
# In my tests *some* installers/applications populate this key on *some* systems
# and Windows shows *some* of these items as "Recently Installed" at the top of
# the start menu. More research is still needed. -Keith Twombley
# ktwombley@gmail.com
#
# Change history # Change history
# 20130412 - created - IN PROCESS; NOT COMPLETE # 20130412 - created - IN PROCESS; NOT COMPLETE
# 20190305 - updated - outputs entries from shc
# #
# #
# References # References
@ -26,7 +32,7 @@ my %config = (hive => "NTUSER\.DAT",
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
osmask => 32, #Windows 8 osmask => 32, #Windows 8
version => 20130412); version => 20190305);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
@ -57,9 +63,16 @@ sub pluginmain {
my @vals = $key->get_list_of_values(); my @vals = $key->get_list_of_values();
if (scalar(@vals) > 0) { if (scalar(@vals) > 0) {
my %shc;
foreach my $v (@vals) { foreach my $v (@vals) {
my $name = $v->get_name();
my $data = $v->get_data();
$shc{$name} = $data
}
foreach my $u (sort {$a <=> $b} keys %shc) {
::rptMsg(" ".$u." -> ".$shc{$u});
} }
} }
else { else {

View File

@ -0,0 +1,238 @@
#-----------------------------------------------------------
# shellactivities.pl
#
#
# Change history
# 20180709 - updated
# 20180611 - created (per request submitted by John McCash)
#
# References
# https://twitter.com/gazambelli/status/1005170301355864065
#
# copyright 2018 QAR, LLC
# author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package shellactivities;
use strict;
my %config = (hive => "NTUSER\.DAT",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20180709);
sub getConfig{return %config}
sub getShortDescr {
return "Gets contents of user's ShellActivities 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 shellactivities v.".$VERSION);
::rptMsg("shellactivities v.".$VERSION);
::rptMsg("- ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($ntuser);
my $root_key = $reg->get_root_key;
my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\CloudStore\\Store\\Cache\\DefaultAccount\\$$windows.data.taskflow.shellactivities\\Current';
my $key;
if ($key = $root_key->get_subkey($key_path)) {
::rptMsg("Key LastWrite: ".gmtime($key->get_timestamp()));
eval {
my $data = $key->get_value("Data")->get_data();
processShellActivities($data);
};
}
else {
::rptMsg($key_path." not found.");
}
}
#-----------------------------------------------------------
#
#-----------------------------------------------------------
sub processShellActivities {
my $data = shift;
my $sz = length($data);
my $count = 0;
my $offset = 4;
my ($l,$tag,$str);
my ($t0,$t1) = unpack("VV",substr($data,$offset,8));
::rptMsg("Time stamp: ".gmtime(::getTime($t0,$t1))." Z");
::rptMsg("");
while ($offset < ($sz - 10)) {
# Code to locate the appropriate identifier
$tag = 1;
while ($tag) {
if (unpack("v",substr($data,$offset,2)) == 0x14d2) {
$tag = 0;
}
else {
$offset++;
}
}
$offset += 2;
$l = unpack("C",substr($data,$offset,1));
# ::rptMsg("String Length: ".sprintf "0x%x",$l);
$offset += 1;
$str = substr($data,$offset,$l * 2);
$str =~ s/\00//g;
::rptMsg("Path: ".$str);
$offset += $l * 2;
$tag = 1;
while ($tag) {
if (unpack("v",substr($data,$offset,2)) == 0x23d2) {
$tag = 0;
}
else {
$offset++;
}
}
$offset += 2;
$l = unpack("C",substr($data,$offset,1));
$offset += 1;
$str = substr($data,$offset,$l * 2);
$str =~ s/\00//g;
# ::rptMsg($str);
$offset += $l * 2;
$tag = 1;
while ($tag) {
if (unpack("v",substr($data,$offset,2)) == 0x28d2) {
$tag = 0;
}
else {
$offset++;
}
}
$offset += 2;
$l = unpack("C",substr($data,$offset,1));
$offset += 1;
$str = substr($data,$offset,$l * 2);
$str =~ s/\00//g;
::rptMsg("Window Title: ".$str);
$offset += $l * 2;
$tag = 1;
while ($tag) {
if (unpack("v",substr($data,$offset,2)) == 0x32c6) {
$tag = 0;
}
else {
$offset++;
}
}
$offset += 3;
# probe(substr($data,$offset,8));
($t0,$t1) = unpack("VV",substr($data,$offset,8));
# ::rptMsg("Time 1: ".gmtime(::getTime($t0,$t1))." Z");
$tag = 1;
while ($tag) {
if (unpack("v",substr($data,$offset,2)) == 0x3cc6) {
$tag = 0;
}
else {
$offset++;
}
}
$offset += 3;
# probe(substr($data,$offset,8));
($t0,$t1) = unpack("VV",substr($data,$offset,8));
# ::rptMsg("Time 2: ".gmtime(::getTime($t0,$t1))." Z");
$offset += 8;
$count++;
::rptMsg("");
}
::rptMsg("Total Count: ".$count);
}
#-----------------------------------------------------------
#
#-----------------------------------------------------------
#-----------------------------------------------------------
#
#-----------------------------------------------------------
#-----------------------------------------------------------
# probe()
#
# Code the uses printData() to insert a 'probe' into a specific
# location and display the data
#
# Input: binary data of arbitrary length
# Output: Nothing, no return value. Displays data to the console
#-----------------------------------------------------------
sub probe {
my $data = shift;
my @d = printData($data);
::rptMsg("");
foreach (0..(scalar(@d) - 1)) {
::rptMsg($d[$_]);
}
::rptMsg("");
}
#-----------------------------------------------------------
# printData()
# subroutine used primarily for debugging; takes an arbitrary
# length of binary data, prints it out in hex editor-style
# format for easy debugging
#
# Usage: see probe()
#-----------------------------------------------------------
sub printData {
my $data = shift;
my $len = length($data);
my @display = ();
my $loop = $len/16;
$loop++ if ($len%16);
foreach my $cnt (0..($loop - 1)) {
# How much is left?
my $left = $len - ($cnt * 16);
my $n;
($left < 16) ? ($n = $left) : ($n = 16);
my $seg = substr($data,$cnt * 16,$n);
my $lhs = "";
my $rhs = "";
foreach my $i ($seg =~ m/./gs) {
# This loop is to process each character at a time.
$lhs .= sprintf(" %02X",ord($i));
if ($i =~ m/[ -~]/) {
$rhs .= $i;
}
else {
$rhs .= ".";
}
}
$display[$cnt] = sprintf("0x%08X %-50s %s",$cnt,$lhs,$rhs);
}
return @display;
}
1;

View File

@ -394,6 +394,7 @@ sub parseVariableEntry {
while($t) { while($t) {
my $sz = unpack("V",substr($stuff,$cnt,4)); my $sz = unpack("V",substr($stuff,$cnt,4));
my $id = unpack("V",substr($stuff,$cnt + 4,4)); my $id = unpack("V",substr($stuff,$cnt + 4,4));
return %item unless (defined $sz);
#-------------------------------------------------------------- #--------------------------------------------------------------
# sub-segment types # sub-segment types
# 0x0a - file name # 0x0a - file name
@ -454,6 +455,7 @@ sub parseVariableEntry {
my $t = 1; my $t = 1;
while ($t) { while ($t) {
my $i = substr($data,$o,1); my $i = substr($data,$o,1);
return %item unless (defined $i);
if ($i =~ m/\00/) { if ($i =~ m/\00/) {
$t = 0; $t = 0;
} }
@ -792,6 +794,7 @@ sub parseFolderEntry {
my $str = ""; my $str = "";
while($tag) { while($tag) {
my $s = substr($data,$ofs_shortname + $cnt,1); my $s = substr($data,$ofs_shortname + $cnt,1);
return %item unless (defined $s);
if ($s =~ m/\00/ && ((($cnt + 1) % 2) == 0)) { if ($s =~ m/\00/ && ((($cnt + 1) % 2) == 0)) {
$tag = 0; $tag = 0;
} }
@ -807,7 +810,9 @@ sub parseFolderEntry {
my $tag = 1; my $tag = 1;
my $cnt = 0; my $cnt = 0;
while ($tag) { while ($tag) {
if (unpack("v",substr($data,$ofs + $cnt,2)) == 0xbeef) { my $s = substr($data,$ofs + $cnt,2);
return %item unless (defined $s);
if (unpack("v",$s) == 0xbeef) {
$tag = 0; $tag = 0;
} }
else { else {
@ -911,7 +916,9 @@ sub parseFolderEntry2 {
my $tag = 1; my $tag = 1;
while ($tag) { while ($tag) {
if (unpack("v",substr($data,$ofs,2)) == 0xbeef) { my $s = substr($data,$ofs,2);
return %item unless (defined $s);
if (unpack("v",$s) == 0xbeef) {
$tag = 0; $tag = 0;
} }
else { else {
@ -1012,6 +1019,7 @@ sub shellItem0x52 {
while ($tag) { while ($tag) {
$d = substr($data,0x32 + $cnt,2); $d = substr($data,0x32 + $cnt,2);
return %item unless (defined $d);
if (unpack("v",$d) == 0) { if (unpack("v",$d) == 0) {
$tag = 0; $tag = 0;
} }

View File

@ -2,7 +2,7 @@
# shellbags_test.pl # shellbags_test.pl
# #
# #
# License: GPL v3 #
# copyright 2012 Quantum Analytics Research, LLC # copyright 2012 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com # Author: H. Carvey, keydet89@yahoo.com
#----------------------------------------------------------- #-----------------------------------------------------------

View File

@ -3,6 +3,7 @@
# RR plugin to parse (Vista, Win7/Win2008R2) shell bags # RR plugin to parse (Vista, Win7/Win2008R2) shell bags
# #
# History: # History:
# 20180702 - code updates, including to parseGUID() function
# 20120810 - added support for parsing Network types; added handling of # 20120810 - added support for parsing Network types; added handling of
# offsets for Folder types (ie, transition to long name offset), # offsets for Folder types (ie, transition to long name offset),
# based on OS version (Vista, Win7); tested against one Win2008R2 # based on OS version (Vista, Win7); tested against one Win2008R2
@ -26,7 +27,7 @@
# Moore for writing the shell bag parser for Registry Decoder, as well as # Moore for writing the shell bag parser for Registry Decoder, as well as
# assistance with some parsing. # assistance with some parsing.
# #
# License: GPL v3 #
# copyright 2012 Quantum Analytics Research, LLC # copyright 2012 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com # Author: H. Carvey, keydet89@yahoo.com
#----------------------------------------------------------- #-----------------------------------------------------------
@ -42,12 +43,12 @@ my %config = (hive => "USRCLASS\.DAT",
hasShortDescr => 1, hasShortDescr => 1,
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
version => 20120810); version => 20180702);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
return "Shell/BagMRU traversal in Win7 USRCLASS.DAT hives"; return "Shell/BagMRU traversal in Win7 USRCLASS\.DAT hives";
} }
sub getDescr{} sub getDescr{}
sub getRefs {} sub getRefs {}
@ -84,6 +85,7 @@ my %cp_guids = ("{bb64f8a7-bee7-4e1a-ab8d-7d8273f7fdb6}" => "Action Center",
"{a3dd4f92-658a-410f-84fd-6fbbbef2fffe}" => "Internet Options", "{a3dd4f92-658a-410f-84fd-6fbbbef2fffe}" => "Internet Options",
"{a304259d-52b8-4526-8b1a-a1d6cecc8243}" => "iSCSI Initiator", "{a304259d-52b8-4526-8b1a-a1d6cecc8243}" => "iSCSI Initiator",
"{725be8f7-668e-4c7b-8f90-46bdb0936430}" => "Keyboard", "{725be8f7-668e-4c7b-8f90-46bdb0936430}" => "Keyboard",
"{bf782cc9-5a52-4a17-806c-2a894ffeeac5}" => "Language Settings",
"{e9950154-c418-419e-a90a-20c5287ae24b}" => "Location and Other Sensors", "{e9950154-c418-419e-a90a-20c5287ae24b}" => "Location and Other Sensors",
"{1fa9085f-25a2-489b-85d4-86326eedcd87}" => "Manage Wireless Networks", "{1fa9085f-25a2-489b-85d4-86326eedcd87}" => "Manage Wireless Networks",
"{6c8eec18-8d75-41b2-a177-8831d59d2d50}" => "Mouse", "{6c8eec18-8d75-41b2-a177-8831d59d2d50}" => "Mouse",
@ -372,7 +374,7 @@ sub parseVariableEntry {
my $num = unpack("V",substr($stuff,$cnt + 13,4)); my $num = unpack("V",substr($stuff,$cnt + 13,4));
my $str = substr($stuff,$cnt + 13 + 4,($num * 2)); my $str = substr($stuff,$cnt + 13 + 4,($num * 2));
$str =~ s/\x00//g; $str =~ s/\00//g;
$item{name} = $str; $item{name} = $str;
} }
$cnt += $sz; $cnt += $sz;
@ -386,8 +388,8 @@ sub parseVariableEntry {
# while($tag) { # while($tag) {
# my $sz = unpack("V",substr($stuff,$cnt,4)); # my $sz = unpack("V",substr($stuff,$cnt,4));
# my $id = unpack("V",substr($stuff,$cnt + 4,4)); # my $id = unpack("V",substr($stuff,$cnt + 4,4));
#
# return %item unless (defined $sz); # return %item unless (defined $sz);
#
# if ($sz == 0x00) { # if ($sz == 0x00) {
# $tag = 0; # $tag = 0;
# next; # next;
@ -396,7 +398,7 @@ sub parseVariableEntry {
# #
# my $num = unpack("V",substr($stuff,$cnt + 13,4)); # my $num = unpack("V",substr($stuff,$cnt + 13,4));
# my $str = substr($stuff,$cnt + 13 + 4,($num * 2)); # my $str = substr($stuff,$cnt + 13 + 4,($num * 2));
# $str =~ s/\x00//g; # $str =~ s/\00//g;
# $item{name} = $str; # $item{name} = $str;
# } # }
# $cnt += $sz; # $cnt += $sz;
@ -410,12 +412,12 @@ sub parseVariableEntry {
elsif ($tag == 0x7b || $tag == 0xbb || $tag == 0xfb) { elsif ($tag == 0x7b || $tag == 0xbb || $tag == 0xfb) {
my ($sz1,$sz2,$sz3) = unpack("VVV",substr($data,0x3e,12)); my ($sz1,$sz2,$sz3) = unpack("VVV",substr($data,0x3e,12));
$item{name} = substr($data,0x4a,$sz1 * 2); $item{name} = substr($data,0x4a,$sz1 * 2);
$item{name} =~ s/\x00//g; $item{name} =~ s/\00//g;
} }
elsif ($tag == 0x02 || $tag == 0x03) { elsif ($tag == 0x02 || $tag == 0x03) {
my ($sz1,$sz2,$sz3,$sz4) = unpack("VVVV",substr($data,0x26,16)); my ($sz1,$sz2,$sz3,$sz4) = unpack("VVVV",substr($data,0x26,16));
$item{name} = substr($data,0x36,$sz1 * 2); $item{name} = substr($data,0x36,$sz1 * 2);
$item{name} =~ s/\x00//g; $item{name} =~ s/\00//g;
} }
else { else {
$item{name} = "Unknown Type"; $item{name} = "Unknown Type";
@ -432,7 +434,7 @@ sub parseNetworkEntry {
my %item = (); my %item = ();
$item{type} = unpack("C",substr($data,2,1)); $item{type} = unpack("C",substr($data,2,1));
my @n = split(/\x00/,substr($data,4,length($data) - 4)); my @n = split(/\00/,substr($data,4,length($data) - 4));
$item{name} = $n[0]; $item{name} = $n[0];
return %item; return %item;
} }
@ -449,13 +451,13 @@ sub parseZipSubFolderItem {
# Get the opened/accessed date/time # Get the opened/accessed date/time
$item{datetime} = substr($data,0x24,6); $item{datetime} = substr($data,0x24,6);
$item{datetime} =~ s/\x00//g; $item{datetime} =~ s/\00//g;
if ($item{datetime} eq "N/A") { if ($item{datetime} eq "N/A") {
} }
else { else {
$item{datetime} = substr($data,0x24,40); $item{datetime} = substr($data,0x24,40);
$item{datetime} =~ s/\x00//g; $item{datetime} =~ s/\00//g;
my ($date,$time) = split(/\s+/,$item{datetime},2); my ($date,$time) = split(/\s+/,$item{datetime},2);
my ($mon,$day,$yr) = split(/\//,$date,3); my ($mon,$day,$yr) = split(/\//,$date,3);
my ($hr,$min,$sec) = split(/:/,$time,3); my ($hr,$min,$sec) = split(/:/,$time,3);
@ -468,9 +470,9 @@ sub parseZipSubFolderItem {
my $sz2 = unpack("V",substr($data,0x58,4)); my $sz2 = unpack("V",substr($data,0x58,4));
my $str1 = substr($data,0x5C,$sz *2) if ($sz > 0); my $str1 = substr($data,0x5C,$sz *2) if ($sz > 0);
$str1 =~ s/\x00//g; $str1 =~ s/\00//g;
my $str2 = substr($data,0x5C + ($sz * 2),$sz2 *2) if ($sz2 > 0); my $str2 = substr($data,0x5C + ($sz * 2),$sz2 *2) if ($sz2 > 0);
$str2 =~ s/\x00//g; $str2 =~ s/\00//g;
if ($sz2 > 0) { if ($sz2 > 0) {
$item{name} = $str1."\\".$str2; $item{name} = $str1."\\".$str2;
@ -509,10 +511,10 @@ sub parseURIEntry {
my $sz = unpack("V",substr($data,0x2a,4)); my $sz = unpack("V",substr($data,0x2a,4));
my $uri = substr($data,0x2e,$sz); my $uri = substr($data,0x2e,$sz);
$uri =~ s/\x00//g; $uri =~ s/\00//g;
my $proto = substr($data,length($data) - 6, 6); my $proto = substr($data,length($data) - 6, 6);
$proto =~ s/\x00//g; $proto =~ s/\00//g;
$item{name} = $proto."://".$uri; $item{name} = $proto."://".$uri;
@ -562,9 +564,29 @@ sub parseGUID {
my $d3 = unpack("v",substr($data,6,2)); my $d3 = unpack("v",substr($data,6,2));
my $d4 = unpack("H*",substr($data,8,2)); my $d4 = unpack("H*",substr($data,8,2));
my $d5 = unpack("H*",substr($data,10,6)); my $d5 = unpack("H*",substr($data,10,6));
return sprintf "{%08x-%x-%x-$d4-$d5}",$d1,$d2,$d3; return sprintf "{%08x-%04x-%04x-$d4-$d5}",$d1,$d2,$d3;
} }
#-----------------------------------------------------------
#
#-----------------------------------------------------------
#sub parseDeviceEntry {
# my $data = shift;
# my %item = ();
#
# my $userlen = unpack("V",substr($data,30,4));
# my $devlen = unpack("V",substr($data,34,4));
#
# my $user = substr($data,0x28,$userlen * 2);
# $user =~ s/\00//g;
#
# my $dev = substr($data,0x28 + ($userlen * 2),$devlen * 2);
# $dev =~ s/\00//g;
#
# $item{name} = $user;
# return %item;
#}
#----------------------------------------------------------- #-----------------------------------------------------------
# #
#----------------------------------------------------------- #-----------------------------------------------------------
@ -572,16 +594,51 @@ sub parseDeviceEntry {
my $data = shift; my $data = shift;
my %item = (); my %item = ();
my $ofs = unpack("v",substr($data,4,2));
my $tag = unpack("V",substr($data,6,4));
#-----------------------------------------------------
# DEBUG
# ::rptMsg("parseDeviceEntry, tag = ".$tag);
#-----------------------------------------------------
if ($tag == 0) {
my $guid1 = parseGUID(substr($data,$ofs + 6,16));
my $guid2 = parseGUID(substr($data,$ofs + 6 + 16,16));
$item{name} = $guid1."\\".$guid2
}
elsif ($tag == 2) {
$item{name} = substr($data,0x0a,($ofs + 6) - 0x0a);
$item{name} =~ s/\00//g;
}
else {
my $ver = unpack("C",substr($data,9,1));
my $idx = unpack("C",substr($data,3,1));
if ($idx == 0x80) {
$item{name} = parseGUID(substr($data,4,16));
}
# Version 3 = XP
elsif ($ver == 3) {
my $guid1 = parseGUID(substr($data,$ofs + 6,16));
my $guid2 = parseGUID(substr($data,$ofs + 6 + 16,16));
$item{name} = $guid1."\\".$guid2
}
# Version 8 = Win7
elsif ($ver == 8) {
my $userlen = unpack("V",substr($data,30,4)); my $userlen = unpack("V",substr($data,30,4));
my $devlen = unpack("V",substr($data,34,4)); my $devlen = unpack("V",substr($data,34,4));
my $user = substr($data,0x28,$userlen * 2); my $user = substr($data,0x28,$userlen * 2);
$user =~ s/\x00//g; $user =~ s/\00//g;
my $dev = substr($data,0x28 + ($userlen * 2),$devlen * 2); my $dev = substr($data,0x28 + ($userlen * 2),$devlen * 2);
$dev =~ s/\x00//g; $dev =~ s/\00//g;
$item{name} = $user; $item{name} = $user;
}
# Version unknown
else {
$item{name} = "Device Entry - Unknown Version";
}
}
return %item; return %item;
} }
@ -647,7 +704,7 @@ sub parseFolderEntry {
($item{mtime_str},$item{mtime}) = convertDOSDate($m[0],$m[1]); ($item{mtime_str},$item{mtime}) = convertDOSDate($m[0],$m[1]);
# Need to read in short name; nul-term ASCII # Need to read in short name; nul-term ASCII
# $item{shortname} = (split(/\x00/,substr($data,12,length($data) - 12),2))[0]; # $item{shortname} = (split(/\00/,substr($data,12,length($data) - 12),2))[0];
$ofs_shortname = $ofs_mdate + 6; $ofs_shortname = $ofs_mdate + 6;
my $tag = 1; my $tag = 1;
my $cnt = 0; my $cnt = 0;
@ -655,7 +712,7 @@ sub parseFolderEntry {
while($tag) { while($tag) {
my $s = substr($data,$ofs_shortname + $cnt,1); my $s = substr($data,$ofs_shortname + $cnt,1);
return %item unless (defined $s); return %item unless (defined $s);
if ($s =~ m/\x00/ && ((($cnt + 1) % 2) == 0)) { if ($s =~ m/\00/ && ((($cnt + 1) % 2) == 0)) {
$tag = 0; $tag = 0;
} }
else { else {
@ -663,12 +720,12 @@ sub parseFolderEntry {
$cnt++; $cnt++;
} }
} }
# $str =~ s/\x00//g; # $str =~ s/\00//g;
my $shortname = $str; my $shortname = $str;
my $ofs = $ofs_shortname + $cnt + 1; my $ofs = $ofs_shortname + $cnt + 1;
# Read progressively, 1 byte at a time, looking for 0xbeef # Read progressively, 1 byte at a time, looking for 0xbeef
$tag = 1; my $tag = 1;
$cnt = 0; my $cnt = 0;
while ($tag) { while ($tag) {
my $s = substr($data,$ofs + $cnt,2); my $s = substr($data,$ofs + $cnt,2);
return %item unless (defined $s); return %item unless (defined $s);
@ -682,10 +739,10 @@ sub parseFolderEntry {
$item{extver} = unpack("v",substr($data,$ofs + $cnt - 4,2)); $item{extver} = unpack("v",substr($data,$ofs + $cnt - 4,2));
$ofs = $ofs + $cnt + 2; $ofs = $ofs + $cnt + 2;
@m = unpack("vv",substr($data,$ofs,4)); my @m = unpack("vv",substr($data,$ofs,4));
($item{ctime_str},$item{ctime}) = convertDOSDate($m[0],$m[1]); ($item{ctime_str},$item{ctime}) = convertDOSDate($m[0],$m[1]);
$ofs += 4; $ofs += 4;
@m = unpack("vv",substr($data,$ofs,4)); my @m = unpack("vv",substr($data,$ofs,4));
($item{atime_str},$item{atime}) = convertDOSDate($m[0],$m[1]); ($item{atime_str},$item{atime}) = convertDOSDate($m[0],$m[1]);
my $jmp; my $jmp;
@ -695,12 +752,16 @@ sub parseFolderEntry {
elsif ($item{extver} == 0x08) { elsif ($item{extver} == 0x08) {
$jmp = 30; $jmp = 30;
} }
elsif ($item{extver} == 0x09) {
$jmp = 34;
}
else {}
$ofs += $jmp; $ofs += $jmp;
$str = substr($data,$ofs,length($data) - 30); my $str = substr($data,$ofs,length($data) - 30);
my $longname = (split(/\x00\x00/,$str,2))[0]; my $longname = (split(/\00\00/,$str,2))[0];
$longname =~ s/\x00//g; $longname =~ s/\00//g;
if ($longname ne "") { if ($longname ne "") {
$item{name} = $longname; $item{name} = $longname;
@ -750,7 +811,7 @@ sub parseNetworkEntry {
my $data = shift; my $data = shift;
my %item = (); my %item = ();
$item{type} = unpack("C",substr($data,2,1)); $item{type} = unpack("C",substr($data,2,1));
my @names = split(/\x00/,substr($data,5,length($data) - 5)); my @names = split(/\00/,substr($data,5,length($data) - 5));
$item{name} = $names[0]; $item{name} = $names[0];
return %item; return %item;
} }

View File

@ -29,7 +29,7 @@
# Moore for writing the shell bag parser for Registry Decoder, as well as # Moore for writing the shell bag parser for Registry Decoder, as well as
# assistance with some parsing. # assistance with some parsing.
# #
# License: GPL v3 #
# copyright 2012 Quantum Analytics Research, LLC # copyright 2012 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com # Author: H. Carvey, keydet89@yahoo.com
#----------------------------------------------------------- #-----------------------------------------------------------
@ -398,8 +398,7 @@ sub parseVariableEntry {
# 0x0c - size # 0x0c - size
#-------------------------------------------------------------- #--------------------------------------------------------------
return %item unless (defined $sz); return %item unless (defined $sz);
if ($sz == 0x00) { if ($sz == 0x00) { $tag = 0;
$tag = 0;
next; next;
} }
elsif ($id == 0x0a) { elsif ($id == 0x0a) {
@ -421,6 +420,7 @@ sub parseVariableEntry {
# my $sz = unpack("V",substr($stuff,$cnt,4)); # my $sz = unpack("V",substr($stuff,$cnt,4));
# my $id = unpack("V",substr($stuff,$cnt + 4,4)); # my $id = unpack("V",substr($stuff,$cnt + 4,4));
# return %item unless (defined $sz); # return %item unless (defined $sz);
#
# if ($sz == 0x00) { # if ($sz == 0x00) {
# $tag = 0; # $tag = 0;
# next; # next;

View File

@ -5,6 +5,8 @@
# works within an analysis process. # works within an analysis process.
# #
# History: # History:
# 20190112 - updated parsing for Win8.1
# 20180311 - updated for more recent version of Win10/Win2016
# 20160528 - updated # 20160528 - updated
# 20160502 - created # 20160502 - created
# #
@ -32,7 +34,7 @@ my %config = (hive => "System",
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
osmask => 31, osmask => 31,
version => 20160528); version => 20190112);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
@ -110,7 +112,10 @@ sub pluginmain {
elsif ($sig == 0x80) { elsif ($sig == 0x80) {
appWin8($app_data); appWin8($app_data);
} }
elsif ($sig == 0x30) { elsif ($sig == 0x0) {
appWin81($app_data);
}
elsif ($sig == 0x30 || $sig == 0x34) {
appWin10($app_data); appWin10($app_data);
} }
else { else {
@ -315,6 +320,39 @@ sub appWin8 {
} }
} }
#-----------------------------------------------------------
# appWin81()
#
#-----------------------------------------------------------
sub appWin81 {
my $data = shift;
my $len = length($data);
my ($tag, $sz, $t0, $t1, $name, $name_len);
my $ct = 0;
# my $ofs = unpack("V",substr($data,0,4));
my $ofs = 0x80;
while ($ofs < $len) {
$tag = substr($data,$ofs,4);
last unless (defined $tag);
if ($tag eq "10ts") {
$sz = unpack("V",substr($data,$ofs + 0x08,4));
$name_len = unpack("v",substr($data,$ofs + 0x0c,2));
my $name = substr($data,$ofs + 0x0e,$name_len);
$name =~ s/\00//g;
# ($t0,$t1) = unpack("VV",substr($data,$ofs + 0x03 + $name_len,8));
($t0,$t1) = unpack("VV",substr($data,$ofs + 0x0e + $name_len + 0x0a,8));
$files{$ct}{filename} = $name;
$files{$ct}{modtime} = ::getTime($t0,$t1);
$ct++;
$ofs += ($sz + 0x0c);
}
}
}
#----------------------------------------------------------- #-----------------------------------------------------------
# appWin10() # appWin10()
# Ref: http://binaryforay.blogspot.com/2015/04/appcompatcache-changes-in-windows-10.html # Ref: http://binaryforay.blogspot.com/2015/04/appcompatcache-changes-in-windows-10.html
@ -324,11 +362,11 @@ sub appWin10 {
my $len = length($data); my $len = length($data);
my ($tag, $sz, $t0, $t1, $name, $name_len); my ($tag, $sz, $t0, $t1, $name, $name_len);
my $ct = 0; my $ct = 0;
my $ofs = 0x30; my $ofs = unpack("V",substr($data,0,4));
# my $ofs = 0x30;
while ($ofs < $len) { while ($ofs < $len) {
$tag = substr($data,$ofs,4); $tag = substr($data,$ofs,4);
last unless (defined $tag);
if ($tag eq "10ts") { if ($tag eq "10ts") {
$sz = unpack("V",substr($data,$ofs + 0x08,4)); $sz = unpack("V",substr($data,$ofs + 0x08,4));

View File

@ -5,6 +5,8 @@
# works within an analysis process. # works within an analysis process.
# #
# History: # History:
# 20190112 - updated parsing for Win8.1
# 20180311 - updated for more recent version of Win10/Win2016
# 20160528 - created # 20160528 - created
# #
# References: # References:
@ -31,7 +33,7 @@ my %config = (hive => "System",
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
osmask => 31, osmask => 31,
version => 20160528); version => 20190112);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
@ -109,7 +111,10 @@ sub pluginmain {
elsif ($sig == 0x80) { elsif ($sig == 0x80) {
appWin8($app_data); appWin8($app_data);
} }
elsif ($sig == 0x30) { elsif ($sig == 0x0) {
appWin81($app_data);
}
elsif ($sig == 0x30 || $sig == 0x34) {
appWin10($app_data); appWin10($app_data);
} }
else { else {
@ -118,14 +123,16 @@ sub pluginmain {
foreach my $f (keys %files) { foreach my $f (keys %files) {
my $str; my $str;
if (exists $files{$f}{executed}) { next if ($files{$f}{modtime} == 0);
$str = "M... [Program Execution] AppCompatCache - ".$files{$f}{filename}; if (exists $files{$f}{updtime}) {
# $str = "[Program Execution] AppCompatCache - ".$files{$f}{filename};
next if ($files{$f}{updtime} == 0);
::rptMsg($files{$f}{updtime}."|REG|||[Program Execution] - ".$files{$f}{filename});
} }
else {
$str = "M... AppCompatCache - ".$files{$f}{filename}; $str = "M... AppCompatCache - ".$files{$f}{filename};
}
$str .= " [Size = ".$files{$f}{size}." bytes]" if (exists $files{$f}{size}); $str .= " [Size = ".$files{$f}{size}." bytes]" if (exists $files{$f}{size});
$str .= " [Executed]" if (exists $files{$f}{executed});
::rptMsg($files{$f}{modtime}."|REG|||".$str); ::rptMsg($files{$f}{modtime}."|REG|||".$str);
} }
} }
@ -148,8 +155,8 @@ sub appXP32Bit {
foreach my $i (0..($num_entries - 1)) { foreach my $i (0..($num_entries - 1)) {
my $x = substr($data,(400 + ($i * 552)),552); my $x = substr($data,(400 + ($i * 552)),552);
my $file = (split(/\x00\x00/,substr($x,0,488)))[0]; my $file = (split(/\00\00/,substr($x,0,488)))[0];
$file =~ s/\x00//g; $file =~ s/\00//g;
$file =~ s/^\\\?\?\\//; $file =~ s/^\\\?\?\\//;
my ($mod1,$mod2) = unpack("VV",substr($x,528,8)); my ($mod1,$mod2) = unpack("VV",substr($x,528,8));
my $modtime = ::getTime($mod1,$mod2); my $modtime = ::getTime($mod1,$mod2);
@ -192,7 +199,7 @@ sub appWin2k3 {
my ($len,$max_len,$ofs,$t0,$t1,$f0,$f1) = unpack("vvVVVVV",$struct); my ($len,$max_len,$ofs,$t0,$t1,$f0,$f1) = unpack("vvVVVVV",$struct);
my $file = substr($data,$ofs,$len); my $file = substr($data,$ofs,$len);
$file =~ s/\x00//g; $file =~ s/\00//g;
$file =~ s/^\\\?\?\\//; $file =~ s/^\\\?\?\\//;
my $t = ::getTime($t0,$t1); my $t = ::getTime($t0,$t1);
$files{$i}{filename} = $file; $files{$i}{filename} = $file;
@ -203,7 +210,7 @@ sub appWin2k3 {
elsif ($struct_sz == 32) { elsif ($struct_sz == 32) {
my ($len,$max_len,$padding,$ofs0,$ofs1,$t0,$t1,$f0,$f1) = unpack("vvVVVVVVV",$struct); my ($len,$max_len,$padding,$ofs0,$ofs1,$t0,$t1,$f0,$f1) = unpack("vvVVVVVVV",$struct);
my $file = substr($data,$ofs0,$len); my $file = substr($data,$ofs0,$len);
$file =~ s/\x00//g; $file =~ s/\00//g;
$file =~ s/^\\\?\?\\//; $file =~ s/^\\\?\?\\//;
my $t = ::getTime($t0,$t1); my $t = ::getTime($t0,$t1);
$files{i}{filename} = $file; $files{i}{filename} = $file;
@ -245,7 +252,7 @@ sub appWin7 {
if ($struct_sz == 32) { if ($struct_sz == 32) {
my ($len,$max_len,$ofs,$t0,$t1,$f0,$f1) = unpack("vvV5x8",$struct); my ($len,$max_len,$ofs,$t0,$t1,$f0,$f1) = unpack("vvV5x8",$struct);
my $file = substr($data,$ofs,$len); my $file = substr($data,$ofs,$len);
$file =~ s/\x00//g; $file =~ s/\00//g;
$file =~ s/^\\\?\?\\//; $file =~ s/^\\\?\?\\//;
my $t = ::getTime($t0,$t1); my $t = ::getTime($t0,$t1);
$files{$i}{filename} = $file; $files{$i}{filename} = $file;
@ -255,7 +262,7 @@ sub appWin7 {
else { else {
my ($len,$max_len,$padding,$ofs0,$ofs1,$t0,$t1,$f0,$f1) = unpack("vvV7x16",$struct); my ($len,$max_len,$padding,$ofs0,$ofs1,$t0,$t1,$f0,$f1) = unpack("vvV7x16",$struct);
my $file = substr($data,$ofs0,$len); my $file = substr($data,$ofs0,$len);
$file =~ s/\x00//g; $file =~ s/\00//g;
$file =~ s/^\\\?\?\\//; $file =~ s/^\\\?\?\\//;
my $t = ::getTime($t0,$t1); my $t = ::getTime($t0,$t1);
$files{$i}{filename} = $file; $files{$i}{filename} = $file;
@ -284,7 +291,7 @@ sub appWin8 {
($t0,$t1) = unpack("VV",substr($data,$ofs + 12,8)); ($t0,$t1) = unpack("VV",substr($data,$ofs + 12,8));
$sz = unpack("v",substr($data,$ofs + 20,2)); $sz = unpack("v",substr($data,$ofs + 20,2));
$name = substr($data,$ofs + 22,$sz); $name = substr($data,$ofs + 22,$sz);
$name =~ s/\x00//g; $name =~ s/\00//g;
$files{$ct}{filename} = $name; $files{$ct}{filename} = $name;
$files{$ct}{modtime} = ::getTime($t0,$t1); $files{$ct}{modtime} = ::getTime($t0,$t1);
$ct++; $ct++;
@ -295,7 +302,7 @@ sub appWin8 {
$jmp = unpack("V",substr($data,$ofs + 8,4)); $jmp = unpack("V",substr($data,$ofs + 8,4));
$sz = unpack("v",substr($data,$ofs + 0x0C,2)); $sz = unpack("v",substr($data,$ofs + 0x0C,2));
$name = substr($data,$ofs + 0x0E,$sz + 2); $name = substr($data,$ofs + 0x0E,$sz + 2);
$name =~ s/\x00//g; $name =~ s/\00//g;
($t0,$t1) = unpack("VV",substr($data,($ofs + 0x0E + $sz +2 + 8),8)); ($t0,$t1) = unpack("VV",substr($data,($ofs + 0x0E + $sz +2 + 8),8));
$files{$ct}{filename} = $name; $files{$ct}{filename} = $name;
$files{$ct}{modtime} = ::getTime($t0,$t1); $files{$ct}{modtime} = ::getTime($t0,$t1);
@ -310,15 +317,16 @@ sub appWin8 {
} }
#----------------------------------------------------------- #-----------------------------------------------------------
# appWin10() # appWin81()
# Ref: http://binaryforay.blogspot.com/2015/04/appcompatcache-changes-in-windows-10.html #
#----------------------------------------------------------- #-----------------------------------------------------------
sub appWin10 { sub appWin81 {
my $data = shift; my $data = shift;
my $len = length($data); my $len = length($data);
my ($tag, $sz, $t0, $t1, $name, $name_len); my ($tag, $sz, $t0, $t1, $name, $name_len);
my $ct = 0; my $ct = 0;
my $ofs = 0x30; # my $ofs = unpack("V",substr($data,0,4));
my $ofs = 0x80;
while ($ofs < $len) { while ($ofs < $len) {
$tag = substr($data,$ofs,4); $tag = substr($data,$ofs,4);
@ -328,7 +336,39 @@ sub appWin10 {
$sz = unpack("V",substr($data,$ofs + 0x08,4)); $sz = unpack("V",substr($data,$ofs + 0x08,4));
$name_len = unpack("v",substr($data,$ofs + 0x0c,2)); $name_len = unpack("v",substr($data,$ofs + 0x0c,2));
my $name = substr($data,$ofs + 0x0e,$name_len); my $name = substr($data,$ofs + 0x0e,$name_len);
$name =~ s/\x00//g; $name =~ s/\00//g;
# ($t0,$t1) = unpack("VV",substr($data,$ofs + 0x03 + $name_len,8));
($t0,$t1) = unpack("VV",substr($data,$ofs + 0x0e + $name_len + 0x0a,8));
$files{$ct}{filename} = $name;
$files{$ct}{modtime} = ::getTime($t0,$t1);
$ct++;
$ofs += ($sz + 0x0c);
}
}
}
#-----------------------------------------------------------
# appWin10()
# Ref: http://binaryforay.blogspot.com/2015/04/appcompatcache-changes-in-windows-10.html
#-----------------------------------------------------------
sub appWin10 {
my $data = shift;
my $len = length($data);
my ($tag, $sz, $t0, $t1, $name, $name_len);
my $ct = 0;
my $ofs = unpack("V",substr($data,0,4));
# my $ofs = 0x30;
while ($ofs < $len) {
$tag = substr($data,$ofs,4);
if ($tag eq "10ts") {
$sz = unpack("V",substr($data,$ofs + 0x08,4));
$name_len = unpack("v",substr($data,$ofs + 0x0c,2));
my $name = substr($data,$ofs + 0x0e,$name_len);
$name =~ s/\00//g;
# ($t0,$t1) = unpack("VV",substr($data,$ofs + 0x03 + $name_len,8)); # ($t0,$t1) = unpack("VV",substr($data,$ofs + 0x03 + $name_len,8));
($t0,$t1) = unpack("VV",substr($data,$ofs + 0x0e + $name_len,8)); ($t0,$t1) = unpack("VV",substr($data,$ofs + 0x0e + $name_len,8));
$files{$ct}{filename} = $name; $files{$ct}{filename} = $name;

View File

@ -0,0 +1,59 @@
#-----------------------------------------------------------
# silentprocessexit
#
# Change history:
# 20180601 - created
#
# Ref:
# https://oddvar.moe/2018/04/10/persistence-using-globalflags-in-image-file-execution-options-hidden-from-autoruns-exe/
#
# copyright 2018 QAR,LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package silentprocessexit;
use strict;
my %config = (hive => "Software",
category => "autostart",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20180601);
sub getConfig{return %config}
sub getShortDescr {
return "Gets contents of SilentProcessExit 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;
::rptMsg("Launching silentProcessexit v.".$VERSION);
::rptMsg("silentprocessexit v.".$VERSION); # banner
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
my $key_path = ('Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit');
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key;
if ($key = $root_key->get_subkey($key_path)) {
my @sk = $key->get_list_of_subkeys();
foreach my $s (@sk) {
::rptMsg($s->get_name());
::rptMsg("LastWrite: ".gmtime($s->get_timestamp())." UTC");
eval {
::rptMsg("MonitorProcess: ".$s->get_value("MonitorProcess")->get_data());
};
::rptMsg("");
}
}
}
1;

View File

@ -0,0 +1,59 @@
#-----------------------------------------------------------
# silentprocessexit_tln
#
# Change history:
# 20180601 - created
#
# Ref:
# https://oddvar.moe/2018/04/10/persistence-using-globalflags-in-image-file-execution-options-hidden-from-autoruns-exe/
#
# copyright 2018 QAR,LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package silentprocessexit_tln;
use strict;
my %config = (hive => "Software",
category => "autostart",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20180601);
sub getConfig{return %config}
sub getShortDescr {
return "Gets contents of SilentProcessExit 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;
# ::rptMsg("Launching silentProcessexit v.".$VERSION);
# ::rptMsg("silentprocessexit v.".$VERSION); # banner
# ::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
my $key_path = ('Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit');
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key;
if ($key = $root_key->get_subkey($key_path)) {
my @sk = $key->get_list_of_subkeys();
foreach my $s (@sk) {
my $mon;
eval {
$mon = $s->get_value("MonitorProcess")->get_data();
};
::rptMsg($s->get_timestamp()."|REG|||SilentProcessExit: ".$s->get_name()." - MonitorProcess: ".$mon);
}
}
}
1;

View File

@ -6,6 +6,8 @@
# sizes; change $min_size value to suit your needs # sizes; change $min_size value to suit your needs
# #
# Change history # Change history
# 20180817 - updated to include brief output, based on suggestion from J. Wood
# 20180607 - modified based on Meterpreter input from Mari DeGrazia
# 20150527 - Created # 20150527 - Created
# #
# copyright 2015 QAR, LLC # copyright 2015 QAR, LLC
@ -14,16 +16,19 @@
package sizes; package sizes;
use strict; use strict;
my $min_size = 5000;
my $output_size = 48;
my %config = (hive => "All", my %config = (hive => "All",
hasShortDescr => 1, hasShortDescr => 1,
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
osmask => 22, osmask => 22,
version => 20150527); version => 20180817);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
return "Scans a hive file looking for binary value data of a min size"; return "Scans a hive file looking for binary value data of a min size (".$min_size.")";
} }
sub getDescr{} sub getDescr{}
sub getRefs {} sub getRefs {}
@ -31,7 +36,7 @@ sub getHive {return $config{hive};}
sub getVersion {return $config{version};} sub getVersion {return $config{version};}
my $VERSION = getVersion(); my $VERSION = getVersion();
my $min_size = 50000; my $count = 0;
sub pluginmain { sub pluginmain {
my $class = shift; my $class = shift;
@ -41,7 +46,15 @@ sub pluginmain {
::logMsg("Launching sizes v.".$VERSION); ::logMsg("Launching sizes v.".$VERSION);
::rptMsg("sizes v.".$VERSION); ::rptMsg("sizes v.".$VERSION);
::rptMsg("(".getHive().") ".getShortDescr()."\n"); ::rptMsg("(".getHive().") ".getShortDescr()."\n");
my $start = time;
traverse($root_key); traverse($root_key);
my $finish = time;
::rptMsg("Scan completed: ".($finish - $start)." sec");
::rptMsg("Total values : ".$count);
} }
sub traverse { sub traverse {
@ -49,8 +62,9 @@ sub traverse {
# my $ts = $key->get_timestamp(); # my $ts = $key->get_timestamp();
foreach my $val ($key->get_list_of_values()) { foreach my $val ($key->get_list_of_values()) {
$count++;
my $type = $val->get_type(); my $type = $val->get_type();
if ($type == 0 || $type == 3) { if ($type == 0 || $type == 3 || $type == 1 || $type == 2) {
my $data = $val->get_data(); my $data = $val->get_data();
my $len = length($data); my $len = length($data);
if ($len > $min_size) { if ($len > $min_size) {
@ -59,10 +73,19 @@ sub traverse {
$name[0] = ""; $name[0] = "";
$name[0] = "\\" if (scalar(@name) == 1); $name[0] = "\\" if (scalar(@name) == 1);
my $path = join('\\',@name); my $path = join('\\',@name);
::rptMsg("Key : ".$path." Value: ".$val->get_name()." Size: ".$len." bytes");
# Data type "none", "Reg_SZ", "Reg_Expand_SZ"
if ($type == 0 || $type == 1 || $type == 2) {
::rptMsg("Data Sample (first ".$output_size." bytes) : ".substr($data,0,$output_size)."...");
}
# Binary data
if ($type == 3) {
my $out = substr($data,0,$output_size);
probe($out);
}
::rptMsg("Key : ".$path);
::rptMsg("Value: ".$val->get_name());
::rptMsg("Size : ".$len." bytes.");
::rptMsg(""); ::rptMsg("");
} }
} }
@ -73,4 +96,65 @@ sub traverse {
} }
} }
#-----------------------------------------------------------
# probe()
#
# Code the uses printData() to insert a 'probe' into a specific
# location and display the data
#
# Input: binary data of arbitrary length
# Output: Nothing, no return value. Displays data to the console
#-----------------------------------------------------------
sub probe {
my $data = shift;
my @d = printData($data);
::rptMsg("");
foreach (0..(scalar(@d) - 1)) {
::rptMsg($d[$_]);
}
::rptMsg("");
}
#-----------------------------------------------------------
# printData()
# subroutine used primarily for debugging; takes an arbitrary
# length of binary data, prints it out in hex editor-style
# format for easy debugging
#
# Usage: see probe()
#-----------------------------------------------------------
sub printData {
my $data = shift;
my $len = length($data);
my @display = ();
my $loop = $len/16;
$loop++ if ($len%16);
foreach my $cnt (0..($loop - 1)) {
# How much is left?
my $left = $len - ($cnt * 16);
my $n;
($left < 16) ? ($n = $left) : ($n = 16);
my $seg = substr($data,$cnt * 16,$n);
my $lhs = "";
my $rhs = "";
foreach my $i ($seg =~ m/./gs) {
# This loop is to process each character at a time.
$lhs .= sprintf(" %02X",ord($i));
if ($i =~ m/[ -~]/) {
$rhs .= $i;
}
else {
$rhs .= ".";
}
}
$display[$cnt] = sprintf("0x%08X %-50s %s",$cnt,$lhs,$rhs);
}
return @display;
}
1; 1;

135
thirdparty/rr-full/plugins/slack.pl vendored Normal file
View File

@ -0,0 +1,135 @@
#! c:\perl\bin\perl.exe
#-----------------------------------------------------------
# slack.pl
#
#
# Change history
# 20180926 - created
#
# References:
#
#
#
# copyright 2018 QAR, LLC
# Author: H. Carvey
#-----------------------------------------------------------
package slack;
use strict;
my %config = (hive => "All",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
category => "slack",
version => 20180926);
sub getConfig{return %config}
sub getShortDescr {
return "Parse hive, print slack space, retrieve keys/values";
}
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);
::logMsg("Launching slack v.".$VERSION);
::rptMsg("slack v.".$VERSION);
::rptMsg("(".getHive().") ".getShortDescr()."\n");
my $block_iter = $reg->get_block_iterator;
while (my $block = $block_iter->get_next) {
my $entry_iter = $block->get_entry_iterator;
while (my $entry = $entry_iter->get_next) {
if ($entry->is_allocated()) {
my $data = $entry->get_raw_bytes();
::rptMsg("------------- Slack Data ------------");
# Value node header is 20 bytes, w/o name string
# Key node header is 76 bytes, w/o name string
my $len = length($data);
if ($len >= 20) {
my $cursor = 0;
while ($cursor < $len) {
if (unpack("v",substr($data,$cursor,2)) == 0x6b76) {
# ::rptMsg("Value node found at ".$cursor);
parseValueNode($data,$cursor);
}
elsif (unpack("v",substr($data,$cursor,2)) == 0x6b6e) {
# ::rptMsg("Key node found at ".$cursor);
parseKeyNode($data,$cursor);
}
else {}
$cursor++;
}
print "\n";
}
::rptMsg($entry->unparsed());
}
}
}
}
sub parseValueNode {
my $data = shift;
my $ofs = shift;
my $name_len = unpack("v",substr($data,$ofs + 0x02,2));
my $data_len = unpack("V",substr($data,$ofs + 0x04,4));
my $data_ofs = unpack("V",substr($data,$ofs + 0x08,4));
my $data_type = unpack("V",substr($data,$ofs + 0x0c,4));
my $data_flag = unpack("v",substr($data,$ofs + 0x10,2));
my $name;
if (($ofs + 0x14 + $name_len) <= length($data)) {
$name = substr($data,$ofs + 0x14,$name_len);
::rptMsg("Value Name: ".$name);
}
}
sub parseKeyNode {
my $data = shift;
my $ofs = shift;
my $len = length($data);
if ($len > 75 && $ofs >= 4) {
my $size = unpack("i",substr($data,$ofs - 4,4));
$size = ($size * -1) if ($size < 0);
# ::rptMsg("Key node size = ".$size);
my $type = unpack("v",substr($data,$ofs + 0x02,2));
# ::rptMsg(sprintf "Node Type = 0x%x",$type);
my ($t1,$t2) = unpack("VV",substr($data,$ofs + 0x04,8));
my $lw = ::getTime($t1,$t2);
# ::rptMsg("Key LastWrite time = ".gmtime($lw)." UTC");
my $sk = unpack("V",substr($data,$ofs + 0x14,4));
# ::rptMsg("Number of subkeys: ".$sk);
my $vals = unpack("V",substr($data,$ofs + 0x24,4));
# ::rptMsg("Number of values: ".$vals);
my $len_name = unpack("V",substr($data,$ofs + 0x48,4));
# print "Name Length: ".$len_name."\n";
my $name;
if (($ofs + 0x4c + $len_name) <= $len) {
$name = substr($data,$ofs + 0x4c,$len_name);
::rptMsg("Key name: ".$name);
}
::rptMsg("Key LastWrite time = ".gmtime($lw)." UTC");
}
}
1;

117
thirdparty/rr-full/plugins/slack_tln.pl vendored Normal file
View File

@ -0,0 +1,117 @@
#! c:\perl\bin\perl.exe
#-----------------------------------------------------------
# slack_tln.pl
#
#
# Change history
# 20190506 - slack_tln.pl created
# 20180926 - original slack.pl created
#
# References:
#
#
#
# copyright 2019 QAR, LLC
# Author: H. Carvey
#-----------------------------------------------------------
package slack_tln;
use strict;
my %config = (hive => "All",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
category => "slack",
version => 20190506);
sub getConfig{return %config}
sub getShortDescr {
return "Parse hive, print slack space, retrieve keys/values";
}
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);
::logMsg("Launching slack v.".$VERSION);
::rptMsg("slack v.".$VERSION);
::rptMsg("(".getHive().") ".getShortDescr()."\n");
my $block_iter = $reg->get_block_iterator;
while (my $block = $block_iter->get_next) {
my $entry_iter = $block->get_entry_iterator;
while (my $entry = $entry_iter->get_next) {
if ($entry->is_allocated()) {
my $data = $entry->get_raw_bytes();
# ::rptMsg("------------- Slack Data ------------");
# Value node header is 20 bytes, w/o name string
# Key node header is 76 bytes, w/o name string
my $len = length($data);
if ($len >= 74) {
my $cursor = 0;
while ($cursor < $len) {
if (unpack("v",substr($data,$cursor,2)) == 0x6b6e) {
# ::rptMsg("Key node found at ".$cursor);
parseKeyNode($data,$cursor);
$cursor += 74;
}
else {
$cursor++;
}
}
}
# ::rptMsg($entry->unparsed());
}
}
}
}
sub parseKeyNode {
my $data = shift;
my $ofs = shift;
my $len = length($data);
if ($len > 75 && $ofs >= 4) {
my $size = unpack("i",substr($data,$ofs - 4,4));
$size = ($size * -1) if ($size < 0);
# ::rptMsg("Key node size = ".$size);
my $type = unpack("v",substr($data,$ofs + 0x02,2));
# ::rptMsg(sprintf "Node Type = 0x%x",$type);
my ($t1,$t2) = unpack("VV",substr($data,$ofs + 0x04,8));
my $lw = ::getTime($t1,$t2);
# ::rptMsg("Key LastWrite time = ".gmtime($lw)." UTC");
my $sk = unpack("V",substr($data,$ofs + 0x14,4));
# ::rptMsg("Number of subkeys: ".$sk);
my $vals = unpack("V",substr($data,$ofs + 0x24,4));
# ::rptMsg("Number of values: ".$vals);
my $len_name = unpack("V",substr($data,$ofs + 0x48,4));
# print "Name Length: ".$len_name."\n";
my $name;
if (($ofs + 0x4c + $len_name) <= $len) {
$name = substr($data,$ofs + 0x4c,$len_name);
# ::rptMsg("Key name: ".$name);
}
::rptMsg($lw."|||| Key found in hive slack: ".$name);
}
}
1;

View File

@ -1,11 +1,10 @@
# 20161213 *ALL* Plugins that apply on SOFTWARE hive, alphabetical order
ahaha ahaha
appcompatflags
appinitdlls appinitdlls
appkeys
apppaths apppaths
apppaths_tln
assoc assoc
at at
at_tln
audiodev audiodev
banner banner
bho bho
@ -13,22 +12,21 @@ bitbucket
btconfig btconfig
clsid clsid
cmd_shell cmd_shell
cmd_shell_tln
codeid codeid
ctrlpnl ctrlpnl
dcom dcom
defbrowser
dfrg dfrg
direct direct
direct_tln
disablesr disablesr
drivers32 drivers32
drwatson drwatson
emdmgmt emdmgmt
esent esent
etos etos
execpolicy
gauss gauss
gpohist gpohist
gpohist_tln
handler handler
ie_version ie_version
ie_zones ie_zones
@ -38,61 +36,67 @@ inprocserver
installedcomp installedcomp
installer installer
javasoft javasoft
kankan
kb950582 kb950582
landesk landesk
landesk_tln
lastloggedon lastloggedon
lazyshell lazyshell
licenses licenses
logmein logmein
logmein_tln
macaddr macaddr
mrt mrt
msis msis
netsh netsh
networkcards networkcards
networklist networklist
networklist_tln
networkuid networkuid
opencandy opencandy
port_dev port_dev
product product
profilelist profilelist
pslogging
psscript
regback regback
removdev removdev
renocide renocide
runonceex
sbs
schedagent schedagent
secctr secctr
sfc sfc
shellexec shellexec
shellext shellext
shelloverlay shelloverlay
silentprocessexit
snapshot snapshot
soft_run soft_run
spp_clients spp_clients
sql_lastconnect sql_lastconnect
srun_tln
ssid ssid
startmenuinternetapps_lm startmenuinternetapps_lm
susclient susclient
svchost svchost
systemindex systemindex
teamviewer teamviewer
termserv
thunderbirdinstalled
tracing tracing
tracing_tln
trappoll trappoll
uac uac
uninstall uninstall
uninstall_tln updates
urlzone urlzone
virut virut
volinfocache volinfocache
watp
wbem wbem
webroot
winbackup winbackup
win_cv
winevt winevt
winlogon winlogon
winlogon_tln
winnt_cv winnt_cv
winver winver
win_cv
wow64
wsh_settings
yahoo_lm yahoo_lm

98
thirdparty/rr-full/plugins/source_os.pl vendored Normal file
View File

@ -0,0 +1,98 @@
#-----------------------------------------------------------
# source_os.pl
#
# History:
# 20180629 - created
#
# References:
# http://az4n6.blogspot.com/2017/02/when-windows-lies.html
#
#
# copyright 2018 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package source_os;
use strict;
my %config = (hive => "System",
hivemask => 4,
output => "report",
category => "Program Execution",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 31, #XP - Win7
version => 20180629);
sub getConfig{return %config}
sub getShortDescr {
return "Parse Source OS subkey values";
}
sub getDescr{}
sub getRefs {}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
my $VERSION = getVersion();
my %files;
my $str = "";
sub pluginmain {
my $class = shift;
my $hive = shift;
::logMsg("Launching source_os v.".$VERSION);
::rptMsg("source_os v.".$VERSION); # banner
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key_path = 'Setup';
my $key;
if ($key = $root_key->get_subkey($key_path)) {
my @sk = $key->get_list_of_subkeys();
foreach my $s (@sk) {
my $name = $s->get_name();
if (substr($name,0,6) eq "Source") {
my $id = $s->get_value("InstallDate")->get_data();
::rptMsg($name);
::rptMsg(" InstallDate: ".gmtime($id)." Z");
eval {
my ($t0,$t1) = unpack("VV",$s->get_value("InstallTime")->get_data());
my $t = ::getTime($t0,$t1);
::rptMsg(" InstallTime: ".gmtime($t)." Z");
};
eval {
::rptMsg(" BuildLab: ".$s->get_value("BuildLab")->get_data());
};
eval {
::rptMsg(" CurrentBuild: ".$s->get_value("CurrentBuild")->get_data());
};
eval {
::rptMsg(" ProductName: ".$s->get_value("ProductName")->get_data());
};
eval {
::rptMsg(" RegisteredOwner: ".$s->get_value("RegisteredOwner")->get_data());
};
eval {
::rptMsg(" ReleaseID: ".$s->get_value("ReleaseID")->get_data());
};
::rptMsg("");
}
}
}
else {
::rptMsg($key_path." not found.");
}
}
1;

View File

@ -25,7 +25,7 @@ my %config = (hive => "System",
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
return "Lists services/drivers in Services key by LastWrite times in a short format with warnings for type mismatches\n^^^^ Indicates non-standard Type\n<<<< Indicates Start mismatch for Driver\n**** Indicates ObjectName mismatch for Driver\n>>>> Indicates Start mismatch for Service\n++++ Indicates nonstandard ObjectName for Service."; return "Lists services/drivers in Services key by LastWrite times in a short format with warnings for type mismatches; ^^^^ Indicates non-standard Type, <<<< Indicates Start mismatch for Driver, **** Indicates ObjectName mismatch for Driver, >>>> Indicates Start mismatch for Service, ++++ Indicates nonstandard ObjectName for Service.";
} }
sub getDescr{} sub getDescr{}
sub getRefs {} sub getRefs {}

2
thirdparty/rr-full/plugins/syscache vendored Normal file
View File

@ -0,0 +1,2 @@
syscache
syscache_csv

114
thirdparty/rr-full/plugins/syscache.pl vendored Normal file
View File

@ -0,0 +1,114 @@
#-----------------------------------------------------------
# syscache.pl
#
# Change history
# 20181209 - created
#
# References
# https://github.com/libyal/winreg-kb/blob/master/documentation/SysCache.asciidoc
#
# Copyright (c) 2018 QAR, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package syscache;
use strict;
my %config = (hive => "syscache",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
category => "program execution",
version => 20181209);
my $VERSION = getVersion();
# Functions #
sub getConfig {return %config}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
sub getDescr {}
sub getShortDescr {
return "Parse SysCache\.hve file";
}
sub getRefs {}
sub pluginmain {
my $class = shift;
my $hive = shift;
::logMsg("Launching syscache v.".$VERSION);
::rptMsg("syscache v.".$VERSION);
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key;
my $key_path = 'DefaultObjectStore\\ObjectTable';
if ($key = $root_key->get_subkey($key_path)) {
my @subkeys = $key->get_list_of_subkeys();
if (scalar @subkeys > 0) {
foreach my $sk (@subkeys) {
processKey($sk);
::rptMsg("");
}
}
}
else {
::rptMsg($key_path." not found");
}
}
sub processKey {
my $key = shift;
my $lw = $key->get_timestamp();
::rptMsg("LastWrite: ".gmtime($lw)." Z");
eval {
my ($f1,$f2,$seq) = unpack("Vvv",$key->get_value("_FileId_")->get_data());
my $entry = mftRecNum($f1,$f2);
::rptMsg(" FileID = ".$entry."/".$seq);
};
eval {
my $aefileid = $key->get_value("AeFileID")->get_data();
$aefileid =~ s/\00//g;
my $sha1 = $aefileid;
$sha1 =~ s/^0000//;
::rptMsg(" AeFileID = ".$aefileid);
::rptMsg(" SHA-1 Hash = ".$sha1);
};
eval {
my ($u1,$u2) = unpack("VV",$key->get_value("_UsnJournalId_")->get_data());
my $usn = ::getTime($u1,$u2);
::rptMsg(" USN Journal ID = ".gmtime($usn)." Z");
};
}
# from: http://www.cse.scu.edu/~tschwarz/coen252_07Fall/Lectures/NTFS.html
# "Each MFT record is addressed by a 48 bit MFT entry value.The first entry has address 0.
# Each MFT entry has a 16 bit sequence number that is incremented when the entry is allocated.
# MFT entry value and sequence number combined yield 64b file reference address.:
#
# The 64-bit field is translated as 48-bits for the entry number and 16-bits for the
# sequence number
#
# variation of the below code shared by David Cowen
sub mftRecNum {
my $f1 = shift;
my $f2 = shift;
if ($f2 == 0) {
return $f1;
}
else {
$f2 = ($f2 * 16777216);
return ($f1 + $f2);
}
}
1;

View File

@ -0,0 +1,116 @@
#-----------------------------------------------------------
# syscache_csv.pl
#
# Change history
# 20190425 - csv output added
# 20181209 - original plugin created
#
# References
# https://github.com/libyal/winreg-kb/blob/master/documentation/SysCache.asciidoc
#
# Copyright (c) 2018 QAR, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package syscache_csv;
use strict;
my %config = (hive => "syscache",
hasShortDescr => 0,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
category => "program execution",
version => 20190425);
my $VERSION = getVersion();
# Functions #
sub getConfig {return %config}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
sub getDescr {}
sub getShortDescr {}
sub getRefs {}
sub pluginmain {
my $class = shift;
my $hive = shift;
# ::logMsg("Launching syscache v.".$VERSION);
# ::rptMsg("syscache_csv v.".$VERSION);
# ::rptMsg("(".$config{hive}.") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key;
my $key_path = 'DefaultObjectStore\\ObjectTable';
if ($key = $root_key->get_subkey($key_path)) {
my @subkeys = $key->get_list_of_subkeys();
if (scalar @subkeys > 0) {
foreach my $sk (@subkeys) {
processKey($sk);
# ::rptMsg("");
}
}
}
else {
::rptMsg($key_path." not found");
}
}
sub processKey {
my $key = shift;
my @str = ();
my $lw = $key->get_timestamp();
# ::rptMsg("LastWrite: ".gmtime($lw)." Z");
push(@str,gmtime($lw)." UTC");
eval {
my ($f1,$f2,$seq) = unpack("Vvv",$key->get_value("_FileId_")->get_data());
my $entry = mftRecNum($f1,$f2);
# ::rptMsg(" FileID = ".$entry."/".$seq);
push(@str,$entry."/".$seq);
};
eval {
my $aefileid = $key->get_value("AeFileID")->get_data();
$aefileid =~ s/\00//g;
my $sha1 = $aefileid;
$sha1 =~ s/^0000//;
push(@str,$sha1);
# ::rptMsg(" AeFileID = ".$aefileid);
# ::rptMsg(" SHA-1 Hash = ".$sha1);
};
# eval {
# my ($u1,$u2) = unpack("VV",$key->get_value("_UsnJournalId_")->get_data());
# my $usn = ::getTime($u1,$u2);
# ::rptMsg(" USN Journal ID = ".gmtime($usn)." Z");
# };
my $s = join(',',@str);
::rptMsg($s);
}
# from: http://www.cse.scu.edu/~tschwarz/coen252_07Fall/Lectures/NTFS.html
# "Each MFT record is addressed by a 48 bit MFT entry value.The first entry has address 0.
# Each MFT entry has a 16 bit sequence number that is incremented when the entry is allocated.
# MFT entry value and sequence number combined yield 64b file reference address.:
#
# The 64-bit field is translated as 48-bits for the entry number and 16-bits for the
# sequence number
#
# variation of the below code shared by David Cowen
sub mftRecNum {
my $f1 = shift;
my $f2 = shift;
if ($f2 == 0) {
return $f1;
}
else {
$f2 = ($f2 * 16777216);
return ($f1 + $f2);
}
}
1;

View File

@ -0,0 +1,114 @@
#-----------------------------------------------------------
# syscache_tln.pl
#
# Change history
# 20190516 - tln output added
# 20181209 - original plugin created
#
# References
# https://github.com/libyal/winreg-kb/blob/master/documentation/SysCache.asciidoc
#
# Copyright (c) 2019 QAR, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package syscache_tln;
use strict;
my %config = (hive => "syscache",
hasShortDescr => 0,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
category => "program execution",
version => 20190516);
my $VERSION = getVersion();
# Functions #
sub getConfig {return %config}
sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
sub getDescr {}
sub getShortDescr {}
sub getRefs {}
sub pluginmain {
my $class = shift;
my $hive = shift;
# ::logMsg("Launching syscache v.".$VERSION);
# ::rptMsg("syscache_csv v.".$VERSION);
# ::rptMsg("(".$config{hive}.") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key;
my $key_path = 'DefaultObjectStore\\ObjectTable';
if ($key = $root_key->get_subkey($key_path)) {
my @subkeys = $key->get_list_of_subkeys();
if (scalar @subkeys > 0) {
foreach my $sk (@subkeys) {
processKey($sk);
# ::rptMsg("");
}
}
}
else {
::rptMsg($key_path." not found");
}
}
sub processKey {
my $key = shift;
my @str = ();
my $lw = $key->get_timestamp();
# ::rptMsg("LastWrite: ".gmtime($lw)." Z");
my $str = $lw."|SYSCACHE|||";
eval {
my ($f1,$f2,$seq) = unpack("Vvv",$key->get_value("_FileId_")->get_data());
my $entry = mftRecNum($f1,$f2);
# ::rptMsg(" FileID = ".$entry."/".$seq);
$str .= "MFT Ref: ".$entry."/".$seq." ";
};
eval {
my $aefileid = $key->get_value("AeFileID")->get_data();
$aefileid =~ s/\00//g;
my $sha1 = $aefileid;
$sha1 =~ s/^0000//;
$str .= "SHA-1: ".$sha1;
# ::rptMsg(" AeFileID = ".$aefileid);
# ::rptMsg(" SHA-1 Hash = ".$sha1);
};
# eval {
# my ($u1,$u2) = unpack("VV",$key->get_value("_UsnJournalId_")->get_data());
# my $usn = ::getTime($u1,$u2);
# ::rptMsg(" USN Journal ID = ".gmtime($usn)." Z");
# };
::rptMsg($str);
}
# from: http://www.cse.scu.edu/~tschwarz/coen252_07Fall/Lectures/NTFS.html
# "Each MFT record is addressed by a 48 bit MFT entry value.The first entry has address 0.
# Each MFT entry has a 16 bit sequence number that is incremented when the entry is allocated.
# MFT entry value and sequence number combined yield 64b file reference address.:
#
# The 64-bit field is translated as 48-bits for the entry number and 16-bits for the
# sequence number
#
# variation of the below code shared by David Cowen
sub mftRecNum {
my $f1 = shift;
my $f2 = shift;
if ($f2 == 0) {
return $f1;
}
else {
$f2 = ($f2 * 16777216);
return ($f1 + $f2);
}
}
1;

View File

@ -1,13 +1,14 @@
# 20161213 *ALL* Plugins that apply on SYSTEM hive, alphabetical order angelfire
appcertdlls appcertdlls
appcompatcache appcompatcache
appcompatcache_tln
auditfail auditfail
backuprestore backuprestore
bam
bthport bthport
comfoo comfoo
compname compname
crashcontrol crashcontrol
dafupnp
ddm ddm
devclass devclass
diag_sr diag_sr
@ -22,10 +23,11 @@ ide
imagedev imagedev
kbdcrash kbdcrash
legacy legacy
legacy_tln
lsa_packages lsa_packages
macaddr
mountdev mountdev
mountdev2 mountdev2
netlogon
netsvcs netsvcs
network network
nic nic
@ -39,6 +41,7 @@ prefetch
processor_architecture processor_architecture
productpolicy productpolicy
producttype producttype
profiler
rdpnla rdpnla
rdpport rdpport
regin regin
@ -49,15 +52,13 @@ securityproviders
services services
shares shares
shimcache shimcache
shimcache_tln
shutdown shutdown
shutdowncount shutdowncount
source_os
stillimage stillimage
svc svc
svcdll svcdll
svc_plus svc_plus
svc_tln
systemindex
termcert termcert
termserv termserv
timezone timezone

View File

@ -3,6 +3,7 @@
# Plugin for Registry Ripper; # Plugin for Registry Ripper;
# #
# Change history # Change history
# 20190527 - Added checks in Software hive
# 20160224 - added SysProcs info # 20160224 - added SysProcs info
# 20131007 - updated with Sticky Keys info # 20131007 - updated with Sticky Keys info
# 20130307 - updated with autostart locations # 20130307 - updated with autostart locations
@ -27,16 +28,16 @@
package termserv; package termserv;
use strict; use strict;
my %config = (hive => "System", my %config = (hive => "System, Software",
hasShortDescr => 1, hasShortDescr => 1,
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
osmask => 22, osmask => 22,
version => 20160224); version => 20190527);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
return "Gets Terminal Server values from System hive"; return "Gets Terminal Server settings from System and Software hives";
} }
sub getDescr{} sub getDescr{}
sub getRefs {} sub getRefs {}
@ -66,8 +67,6 @@ sub pluginmain {
::rptMsg($ts_path); ::rptMsg($ts_path);
::rptMsg("LastWrite Time ".gmtime($ts->get_timestamp())." (UTC)"); ::rptMsg("LastWrite Time ".gmtime($ts->get_timestamp())." (UTC)");
::rptMsg(""); ::rptMsg("");
::rptMsg("Reference: http://support.microsoft.com/kb/243215");
::rptMsg("");
my $ver; my $ver;
eval { eval {
@ -151,6 +150,14 @@ sub pluginmain {
}; };
::rptMsg(" InitialProgram value not found\.") if ($@); ::rptMsg(" InitialProgram value not found\.") if ($@);
# Added 20190527
eval {
my $sec = $ts->get_subkey("WinStations\\RDP-Tcp")->get_value("SecurityLayer")->get_data();
::rptMsg("WinStations\\RDP-Tcp key");
::rptMsg(" SecurityLayer: ".$sec);
::rptMsg("Analysis Tip: Maybe be empty; appears as '{blank}'");
};
# Added 20160224 # Added 20160224
eval { eval {
my $sys = $ts->get_subkey("SysProcs"); my $sys = $ts->get_subkey("SysProcs");
@ -185,5 +192,41 @@ sub pluginmain {
else { else {
::rptMsg($key_path." not found."); ::rptMsg($key_path." not found.");
} }
# Added 20190527
$key_path = "Policies\\Microsoft\\Windows NT\\Terminal Services";
if ($key = $root_key->get_subkey($key_path)) {
my $lw = $key->get_timestamp();
::rptMsg($key_path);
::rptMsg("LastWrite: ".gmtime($lw)." Z");
::rptMsg("");
# Note: fDenyTSConnections was added here because I've seen it used by bad actors,
# not due to any MS documentation
eval {
my $deny = $key->get_value("fDenyTSConnections")->get_data();
::rptMsg("fDenyTSConnections value = ".$deny);
};
eval {
my $fallow = $key->get_value("fAllowUnsolicited")->get_data();
::rptMsg("fAllowUnsolicited value = ".$fallow);
};
eval {
my $fallowfc = $key->get_value("fAllowUnsolicitedFullControl")->get_data();
::rptMsg("fAllowUnsolicitedFullControl value = ".$fallowfc);
};
eval {
my $user = $key->get_value("UserAuthentication")->get_data();
::rptMsg("UserAuthentication value = ".$user);
};
}
else {
::rptMsg($key_path." not found.");
}
} }
1; 1;

View File

@ -0,0 +1,92 @@
#-----------------------------------------------------------
# thunderbirdinstalled
# Shows install current status for Mozilla Thunderbird
#
# References
# https://www.thunderbird.net/en-US/
#
# History:
# 20180712 - created
#
# Author:
# M. Jones, mictjon@gmail.com
#-----------------------------------------------------------
package thunderbirdinstalled;
use strict;
my %config = (hive => "Software,NTUSER\.DAT",
osmask => 22,
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 1,
version => 20120524);
sub getConfig{return %config}
sub getShortDescr {
return "Shows install status of Thunderbird";
}
sub getDescr{}
sub getRefs {
my %refs = ("Mozilla" =>
"https://www.thunderbird.net/en-US/");
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 thunderbirdinstalled v.".$VERSION);
::rptMsg("thunderbirdinstalled v.".$VERSION); # banner
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
# used a list of values to address the need for parsing the App Paths key
# in the Wow6432Node key, if it exists.
my @paths = ("Microsoft\\Windows\\CurrentVersion\\App Paths\\thunderbird.exe",
"WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\App Paths\\thunderbird.exe");
foreach my $key_path (@paths) {
my $key;
if ($key = $root_key->get_subkey($key_path)) {
::rptMsg("Thunderbird installed");
::rptMsg($key_path);
::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
::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.");
}
}
else {
::rptMsg($key_path." not found.");
::rptMsg(" Thunderbird not installed.");
}
}
}
1;

View File

@ -4,10 +4,15 @@
# the default security settings for the application # the default security settings for the application
# #
# Change history # Change history
# 20190626 - updated to more recent versions of Office
# 20160224 - modified per Mari's blog post # 20160224 - modified per Mari's blog post
# 20120716 - created # 20120716 - created
# #
# References # References
# 20190626 updates
# https://decentsecurity.com/block-office-macros
# https://gist.github.com/PSJoshi/749cf1733217d8791cf956574a3583a2
#
# http://az4n6.blogspot.com/2016/02/more-on-trust-records-macros-and.html # http://az4n6.blogspot.com/2016/02/more-on-trust-records-macros-and.html
# ForensicArtifacts.com posting by Andrew Case: # ForensicArtifacts.com posting by Andrew Case:
# http://forensicartifacts.com/2012/07/ntuser-trust-records/ # http://forensicartifacts.com/2012/07/ntuser-trust-records/
@ -25,7 +30,7 @@ my %config = (hive => "NTUSER\.DAT",
hasDescr => 0, hasDescr => 0,
hasRefs => 0, hasRefs => 0,
osmask => 22, osmask => 22,
version => 20160224); version => 20190626);
sub getConfig{return %config} sub getConfig{return %config}
sub getShortDescr { sub getShortDescr {
@ -76,7 +81,7 @@ sub pluginmain {
# Now that we have the most recent version of Office installed, let's # Now that we have the most recent version of Office installed, let's
# start looking at the various subkeys # start looking at the various subkeys
my @apps = ("Word","PowerPoint","Excel","Access"); my @apps = ("Word","PowerPoint","Excel","Access");
$key_path = "Software\\Microsoft\\Office\\".$office_version; my $key_path = "Software\\Microsoft\\Office\\".$office_version;
foreach my $app (@apps) { foreach my $app (@apps) {
::rptMsg("**".$app."**"); ::rptMsg("**".$app."**");
@ -90,11 +95,22 @@ sub pluginmain {
::rptMsg(""); ::rptMsg("");
} }
}; };
# Added 20190626
eval {
if (my $sec = $root_key->get_subkey($app_path)) {
my $blk = $sec->get_value("blockcontentexecutionfrominternet")->get_data();
::rptMsg("blockcontentexecutionfrominternet = ".$blk);
::rptMsg("");
}
};
# Trusted Documents/Trust Records # Trusted Documents/Trust Records
$app_path = $key_path."\\".$app."\\Security\\Trusted Documents"; $app_path = $key_path."\\".$app."\\Security\\Trusted Documents";
if (my $app_key = $root_key->get_subkey($app_path)) { if (my $app_key = $root_key->get_subkey($app_path)) {
if (my $trust = $app_key->get_subkey("TrustRecords")) { if (my $trust = $app_key->get_subkey("TrustRecords")) {
my @vals = $trust->get_list_of_values(); my @vals = $trust->get_list_of_values();
::rptMsg("TrustRecords");
foreach my $v (@vals) { foreach my $v (@vals) {
my $data = $v->get_data(); my $data = $v->get_data();
my ($t0,$t1) = (unpack("VV",substr($data,0,8))); my ($t0,$t1) = (unpack("VV",substr($data,0,8)));

Some files were not shown because too many files have changed in this diff Show More