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 ProgressIndicator progressIndicator;
private volatile boolean cancelRequested;
private final boolean isNewCase;
/**
* Constructs the context for the creation/opening/upgrading of
@ -100,9 +101,23 @@ public interface AutopsyService {
* case-level resources
*/
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.progressIndicator = progressIndicator;
this.cancelRequested = false;
this.isNewCase = isNewCase;
}
/**
@ -145,6 +160,16 @@ public interface AutopsyService {
public boolean 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<Content> newDataSources = new ArrayList<>();
try {
currentCase.getSleuthkitCase().acquireSingleUserCaseWriteLock();
synchronized (tskAddImageProcessLock) {
if (!tskAddImageProcessStopped) {
tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true, ignoreFatOrphanFiles, imageWriterPath);
@ -147,7 +146,6 @@ class AddImageTask implements Runnable {
commitOrRevertAddImageProcess(currentCase, errorMessages, newDataSources);
progressMonitor.setProgress(100);
} finally {
currentCase.getSleuthkitCase().releaseSingleUserCaseWriteLock();
DataSourceProcessorCallback.DataSourceProcessorResult result;
if (criticalErrorOccurred) {
result = DataSourceProcessorResult.CRITICAL_ERRORS;

View File

@ -1958,7 +1958,7 @@ public class Case {
checkForCancellation();
openCaseLevelServices(progressIndicator);
checkForCancellation();
openAppServiceCaseResources(progressIndicator);
openAppServiceCaseResources(progressIndicator, true);
checkForCancellation();
openCommunicationChannels(progressIndicator);
return null;
@ -2007,7 +2007,7 @@ public class Case {
checkForCancellation();
openCaseLevelServices(progressIndicator);
checkForCancellation();
openAppServiceCaseResources(progressIndicator);
openAppServiceCaseResources(progressIndicator, false);
checkForCancellation();
openCommunicationChannels(progressIndicator);
checkForCancellation();
@ -2518,7 +2518,7 @@ public class Case {
"# {0} - service name", "Case.serviceOpenCaseResourcesProgressIndicator.cancellingMessage=Cancelling opening case resources by {0}...",
"# {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
* task, running in a named thread managed by an executor service, with
@ -2550,7 +2550,7 @@ public class Case {
appServiceProgressIndicator = new LoggingProgressIndicator();
}
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
threadNameSuffix = threadNameSuffix.toLowerCase();
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 int TAG_SETTINGS_VERSION = 1;
private static final String CATEGORY_ONE_NAME = "CAT-1: Child Exploitation (Illegal)";
private static final String CATEGORY_TWO_NAME = "CAT-2: Child Exploitation (Non-Illegal/Age Difficult)";
private static final String CATEGORY_THREE_NAME = "CAT-3: CGI/Animation (Child Exploitive)";
private static final String CATEGORY_FOUR_NAME = "CAT-4: Exemplar/Comparison (Internal Use Only)";
private static final String CATEGORY_FIVE_NAME = "CAT-5: Non-pertinent";
private static final String CATEGORY_ONE_NAME = "Child Exploitation (Illegal)";
private static final String CATEGORY_TWO_NAME = "Child Exploitation (Non-Illegal/Age Difficult)";
private static final String CATEGORY_THREE_NAME = "CGI/Animation (Child Exploitive)";
private static final String CATEGORY_FOUR_NAME = "Exemplar/Comparison (Internal Use Only)";
private static final String CATEGORY_FIVE_NAME = "Non-pertinent";
private final String displayName;
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> PROJECT_VIC_TAG_DEFINITIONS = new HashMap<>();
private static final List<String> OLD_CATEGORY_TAG_NAMES = new ArrayList<>();
static {
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_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));
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;
}
/**
* 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.
*
@ -300,6 +336,7 @@ final class TagNameDefinition implements Comparable<TagNameDefinition> {
if (version == null) {
String tagsProperty = ModuleSettings.getConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY);
if (tagsProperty == null || tagsProperty.isEmpty()) {
ModuleSettings.setConfigSetting(TAGS_SETTINGS_NAME, TAG_SETTING_VERSION_KEY, Integer.toString(TAG_SETTINGS_VERSION));
return;
}
@ -339,7 +376,8 @@ final class TagNameDefinition implements Comparable<TagNameDefinition> {
List<String> tagStrings = new ArrayList<>();
List<String> standardTags = getStandardTagNames();
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());
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2018 Basis Technology Corp.
* Copyright 2011-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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 final SleuthkitCase caseDb;
static String DEFAULT_TAG_SET_NAME = "Project VIC (United States)";
private static String DEFAULT_TAG_SET_NAME = "Project VIC";
static {
@ -184,7 +184,62 @@ public class TagsManager implements Closeable {
* @return list of predefined tag names
*/
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

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

View File

@ -116,30 +116,25 @@ class AddMultipleImagesTask implements Runnable {
* Try to add the input image files as images.
*/
List<String> corruptedImageFilePaths = new ArrayList<>();
try {
currentCase.getSleuthkitCase().acquireSingleUserCaseWriteLock();
progressMonitor.setIndeterminate(true);
for (String imageFilePath : imageFilePaths) {
synchronized (tskAddImageProcessLock) {
if (!tskAddImageProcessStopped) {
addImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, false, false, "");
} else {
return;
}
}
run(imageFilePath, corruptedImageFilePaths, errorMessages);
commitOrRevertAddImageProcess(imageFilePath, errorMessages, newDataSources);
synchronized (tskAddImageProcessLock) {
if (tskAddImageProcessStopped) {
errorMessages.add(Bundle.AddMultipleImagesTask_cancelled());
result = DataSourceProcessorResult.CRITICAL_ERRORS;
newDataSources = emptyDataSources;
return;
}
progressMonitor.setIndeterminate(true);
for (String imageFilePath : imageFilePaths) {
synchronized (tskAddImageProcessLock) {
if (!tskAddImageProcessStopped) {
addImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, false, false, "");
} else {
return;
}
}
run(imageFilePath, corruptedImageFilePaths, errorMessages);
commitOrRevertAddImageProcess(imageFilePath, errorMessages, newDataSources);
synchronized (tskAddImageProcessLock) {
if (tskAddImageProcessStopped) {
errorMessages.add(Bundle.AddMultipleImagesTask_cancelled());
result = DataSourceProcessorResult.CRITICAL_ERRORS;
newDataSources = emptyDataSources;
return;
}
}
} finally {
currentCase.getSleuthkitCase().releaseSingleUserCaseWriteLock();
}
/*
@ -153,8 +148,6 @@ class AddMultipleImagesTask implements Runnable {
try {
progressMonitor.setProgressText(Bundle.AddMultipleImagesTask_addingFileAsLogicalFile(corruptedImageFilePaths.toString()));
caseDatabase.acquireSingleUserCaseWriteLock();
Image dataSource = caseDatabase.addImageInfo(0, corruptedImageFilePaths, timeZone);
newDataSources.add(dataSource);
List<TskFileRange> fileRanges = new ArrayList<>();
@ -177,8 +170,6 @@ class AddMultipleImagesTask implements Runnable {
} catch (TskCoreException ex) {
errorMessages.add(Bundle.AddMultipleImagesTask_errorAddingImgWithoutFileSystem(deviceId, ex.getLocalizedMessage()));
criticalErrorOccurred = true;
} finally {
caseDatabase.releaseSingleUserCaseWriteLock();
}
}

View File

@ -146,30 +146,25 @@ final class AddMemoryImageTask implements Runnable {
progressMonitor.setProgressText(Bundle.AddMemoryImageTask_progressMessage_addingImageFile( memoryImagePath));
SleuthkitCase caseDatabase = Case.getCurrentCaseThrows().getSleuthkitCase();
caseDatabase.acquireSingleUserCaseWriteLock();
try {
/*
* Verify the memory image file exists.
*/
File imageFile = Paths.get(memoryImagePath).toFile();
if (!imageFile.exists()) {
throw new TskCoreException(Bundle.AddMemoryImageTask_exceptionMessage_noImageFile(memoryImagePath, deviceId));
}
/*
* Add the data source.
*
* NOTE: The object id for device passed to
* SleuthkitCase.addImageInfo is hard-coded to zero for now. This
* will need to be changed when a Device abstraction is added to the
* SleuthKit data model.
*/
Image dataSource = caseDatabase.addImageInfo(0, new ArrayList<>(Arrays.asList(memoryImagePath)), timeZone);
return dataSource;
} finally {
caseDatabase.releaseSingleUserCaseWriteLock();
/*
* Verify the memory image file exists.
*/
File imageFile = Paths.get(memoryImagePath).toFile();
if (!imageFile.exists()) {
throw new TskCoreException(Bundle.AddMemoryImageTask_exceptionMessage_noImageFile(memoryImagePath, deviceId));
}
/*
* Add the data source.
*
* NOTE: The object id for device passed to
* SleuthkitCase.addImageInfo is hard-coded to zero for now. This
* will need to be changed when a Device abstraction is added to the
* SleuthKit data model.
*/
Image dataSource = caseDatabase.addImageInfo(0, new ArrayList<>(Arrays.asList(memoryImagePath)), timeZone);
return dataSource;
}
/**

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.ContentTagDeletedEvent;
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.Logger;
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.events.DataSourceAnalysisEvent;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector.FileTypeDetectorInitException;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.Content;
@ -108,8 +110,6 @@ public final class ImageGalleryController {
Case.Events.CONTENT_TAG_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
@ -725,19 +725,19 @@ public final class ImageGalleryController {
private static boolean isDrawableAndNotKnown(AbstractFile abstractFile) throws FileTypeDetector.FileTypeDetectorInitException {
return (abstractFile.getKnown() != TskData.FileKnown.KNOWN) && FileTypeUtils.isDrawable(abstractFile);
}
/**
* Returns the TagSet with the image gallery categories.
*
*
* @return Category TagSet.
*
* @throws TskCoreException
*
* @throws TskCoreException
*/
private TagSet getCategoryTagSet() throws TskCoreException {
List<TagSet> tagSetList = getCaseDatabase().getTaggingManager().getTagSets();
if (tagSetList != null && !tagSetList.isEmpty()) {
for (TagSet set : tagSetList) {
if (set.getName().startsWith(CATEGORY_TAG_SET_PREFIX)) {
if (set.getName().equals(TagsManager.getCategoryTagSetName())) {
return set;
}
}

View File

@ -82,7 +82,6 @@ public class CategorizeAction extends Action {
this.tagName = tagName;
setGraphic(getGraphic(tagName));
setEventHandler(actionEvent -> addCatToFiles(selectedFileIDs));
setAccelerator(new KeyCodeCombination(KeyCode.getKeyCode(getCategoryNumberFromTagName(tagName))));
}
static public Menu getCategoriesMenu(ImageGalleryController controller) {
@ -94,16 +93,6 @@ public class CategorizeAction extends Action {
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
* selecting a category

View File

@ -13,6 +13,4 @@ DrawableAttribute.name=Name
DrawableAttribute.path=Path
DrawableAttribute.tags=Tags
DrawableAttribute.width=Width
DrawableTagsManager.bookMark=Bookmark
DrawableTagsManager.followUp=Follow Up
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.DeletedContentTagInfo;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.DhsImageCategory;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.TagName;
@ -62,9 +61,7 @@ public class CategoryManager {
private static final Logger LOGGER = Logger.getLogger(CategoryManager.class.getName());
/**
* the DrawableDB that backs the category counts cache. The counts are
* initialized from this, and the counting of CAT-0 is always delegated to
* this db.
* the DrawableDB that backs the category counts cache.
*/
private final DrawableDB drawableDb;

View File

@ -29,7 +29,6 @@ import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
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.ContentTagDeletedEvent;
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
* the autopsy Db. Delegates some work to the backing autopsy TagsManager.
*/
@NbBundle.Messages({"DrawableTagsManager.followUp=Follow Up",
"DrawableTagsManager.bookMark=Bookmark"})
public final class DrawableTagsManager {
private static final Logger logger = Logger.getLogger(DrawableTagsManager.class.getName());
@ -78,8 +75,8 @@ public final class DrawableTagsManager {
public DrawableTagsManager(ImageGalleryController controller) throws TskCoreException {
this.autopsyTagsManager = controller.getCase().getServices().getTagsManager();
followUpTagName = getTagName(Bundle.DrawableTagsManager_followUp());
bookmarkTagName = getTagName(Bundle.DrawableTagsManager_bookMark());
followUpTagName = getTagName(TagsManager.getFollowUpDisplayString());
bookmarkTagName = getTagName(TagsManager.getBookmarkDisplayString());
this.controller = controller;
compareByDisplayName = new Comparator<TagName>() {

View File

@ -1497,11 +1497,11 @@ class ExtractRegistry extends Extract {
line = line.trim();
// 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
while (!line.contains(SECTION_DIVIDER)) {
while (!line.contains(SECTION_DIVIDER) && !line.contains("MSOffice version not found.")) {
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
// 1294283922|REG|||OfficeDocs2010 - F:\Windows_time_Rules_xp.doc
String tokens[] = line.split("\\|");
@ -1551,7 +1551,7 @@ class ExtractRegistry extends Extract {
line = line.trim();
usedTime = Long.valueOf(0);
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
// Date : <File Name>/<Website>
// 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
its effectiveness or stability. While it shouldn't cause any problems
whatsoever with your system, there's always the chance that someone may find
a way to blame a system crash or loss of data on software like this...you've
been warned!
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:
This software is released under the GNU Public License -
http://www.gnu.org/copyleft/gpl.html
The above copyright notice and this permission notice shall be included in all copies or substantial
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.

View File

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

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
#
# Change history
# 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
@ -9,9 +10,10 @@
# 20131204 - created
#
# 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
#
# Copyright (c) 2017 QAR, LLC
# Copyright (c) 2018 QAR, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package amcache;
@ -23,7 +25,7 @@ my %config = (hive => "amcache",
hasRefs => 1,
osmask => 22,
category => "program execution",
version => 20170315);
version => 20180311);
my $VERSION = getVersion();
# Functions #
@ -40,121 +42,208 @@ sub pluginmain {
my $class = shift;
my $hive = shift;
# Initialize #
::logMsg("Launching amcache v.".$VERSION);
::rptMsg("amcache v.".$VERSION);
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key;
my @sk1;
my @sk;
my (@t,$gt);
my $key_path = 'Root\\File';
::rptMsg("***Files***");
if ($key = $root_key->get_subkey($key_path)) {
# Newer version Amcache.hve files
# Devices not parsed at this time
my $key_path = 'Root\\InventoryApplicationFile';
if ($key = $root_key->get_subkey($key_path)) {
parseInventoryApplicationFile($key);
@sk1 = $key->get_list_of_subkeys();
foreach my $s1 (@sk1) {
# Volume GUIDs
::rptMsg($s1->get_name());
@sk = $s1->get_list_of_subkeys();
if (scalar(@sk) > 0) {
foreach my $s (@sk) {
::rptMsg("File Reference: ".$s->get_name());
::rptMsg("LastWrite : ".gmtime($s->get_timestamp())." Z");
# update 20131213: based on trial and error, it appears that not all file
# references will have all of the values, such as Path, or SHA-1
eval {
::rptMsg("Path : ".$s->get_value("15")->get_data());
};
eval {
::rptMsg("Company Name : ".$s->get_value("1")->get_data());
};
eval {
::rptMsg("Product Name : ".$s->get_value("0")->get_data());
};
eval {
::rptMsg("File Descr : ".$s->get_value("c")->get_data());
};
eval {
::rptMsg("Lang Code : ".$s->get_value("3")->get_data());
};
eval {
::rptMsg("SHA-1 : ".$s->get_value("101")->get_data());
};
eval {
@t = unpack("VV",$s->get_value("11")->get_data());
$gt = gmtime(::getTime($t[0],$t[1]));
::rptMsg("Last Mod Time : ".$gt." Z");
};
eval {
@t = unpack("VV",$s->get_value("17")->get_data());
$gt = gmtime(::getTime($t[0],$t[1]));
::rptMsg("Last Mod Time2: ".$gt." Z");
};
eval {
@t = unpack("VV",$s->get_value("12")->get_data());
$gt = gmtime(::getTime($t[0],$t[1]));
::rptMsg("Create Time : ".$gt." Z");
};
eval {
$gt = gmtime($s->get_value("f")->get_data());
# $gt = gmtime(unpack("V",$s->get_value("f")->get_data()));
::rptMsg("Compile Time : ".$gt." Z");
};
::rptMsg("");
}
}
else {
# ::rptMsg("Key ".$s1->get_name()." has no 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';
::rptMsg("***Programs***");
if ($key = $root_key->get_subkey($key_path)) {
@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("");
}
}
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) {
# Volume GUIDs
::rptMsg($s1->get_name());
my @sk = $s1->get_list_of_subkeys();
if (scalar(@sk) > 0) {
foreach my $s (@sk) {
::rptMsg("File Reference: ".$s->get_name());
::rptMsg("LastWrite : ".gmtime($s->get_timestamp())." Z");
# update 20131213: based on trial and error, it appears that not all file
# references will have all of the values, such as Path, or SHA-1
eval {
::rptMsg("Path : ".$s->get_value("15")->get_data());
};
eval {
::rptMsg("Company Name : ".$s->get_value("1")->get_data());
};
eval {
::rptMsg("Product Name : ".$s->get_value("0")->get_data());
};
eval {
::rptMsg("File Descr : ".$s->get_value("c")->get_data());
};
eval {
::rptMsg("Lang Code : ".$s->get_value("3")->get_data());
};
eval {
::rptMsg("SHA-1 : ".$s->get_value("101")->get_data());
};
eval {
@t = unpack("VV",$s->get_value("11")->get_data());
$gt = gmtime(::getTime($t[0],$t[1]));
::rptMsg("Last Mod Time : ".$gt." Z");
};
eval {
@t = unpack("VV",$s->get_value("17")->get_data());
$gt = gmtime(::getTime($t[0],$t[1]));
::rptMsg("Last Mod Time2: ".$gt." Z");
};
eval {
@t = unpack("VV",$s->get_value("12")->get_data());
$gt = gmtime(::getTime($t[0],$t[1]));
::rptMsg("Create Time : ".$gt." Z");
};
eval {
$gt = gmtime($s->get_value("f")->get_data());
# $gt = gmtime(unpack("V",$s->get_value("f")->get_data()));
::rptMsg("Compile Time : ".$gt." Z");
};
::rptMsg("");
}
}
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;

View File

@ -2,12 +2,18 @@
# amcache_tln.pl
#
# 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
# 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
#
# Copyright (c) 2017 QAR, LLC
# Copyright (c) 2018 QAR, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package amcache_tln;
@ -19,7 +25,7 @@ my %config = (hive => "amcache",
hasRefs => 1,
osmask => 22,
category => "program execution",
version => 20170315);
version => 20180311);
my $VERSION = getVersion();
# Functions #
@ -28,88 +34,199 @@ sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
sub getDescr {}
sub getShortDescr {
return "Parse AmCache\.hve file, TLN format";
return "Parse AmCache\.hve file";
}
sub getRefs {}
sub pluginmain {
my $class = shift;
my $hive = shift;
# Initialize #
::logMsg("Launching amcache_tln v.".$VERSION);
# ::rptMsg("amcache v.".$VERSION);
# ::rptMsg("(".$config{hive}.") ".getShortDescr()."\n");
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key;
my @sk1;
my @sk;
my (@t,$gt);
my $key_path = 'Root\\File';
# ::rptMsg("***Files***");
if ($key = $root_key->get_subkey($key_path)) {
# Newer version Amcache.hve files
# Devices not parsed at this time
my $key_path = 'Root\\InventoryApplicationFile';
if ($key = $root_key->get_subkey($key_path)) {
parseInventoryApplicationFile($key);
@sk1 = $key->get_list_of_subkeys();
foreach my $s1 (@sk1) {
# Volume GUIDs
::rptMsg($s1->get_name());
}
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();
};
@sk = $s1->get_list_of_subkeys();
if (scalar(@sk) > 0) {
foreach my $s (@sk) {
my $fileref = $s->get_name();
my $lw = $s->get_timestamp();
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) {
# Volume GUIDs
::rptMsg($s1->get_name());
my @sk = $s1->get_list_of_subkeys();
if (scalar(@sk) > 0) {
foreach my $s (@sk) {
my $fileref = $s->get_name();
my $lw = $s->get_timestamp();
# First, report key lastwrite time (== execution time??)
eval {
$fileref = $fileref.":".$s->get_value("15")->get_data();
};
::rptMsg($lw."|AmCache|||Key LastWrite - ".$fileref);
eval {
$fileref = $fileref.":".$s->get_value("15")->get_data();
};
::rptMsg($lw."|AmCache|||Key LastWrite - ".$fileref);
# get last mod./creation times
my @dots = qw/. . . ./;
my %t_hash = ();
my @vals = ();
my @dots = qw/. . . ./;
my %t_hash = ();
my @vals = ();
# last mod time
eval {
my @t = unpack("VV",$s->get_value("11")->get_data());
$vals[1] = ::getTime($t[0],$t[1]);
};
eval {
my @t = unpack("VV",$s->get_value("11")->get_data());
$vals[1] = ::getTime($t[0],$t[1]);
};
# creation time
eval {
my @t = unpack("VV",$s->get_value("12")->get_data());
$vals[3] = ::getTime($t[0],$t[1]);
};
eval {
my @t = unpack("VV",$s->get_value("12")->get_data());
$vals[3] = ::getTime($t[0],$t[1]);
};
foreach my $v (@vals) {
@{$t_hash{$v}} = @dots unless ($v == 0);
}
foreach my $v (@vals) {
@{$t_hash{$v}} = @dots unless ($v == 0);
}
${$t_hash{$vals[0]}}[1] = "A" unless ($vals[0] == 0);
${$t_hash{$vals[1]}}[0] = "M" unless ($vals[1] == 0);
${$t_hash{$vals[2]}}[2] = "C" unless ($vals[2] == 0);
${$t_hash{$vals[3]}}[3] = "B" unless ($vals[3] == 0);
${$t_hash{$vals[0]}}[1] = "A" unless ($vals[0] == 0);
${$t_hash{$vals[1]}}[0] = "M" unless ($vals[1] == 0);
${$t_hash{$vals[2]}}[2] = "C" unless ($vals[2] == 0);
${$t_hash{$vals[3]}}[3] = "B" unless ($vals[3] == 0);
foreach my $t (reverse sort {$a <=> $b} keys %t_hash) {
my $str = join('',@{$t_hash{$t}});
::rptMsg($t."|AmCache|||".$str." ".$fileref);
}
foreach my $t (reverse sort {$a <=> $b} keys %t_hash) {
my $str = join('',@{$t_hash{$t}});
::rptMsg($t."|AmCache|||".$str." ".$fileref);
}
# check for PE Compile times
eval {
my $pe = $s->get_value("f")->get_data();
::rptMsg($pe."|AmCache|||PE Compile time - ".$fileref);
::rptMsg("Compile Time : ".$gt." Z");
};
}
eval {
my $pe = $s->get_value("f")->get_data();
::rptMsg($pe."|AmCache|||PE Compile time - ".$fileref);
::rptMsg("Compile Time : ".$gt." Z");
};
}
}
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
#
# 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
# 20160217 - updated to correctly support Win10
# 20150611 - mod'd for Kevin Pagano
@ -42,7 +44,7 @@ my %config = (hive => "System",
hasDescr => 0,
hasRefs => 0,
osmask => 31, #XP - Win7
version => 20160528);
version => 20190112);
sub getConfig{return %config}
sub getShortDescr {
@ -120,12 +122,18 @@ sub pluginmain {
# 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
appWin10($app_data);
}
else {
::rptMsg(sprintf "Unknown signature: 0x%x",$sig);
# probe($app_data);
}
# this is where we print out the files
foreach my $f (keys %files) {
@ -296,7 +304,7 @@ sub appWin8 {
while($ofs < $len) {
my $tag = unpack("V",substr($data,$ofs,4));
last unless (defined $tag);
last unless (defined $tag);
# 32-bit
if ($tag == 0x73746f72) {
$jmp = unpack("V",substr($data,$ofs + 8,4));
@ -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()
# Ref: http://binaryforay.blogspot.com/2015/04/appcompatcache-changes-in-windows-10.html
@ -337,11 +377,11 @@ sub appWin10 {
my $len = length($data);
my ($tag, $sz, $t0, $t1, $name, $name_len);
my $ct = 0;
my $ofs = 0x30;
my $ofs = unpack("V",substr($data,0,4));
# my $ofs = 0x30;
while ($ofs < $len) {
$tag = substr($data,$ofs,4);
last unless (defined $tag);
if ($tag eq "10ts") {
$sz = unpack("V",substr($data,$ofs + 0x08,4));

View File

@ -2,6 +2,8 @@
# appcompatcache_tln.pl
#
# 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
# 20160217 - updated to correctly support Win10
# 20150611 - mod'd for Kevin Pagano
@ -42,7 +44,7 @@ my %config = (hive => "System",
hasDescr => 0,
hasRefs => 0,
osmask => 31, #XP - Win7
version => 20160528);
version => 20190112);
sub getConfig{return %config}
sub getShortDescr {
@ -120,7 +122,10 @@ sub pluginmain {
# probe($app_data);
}
elsif ($sig == 0x30) {
elsif ($sig == 0x0) {
appWin81($app_data);
}
elsif ($sig == 0x30 || $sig == 0x34) {
# Windows 10 system
appWin10($app_data);
}
@ -291,7 +296,7 @@ sub appWin8 {
while($ofs < $len) {
my $tag = unpack("V",substr($data,$ofs,4));
last unless (defined $tag);
last unless (defined $tag);
# 32-bit
if ($tag == 0x73746f72) {
$jmp = unpack("V",substr($data,$ofs + 8,4));
@ -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()
# Ref: http://binaryforay.blogspot.com/2015/04/appcompatcache-changes-in-windows-10.html
@ -332,11 +370,11 @@ sub appWin10 {
my $len = length($data);
my ($tag, $sz, $t0, $t1, $name, $name_len);
my $ct = 0;
my $ofs = 0x30;
my $ofs = unpack("V",substr($data,0,4));
# my $ofs = 0x30;
while ($ofs < $len) {
$tag = substr($data,$ofs,4);
last unless (defined $tag);
if ($tag eq "10ts") {
$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

@ -122,7 +122,7 @@ sub parsePath {
while($tag) {
$ofs += 2;
my $i = substr($data,$ofs,2);
last unless (defined $i);
last unless (defined $i);
if (unpack("v",$i) == 0) {
$tag = 0;
}

View File

@ -3,17 +3,22 @@
# Plugin to extract file association data from the Software hive file
# 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
#-----------------------------------------------------------
package assoc;
use strict;
my %config = (hive => "Software",
my %config = (hive => "Software,USRCLASS",
osmask => 22,
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
version => 20080815);
version => 20180117);
sub getConfig{return %config}
@ -32,58 +37,55 @@ sub pluginmain {
my $hive = shift;
::logMsg("Launching assoc v.".$VERSION);
::rptMsg("assoc v.".$VERSION); # banner
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
my $reg = Parse::Win32Registry->new($hive);
my $root_key = $reg->get_root_key;
my $key_path = "Classes";
my @paths = ("Classes","Classes\\Wow6432Node","Wow6432Node");
my $key;
if ($key = $root_key->get_subkey($key_path)) {
::rptMsg("assoc");
::rptMsg($key_path);
foreach my $key_path (@paths) {
if ($key = $root_key->get_subkey($key_path)) {
::rptMsg("assoc");
::rptMsg($key_path);
# ::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
::rptMsg("");
::rptMsg("");
# First step will be to get a list of all of the file extensions
my %ext;
my @sk = $key->get_list_of_subkeys();
if (scalar(@sk) > 0) {
foreach my $s (@sk) {
my $name = $s->get_name();
next unless ($name =~ m/^\.\w+$/);
my $data;
eval {
$data = $s->get_value("")->get_data();
};
if ($@) {
my %ext;
my @sk = $key->get_list_of_subkeys();
if (scalar(@sk) > 0) {
foreach my $s (@sk) {
my $name = $s->get_name();
next unless ($name =~ m/^\.\w+$/);
my $data;
eval {
$data = $s->get_value("")->get_data();
};
if ($@) {
# Error generated, as "(Default)" value was not found
}
else {
$ext{$name} = $data if ($data ne "");
}
}
else {
$ext{$name} = $data if ($data ne "");
}
}
# Once a list of all file ext subkeys has been compiled, access the file type
# to determine the command line used to launch files with that extension
foreach my $e (keys %ext) {
my $cmd;
eval {
$cmd = $key->get_subkey($ext{$e}."\\shell\\open\\command")->get_value("")->get_data();
};
if ($@) {
foreach my $e (keys %ext) {
my $cmd;
eval {
$cmd = $key->get_subkey($ext{$e}."\\shell\\open\\command")->get_value("")->get_data();
};
if ($@) {
# error generated attempting to locate <file type>.\shell\open\command\(Default) value
}
else {
::rptMsg($e." : ".$cmd);
}
else {
::rptMsg($e." : ".$cmd);
}
}
}
}
else {
::rptMsg($key_path." has no subkeys.");
else {
::rptMsg($key_path." has no subkeys.");
}
}
}
else {
::rptMsg($key_path." not found.");
::logMsg($key_path." not found.");
}
}
1;

View File

@ -4,6 +4,7 @@
# *Works for Win7 and Win10 at the moment
#
# History
# 20190510 - updated; Win2016
# 20151202 - created
#
# Ref:
@ -24,7 +25,7 @@ my %config = (hive => "Security",
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20151202);
version => 20190510);
sub getConfig{return %config}
sub getShortDescr {
@ -71,9 +72,15 @@ sub pluginmain {
@policy = processWin10($data)
}
elsif (length($data) == 138 && $id == 0x78) {
::rptMsg("Possible Win7/Win2008");
@policy = processWin7($data);
}
elsif (length($data) == 0x96 && $id == 0x84) {
::rptMsg("Possible Win10(1607+)/Win2016");
@policy = processWin2016($data);
}
else {
::rptMsg(sprintf "Data Length: 0x%x",length($data));
my @d = printData($data);
foreach (0..(scalar(@d) - 1)) {
::rptMsg($d[$_]);
@ -213,6 +220,71 @@ sub processWin7 {
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()
# 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)
#
# 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/
# 20130115 - created
#
# Category:
#
# copyright 2017 Quantum Analytics Research, LLC
# copyright 2018 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package bthport;
@ -21,7 +22,7 @@ my %config = (hive => "System",
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20170129);
version => 20180705);
sub getConfig{return %config}
sub getShortDescr {
@ -67,22 +68,21 @@ sub pluginmain {
# Note: Need to get VID and PID values for translation and mapping
my $devname;
eval {
# May need to work on parsing the binary "Name" value data into an actual name...
my @str1 = split(//,unpack("H*",$s->get_value("Name")->get_data()));
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);
my $n = $s->get_value("Name")->get_data();
::rptMsg("Name : ".$n);
};
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 {
@ -92,7 +92,7 @@ sub pluginmain {
else {
::rptMsg($cn_path." not found.");
}
::rptMsg("");
my $rs_path = $ccs."\\services\\BTHPORT\\Parameters\\Radio Support";
my $rs;
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
#
# 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
# 20100227 - 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 2010, Quantum Analytics Research, LLC
# copyright 2018, Quantum Analytics Research, LLC
#-----------------------------------------------------------
package clsid;
use strict;
@ -20,7 +26,7 @@ my %config = (hive => "Software",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
version => 20130603);
version => 20180823);
sub getConfig{return %config}
@ -40,77 +46,55 @@ sub pluginmain {
my %clsid;
::logMsg("Launching clsid v.".$VERSION);
::rptMsg("clsid v.".$VERSION); # banner
::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # 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 $key;
if ($key = $root_key->get_subkey($key_path)) {
::rptMsg($key_path);
# 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("");
::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 %ext;
my @sk = $key->get_list_of_subkeys();
if (scalar(@sk) > 0) {
foreach my $s (@sk) {
my $name = $s->get_name();
eval {
my $n = $s->get_value("")->get_data();
$name .= " ".$n unless ($n eq "");
};
my $name = $s->get_name();
my $n;
eval {
$n = $s->get_value("")->get_data();
$name .= " ".$n unless ($n eq "");
};
::rptMsg($name);
::rptMsg(" LastWrite: ".gmtime($s->get_timestamp())." Z");
eval {
my $proc = $s->get_subkey("InprocServer32")->get_value("")->get_data();
::rptMsg(" InprocServer32: ".$proc);
};
eval {
my $path = $s->get_subkey("InprocServer32")->get_value("")->get_data();
alertCheckPath($path);
alertCheckADS($path);
};
push(@{$clsid{$s->get_timestamp()}},$name);
}
foreach my $t (reverse sort {$a <=> $b} keys %clsid) {
::rptMsg(gmtime($t)." Z");
foreach my $item (@{$clsid{$t}}) {
::rptMsg(" ".$item);
eval {
my $treat = $s->get_subkey("TreatAs")->get_value("")->get_data();
::rptMsg(" TreatAs: ".$treat);
};
::rptMsg("");
}
}
else {
::rptMsg($key_path." has no subkeys.");
}
}
else {
::rptMsg($key_path." has no subkeys.");
}
}
else {
::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);
::rptMsg($key_path." not found.");
}
}
}
#-----------------------------------------------------------
# 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;

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,11 +3,13 @@
# Checks key for files to autostart from cmd.exe
#
# Change History
# 20190223 - added reference
# 20130425 - added alertMsg() functionality
# 20130115 - created
#
# References:
#
# https://unit42.paloaltonetworks.com/new-babyshark-malware-targets-u-s-national-security-think-tanks/
#
# Category: autostart,malware,programexecution
#
# copyright 2013 Quantum Analytics Research,
@ -21,12 +23,12 @@ my %config = (hive => "NTUSER\.DAT",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
version => 20130425);
version => 20190223);
sub getConfig{return %config}
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 getRefs {}
@ -64,4 +66,4 @@ sub pluginmain {
::rptMsg($key_path." not found.");
}
}
1;
1;

View File

@ -3,6 +3,8 @@
# Plugin for Registry Ripper
#
# 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 parse shell item ID lists
# 20100409 - updated to include Vista and above
@ -14,7 +16,7 @@
# Win2000 - http://support.microsoft.com/kb/319958
# 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
#-----------------------------------------------------------
package comdlg32;
@ -26,7 +28,7 @@ my %config = (hive => "NTUSER\.DAT",
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20121008);
version => 20180702);
sub getConfig{return %config}
sub getShortDescr {
@ -39,6 +41,50 @@ sub getVersion {return $config{version};}
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 {
my $class = shift;
my $ntuser = shift;
@ -128,9 +174,9 @@ sub parseLastVisitedMRU {
@mrulist = split(//,$lvmru{MRUList});
delete($lvmru{MRUList});
foreach my $m (@mrulist) {
my ($file,$dir) = split(/\x00\x00/,$lvmru{$m},2);
$file =~ s/\x00//g;
$dir =~ s/\x00//g;
my ($file,$dir) = split(/\00\00/,$lvmru{$m},2);
$file =~ s/\00//g;
$dir =~ s/\00//g;
::rptMsg(" ".$m." -> EXE: ".$file);
::rptMsg(" -> Last Dir: ".$dir);
}
@ -213,8 +259,8 @@ sub parseCIDSizeMRU {
delete $mru{0xffffffff};
foreach my $m (sort {$a <=> $b} keys %mru) {
# my $file = parseStr($mru{$m});
my $file = (split(/\x00\x00/,$mru{$m},2))[0];
$file =~ s/\x00//g;
my $file = (split(/\00\00/,$mru{$m},2))[0];
$file =~ s/\00//g;
::rptMsg(" ".$file);
}
}
@ -251,18 +297,18 @@ sub parseFirstFolder {
delete $mru{0xffffffff};
foreach my $m (sort {$a <=> $b} keys %mru) {
# my $file = parseStr($mru{$m});
my @files = split(/\x00\x00/,$mru{$m});
my @files = split(/\00\00/,$mru{$m});
if (scalar(@files) == 0) {
::rptMsg(" No files listed.");
}
elsif (scalar(@files) == 1) {
$files[0] =~ s/\x00//g;
$files[0] =~ s/\00//g;
::rptMsg(" ".$files[0]);
}
elsif (scalar(@files) > 1) {
my @files2;
foreach my $file (@files) {
$file =~ s/\x00//g;
$file =~ s/\00//g;
push(@files2,$file);
}
::rptMsg(" ".join(' ',@files2));
@ -305,9 +351,9 @@ sub parseLastVisitedPidlMRU {
delete $mru{0xffffffff};
foreach my $m (sort {$a <=> $b} keys %mru) {
my ($file,$shell) = split(/\x00\x00/,$mru{$m},2);
$file =~ s/\x00//g;
$shell =~ s/^\x00//;
my ($file,$shell) = split(/\00\00/,$mru{$m},2);
$file =~ s/\00//g;
$shell =~ s/^\00//;
my $str = parseShellItem($shell);
::rptMsg(" ".$file." - ".$str);
}
@ -386,7 +432,7 @@ sub parseShellItem {
while ($tag) {
my %item = ();
my $sz = unpack("v",substr($data,$cnt,2));
return %str unless (defined $sz);
return %str unless (defined $sz);
$tag = 0 if (($sz == 0) || ($cnt + $sz > $len));
my $dat = substr($data,$cnt,$sz);
@ -398,6 +444,11 @@ sub parseShellItem {
%item = parseSystemFolderEntry($dat);
$str .= "\\".$item{name};
}
elsif ($type == 0x2E) {
# probe($dat);
%item = parseDeviceEntry($dat);
$str .= "\\".$item{name};
}
elsif ($type == 0x2F) {
# Volume (Drive Letter)
%item = parseDriveEntry($dat);
@ -476,7 +527,17 @@ sub parseGUID {
my $d3 = unpack("v",substr($data,6,2));
my $d4 = unpack("H*",substr($data,8,2));
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 = ();
$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} =~ s/^\W//;
return %item;
@ -538,15 +599,15 @@ sub parseFolderEntry {
($item{mtime_str},$item{mtime}) = convertDOSDate($m[0],$m[1]);
# 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;
my $tag = 1;
my $cnt = 0;
my $str = "";
while($tag) {
my $s = substr($data,$ofs_shortname + $cnt,1);
return %item unless (defined $s);
if ($s =~ m/\x00/ && ((($cnt + 1) % 2) == 0)) {
return %item unless (defined $s);
if ($s =~ m/\00/ && ((($cnt + 1) % 2) == 0)) {
$tag = 0;
}
else {
@ -554,19 +615,19 @@ sub parseFolderEntry {
$cnt++;
}
}
# $str =~ s/\x00//g;
# $str =~ s/\00//g;
my $shortname = $str;
my $ofs = $ofs_shortname + $cnt + 1;
# Read progressively, 1 byte at a time, looking for 0xbeef
$tag = 1;
$cnt = 0;
my $tag = 1;
my $cnt = 0;
while ($tag) {
my $s = substr($data,$ofs + $cnt,2);
return %item unless (defined $s);
my $s = substr($data,$ofs + $cnt,2);
return %item unless (defined $s);
if (unpack("v",$s) == 0xbeef) {
$tag = 0;
}
else {
else {
$cnt++;
}
}
@ -577,10 +638,10 @@ sub parseFolderEntry {
$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]);
$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]);
$ofs += 4;
@ -594,15 +655,19 @@ sub parseFolderEntry {
elsif ($item{extver} == 0x08) {
$jmp = 26;
}
# Updated for Windows 10
elsif ($item{extver} == 0x09) {
$jmp = 30;
}
else {}
$ofs += $jmp;
# ::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];
$longname =~ s/\x00//g;
my $longname = (split(/\00\00/,$str,2))[0];
$longname =~ s/\00//g;
if ($longname ne "") {
$item{name} = $longname;
@ -613,6 +678,61 @@ sub parseFolderEntry {
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()
# subroutine to convert 4 bytes of binary data into a human-
@ -701,4 +821,4 @@ sub printData {
return @display;
}
1;
1;

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
# 20190506 - updated
# 20140807 - created
#
# References:
#
# https://metacpan.org/pod/Parse::Win32Registry
# https://github.com/msuhanov/regf/blob/master/Windows%20registry%20file%20format%20specification.md
#
#
# copyright 2014 QAR, LLC
# copyright 2019 QAR, LLC
# Author: H. Carvey
#-----------------------------------------------------------
package del;
@ -22,7 +24,7 @@ my %config = (hive => "All",
hasRefs => 0,
osmask => 22,
category => "deleted",
version => 20140807);
version => 20190506);
sub getConfig{return %config}
sub getShortDescr {
@ -35,6 +37,19 @@ sub getVersion {return $config{version};}
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;
sub pluginmain {
@ -48,34 +63,92 @@ sub pluginmain {
my $entry_iter = $reg->get_entry_iterator;
while (defined(my $entry = $entry_iter->get_next)) {
next if $entry->is_allocated;
# printf "0x%x ", $entry->get_offset;
# print $entry->unparsed()."\n";
my $tag = $entry->get_tag();
my $str = $entry->as_string();
next if ($str eq "(unidentified entry)");
if ($tag eq "vk") {
::rptMsg("Value: ".$str);
}
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");
}
}
else {}
# printf "0x%x ", $entry->get_offset;
# print $entry->unparsed()."\n";
my $data = $entry->get_raw_bytes();
my $len = length($data);
next if ($len <= 8);
::rptMsg("------------- Deleted Data ------------");
# Value node header is 20 bytes, w/o name string
# 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++;
}
}
}
::rptMsg($entry->unparsed());
}
}
sub parseDelKeyName {
my $str = shift;
my $name_str = (split(/\s\[/,$str))[0];
my @list = split(/\\/,$name_str);
shift(@list);
return join('\\',@list);
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);
::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;

View File

@ -4,13 +4,15 @@
#
#
# Change history
# 20190506 - updated
# 20140807 - created
#
# References:
#
# https://metacpan.org/pod/Parse::Win32Registry
# https://github.com/msuhanov/regf/blob/master/Windows%20registry%20file%20format%20specification.md
#
#
# copyright 2014 QAR, LLC
# copyright 2019 QAR, LLC
# Author: H. Carvey
#-----------------------------------------------------------
package del_tln;
@ -22,7 +24,7 @@ my %config = (hive => "All",
hasRefs => 0,
osmask => 22,
category => "deleted",
version => 20140807);
version => 20190506);
sub getConfig{return %config}
sub getShortDescr {
@ -41,38 +43,72 @@ sub pluginmain {
my $class = shift;
my $file = shift;
my $reg = Parse::Win32Registry->new($file);
my $root_key = $reg->get_root_key;
# ::logMsg("Launching del v.".$VERSION);
# ::rptMsg("del v.".$VERSION); # banner
::logMsg("Launching del_tln v.".$VERSION);
# ::rptMsg("del_tln v.".$VERSION); # banner
# ::rptMsg("(".getHive().") ".getShortDescr()."\n"); # banner
my $entry_iter = $reg->get_entry_iterator;
while (defined(my $entry = $entry_iter->get_next)) {
next if $entry->is_allocated;
# printf "0x%x ", $entry->get_offset;
# print $entry->unparsed()."\n";
my $tag = $entry->get_tag();
my $str = $entry->as_string();
next if ($str eq "(unidentified entry)");
if ($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($lw."|REG|||[Deleted key]: ".parseDelKeyName($str));
}
}
else {}
# printf "0x%x ", $entry->get_offset;
# print $entry->unparsed()."\n";
my $data = $entry->get_raw_bytes();
my $len = length($data);
next if ($len <= 8);
# 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)) == 0x6b6e) {
# ::rptMsg("Key node found at ".$cursor);
parseKeyNode($data,$cursor);
$cursor += 0x4a;
}
else {
$cursor++;
}
}
}
# ::rptMsg($entry->unparsed());
}
}
sub parseDelKeyName {
my $str = shift;
my $name_str = (split(/\s\[/,$str))[0];
my @list = split(/\\/,$name_str);
shift(@list);
return join('\\',@list);
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($lw."|||| Deleted key: ".$name);
}
}
1;

View File

@ -1,8 +1,15 @@
#-----------------------------------------------------------
# disablelastaccess.pl
#
# History:
# 20181207 - updated for Win10 v.1803 (Maxim, David Cohen)
# 20090118 -
#
# References:
# http://support.microsoft.com/kb/555041
# 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/894372
#
# copyright 2008 H. Carvey, keydet89@yahoo.com
@ -15,10 +22,15 @@ my %config = (hive => "System",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
version => 20090118);
version => 20181207);
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 {
return "Get NTFSDisableLastAccessUpdate value";
}
@ -48,7 +60,8 @@ sub pluginmain {
$ccs = "ControlSet00".$current;
}
$key_path = $ccs."\\Control\\FileSystem";
my $key_path = $ccs."\\Control\\FileSystem";
my $key;
if ($key = $root_key->get_subkey($key_path)) {
::rptMsg("NtfsDisableLastAccessUpdate");
::rptMsg($key_path);
@ -57,8 +70,19 @@ sub pluginmain {
if (scalar(@vals) > 0) {
foreach my $v (@vals) {
if ($v->get_name() eq "NtfsDisableLastAccessUpdate") {
::rptMsg("NtfsDisableLastAccessUpdate = ".$v->get_data());
my $dat = $v->get_data();
::rptMsg(sprintf "NtfsDisableLastAccessUpdate = 0x%08x",$dat);
$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);
@ -71,4 +95,4 @@ sub pluginmain {
::rptMsg($key_path." not found.");
}
}
1;
1;

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;
use strict;
my %config = (hive => "NTUSER\.DAT;Software",
my %config = (hive => "NTUSER\.DAT,Software",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,

View File

@ -5,8 +5,10 @@
# http://msdn2.microsoft.com/en-us/library/a329t4ed(VS\.80)\.aspx
# CWDIllegalInDllSearch: http://support.microsoft.com/kb/2264107
# 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:
# 20190511 - added search for 'auto' value
# 20131007 - added Carnal0wnage reference
# 20130425 - added alertMsg() functionality
# 20130410 - added Wow6432Node support
@ -23,7 +25,7 @@ my %config = (hive => "Software",
hasRefs => 0,
osmask => 22,
category => "malware",
version => 20131007);
version => 20190511);
sub getConfig{return %config}
sub getShortDescr {
@ -76,6 +78,11 @@ sub pluginmain {
eval {
$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
# found within the key, so we don't need to do anything w/ the error
if ($dllsearch ne "") {
@ -88,7 +95,7 @@ sub pluginmain {
foreach my $d (keys %debug) {
::rptMsg($d." LastWrite: ".gmtime($debug{$d}{lastwrite}));
::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});
}
}

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 = "";
while($tag) {
my $s = substr($data,$ofs_shortname + $cnt,1);
return %item unless (defined $s);
if ($s =~ m/\x00/ && ((($cnt + 1) % 2) == 0)) {
$tag = 0;
}
@ -240,7 +241,9 @@ sub parseFolderItem {
$tag = 1;
$cnt = 0;
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;
}
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
#
# History
# 20190714 - updated
# 20140414 - created
#
# Registry entries created by devices that support device stage
# Reference: http://nicoleibrahim.com/part-4-usb-device-research-usb-first-insert-results/
#
# Author: Jasmine Chua, babymagic06@gmail.com
# updates: QAR, LLC (H. Carvey, keydet89@yahoo.com)
#-----------------------------------------------------------------------------------------
package knowndev;
use strict;
@ -17,7 +19,7 @@ my %config = (hive => "NTUSER\.DAT",
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20140414);
version => 20190714);
sub getConfig{return %config}
sub getShortDescr {
@ -50,43 +52,18 @@ sub pluginmain {
if (scalar @subkeys > 0) {
foreach my $s (@subkeys) {
my $name = $s->get_name();
if ($name =~ m/_COMP/) {
my $m = (split(/#/,$name,3))[1];
my $device = (split(/&/,$m,3))[0];
my $model = (split(/&/,$m,3))[1];
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("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");
}
my $lw = gmtime($s->get_timestamp());
::rptMsg($name." ".$lw." Z");
eval {
my $label = $s->get_value("Label")->get_data();
::rptMsg("Label: ".$label);
};
::rptMsg("");
}
}
else {
::rptMsg($key_path." has no subkeys.");
::rptMsg($key_path." has no subkeys.");
}
}
else {

View File

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

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

View File

@ -8,6 +8,9 @@
# <included inline>
#
# Change history:
# 20190527 - updates
# 20190107 - added remote UAC bypass check
# 20180702 - added values to check for MS Defender being disabled
# 20161210 - added WebRoot check
# 20160615 - added new Sofacy persistence
# 20160412 - added Ramdo checks
@ -19,7 +22,7 @@
# 20151008 - added keys
# 20150828 - created
#
# copyright 2015 Quantum Analytics Research, LLC
# copyright 2018 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package malware;
@ -31,7 +34,7 @@ my %config = (hive => "All",
hasRefs => 0,
osmask => 22,
category => "malware",
version => 20161210);
version => 20190527);
sub getConfig{return %config}
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
# 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
# http://www.symantec.com/security_response/earthlink_writeup.jsp?docid=2013-112101-0135-99
# 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
# 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
# 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
# 20190316 - updated references
# 20160926 - created
#
# Copyright 2016 QAR, LLC
# Copyright 2019 QAR, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
package netsh;
use strict;
@ -18,7 +22,7 @@ my %config = (hive => "Software",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
version => 20160926);
version => 20190316);
sub getConfig{return %config}
@ -45,12 +49,13 @@ sub pluginmain {
if ($key = $root_key->get_subkey($key_path)) {
::rptMsg($key_path);
::rptMsg("LastWrite: ".gmtime($key->get_timestamp())." Z");
::rptMsg("");
::rptMsg("LastWrite Time ".gmtime($key->get_timestamp())." (UTC)");
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) {
::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:
# 20190128 - Added Nla\Wireless data
# 20150812 - updated to include Nla\Cache data
# 20120917 - updated to include NameType value
# 20090812 - updated code to parse DateCreated and DateLastConnected
@ -24,7 +25,7 @@ my %config = (hive => "Software",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
version => 20150812);
version => 20190128);
sub getConfig{return %config}
@ -125,7 +126,7 @@ sub pluginmain {
foreach my $n (keys %nl) {
my $str = sprintf "%-15s Gateway Mac: ".$nl{$n}{DefaultGatewayMac},$nl{$n}{ProfileName};
::rptMsg($nl{$n}{ProfileName});
::rptMsg(" Key LastWrite : ".gmtime($nl{$n}{LastWrite})." Z");
# ::rptMsg(" Key LastWrite : ".gmtime($nl{$n}{LastWrite})." Z");
::rptMsg(" DateLastConnected: ".$nl{$n}{DateLastConnected});
::rptMsg(" DateCreated : ".$nl{$n}{DateCreated});
::rptMsg(" DefaultGatewayMac: ".$nl{$n}{DefaultGatewayMac});
@ -147,9 +148,30 @@ sub pluginmain {
if ($key = $root_key->get_subkey($key_path)) {
my @subkeys = $key->get_list_of_subkeys();
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) {
::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,150 +1,149 @@
# 20161213 *ALL* Plugins that apply on NTUSER hive, alphabetical order
acmru
adoberdr
aim
aports
appcompatflags
applets
applets_tln
appspecific
ares
arpcache
attachmgr
attachmgr_tln
autoendtasks
autorun
bitbucket_user
brisv
cached
cached_tln
cain
ccleaner
cdstaginginfo
clampi
clampitm
cmdproc
cmdproc_tln
comdlg32
compdesc
controlpanel
cortana
cpldontload
ddo
decaf
dependency_walker
domains
environment
fileexts
filehistory
gthist
gtwhitelist
haven_and_hearth
identities
iejava
ie_main
ie_settings
ie_zones
internet_explorer_cu
internet_settings_cu
itempos
javafx
kankan
knowndev
latentbot
listsoft
liveContactsGUID
load
logonusername
menuorder
mixer
mixer_tln
mmc
mmc_tln
mmo
mndmru
mndmru_tln
mp2
mp3
mpmru
mspaper
muicache
muicache_tln
nero
netassist
ntusernetwork
odysseus
officedocs
officedocs2010
officedocs2010_tln
oisc
olsearch
osversion
osversion_tln
outlook
outlook2
policies_u
printermru
printers
privoxy
profiler
proxysettings
publishingwizard
putty
rdphint
reading_locations
realplayer6
realvnc
recentdocs
recentdocs_tln
reveton
rootkit_revealer
runmru
runmru_tln
sevenzip
shc
shellbags_xp
shellfolders
skype
snapshot_viewer
ssh_host_keys
startmenuinternetapps_cu
startpage
startup
sysinternals
sysinternals_tln
trustrecords
trustrecords_tln
tsclient
tsclient_tln
typedpaths
typedpaths_tln
typedurls
typedurlstime
typedurlstime_tln
typedurls_tln
unreadmail
urun_tln
userassist
userassist_tln
userinfo
userlocsvc
user_run
user_win
vawtrak
vista_bitbucket
vmplayer
vmware_vsphere_client
vnchooksapplicationprefs
vncviewer
wallpaper
warcraft3
winlogon_u
winrar
winrar2
winrar_tln
winscp
winscp_sessions
winvnc
winzip
wordwheelquery
yahoo_cu
acmru
adoberdr
ahaha
aim
aports
appassoc
appcompatflags
appkeys
applets
appspecific
ares
arpcache
attachmgr
autoendtasks
autorun
bitbucket_user
brisv
cached
cain
ccleaner
cdstaginginfo
clampi
clampitm
cmdproc
comdlg32
compdesc
controlpanel
cortana
cpldontload
ddo
decaf
dependency_walker
disablemru
domains
environment
eraser
fileexts
filehistory
foxitrdr
gthist
gtwhitelist
haven_and_hearth
identities
iejava
ie_main
ie_settings
ie_zones
imgburn1
internet_explorer_cu
internet_settings_cu
itempos
javafx
jumplistdata
kankan
knowndev
latentbot
listsoft
liveContactsGUID
load
logonstats
logonusername
menuorder
mixer
mmc
mmo
mndmru
mp2
mp3
mpmru
mspaper
muicache
mzthunderbird
nation
nero
netassist
ntusernetwork
odysseus
officedocs
officedocs2010
officedocs2010_tln
oisc
olsearch
osversion
outlook
outlook2
policies_u
printermru
printers
privoxy
profiler
proxysettings
pslogging
publishingwizard
putty
putty_sessions
rdphint
reading_locations
realplayer6
realvnc
recentapps
recentdocs
recentdocs_timeline
reveton
rootkit_revealer
runmru
searchscopes
sevenzip
shc
shellactivities
shellbags_xp
shellfolders
skype
snapshot_viewer
ssh_host_keys
startmenuinternetapps_cu
startpage
startup
sysinternals
thunderbirdinstalled
trustrecords
tsclient
typedpaths
typedurls
typedurlstime
uninstall
unreadmail
userassist
userinfo
userlocsvc
user_run
user_win
utorrent
vawtrak
vista_bitbucket
vmplayer
vmware_vsphere_client
vnchooksapplicationprefs
vncviewer
wallpaper
warcraft3
winlogon_u
winrar
winrar2
winscp
winscp_sessions
winvnc
winzip
wordwheelquery
yahoo_cu

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;
use strict;
my %config = (hive => "NTUSER",
my %config = (hive => "NTUSER\.DAT",
osmask => 22,
hasShortDescr => 1,
hasDescr => 0,

View File

@ -4,6 +4,7 @@
#
# Change history
# 20140130 - created
# 20190211 - added "paragraphID" int to hex conversion
#
# References
# http://dfstream.blogspot.com/2014/01/ms-word-2013-reading-locations.html
@ -66,7 +67,9 @@ sub pluginmain {
eval {
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("");
}

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_tln
samparse

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_xp
lsasecrets
polacdms
secrets
secrets_tln
securityproviders
auditpol
auditpol_xp
lsasecrets
polacdms
secrets

View File

@ -3,8 +3,14 @@
# This key may have something to do with the Start Menu Cache - nothing
# 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
# 20130412 - created - IN PROCESS; NOT COMPLETE
# 20190305 - updated - outputs entries from shc
#
#
# References
@ -26,7 +32,7 @@ my %config = (hive => "NTUSER\.DAT",
hasDescr => 0,
hasRefs => 0,
osmask => 32, #Windows 8
version => 20130412);
version => 20190305);
sub getConfig{return %config}
sub getShortDescr {
@ -57,9 +63,16 @@ sub pluginmain {
my @vals = $key->get_list_of_values();
if (scalar(@vals) > 0) {
my %shc;
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 {

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

View File

@ -2,7 +2,7 @@
# shellbags_test.pl
#
#
# License: GPL v3
#
# copyright 2012 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
@ -358,7 +358,7 @@ sub parseFolderItem {
my $str = "";
while($tag) {
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)) {
$tag = 0;
}
@ -374,8 +374,8 @@ sub parseFolderItem {
$tag = 1;
$cnt = 0;
while ($tag) {
my $s = substr($data,$ofs + $cnt,2);
return %item unless (defined $s);
my $s = substr($data,$ofs + $cnt,2);
return %item unless (defined $s);
if (unpack("v",$s) == 0xbeef) {
$tag = 0;
}

View File

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

View File

@ -29,7 +29,7 @@
# Moore for writing the shell bag parser for Registry Decoder, as well as
# assistance with some parsing.
#
# License: GPL v3
#
# copyright 2012 Quantum Analytics Research, LLC
# Author: H. Carvey, keydet89@yahoo.com
#-----------------------------------------------------------
@ -397,9 +397,8 @@ sub parseVariableEntry {
# 0x0e, 0x0f, 0x10 - mod date, create date, access date(?)
# 0x0c - size
#--------------------------------------------------------------
return %item unless (defined $sz);
if ($sz == 0x00) {
$tag = 0;
return %item unless (defined $sz);
if ($sz == 0x00) { $tag = 0;
next;
}
elsif ($id == 0x0a) {
@ -421,6 +420,7 @@ sub parseVariableEntry {
# my $sz = unpack("V",substr($stuff,$cnt,4));
# my $id = unpack("V",substr($stuff,$cnt + 4,4));
# return %item unless (defined $sz);
#
# if ($sz == 0x00) {
# $tag = 0;
# next;
@ -726,7 +726,7 @@ sub parseFolderEntry {
my $str = "";
while($tag) {
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)) {
$tag = 0;
}
@ -742,8 +742,8 @@ sub parseFolderEntry {
$tag = 1;
$cnt = 0;
while ($tag) {
my $s = substr($data,$ofs + $cnt,2);
return %item unless (defined $s);
my $s = substr($data,$ofs + $cnt,2);
return %item unless (defined $s);
if (unpack("v",$s) == 0xbeef) {
$tag = 0;
}
@ -833,8 +833,8 @@ sub parseFolderEntry2 {
my $tag = 1;
while ($tag) {
my $s = substr($data,$ofs,2);
return %item unless (defined $s);
my $s = substr($data,$ofs,2);
return %item unless (defined $s);
if (unpack("v",$s) == 0xbeef) {
$tag = 0;
}

View File

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

View File

@ -5,6 +5,8 @@
# works within an analysis process.
#
# History:
# 20190112 - updated parsing for Win8.1
# 20180311 - updated for more recent version of Win10/Win2016
# 20160528 - created
#
# References:
@ -31,7 +33,7 @@ my %config = (hive => "System",
hasDescr => 0,
hasRefs => 0,
osmask => 31,
version => 20160528);
version => 20190112);
sub getConfig{return %config}
sub getShortDescr {
@ -109,7 +111,10 @@ sub pluginmain {
elsif ($sig == 0x80) {
appWin8($app_data);
}
elsif ($sig == 0x30) {
elsif ($sig == 0x0) {
appWin81($app_data);
}
elsif ($sig == 0x30 || $sig == 0x34) {
appWin10($app_data);
}
else {
@ -118,14 +123,16 @@ sub pluginmain {
foreach my $f (keys %files) {
my $str;
if (exists $files{$f}{executed}) {
$str = "M... [Program Execution] AppCompatCache - ".$files{$f}{filename};
}
else {
$str = "M... AppCompatCache - ".$files{$f}{filename};
next if ($files{$f}{modtime} == 0);
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});
}
$str = "M... AppCompatCache - ".$files{$f}{filename};
$str .= " [Size = ".$files{$f}{size}." bytes]" if (exists $files{$f}{size});
$str .= " [Executed]" if (exists $files{$f}{executed});
::rptMsg($files{$f}{modtime}."|REG|||".$str);
}
}
@ -148,8 +155,8 @@ sub appXP32Bit {
foreach my $i (0..($num_entries - 1)) {
my $x = substr($data,(400 + ($i * 552)),552);
my $file = (split(/\x00\x00/,substr($x,0,488)))[0];
$file =~ s/\x00//g;
my $file = (split(/\00\00/,substr($x,0,488)))[0];
$file =~ s/\00//g;
$file =~ s/^\\\?\?\\//;
my ($mod1,$mod2) = unpack("VV",substr($x,528,8));
my $modtime = ::getTime($mod1,$mod2);
@ -192,7 +199,7 @@ sub appWin2k3 {
my ($len,$max_len,$ofs,$t0,$t1,$f0,$f1) = unpack("vvVVVVV",$struct);
my $file = substr($data,$ofs,$len);
$file =~ s/\x00//g;
$file =~ s/\00//g;
$file =~ s/^\\\?\?\\//;
my $t = ::getTime($t0,$t1);
$files{$i}{filename} = $file;
@ -203,7 +210,7 @@ sub appWin2k3 {
elsif ($struct_sz == 32) {
my ($len,$max_len,$padding,$ofs0,$ofs1,$t0,$t1,$f0,$f1) = unpack("vvVVVVVVV",$struct);
my $file = substr($data,$ofs0,$len);
$file =~ s/\x00//g;
$file =~ s/\00//g;
$file =~ s/^\\\?\?\\//;
my $t = ::getTime($t0,$t1);
$files{i}{filename} = $file;
@ -245,7 +252,7 @@ sub appWin7 {
if ($struct_sz == 32) {
my ($len,$max_len,$ofs,$t0,$t1,$f0,$f1) = unpack("vvV5x8",$struct);
my $file = substr($data,$ofs,$len);
$file =~ s/\x00//g;
$file =~ s/\00//g;
$file =~ s/^\\\?\?\\//;
my $t = ::getTime($t0,$t1);
$files{$i}{filename} = $file;
@ -255,7 +262,7 @@ sub appWin7 {
else {
my ($len,$max_len,$padding,$ofs0,$ofs1,$t0,$t1,$f0,$f1) = unpack("vvV7x16",$struct);
my $file = substr($data,$ofs0,$len);
$file =~ s/\x00//g;
$file =~ s/\00//g;
$file =~ s/^\\\?\?\\//;
my $t = ::getTime($t0,$t1);
$files{$i}{filename} = $file;
@ -277,14 +284,14 @@ sub appWin8 {
while($ofs < $len) {
my $tag = unpack("V",substr($data,$ofs,4));
last unless (defined $tag);
last unless (defined $tag);
# 32-bit
if ($tag == 0x73746f72) {
$jmp = unpack("V",substr($data,$ofs + 8,4));
($t0,$t1) = unpack("VV",substr($data,$ofs + 12,8));
$sz = unpack("v",substr($data,$ofs + 20,2));
$name = substr($data,$ofs + 22,$sz);
$name =~ s/\x00//g;
$name =~ s/\00//g;
$files{$ct}{filename} = $name;
$files{$ct}{modtime} = ::getTime($t0,$t1);
$ct++;
@ -295,7 +302,7 @@ sub appWin8 {
$jmp = unpack("V",substr($data,$ofs + 8,4));
$sz = unpack("v",substr($data,$ofs + 0x0C,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));
$files{$ct}{filename} = $name;
$files{$ct}{modtime} = ::getTime($t0,$t1);
@ -309,6 +316,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()
# Ref: http://binaryforay.blogspot.com/2015/04/appcompatcache-changes-in-windows-10.html
@ -318,17 +358,17 @@ sub appWin10 {
my $len = length($data);
my ($tag, $sz, $t0, $t1, $name, $name_len);
my $ct = 0;
my $ofs = 0x30;
my $ofs = unpack("V",substr($data,0,4));
# my $ofs = 0x30;
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/\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,8));
$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
#
# 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
#
# copyright 2015 QAR, LLC
@ -14,16 +16,19 @@
package sizes;
use strict;
my $min_size = 5000;
my $output_size = 48;
my %config = (hive => "All",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20150527);
version => 20180817);
sub getConfig{return %config}
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 getRefs {}
@ -31,7 +36,7 @@ sub getHive {return $config{hive};}
sub getVersion {return $config{version};}
my $VERSION = getVersion();
my $min_size = 50000;
my $count = 0;
sub pluginmain {
my $class = shift;
@ -40,8 +45,16 @@ sub pluginmain {
my $root_key = $reg->get_root_key;
::logMsg("Launching sizes v.".$VERSION);
::rptMsg("sizes v.".$VERSION);
::rptMsg("(".getHive().") ".getShortDescr()."\n");
::rptMsg("(".getHive().") ".getShortDescr()."\n");
my $start = time;
traverse($root_key);
my $finish = time;
::rptMsg("Scan completed: ".($finish - $start)." sec");
::rptMsg("Total values : ".$count);
}
sub traverse {
@ -49,8 +62,9 @@ sub traverse {
# my $ts = $key->get_timestamp();
foreach my $val ($key->get_list_of_values()) {
$count++;
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 $len = length($data);
if ($len > $min_size) {
@ -59,10 +73,19 @@ sub traverse {
$name[0] = "";
$name[0] = "\\" if (scalar(@name) == 1);
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("");
}
}
@ -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;

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,98 +1,102 @@
# 20161213 *ALL* Plugins that apply on SOFTWARE hive, alphabetical order
ahaha
appinitdlls
apppaths
apppaths_tln
assoc
at
at_tln
audiodev
banner
bho
bitbucket
btconfig
clsid
cmd_shell
cmd_shell_tln
codeid
ctrlpnl
dcom
dfrg
direct
direct_tln
disablesr
drivers32
drwatson
emdmgmt
esent
etos
gauss
gpohist
gpohist_tln
handler
ie_version
ie_zones
imagefile
init_dlls
inprocserver
installedcomp
installer
javasoft
kb950582
landesk
landesk_tln
lastloggedon
lazyshell
licenses
logmein
logmein_tln
macaddr
mrt
msis
netsh
networkcards
networklist
networklist_tln
networkuid
opencandy
port_dev
product
profilelist
regback
removdev
renocide
schedagent
secctr
sfc
shellexec
shellext
shelloverlay
snapshot
soft_run
spp_clients
sql_lastconnect
srun_tln
ssid
startmenuinternetapps_lm
susclient
svchost
systemindex
teamviewer
tracing
tracing_tln
trappoll
uac
uninstall
uninstall_tln
urlzone
virut
volinfocache
wbem
winbackup
win_cv
winevt
winlogon
winlogon_tln
winnt_cv
winver
yahoo_lm
ahaha
appcompatflags
appinitdlls
appkeys
apppaths
assoc
at
audiodev
banner
bho
bitbucket
btconfig
clsid
cmd_shell
codeid
ctrlpnl
dcom
defbrowser
dfrg
direct
disablesr
drivers32
drwatson
emdmgmt
esent
etos
execpolicy
gauss
gpohist
handler
ie_version
ie_zones
imagefile
init_dlls
inprocserver
installedcomp
installer
javasoft
kankan
kb950582
landesk
lastloggedon
lazyshell
licenses
logmein
macaddr
mrt
msis
netsh
networkcards
networklist
networkuid
opencandy
port_dev
product
profilelist
pslogging
psscript
regback
removdev
renocide
runonceex
sbs
schedagent
secctr
sfc
shellexec
shellext
shelloverlay
silentprocessexit
snapshot
soft_run
spp_clients
sql_lastconnect
ssid
startmenuinternetapps_lm
susclient
svchost
systemindex
teamviewer
termserv
thunderbirdinstalled
tracing
trappoll
uac
uninstall
updates
urlzone
virut
volinfocache
watp
wbem
webroot
winbackup
winevt
winlogon
winnt_cv
winver
win_cv
wow64
wsh_settings
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 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 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,70 +1,71 @@
# 20161213 *ALL* Plugins that apply on SYSTEM hive, alphabetical order
appcertdlls
appcompatcache
appcompatcache_tln
auditfail
backuprestore
bthport
comfoo
compname
crashcontrol
ddm
devclass
diag_sr
disablelastaccess
dllsearch
dnschanger
eventlog
eventlogs
fw_config
hibernate
ide
imagedev
kbdcrash
legacy
legacy_tln
lsa_packages
mountdev
mountdev2
netsvcs
network
nic
nic2
nic_mst2
nolmhash
pagefile
pending
phdet
prefetch
processor_architecture
productpolicy
producttype
rdpnla
rdpport
regin
remoteaccess
routes
safeboot
securityproviders
services
shares
shimcache
shimcache_tln
shutdown
shutdowncount
stillimage
svc
svcdll
svc_plus
svc_tln
systemindex
termcert
termserv
timezone
usb
usbdevices
usbstor
usbstor2
usbstor3
wpdbusenum
xpedition
angelfire
appcertdlls
appcompatcache
auditfail
backuprestore
bam
bthport
comfoo
compname
crashcontrol
dafupnp
ddm
devclass
diag_sr
disablelastaccess
dllsearch
dnschanger
eventlog
eventlogs
fw_config
hibernate
ide
imagedev
kbdcrash
legacy
lsa_packages
macaddr
mountdev
mountdev2
netlogon
netsvcs
network
nic
nic2
nic_mst2
nolmhash
pagefile
pending
phdet
prefetch
processor_architecture
productpolicy
producttype
profiler
rdpnla
rdpport
regin
remoteaccess
routes
safeboot
securityproviders
services
shares
shimcache
shutdown
shutdowncount
source_os
stillimage
svc
svcdll
svc_plus
termcert
termserv
timezone
usb
usbdevices
usbstor
usbstor2
usbstor3
wpdbusenum
xpedition

View File

@ -3,6 +3,7 @@
# Plugin for Registry Ripper;
#
# Change history
# 20190527 - Added checks in Software hive
# 20160224 - added SysProcs info
# 20131007 - updated with Sticky Keys info
# 20130307 - updated with autostart locations
@ -27,16 +28,16 @@
package termserv;
use strict;
my %config = (hive => "System",
my %config = (hive => "System, Software",
hasShortDescr => 1,
hasDescr => 0,
hasRefs => 0,
osmask => 22,
version => 20160224);
version => 20190527);
sub getConfig{return %config}
sub getShortDescr {
return "Gets Terminal Server values from System hive";
return "Gets Terminal Server settings from System and Software hives";
}
sub getDescr{}
sub getRefs {}
@ -66,8 +67,6 @@ sub pluginmain {
::rptMsg($ts_path);
::rptMsg("LastWrite Time ".gmtime($ts->get_timestamp())." (UTC)");
::rptMsg("");
::rptMsg("Reference: http://support.microsoft.com/kb/243215");
::rptMsg("");
my $ver;
eval {
@ -151,6 +150,14 @@ sub pluginmain {
};
::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
eval {
my $sys = $ts->get_subkey("SysProcs");
@ -185,5 +192,41 @@ sub pluginmain {
else {
::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;

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;

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