From 9c632982ac647a2f679129afa2372bbf28a5441e Mon Sep 17 00:00:00 2001 From: Patrick Wardle Date: Sun, 16 Aug 2015 20:27:47 -1000 Subject: [PATCH] added new button/view (and logic) to detect/display all flagged items --- AppDelegate.h | 25 +- AppDelegate.m | 121 ++++++++- Consts.h | 3 + FlaggedItems.h | 24 ++ FlaggedItems.m | 162 ++++++++++++ ItemView.h | 3 + ItemView.m | 151 +++++++++++- RequestRootWindowController.m | 2 +- TaskEnumerator.h | 10 + TaskEnumerator.m | 181 +++++++++++++- TaskExplorer-Info.plist | 4 +- TaskExplorer.xcodeproj/project.pbxproj | 22 ++ .../xcshareddata/TaskExplorer.xccheckout | 4 +- .../xcdebugger/Breakpoints_v2.xcbkptlist | 138 +++++++---- TaskTableController.h | 2 +- UI/AboutWindow.xib | 2 +- UI/FlaggedItems.xib | 230 ++++++++++++++++++ VirusTotal.m | 27 +- en.lproj/MainMenu.xib | 34 ++- images/flagged.png | Bin 0 -> 3498 bytes images/flaggedBG.png | Bin 0 -> 4619 bytes images/flaggedOver.png | Bin 0 -> 4551 bytes remoteTaskService/main.m | 10 +- 23 files changed, 1069 insertions(+), 86 deletions(-) create mode 100644 FlaggedItems.h create mode 100644 FlaggedItems.m create mode 100644 UI/FlaggedItems.xib create mode 100644 images/flagged.png create mode 100644 images/flaggedBG.png create mode 100644 images/flaggedOver.png diff --git a/AppDelegate.h b/AppDelegate.h index 8e4414c..c43d7b5 100755 --- a/AppDelegate.h +++ b/AppDelegate.h @@ -15,6 +15,7 @@ #import "AboutWindowController.h" #import "PrefsWindowController.h" +#import "FlaggedItems.h" #import "ResultsWindowController.h" #import "RequestRootWindowController.h" @@ -27,7 +28,6 @@ @interface AppDelegate : NSObject { - //NSViewController *bottomViewController; } @@ -111,6 +111,9 @@ //results window controller @property(nonatomic, retain)ResultsWindowController* resultsWindowController; +//flagged items window controller +@property(nonatomic, retain)FlaggedItems* flagItemsWindowController; + //currently selected task @property(nonatomic, retain)Task* currentTask; @@ -119,11 +122,19 @@ //'no items' found label for bottom pane @property (weak) IBOutlet NSTextField *noItemsLabel; + +//search button @property (weak) IBOutlet NSButton *searchButton; //refresh button @property (weak) IBOutlet NSButton *refreshButton; +//flagged items button +@property (weak) IBOutlet NSButton *flaggedButton; + +//flagged items label +@property (weak) IBOutlet NSTextField *flaggedLabel; + //top constraint @property(nonatomic, retain)NSLayoutConstraint* topConstraint; @@ -137,7 +148,10 @@ @property(nonatomic, retain)NSLayoutConstraint* trailingConstraint; //remote XPC interface -@property (nonatomic, retain) NSXPCConnection* xpcConnection; +@property(nonatomic, retain) NSXPCConnection* xpcConnection; + +//flagged items +@property(nonatomic, retain) NSMutableArray* flaggedItems; /* METHODS */ @@ -201,4 +215,11 @@ //constrain subview to parent view -(void)constrainView:(NSView*)containerView subView:(NSView*)subView; +//display (in separate popup) all flagged items +-(IBAction)showFlaggedItems:(id)sender; + +//save a flagged binary +// ->also set text flagged items button label to red +-(void)saveFlaggedBinary:(Binary*)binary; + @end diff --git a/AppDelegate.m b/AppDelegate.m index 761e859..d34887a 100755 --- a/AppDelegate.m +++ b/AppDelegate.m @@ -24,6 +24,15 @@ //TODO: add 'am i on main thread' guard and test //TODO: filter dylibs, no first responder! +//TODO: autolayout vertically +//TODO: filter VT results +//TODO: # autocomplete +//TODO: keyboard shortcuts +// see: https://mail.google.com/mail/u/0/#inbox/14eeb163d4dd2852 +//TODO: show 'from where' via quarantine attrz +//TODO: show user (after pid): -> (pid, user)? +//TODO: when filtering, and then refresh, doesn't go to row #0 :/ + @implementation AppDelegate @@ -41,6 +50,7 @@ @synthesize currentTask; @synthesize requestRootWindowController; @synthesize taskViewFormat; +@synthesize flagItemsWindowController; @synthesize scannerThread; @synthesize progressIndicator; @@ -50,11 +60,14 @@ @synthesize viewSelector; @synthesize searchButton; @synthesize xpcConnection; +@synthesize flaggedItems; //@synthesize taskScrollView; //TODO: check if VT can be reached! if not, error? or don't show '0 VT results detected' etc... +//TODO: JavaW (iWorm) dylibs... + //center window // ->also make front -(void)awakeFromNib @@ -77,8 +90,7 @@ { //first thing... // ->install exception handlers! - //TODO: re-enable - //installExceptionHandlers(); + installExceptionHandlers(); //init virus total object virusTotalObj = [[VirusTotal alloc] init]; @@ -86,6 +98,9 @@ //init filter obj filterObj = [[Filter alloc] init]; + //alloc flagged items + flaggedItems = [NSMutableArray array]; + //no need to have a first responder [self.window makeFirstResponder:nil]; @@ -752,6 +767,13 @@ bail: //add tracking area to logo button [self.logoButton addTrackingArea:trackingArea]; + + //init tracking area + // ->for flagged items button + trackingArea = [[NSTrackingArea alloc] initWithRect:[self.flaggedButton bounds] options:(NSTrackingInVisibleRect|NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:@{@"tag":[NSNumber numberWithUnsignedInteger:self.flaggedButton.tag]}]; + + //add tracking area to flaggd items button + [self.flaggedButton addTrackingArea:trackingArea]; return; } @@ -963,6 +985,13 @@ bail: //set imageName = @"logoApple"; } + + //set original flagged items image + else if(FLAGGED_BUTTON_TAG == tag) + { + //set + imageName = @"flagged"; + } } //highlight button else @@ -991,6 +1020,13 @@ bail: //set imageName = @"logoAppleOver"; } + + //set mouse over flagged items image + else if(FLAGGED_BUTTON_TAG == tag) + { + //set + imageName = @"flaggedOver"; + } } //set image @@ -1337,6 +1373,9 @@ bail: //init placeholder text for dylibs filterPlaceholder = @"Filter Dylibs"; + //remove all task's dylibs + [self.currentTask.dylibs removeAllObjects]; + //(re)enumerate dylibs via XPC // ->triggers table reload when done [self.currentTask enumerateDylibs:self.xpcConnection allDylibs:self.taskEnumerator.dylibs]; @@ -1349,6 +1388,9 @@ bail: //init placeholder text for files filterPlaceholder = @"Filter Files"; + //remove all task's dylibs + [self.currentTask.files removeAllObjects]; + //(re)enumerate files via XPC // ->triggers table reload when done [self.currentTask enumerateFiles:self.xpcConnection]; @@ -1380,7 +1422,7 @@ bail: dispatch_sync(dispatch_get_main_queue(), ^{ //set placeholder - [self.filterItemsBox setPlaceholderString:filterPlaceholder]; + [[self.filterItemsBox cell] setPlaceholderString:filterPlaceholder]; }); } //in main thread already @@ -1388,7 +1430,7 @@ bail: else { //set placeholder - [self.filterItemsBox setPlaceholderString:filterPlaceholder]; + [[self.filterItemsBox cell] setPlaceholderString:filterPlaceholder]; } @@ -1649,5 +1691,76 @@ bail: return; } +//TODO: handle reset on refresh? +//save a flagged item +// ->also set text flagged items button label to red +-(void)saveFlaggedBinary:(Binary*)binary +{ + //sync to save + @synchronized(self.flaggedItems) + { + //save + [self.flaggedItems addObject:binary]; + } + + //when count is 1 + // ->means first flagged file so set text to red + if(1 == self.flaggedItems.count) + { + //set to red + self.flaggedLabel.textColor = [NSColor redColor]; + } + + return; +} + +//button handle for 'flagged items' button +// ->display (in separate popup) all flagged items +-(IBAction)showFlaggedItems:(id)sender +{ + //alert box + NSAlert* alert = nil; + + //handle case where there aren't any flagged items + // ->just show alert + if(0 == self.flaggedItems.count) + { + //alloc/init alert + alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:@"No items flagged by VirusTotal"] defaultButton:@"Ok" alternateButton:nil otherButton:nil informativeTextWithFormat:@"horray! 😇"]; + + //and show it + [alert runModal]; + } + + //show flagged items + else + { + //alloc/init settings window + if(nil == self.flagItemsWindowController) + { + //alloc/init + flagItemsWindowController = [[FlaggedItems alloc] initWithWindowNibName:@"FlaggedItems"]; + } + + //show it + [self.flagItemsWindowController showWindow:self]; + + //invoke function in background that will make window modal + // ->waits until window is non-nil + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + //make modal + makeModal(self.prefsWindowController); + + }); + + + } + + //NSLog(@"would show flagged items"); + + return; +} + @end diff --git a/Consts.h b/Consts.h index 796db4c..99b8e07 100644 --- a/Consts.h +++ b/Consts.h @@ -95,6 +95,9 @@ //logo button #define LOGO_BUTTON_TAG 10004 +//flagged items button +#define FLAGGED_BUTTON_TAG 10005 + //category table diff --git a/FlaggedItems.h b/FlaggedItems.h new file mode 100644 index 0000000..09e0edb --- /dev/null +++ b/FlaggedItems.h @@ -0,0 +1,24 @@ +// +// FlaggedItems.h +// TaskExplorer +// +// Created by Patrick Wardle on 8/14/15. +// Copyright (c) 2015 Lucas Derraugh. All rights reserved. +// + +#import + +@interface FlaggedItems : NSWindowController + +//PROPERTIES + +//flag for first time init's +@property BOOL didInit; + +//table +@property (weak) IBOutlet NSTableView *flaggedItemTable; + +//vt window controller +@property (nonatomic, retain)VTInfoWindowController* vtWindowController; + +@end diff --git a/FlaggedItems.m b/FlaggedItems.m new file mode 100644 index 0000000..82783a1 --- /dev/null +++ b/FlaggedItems.m @@ -0,0 +1,162 @@ +// +// FlaggedItems.m +// TaskExplorer +// +// Created by Patrick Wardle on 8/14/15. +// Copyright (c) 2015 Lucas Derraugh. All rights reserved. +// + +#import "AppDelegate.h" +#import "FlaggedItems.h" +#import "ItemView.h" +#import "KKRow.h" + + +@interface FlaggedItems () + +@end + +@implementation FlaggedItems + +@synthesize didInit; +@synthesize flaggedItemTable; +@synthesize vtWindowController; + +//automatically called when nib is loaded +// ->center window +-(void)awakeFromNib +{ + //single time init + if(YES != self.didInit) + { + //center + [self.window center]; + + //set flag + self.didInit = YES; + } + + return; +} + +//automatically invoked when window is loaded +// ->set to white +-(void)windowDidLoad +{ + //super + [super windowDidLoad]; + + //table reload + [self.flaggedItemTable reloadData]; +} + +//table delegate +// ->return number of rows, which is just number of items in the currently selected plugin +-(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView +{ + return ((AppDelegate*)[[NSApplication sharedApplication] delegate]).flaggedItems.count; +} + +//table delegate method +// ->return cell for row +-(NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row +{ + //flagged items + NSMutableArray* flaggedItems = nil; + + //row view + NSView* rowView = nil; + + //grab flagged items + flaggedItems = ((AppDelegate*)[[NSApplication sharedApplication] delegate]).flaggedItems; + + //sanity check + // ->make sure there is table item for row + if(row >= flaggedItems.count) + { + //bail + goto bail; + } + + //create the view + // ->inits row w/ all required info + rowView = createItemView(tableView, self, [flaggedItems objectAtIndex:row]); + +//bail +bail: + + return rowView; +} + +//automatically invoked +// ->create custom (sub-classed) NSTableRowView +-(NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row +{ + //row view + KKRow* rowView = nil; + + //row ID + static NSString* const kRowIdentifier = @"TableRowView"; + + //try grab existing row view + rowView = [tableView makeViewWithIdentifier:kRowIdentifier owner:self]; + + //make new if needed + if(nil == rowView) + { + //create new + // ->size doesn't matter + rowView = [[KKRow alloc] initWithFrame:NSZeroRect]; + + //set row ID + rowView.identifier = kRowIdentifier; + } + + return rowView; +} + +//invoked when the user clicks 'virus total' icon +// ->launch browser and browse to virus total's page +-(void)showVTInfo:(id)sender +{ + //binary + Binary* item = nil; + + //row + NSInteger itemRow = 0; + + //flagged items + NSMutableArray* flaggedItems = nil; + + //grab flagged items + flaggedItems = ((AppDelegate*)[[NSApplication sharedApplication] delegate]).flaggedItems; + + //grab sender's row + itemRow = [self.flaggedItemTable rowForView:sender]; + + //sanity check(s) + // ->make sure row is decent + if( (-1 == itemRow) || + (itemRow >= flaggedItems.count) ) + { + //bail + goto bail; + } + + //extract item for row + item = flaggedItems[itemRow]; + + //alloc/init info window + vtWindowController = [[VTInfoWindowController alloc] initWithItem:item]; + + //show it + [self.vtWindowController.windowController showWindow:self]; + + +//bail +bail: + + return; +} + +@end diff --git a/ItemView.h b/ItemView.h index f14acfd..e3c799d 100644 --- a/ItemView.h +++ b/ItemView.h @@ -19,6 +19,9 @@ //create customize item view NSTableCellView* createItemView(NSTableView* tableView, id owner, id item); +//create & customize flagged item view +NSTableCellView* createFlaggedItemView(NSTableView* tableView, id owner, id item); + //create & customize task view NSTableCellView* createTaskView(NSTableView* tableView, id owner, id item); diff --git a/ItemView.m b/ItemView.m index 31497ed..01d2d6c 100644 --- a/ItemView.m +++ b/ItemView.m @@ -19,15 +19,22 @@ NSTableCellView* createItemView(NSTableView* tableView, id owner, id item) //item cell NSTableCellView *itemCell = nil; - //sanity chec + //sanity check if(nil == item) { //bail goto bail; } + //first handle logic for flagged items + if(YES == [owner isKindOfClass:[FlaggedItems class]]) + { + //create & config view + itemCell = createFlaggedItemView(tableView, owner, item); + } + //logic to create task view - if(YES == [item isKindOfClass:[Task class]]) + else if(YES == [item isKindOfClass:[Task class]]) { //create & config view itemCell = createTaskView(tableView, owner, item); @@ -126,9 +133,147 @@ NSImage* getCodeSigningIcon(Binary* binary) } return codeSignIcon; - } +//create & customize flagged item view +NSTableCellView* createFlaggedItemView(NSTableView* tableView, id owner, Binary* binary) +{ + //item cell + NSTableCellView* flaggedItemCell = nil; + + //matching or host tasks + NSMutableArray* tasks = nil; + + //pid or 'loaded in' string + NSMutableString* pidString = nil; + + //task's name frame + CGRect nameFrame = {0}; + + //for main (task) binaries + // ->just need task's pid + if(YES == binary.isTaskBinary) + { + //get all matching tasks + tasks = [((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator tasksForBinary:binary]; + + //start 'tasks: ...' str + pidString = [NSMutableString stringWithFormat:@"(tasks:"]; + + //add all tasks + for(Task* task in tasks) + { + //append name + [pidString appendFormat:@" %@,", task.pid]; + } + + //remove last ',' + if(YES == [pidString hasSuffix:@","]) + { + //remove + [pidString deleteCharactersInRange:NSMakeRange([pidString length]-1, 1)]; + } + + //terminate list/output + [pidString appendString:@")"]; + } + //for dylibs + // ->list all tasks the flagged dylib is loaded in + else + { + //get host tasks + tasks = [((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator loadedIn:binary]; + + //start 'loaded in: ...' str + pidString = [NSMutableString stringWithFormat:@"(loaded in:"]; + + //add all tasks + for(Task* task in tasks) + { + //append name + [pidString appendFormat:@" %@,", task.binary.name]; + } + + //remove last ',' + if(YES == [pidString hasSuffix:@","]) + { + //remove + [pidString deleteCharactersInRange:NSMakeRange([pidString length]-1, 1)]; + } + + //terminate list/output + [pidString appendString:@")"]; + } + + //create cell + flaggedItemCell = [tableView makeViewWithIdentifier:@"FlaggedItem" owner:owner]; + if(nil == flaggedItemCell) + { + //bail + goto bail; + } + + //brand new cells need tracking areas + // ->determine if new, by checking default (.xib/IB) value + if(YES == [flaggedItemCell.textField.stringValue isEqualToString:@"Flagged Item Name"]) + { + //add tracking area + // ->'vt' button + addTrackingArea(flaggedItemCell, TABLE_ROW_VT_BUTTON, owner); + + //add tracking area + // ->'info' button + addTrackingArea(flaggedItemCell, TABLE_ROW_INFO_BUTTON, owner); + + //add tracking area + // ->'show' button + addTrackingArea(flaggedItemCell, TABLE_ROW_SHOW_BUTTON, owner); + } + + //set icon + flaggedItemCell.imageView.image = [binary icon]; + + //set code signing icon + ((NSImageView*)[flaggedItemCell viewWithTag:TABLE_ROW_SIGNATURE_ICON]).image = getCodeSigningIcon(binary); + + //default + // ->(re)set main textfield's color to black + flaggedItemCell.textField.textColor = [NSColor blackColor]; + + //set main text + // ->name + [flaggedItemCell.textField setStringValue:binary.name]; + + //get name frame + nameFrame = flaggedItemCell.textField.frame; + + //adjust width to fit text + nameFrame.size.width = [flaggedItemCell.textField.stringValue sizeWithAttributes: @{NSFontAttributeName: flaggedItemCell.textField.font}].width + 5; + + //disable autolayout for name + flaggedItemCell.textField.translatesAutoresizingMaskIntoConstraints = YES; + + //update name frame + // ->should now be exact size of text + flaggedItemCell.textField.frame = nameFrame; + + //set pid + // ->immediately follows name + [((NSTextField*)[flaggedItemCell viewWithTag:TABLE_ROW_PID_LABEL]) setStringValue:pidString]; + + //set path + [[flaggedItemCell viewWithTag:TABLE_ROW_SUB_TEXT_TAG] setStringValue:binary.path]; + + //config VT button + configVTButton(flaggedItemCell, owner, binary); + +//bail +bail: + + return flaggedItemCell; +} + + //create & customize Task view NSTableCellView* createTaskView(NSTableView* tableView, id owner, Task* task) { diff --git a/RequestRootWindowController.m b/RequestRootWindowController.m index 45ab92e..4e23eaf 100644 --- a/RequestRootWindowController.m +++ b/RequestRootWindowController.m @@ -155,7 +155,7 @@ //2nd arg: permissions // ->4 at front is setuid //TODO: make 4755 before deploy (for testing, 777 makes XCOde be able to del it during build!) - installArgs[1] = "4755"; + installArgs[1] = "4777"; //3rd arg: XPC service installArgs[2] = [xpcService UTF8String]; diff --git a/TaskEnumerator.h b/TaskEnumerator.h index b407206..515ff93 100644 --- a/TaskEnumerator.h +++ b/TaskEnumerator.h @@ -57,5 +57,15 @@ // ->get list of all child pids -(void)getAllChildren:(Task*)parent children:(NSMutableArray*)children; +//get all tasks a dylib is loaded into +-(NSMutableArray*)loadedIn:(Binary*)dylib; + +//get all task pids for a given binary +-(NSMutableArray*)tasksForBinary:(Binary*)binary; + +//ensure that the list of flagged items is correctly updated +// when a dead task or any of its dylibs were flagged... +-(void)updateFlaggedItems:(Task*)deadTask; + @end diff --git a/TaskEnumerator.m b/TaskEnumerator.m index d8198cc..c62b111 100644 --- a/TaskEnumerator.m +++ b/TaskEnumerator.m @@ -70,7 +70,8 @@ //new tasks OrderedDictionary* newTasks = nil; - //set connected flag + //determine if network is connected + // ->sets 'isConnected' flag ((AppDelegate*)[[NSApplication sharedApplication] delegate]).isConnected = isNetworkConnected(); //get all tasks @@ -138,6 +139,7 @@ //reload bottom pane [((AppDelegate*)[[NSApplication sharedApplication] delegate]) selectBottomPaneContent:nil]; + }); //now generate signing info @@ -167,6 +169,16 @@ }//signing info for all new tasks + //begin dylib enumeration + for(NSNumber* key in newTasks) + { + //get task + newTask = newTasks[key]; + + //enumerate + [newTask enumerateDylibs:((AppDelegate*)[[NSApplication sharedApplication] delegate]).xpcConnection allDylibs:self.dylibs]; + } + return; } @@ -360,7 +372,7 @@ bail: } //remove a task -// ->contains extra logic to remove children, etc +// ->contains extra logic to remove children, flagged items, etc -(void)removeTask:(Task*)deadTask { //parent @@ -379,6 +391,18 @@ bail: //alloc array for children children = [NSMutableArray array]; + //ensure that flagged item list is accurate + // ->the dead task or its dylibs might have been flagged + [self updateFlaggedItems:deadTask]; + + //(re)set label for flagged items to black + // when there are no flagged items + if(0 == ((AppDelegate*)[[NSApplication sharedApplication] delegate]).flaggedItems.count) + { + //set to gray + ((AppDelegate*)[[NSApplication sharedApplication] delegate]).flaggedLabel.textColor = [NSColor lightGrayColor]; + } + //get launchd's task // ->its 'pid' is 0x1 launchdTask = self.tasks[@1]; @@ -415,6 +439,83 @@ bail: return; } +//TODO: test w/ dylib!! +//ensure that the list of flagged items is correctly updated +// when a dead task or any of its dylibs were flagged... +-(void)updateFlaggedItems:(Task*)deadTask +{ + //task + Task* task = nil; + + //number of task instances + NSUInteger taskInstances = 0; + + //tasks that host flagged dylib + NSMutableArray* taskHosts = nil; + + //remove any dylibs that are flagged and loaded (only!) in dead task + for(Binary* dylib in deadTask.dylibs) + { + //skip dylibs that aren't flagged + if(YES != [((AppDelegate*)[[NSApplication sharedApplication] delegate]).flaggedItems containsObject:dylib]) + { + //skip + continue; + } + + //get all tasks that host the flagged dylib + taskHosts = [self tasksForBinary:dylib]; + + //skip dylibs that are hosted in more than one task + // or aren't hosted in dead task + if( (1 != taskHosts.count) || + (taskHosts.firstObject != deadTask.binary) ) + { + //skip + continue; + } + + //dylib is flagged and only hosted in dead task + // ->remove it from flaggedItems + @synchronized(((AppDelegate*)[[NSApplication sharedApplication] delegate]).flaggedItems) + { + //remove + [((AppDelegate*)[[NSApplication sharedApplication] delegate]).flaggedItems removeObject:dylib]; + } + } + + //also remove task if its flagged and only instance + if(YES == [((AppDelegate*)[[NSApplication sharedApplication] delegate]).flaggedItems containsObject:deadTask.binary]) + { + //get number of task instances + // ->might be more (flagged) instances that are still alive + for(NSNumber* taskPid in self.tasks) + { + //extract task + task = self.tasks[taskPid]; + + //check for task has dylib + if(task.binary == deadTask.binary) + { + //inc + taskInstances++; + } + } + + //remove if only instance + if(1 == taskInstances) + { + //sync and remove + @synchronized(((AppDelegate*)[[NSApplication sharedApplication] delegate]).flaggedItems) + { + //remove + [((AppDelegate*)[[NSApplication sharedApplication] delegate]).flaggedItems removeObject:deadTask.binary]; + } + } + } + + return; +} //given a task // ->get list of all child pids @@ -441,5 +542,81 @@ bail: return; } +//get all task pids for a given binary +-(NSMutableArray*)tasksForBinary:(Binary*)binary +{ + //array of tasks + NSMutableArray* matchingTasks = nil; + + //task + Task* task = nil; + + //tasks + matchingTasks = [NSMutableArray array]; + + //sync + @synchronized(self.tasks) + { + //reload each row w/ new VT info + for(NSNumber* taskPid in self.tasks) + { + //extract task + task = self.tasks[taskPid]; + + //check for task has dylib + if(task.binary == binary) + { + //save + [matchingTasks addObject:task]; + } + } + + }//sync + + return matchingTasks; +} + + +//get all tasks a dylib is loaded into +-(NSMutableArray*)loadedIn:(Binary*)dylib +{ + //array of tasks + NSMutableArray* hostTasks = nil; + + //task + Task* task = nil; + + //tasks + hostTasks = [NSMutableArray array]; + + //sync + @synchronized(self.tasks) + { + //reload each row w/ new VT info + for(NSNumber* taskPid in self.tasks) + { + //extract task + task = self.tasks[taskPid]; + + //check if dylib is loaded in task + for(Binary* taskDylib in task.dylibs) + { + //check for task has dylib + if(taskDylib == dylib) + { + //save + [hostTasks addObject:task]; + + //can bail, since match was found + break; + } + } + } + + }//sync + + return hostTasks; +} + @end diff --git a/TaskExplorer-Info.plist b/TaskExplorer-Info.plist index 3ed331a..06c5280 100755 --- a/TaskExplorer-Info.plist +++ b/TaskExplorer-Info.plist @@ -17,11 +17,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0.0 + 1.0.1 CFBundleSignature ???? CFBundleVersion - 1.0.0 + 1.0.1 LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} NSHumanReadableCopyright diff --git a/TaskExplorer.xcodeproj/project.pbxproj b/TaskExplorer.xcodeproj/project.pbxproj index bde41de..42cdd8e 100755 --- a/TaskExplorer.xcodeproj/project.pbxproj +++ b/TaskExplorer.xcodeproj/project.pbxproj @@ -43,6 +43,10 @@ CD6AFB861B4BABB200D42C34 /* refreshIconBG.png in Resources */ = {isa = PBXBuildFile; fileRef = CD6AFB841B4BABB200D42C34 /* refreshIconBG.png */; }; CD6AFB871B4BABB200D42C34 /* refreshIconOver.png in Resources */ = {isa = PBXBuildFile; fileRef = CD6AFB851B4BABB200D42C34 /* refreshIconOver.png */; }; CD6E54FF1B1162B5007953AB /* ItemView.m in Sources */ = {isa = PBXBuildFile; fileRef = CD6E54FE1B1162B5007953AB /* ItemView.m */; }; + CD74A06D1B7DA71200A8AAD3 /* flaggedBG.png in Resources */ = {isa = PBXBuildFile; fileRef = CD74A06B1B7DA71200A8AAD3 /* flaggedBG.png */; }; + CD74A06E1B7DA71200A8AAD3 /* flaggedOver.png in Resources */ = {isa = PBXBuildFile; fileRef = CD74A06C1B7DA71200A8AAD3 /* flaggedOver.png */; }; + CD74A07B1B7F170B00A8AAD3 /* FlaggedItems.m in Sources */ = {isa = PBXBuildFile; fileRef = CD74A0791B7F170B00A8AAD3 /* FlaggedItems.m */; }; + CD74A07E1B81B5D400A8AAD3 /* FlaggedItems.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD74A07D1B81B5D400A8AAD3 /* FlaggedItems.xib */; }; CD7B9F4D1ACB959200DF3C71 /* logoAppleOver.png in Resources */ = {isa = PBXBuildFile; fileRef = CD7B9F4C1ACB959200DF3C71 /* logoAppleOver.png */; }; CD7B9F501ACB9A8400DF3C71 /* Exception.m in Sources */ = {isa = PBXBuildFile; fileRef = CD7B9F4F1ACB9A8400DF3C71 /* Exception.m */; }; CD7B9FA41ACBCFAD00DF3C71 /* spotlightIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CD7B9FA31ACBCFAD00DF3C71 /* spotlightIcon.png */; }; @@ -113,6 +117,7 @@ CDF08CF01ACA677B009B3423 /* kernelIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CEE1ACA677B009B3423 /* kernelIcon.png */; }; CDF08CF31ACA6864009B3423 /* browserIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CF11ACA6864009B3423 /* browserIcon.png */; }; CDF08CF41ACA6864009B3423 /* loginIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CF21ACA6864009B3423 /* loginIcon.png */; }; + CDFCA3561B7940970075492D /* flagged.png in Resources */ = {isa = PBXBuildFile; fileRef = CDFCA3551B7940970075492D /* flagged.png */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -192,6 +197,11 @@ CD6AFB851B4BABB200D42C34 /* refreshIconOver.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = refreshIconOver.png; path = images/refreshIconOver.png; sourceTree = SOURCE_ROOT; }; CD6E54FD1B1162B5007953AB /* ItemView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ItemView.h; sourceTree = ""; }; CD6E54FE1B1162B5007953AB /* ItemView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ItemView.m; sourceTree = ""; }; + CD74A06B1B7DA71200A8AAD3 /* flaggedBG.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = flaggedBG.png; path = images/flaggedBG.png; sourceTree = SOURCE_ROOT; }; + CD74A06C1B7DA71200A8AAD3 /* flaggedOver.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = flaggedOver.png; path = images/flaggedOver.png; sourceTree = SOURCE_ROOT; }; + CD74A0781B7F170B00A8AAD3 /* FlaggedItems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlaggedItems.h; sourceTree = ""; }; + CD74A0791B7F170B00A8AAD3 /* FlaggedItems.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlaggedItems.m; sourceTree = ""; }; + CD74A07D1B81B5D400A8AAD3 /* FlaggedItems.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = FlaggedItems.xib; path = UI/FlaggedItems.xib; sourceTree = ""; }; CD7B9F4C1ACB959200DF3C71 /* logoAppleOver.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = logoAppleOver.png; path = images/logoAppleOver.png; sourceTree = SOURCE_ROOT; }; CD7B9F4E1ACB9A8400DF3C71 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = SOURCE_ROOT; }; CD7B9F4F1ACB9A8400DF3C71 /* Exception.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Exception.m; sourceTree = SOURCE_ROOT; }; @@ -285,6 +295,7 @@ CDF08CEE1ACA677B009B3423 /* kernelIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = kernelIcon.png; path = images/kernelIcon.png; sourceTree = SOURCE_ROOT; }; CDF08CF11ACA6864009B3423 /* browserIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = browserIcon.png; path = images/browserIcon.png; sourceTree = SOURCE_ROOT; }; CDF08CF21ACA6864009B3423 /* loginIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = loginIcon.png; path = images/loginIcon.png; sourceTree = SOURCE_ROOT; }; + CDFCA3551B7940970075492D /* flagged.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = flagged.png; path = images/flagged.png; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -312,6 +323,8 @@ 1D21BC42172AF43D009D1CFD = { isa = PBXGroup; children = ( + CD74A0781B7F170B00A8AAD3 /* FlaggedItems.h */, + CD74A0791B7F170B00A8AAD3 /* FlaggedItems.m */, CD4D54201B2CE6F200008030 /* NSMutableArray+QueueAdditions.h */, CDBE49161B58DC9B0031FC22 /* NSApplicationKeyEvents.h */, CDBE49171B58DC9B0031FC22 /* NSApplicationKeyEvents.m */, @@ -410,6 +423,9 @@ CD6095501A8329FA00E091CD /* images */ = { isa = PBXGroup; children = ( + CD74A06B1B7DA71200A8AAD3 /* flaggedBG.png */, + CD74A06C1B7DA71200A8AAD3 /* flaggedOver.png */, + CDFCA3551B7940970075492D /* flagged.png */, CD6AFB841B4BABB200D42C34 /* refreshIconBG.png */, CD6AFB851B4BABB200D42C34 /* refreshIconOver.png */, CD6AFB821B4BAA2100D42C34 /* refreshIcon.png */, @@ -535,6 +551,7 @@ CDA81E621AA020E8009790E2 /* UI */ = { isa = PBXGroup; children = ( + CD74A07D1B81B5D400A8AAD3 /* FlaggedItems.xib */, CD4D54271B2EAC7800008030 /* NetworkInfoWindow.xib */, CD4D54231B2D082300008030 /* DylibInfoWindow.xib */, CDA5F6C01B16E1D6003CE340 /* RequestRootWindow.xib */, @@ -651,7 +668,9 @@ CDA81D5B1A95B4B4009790E2 /* InfoPlist.strings in Resources */, CD4D53CA1B20296E00008030 /* unknown.png in Resources */, CDEE77081B41220300763826 /* searchOver.png in Resources */, + CD74A07E1B81B5D400A8AAD3 /* FlaggedItems.xib in Resources */, CDA81D6B1A95B4E9009790E2 /* show.png in Resources */, + CD74A06D1B7DA71200A8AAD3 /* flaggedBG.png in Resources */, CDF08CF31ACA6864009B3423 /* browserIcon.png in Resources */, CDEE77061B41220300763826 /* search.png in Resources */, CDAB98A11AEAFAFA00C75B4B /* authorizationIcon.png in Resources */, @@ -680,6 +699,7 @@ CD6AFB7F1B4736DF00D42C34 /* flatIcon.png in Resources */, CD6AFB811B4737AC00D42C34 /* arrow.png in Resources */, CDA81DCC1A9960A3009790E2 /* virusTotalBG.png in Resources */, + CD74A06E1B7DA71200A8AAD3 /* flaggedOver.png in Resources */, CD001B381AB903040089014A /* logo.png in Resources */, CDA81D6D1A95B4E9009790E2 /* scanIcon.png in Resources */, CDF08CCF1AC4C6E8009B3423 /* settingsOver.png in Resources */, @@ -689,6 +709,7 @@ CD4D543F1B2FF32C00008030 /* signedAppleIcon.png in Resources */, CD3F4D161AF89066002A2647 /* TreeView.xib in Resources */, CD0219501AD34D8B005148A2 /* PrefsWindow.xib in Resources */, + CDFCA3561B7940970075492D /* flagged.png in Resources */, CDA81D6C1A95B4E9009790E2 /* showBG.png in Resources */, CD3F4CFF1AF72BC4002A2647 /* TaskInfoWindow.xib in Resources */, CDEE77001B3FD4B000763826 /* saveIconOver.png in Resources */, @@ -729,6 +750,7 @@ files = ( CD3F4CE81AF5CF68002A2647 /* TaskEnumerator.m in Sources */, CD4D54221B2CE6F200008030 /* NSMutableArray+QueueAdditions.m in Sources */, + CD74A07B1B7F170B00A8AAD3 /* FlaggedItems.m in Sources */, CDA5F6C41B16E20E003CE340 /* RequestRootWindowController.m in Sources */, CDD2483B1AF5CC4D00232422 /* Task.m in Sources */, CD83887F1AACCEDF000EB098 /* VirusTotal.m in Sources */, diff --git a/TaskExplorer.xcodeproj/project.xcworkspace/xcshareddata/TaskExplorer.xccheckout b/TaskExplorer.xcodeproj/project.xcworkspace/xcshareddata/TaskExplorer.xccheckout index c0c67db..df18232 100644 --- a/TaskExplorer.xcodeproj/project.xcworkspace/xcshareddata/TaskExplorer.xccheckout +++ b/TaskExplorer.xcodeproj/project.xcworkspace/xcshareddata/TaskExplorer.xccheckout @@ -7,14 +7,14 @@ IDESourceControlProjectIdentifier FE4103FE-6F26-4639-8C9F-D8D32C76D6A9 IDESourceControlProjectName - project + TaskExplorer IDESourceControlProjectOriginsDictionary 61F07AFB33748EF0C810BEEF6126283DAC63A899 https://bitbucket.org/objective-see/taskexplorer.git IDESourceControlProjectPath - TaskExplorer.xcodeproj/project.xcworkspace + TaskExplorer.xcodeproj IDESourceControlProjectRelativeInstallPathDictionary 61F07AFB33748EF0C810BEEF6126283DAC63A899 diff --git a/TaskExplorer.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/TaskExplorer.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 8a85ee7..897e481 100644 --- a/TaskExplorer.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/TaskExplorer.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -87,22 +87,6 @@ landmarkType = "5"> - - - - @@ -190,11 +174,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "AppDelegate.m" - timestampString = "460362206.963852" + timestampString = "461485530.290068" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "1597" - endingLineNumber = "1597" + startingLineNumber = "1638" + endingLineNumber = "1638" landmarkName = "-constrainView:subView:" landmarkType = "5"> @@ -254,31 +238,15 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "AppDelegate.m" - timestampString = "460362206.963852" + timestampString = "461485530.290068" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "806" - endingLineNumber = "806" + startingLineNumber = "827" + endingLineNumber = "827" landmarkName = "-reloadTaskTable" landmarkType = "5"> - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/TaskTableController.h b/TaskTableController.h index 23c3435..89fcd77 100644 --- a/TaskTableController.h +++ b/TaskTableController.h @@ -41,7 +41,7 @@ //info window @property(retain, nonatomic)InfoWindowController* infoWindowController; -//preferences window controller +//virus total window controller @property (nonatomic, retain)VTInfoWindowController* vtWindowController; //currently selected row diff --git a/UI/AboutWindow.xib b/UI/AboutWindow.xib index e745a9a..78dbf1b 100644 --- a/UI/AboutWindow.xib +++ b/UI/AboutWindow.xib @@ -1,5 +1,5 @@ - + diff --git a/UI/FlaggedItems.xib b/UI/FlaggedItems.xib new file mode 100644 index 0000000..81bd7e6 --- /dev/null +++ b/UI/FlaggedItems.xib @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/VirusTotal.m b/VirusTotal.m index 454db19..e2740ca 100644 --- a/VirusTotal.m +++ b/VirusTotal.m @@ -370,20 +370,11 @@ //save result item.vtInfo = results; - //TODO: do something if it's flagged! - //if its flagged save in File's plugin + //save flagged item if(0 != [results[VT_RESULTS_POSITIVES] unsignedIntegerValue]) { - /* - //sync - // ->since array will be reset if user clicks 'stop' scan - @synchronized(fileObj.plugin.flaggedItems) - { - //save - [fileObj.plugin.flaggedItems addObject:fileObj]; - } - */ - + //save + [((AppDelegate*)[[NSApplication sharedApplication] delegate]) saveFlaggedBinary:item]; } //call up into app delegate to smartly reload @@ -722,13 +713,15 @@ bail: //save VT results into item queriedItem.vtInfo = result; + //save flagged item + if(0 != [result[VT_RESULTS_POSITIVES] unsignedIntegerValue]) + { + //save + [((AppDelegate*)[[NSApplication sharedApplication] delegate]) saveFlaggedBinary:queriedItem]; + } + //call up into app delegate to smartly reload [((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadBinary:queriedItem]; - - - //TODO: do something with detections!? - // ->blinking button, user's can click to see 'flagged items' popup - //if(0 != [result[VT_RESULTS_POSITIVES] unsignedIntegerValue]) } return; diff --git a/en.lproj/MainMenu.xib b/en.lproj/MainMenu.xib index 502add9..8936c57 100755 --- a/en.lproj/MainMenu.xib +++ b/en.lproj/MainMenu.xib @@ -1,5 +1,5 @@ - + @@ -155,7 +155,7 @@ + + + + + + + + - + + + @@ -283,6 +307,8 @@ + + @@ -308,6 +334,8 @@ + + diff --git a/images/flagged.png b/images/flagged.png new file mode 100644 index 0000000000000000000000000000000000000000..dd90cf32cc6e32d68d8eebad8b6cb0ddb82e13f4 GIT binary patch literal 3498 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 literal 0 HcmV?d00001 diff --git a/remoteTaskService/main.m b/remoteTaskService/main.m index 55ad89b..ccc6fb6 100644 --- a/remoteTaskService/main.m +++ b/remoteTaskService/main.m @@ -15,9 +15,13 @@ @implementation ServiceDelegate -- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection { - // This method is where the NSXPCListener configures, accepts, and resumes a new incoming NSXPCConnection. - + +//TODO: check for 'signed by Obj-C' +//automatically invoked +//->allows NSXPCListener to configure/accept/resume a new incoming NSXPCConnection. +-(BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection +{ + // Configure the connection. // First, set the interface that the exported object implements. newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(remoteTaskProto)];