diff --git a/AppDelegate.h b/AppDelegate.h index 9583022..35f5d91 100755 --- a/AppDelegate.h +++ b/AppDelegate.h @@ -32,6 +32,9 @@ } +//start time +@property NSTimeInterval startTime; + //connection flag @property BOOL isConnected; @@ -80,7 +83,7 @@ @property (weak) IBOutlet NSButton *logoButton; -@property (weak) IBOutlet NSButton *showPreferencesButton; +//@property (weak) IBOutlet NSButton *showPreferencesButton; //spinner @property (weak) IBOutlet NSProgressIndicator *progressIndicator; @@ -127,11 +130,14 @@ //'no items' found label for bottom pane @property (weak) IBOutlet NSTextField *noItemsLabel; +//refresh button +@property (weak) IBOutlet NSButton *refreshButton; + //search button @property (weak) IBOutlet NSButton *searchButton; -//refresh button -@property (weak) IBOutlet NSButton *refreshButton; +//save button +@property (weak) IBOutlet NSButton *saveButton; //flagged items button @property (weak) IBOutlet NSButton *flaggedButton; @@ -182,7 +188,7 @@ //-(void)applyPreferences; //button handler for when settings icon (gear) is clicked --(IBAction)showPreferences:(id)sender; +//-(IBAction)showPreferences:(id)sender; //button handler for logo -(IBAction)logoButtonHandler:(id)sender; diff --git a/AppDelegate.m b/AppDelegate.m index 96d5156..daefc65 100755 --- a/AppDelegate.m +++ b/AppDelegate.m @@ -16,13 +16,9 @@ #import "Task.h" -//TODO: path truncated in 'info' window (1password mini) - but weird when selected :/ -// resize text manually? http://stackoverflow.com/questions/6519995/modifying-an-nstextfields-font-size-according-to-content-length - //TODO: filter out dup'd networks (airportd 0:0..) -not sure want to do this -//TODO: 'flagged' items button? //TODO: add 'am i on main thread' guard and test -//TODO: filter dylibs, no first responder! + //TODO: autolayout vertically //TODO: filter VT results @@ -31,24 +27,24 @@ // 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 :/ //TODO: check if VT can be reached! if not, error? or don't show '0 VT results detected' etc... //TODO: JavaW (iWorm) dylibs... + //TODO: remove task, remove from taskEnum's global list for executables, and dylibs, etc //TODO: also refresh!.... @implementation AppDelegate - @synthesize filterObj; +@synthesize startTime; @synthesize vtThreads; +@synthesize saveButton; @synthesize isConnected; @synthesize virusTotalObj; @synthesize taskTableController; @synthesize aboutWindowController; @synthesize prefsWindowController; -@synthesize showPreferencesButton; @synthesize resultsWindowController; @synthesize bottomPane; @synthesize bottomViewController; @@ -89,10 +85,9 @@ // ->main entry point -(void)applicationDidFinishLaunching:(NSNotification *)notification { - //TODO: re-enable for release! //first thing... // ->install exception handlers! - //installExceptionHandlers(); + installExceptionHandlers(); //init virus total object virusTotalObj = [[VirusTotal alloc] init]; @@ -103,6 +98,12 @@ //alloc flagged items flaggedItems = [NSMutableArray array]; + //set start time + self.startTime = [NSDate timeIntervalSinceReferenceDate]; + + //center + [self.window center]; + //no need to have a first responder [self.window makeFirstResponder:nil]; @@ -328,9 +329,8 @@ bail: // ->waits until window is non-nil dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - //TODO: re-enable //make modal - //makeModal(self.requestRootWindowController); + makeModal(self.requestRootWindowController); }); @@ -748,14 +748,6 @@ bail: //add tracking area to pref button [self.refreshButton addTrackingArea:trackingArea]; - - - //init tracking area - // ->for preference button - trackingArea = [[NSTrackingArea alloc] initWithRect:[self.showPreferencesButton bounds] options:(NSTrackingInVisibleRect|NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:@{@"tag":[NSNumber numberWithUnsignedInteger:self.showPreferencesButton.tag]}]; - - //add tracking area to pref button - [self.showPreferencesButton addTrackingArea:trackingArea]; //init tracking area // ->for search button @@ -764,6 +756,13 @@ bail: //add tracking area to search button [self.searchButton addTrackingArea:trackingArea]; + //init tracking area + // ->for save button + trackingArea = [[NSTrackingArea alloc] initWithRect:[self.saveButton bounds] options:(NSTrackingInVisibleRect|NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:@{@"tag":[NSNumber numberWithUnsignedInteger:self.saveButton.tag]}]; + + //add tracking area to search button + [self.saveButton addTrackingArea:trackingArea]; + //init tracking area // ->for logo button trackingArea = [[NSTrackingArea alloc] initWithRect:[self.logoButton bounds] options:(NSTrackingInVisibleRect|NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:@{@"tag":[NSNumber numberWithUnsignedInteger:self.logoButton.tag]}]; @@ -781,26 +780,6 @@ bail: return; } - -//TODO: don't need, and scannerThread can be removed!! and progressIndicator too! -//automatically invoked when window is un-minimized -// since the progress indicator is stopped (bug?), restart it --(void)windowDidDeminiaturize:(NSNotification *)notification -{ - //make sure scan is going on - // ->and then restart spinner - if(YES == [self.scannerThread isExecuting]) - { - //show - [self.progressIndicator setHidden:NO]; - - //start spinner - [self.progressIndicator startAnimation:nil]; - } - - return; -} - //automatically invoked when user clicks logo // ->load objective-see's html page -(IBAction)logoButtonHandler:(id)sender @@ -1145,7 +1124,6 @@ bail: bail: return; - } //automatically invoked when user clicks 'search' button @@ -1165,17 +1143,6 @@ bail: //show it [self.searchWindowController 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.searchWindowController); - - }); - */ - return; } @@ -1201,6 +1168,7 @@ bail: return; } +/* //automatically invoked when user clicks gear icon // ->show preferences @@ -1227,7 +1195,10 @@ bail: return; } + +*/ +/* //automatically invoked when menu is clicked // ->tell menu to disable 'Preferences' when scan is running -(BOOL)validateMenuItem:(NSMenuItem *)item @@ -1238,19 +1209,20 @@ bail: //check if item is 'Preferences' if(PREF_MENU_ITEM_TAG == item.tag) { - /* //unset enabled flag if scan is running if(YES != [[self.scanButtonLabel stringValue] isEqualToString:START_SCAN]) { //disable bEnabled = NO; } - */ + } return bEnabled; } +*/ + //automatically invoked when user clicks on Flat/Tree view // ->invoke helper function to change view @@ -1641,6 +1613,10 @@ bail: //scroll to top [self.taskTableController scrollToTop]; + //reload + // ->ensure that top row/task is correctly selected + //[self.taskTableController.itemView reloadData]; + //select top row [self.taskTableController.itemView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO]; @@ -1714,6 +1690,14 @@ bail: // ->also set text flagged items button label to red -(void)saveFlaggedBinary:(Binary*)binary { + //first check if item is already flagged + if(YES == [self.flaggedItems containsObject:binary]) + { + //no need to add + // ->so bail + goto bail; + } + //sync to save @synchronized(self.flaggedItems) { @@ -1729,6 +1713,9 @@ bail: self.flaggedLabel.textColor = [NSColor redColor]; } +//bail +bail: + return; } diff --git a/Consts.h b/Consts.h index 99b8e07..307b1e8 100644 --- a/Consts.h +++ b/Consts.h @@ -305,10 +305,14 @@ //sort by name #define SORT_BY_NAME 0x1 - //delta for pid tag #define PID_TAG_DELTA 1000 +//search wait time (from app's launch) +#define SEARCH_WAIT_TIME 30 + +//pls wait (search) message +#define PLS_WAIT_MESSAGE @"completing (intial) task/dylib/file enumeration please wait" diff --git a/Exception.m b/Exception.m index c34e107..d719de2 100755 --- a/Exception.m +++ b/Exception.m @@ -61,8 +61,6 @@ void showAlert() return; } - - //exception handler // will be invoked for Obj-C exceptions void exceptionHandler(NSException *exception) diff --git a/FlaggedItems.m b/FlaggedItems.m index 1c02455..bc0bf8e 100644 --- a/FlaggedItems.m +++ b/FlaggedItems.m @@ -25,14 +25,14 @@ @synthesize infoWindowController; //automatically called when nib is loaded -// ->center window +// ->first time (when outlets aren't nil), init UI -(void)awakeFromNib { //single time init if(YES != self.didInit) { - //center - [self.window center]; + //init UI + [self initUI]; //set flag self.didInit = YES; @@ -51,9 +51,17 @@ //init array for flagged items flaggedItems = [NSMutableArray array]; - //table reload w/ blank array - // ->make sure all is reset - [self.flaggedItemTable reloadData]; + //first time outlets are nil + // ->thus 'initUI' method called in 'awakeFromNib' + if(nil != self.window) + { + //can init UI + // ->center window, etc + [self initUI]; + + //set flag + self.didInit = YES; + } //populate flagged items array for(Binary* flaggedItem in ((AppDelegate*)[[NSApplication sharedApplication] delegate]).flaggedItems) @@ -65,16 +73,23 @@ //get all tasks instances flaggedTasks = [((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator tasksForBinary:flaggedItem]; - //save all tasks - [self.flaggedItems addObjectsFromArray:flaggedTasks]; + //sync to save + @synchronized(self.flaggedItems) + { + //save all tasks + [self.flaggedItems addObjectsFromArray:flaggedTasks]; + } } //when binary is dylib // ->just add, since will be processed as single item else { - //add - [self.flaggedItems addObject:flaggedItem]; - + //sync to save + @synchronized(self.flaggedItems) + { + //add + [self.flaggedItems addObject:flaggedItem]; + } } } @@ -85,6 +100,21 @@ } +//init the UI +// ->each time window is shown, reset, show spinner if needed, etc +-(void)initUI +{ + //center + [self.window center]; + + //table reload + // ->make sure all is reset + [self.flaggedItemTable reloadData]; + + return; +} + + //table delegate // ->return number of rows, which is just number of items in the currently selected plugin -(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView diff --git a/ItemView.h b/ItemView.h index 429571b..4c32b43 100644 --- a/ItemView.h +++ b/ItemView.h @@ -3,7 +3,7 @@ // TaskExplorer // // Created by Patrick Wardle on 5/23/15. -// Copyright (c) 2015 Lucas Derraugh. All rights reserved. +// Copyright (c) 2015 Objective-See, LLC. All rights reserved. // #import "File.h" diff --git a/ItemView.m b/ItemView.m index 1b1f7a8..c4cb466 100644 --- a/ItemView.m +++ b/ItemView.m @@ -3,7 +3,7 @@ // TaskExplorer // // Created by Patrick Wardle on 5/23/15. -// Copyright (c) 2015 Lucas Derraugh. All rights reserved. +// Copyright (c) 2015 Objective-See, LLC. All rights reserved. // #import "Consts.h" @@ -38,7 +38,7 @@ NSTableCellView* createItemView(NSTableView* tableView, id owner, id item) //handle logic for search results // ->dylibs and files have the special global 'loaded in' views else if( (YES == [owner isKindOfClass:[SearchWindowController class]]) && - ( (YES == [item isKindOfClass:[Binary class]]) || (YES == [item isKindOfClass:[File class]]) ) ) + ( (YES == [item isKindOfClass:[Binary class]]) || (YES == [item isKindOfClass:[File class]]) ) ) { //create & config view itemCell = createLoadedItemView(tableView, owner, item); @@ -163,12 +163,25 @@ NSTableCellView* createLoadedItemView(NSTableView* tableView, id owner, id item) CGRect nameFrame = {0}; //get host tasks - // TODO: make this work for files too! + // ->works with dylibs or files + //TODO: make work w/ network connections tasks = [((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator loadedIn:item]; - - //start 'loaded in: ...' str - loadedIn = [NSMutableString stringWithFormat:@"(loaded in:"]; - + + //add dylib indicator + //-> '(dylib, loaded in: ... ' + if(YES == [item isKindOfClass:[Binary class]]) + { + //init + loadedIn = [NSMutableString stringWithFormat:@"(dylib, loaded in:"]; + } + //add file indicator + //-> '(file, loaded in: ... ' + else if(YES == [item isKindOfClass:[File class]]) + { + //init + loadedIn = [NSMutableString stringWithFormat:@"(file, loaded in:"]; + } + //add all tasks for(Task* task in tasks) { @@ -289,6 +302,9 @@ NSTableCellView* createTaskView(NSTableView* tableView, id owner, Task* task) //task's name frame CGRect nameFrame = {0}; + //string for pid + NSString* pidString = nil; + //sanity check if(nil == task.binary) { @@ -349,9 +365,24 @@ NSTableCellView* createTaskView(NSTableView* tableView, id owner, Task* task) // ->should now be exact size of text taskCell.textField.frame = nameFrame; + //init pid string + // ->search mode, show 'task,' to differential between files, etc + if(YES ==[owner isKindOfClass:[SearchWindowController class]]) + { + //init + pidString = [NSString stringWithFormat:@"(task: %@)", task.pid]; + } + //otherwise + // ->just set pid + else + { + //init + pidString = [NSString stringWithFormat:@"(%@)", task.pid]; + } + //set pid // ->immediately follows name - [((NSTextField*)[taskCell viewWithTag:TABLE_ROW_PID_LABEL]) setStringValue:[NSString stringWithFormat:@"(%@)", task.pid]]; + [((NSTextField*)[taskCell viewWithTag:TABLE_ROW_PID_LABEL]) setStringValue:pidString]; //set path [[taskCell viewWithTag:TABLE_ROW_SUB_TEXT_TAG] setStringValue:task.binary.path]; diff --git a/Items/File.m b/Items/File.m index 9e4e7bf..398f382 100644 --- a/Items/File.m +++ b/Items/File.m @@ -29,7 +29,7 @@ if(YES != [[NSFileManager defaultManager] fileExistsAtPath:params[KEY_RESULT_PATH]]) { //err msg - syslog(LOG_ERR, "OBJECTIVE-SEE ERROR: %s not found", [params[KEY_RESULT_PATH] UTF8String]); + //syslog(LOG_ERR, "OBJECTIVE-SEE ERROR: %s not found", [params[KEY_RESULT_PATH] UTF8String]); //set self to nil self = nil; diff --git a/NSApplicationKeyEvents.h b/NSApplicationKeyEvents.h index 88f315b..4a4d321 100644 --- a/NSApplicationKeyEvents.h +++ b/NSApplicationKeyEvents.h @@ -3,7 +3,7 @@ // KnockKnock // // Created by Patrick Wardle on 7/11/15. -// Copyright (c) 2015 Lucas Derraugh. All rights reserved. +// Copyright (c) 2015 Objective-See, LLC. All rights reserved. // #import diff --git a/RequestRootWindowController.m b/RequestRootWindowController.m index 4e23eaf..0f8386f 100644 --- a/RequestRootWindowController.m +++ b/RequestRootWindowController.m @@ -154,8 +154,9 @@ //2nd arg: permissions // ->4 at front is setuid + //TODO: CHANGE B4 RELEASE!! //TODO: make 4755 before deploy (for testing, 777 makes XCOde be able to del it during build!) - installArgs[1] = "4777"; + installArgs[1] = "4755"; //3rd arg: XPC service installArgs[2] = [xpcService UTF8String]; diff --git a/SearchWindowController.h b/SearchWindowController.h index bb378df..1ea844e 100644 --- a/SearchWindowController.h +++ b/SearchWindowController.h @@ -46,21 +46,15 @@ @property (nonatomic, retain)VTInfoWindowController* vtWindowController; //info window controller -@property(retain, nonatomic)InfoWindowController* infoWindowController; +@property(nonatomic, retain)InfoWindowController* infoWindowController; + +//'pls wait' label +@property(nonatomic, retain)NSString* plsWaitMessage; + +//overlay view +@property (weak) IBOutlet NSView *overlayView; -//TODO: remove! -//tasks -@property(nonatomic, retain)NSMutableDictionary* tasks; - -//dylibs -@property(nonatomic, retain)NSMutableDictionary* dylibs; - -//files -@property(nonatomic, retain)NSMutableDictionary* files; - -//connections -@property(nonatomic, retain)NSMutableDictionary* connections; /* METHODS */ diff --git a/SearchWindowController.m b/SearchWindowController.m index c58cc6b..163d2ff 100644 --- a/SearchWindowController.m +++ b/SearchWindowController.m @@ -16,31 +16,29 @@ #import "KKRow.h" #import "Filter.h" #import "Utilities.h" +#import "Consts.h" @implementation SearchWindowController -@synthesize tasks; -@synthesize dylibs; -@synthesize files; -@synthesize connections; @synthesize didInit; -@synthesize searchTable; @synthesize filterObj; -@synthesize searchResults; @synthesize searchBox; +@synthesize overlayView; +@synthesize searchTable; +@synthesize searchResults; +@synthesize plsWaitMessage; @synthesize vtWindowController; @synthesize infoWindowController; -/* + //automatically called when nib is loaded -// ->center window +// ->first time (when outlets aren't nil), init UI -(void)awakeFromNib { //single time init if(YES != self.didInit) { - //TODO: Flaggged Item window, use same logic! //init UI [self initUI]; @@ -50,42 +48,6 @@ return; } -*/ - -//TODO: center window each time? - -/* -//automatically invoked when window is loaded -// ->set to white --(void)windowDidLoad -{ - //super - //[super windowDidLoad]; - - - //TODO: reset searchResults when user clears search box~! - - - //init search data - // ->loads all current tasks, dylibs, files, network conns - //[self initSearchData]; - - //TODO: disable search box till done generating search dicts? - - return; -} -*/ - -//TODO: delete/remove -//automatically invoked when window is closing -// ->make ourselves unmodal --(void)windowWillClose:(NSNotification *)notification -{ - //make un-modal - //[[NSApplication sharedApplication] stopModal]; - - return; -} //init/prepare // ->make sure everything is cleanly init'd before displaying @@ -103,6 +65,38 @@ { //can init UI [self initUI]; + + //set flag + self.didInit = YES; + } + + return; +} + +//automatically invoked when window is un-minimized +// since the progress indicator is stopped/hidden (bug?), restart it +-(void)windowDidDeminiaturize:(NSNotification *)notification +{ + //current time + NSTimeInterval currentTime = 0.0f; + + //grab current time + currentTime = [NSDate timeIntervalSinceReferenceDate]; + + //make sure search is still waiting... + // ->and then restart spinner + if((currentTime - ((AppDelegate*)[[NSApplication sharedApplication] delegate]).startTime) < SEARCH_WAIT_TIME) + { + //update UI on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + + //show + self.activityIndicator.hidden = NO; + + //start spinner + [self.activityIndicator startAnimation:nil]; + + }); } return; @@ -112,6 +106,12 @@ // ->each time window is shown, reset, show spinner if needed, etc -(void)initUI { + //current time + NSTimeInterval currentTime = 0.0f; + + //time left + NSTimeInterval timeRemaining = 0.0f; + //center [self.window center]; @@ -122,9 +122,40 @@ //reset search string [self.searchBox setStringValue:@""]; - //show activity indicator while tasks are still being enumerated - if(YES == ((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator.isEnumerating) + //grab current time + currentTime = [NSDate timeIntervalSinceReferenceDate]; + + //check if search timeout has been hit + // ->when this occur, no need to show activity indicator, etc + if((currentTime - ((AppDelegate*)[[NSApplication sharedApplication] delegate]).startTime) > SEARCH_WAIT_TIME) { + //make search box first responder + [self.window makeFirstResponder:self.searchBox]; + } + //show activity indicator while tasks are still being enumerated + else + { + //calc time remaining + timeRemaining = SEARCH_WAIT_TIME - (currentTime - ((AppDelegate*)[[NSApplication sharedApplication] delegate]).startTime); + + //pre-req + [self.overlayView setWantsLayer:YES]; + + //rounded corners + self.overlayView.layer.cornerRadius = 20.0; + + //maks + self.overlayView.layer.masksToBounds = YES; + + //set overlay's view color to black + self.overlayView.layer.backgroundColor = [NSColor blackColor].CGColor; + + //make it semi-transparent + self.overlayView.alphaValue = 0.20; + + //show overlay + self.overlayView.hidden = NO; + //disable search box self.searchBox.enabled = NO; @@ -137,18 +168,13 @@ //start spinner [self.activityIndicator startAnimation:nil]; + //update w/ time + self.activityIndicatorLabel.stringValue = [NSString stringWithFormat:@"%@ (%d)", PLS_WAIT_MESSAGE, (int)timeRemaining]; + //spin up thread to watch/wait until task enumeration is pau [NSThread detachNewThreadSelector:@selector(waitTillPau) toTarget:self withObject:nil]; } - //can search right now! - else - { - //make search box first responder - [self.window makeFirstResponder:self.searchBox]; - } - - return; } @@ -156,104 +182,54 @@ // ->wait until task enumeration is done, then allow user to search -(void)waitTillPau { + //time left + NSTimeInterval timeRemaining = 0.0f; + + //calc time remaining + timeRemaining = SEARCH_WAIT_TIME - ([NSDate timeIntervalSinceReferenceDate] - ((AppDelegate*)[[NSApplication sharedApplication] delegate]).startTime); + //nap/check/etc - while(YES == ((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator.isEnumerating) + while(timeRemaining > 0.0f) { //nap [NSThread sleepForTimeInterval:1.0f]; - } - - //ughh, don't know exactly how long q-processing will take - // ->so just nap a little longer - [NSThread sleepForTimeInterval:15.0f]; - - //yay all done - // ->hide activity indicator - self.activityIndicator.hidden = YES; - - //hide activity indicator label - self.activityIndicatorLabel.hidden = YES; - - //enable search box - self.searchBox.enabled = YES; - - //make search box first responder - [self.window makeFirstResponder:self.searchBox]; - - return; -} - - -/* - -//init search data -// ->load all tasks/dylibs/files/connections into dictionaries for easy/quick searching --(void)initSearchData:(NSString*)searchString -{ - //alloc task dictionary - tasks = ((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator.tasks; - - //alloc dylibs dictionary - dylibs = [NSMutableDictionary dictionary]; - - //alloc files dictionary - files = [NSMutableDictionary dictionary]; - - //alloc connections dictionary - connections = [NSMutableDictionary dictionary]; - - - /* - //'#' indicates a keyword search - // ->check for keyword match, then filter by keyword - if(YES == [search.string hasPrefix:@"#"]) - { - //ignore #search strings that don't match a keyword - if(YES != [filterObj isKeyword:search.string]) - { - //ignore - goto bail; - } - } - - //filter - [self.filterObj filterTasks:search.string items:self.taskEnumerator.tasks results:self.taskTableController.filteredItems]; - */ - - //process each - // ->add files, tasks, network connections -/* - for(NSNumber* taskPid in tasks) - { - //extract task - task = tasks[taskPid]; - // + //calc time remaining + timeRemaining = SEARCH_WAIT_TIME - ([NSDate timeIntervalSinceReferenceDate] - ((AppDelegate*)[[NSApplication sharedApplication] delegate]).startTime); - } - */ - /* - - return; -} -*/ -/* --(void)search:(NSString*)searchString -{ - //filter object - Filter* filterObj = nil; - - //task - Task* task = nil; - - //init filter obj - filterObj = [[Filter alloc] init]; - - - return; -} -*/ + //update UI on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + + //update w/ time + self.activityIndicatorLabel.stringValue = [NSString stringWithFormat:@"%@ (%d)", PLS_WAIT_MESSAGE, (int)timeRemaining]; + + }); + } + + //update UI on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + + //hide overlay + self.overlayView.hidden = YES; + + //yay all done + // ->hide activity indicator + self.activityIndicator.hidden = YES; + + //hide activity indicator label + self.activityIndicatorLabel.hidden = YES; + + //enable search box + self.searchBox.enabled = YES; + + //make search box first responder + [self.window makeFirstResponder:self.searchBox]; + + }); + + return; +} //table delegate // ->return number of rows @@ -399,10 +375,17 @@ bail: goto bail; } } - + //1st: search for all matching tasks + //sync + @synchronized(allTasks) + { + + //search for all matching tasks [self.filterObj filterTasks:searchString items:allTasks results:matchingTasks]; + }//sync + //add all tasks [self.searchResults addObjectsFromArray:matchingTasks]; diff --git a/Task.h b/Task.h index f4a9a19..958b8db 100644 --- a/Task.h +++ b/Task.h @@ -3,7 +3,7 @@ // TaskExplorer // // Created by Patrick Wardle on 5/2/15. -// Copyright (c) 2015 Lucas Derraugh. All rights reserved. +// Copyright (c) 2015 Objective-See, LLC. All rights reserved. // #import "Binary.h" diff --git a/Task.m b/Task.m index 76ec424..fc7e8d8 100644 --- a/Task.m +++ b/Task.m @@ -3,7 +3,7 @@ // TaskExplorer // // Created by Patrick Wardle on 5/2/15. -// Copyright (c) 2015 Lucas Derraugh. All rights reserved. +// Copyright (c) 2015 Objective-See, LLC. All rights reserved. // #import "Task.h" @@ -317,17 +317,17 @@ bail: //alloc array for new dylibs newDylibs = [NSMutableArray array]; - //sync - @synchronized(self.dylibs) - { - //reset existing dylibs - [self.dylibs removeAllObjects]; - } - //invoke XPC service (running as r00t) // ->will enumerate dylibs, then invoke reply block to save into iVar [[xpcConnection remoteObjectProxy] enumerateDylibs:self.pid withReply:^(NSMutableArray* dylibPaths) { + //sync + @synchronized(self.dylibs) + { + + //reset existing dylibs + [self.dylibs removeAllObjects]; + //add all dylibs for(NSString* dylibPath in dylibPaths) { @@ -381,30 +381,24 @@ bail: } } - //sync - @synchronized(self.dylibs) - { - //add to task's dylibs - [self.dylibs addObject:dylib]; - } - + //add to task's dylibs + [self.dylibs addObject:dylib]; + } //all dylibs - //sync to sort - @synchronized(self.dylibs) + //sort by name + self.dylibs = [[self.dylibs sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { - //sort by name - self.dylibs = [[self.dylibs sortedArrayUsingComparator:^NSComparisonResult(id a, id b) - { - //sort - return [[(Binary*)a name] compare:[(Binary*)b name] options:NSCaseInsensitiveSearch]; - - }] mutableCopy]; - } + //sort + return [[(Binary*)a name] compare:[(Binary*)b name] options:NSCaseInsensitiveSearch]; + + }] mutableCopy]; //reload bottom pane now // ->this will only reload if new task is the currently selected one, etc [((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadBottomPane:self itemView:DYLIBS_VIEW]; + + }//sync //complete dylib processing for new dylib // ->get signing info, hash, etc, & save into global list @@ -445,17 +439,17 @@ bail: //alloc array for new files newFiles = [NSMutableArray array]; - //sync - @synchronized(self.files) - { - //reset existing files - [self.files removeAllObjects]; - } - //invoke XPC service (running as r00t) // ->will enumerate files, then invoke reply block so can save into iVar [[xpcConnection remoteObjectProxy] enumerateFiles:self.pid withReply:^(NSMutableArray* fileDescriptors) { + //sync + @synchronized(self.files) + { + + //reset existing files + [self.files removeAllObjects]; + //create/add all files for(NSMutableDictionary* fileDescriptor in fileDescriptors) { @@ -489,20 +483,18 @@ bail: } } - //sync to sort - @synchronized(self.files) + //sort by name + self.files = [[self.files sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { - //sort by name - self.files = [[self.files sortedArrayUsingComparator:^NSComparisonResult(id a, id b) - { - //sort - return [[(File*)a name] compare:[(File*)b name] options:NSCaseInsensitiveSearch]; - - }] mutableCopy]; - } + //sort + return [[(File*)a name] compare:[(File*)b name] options:NSCaseInsensitiveSearch]; + + }] mutableCopy]; //reload bottom pane [((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadBottomPane:self itemView:FILES_VIEW]; + + }//sync //process all new files // ->calculate hash, etc & save into global list @@ -529,15 +521,16 @@ bail: //File object __block Connection* connection = nil; - //remove any existing enum'd networking sockets/connections - [self.connections removeAllObjects]; - - //dbg msg - //NSLog(@"invoking XPC to enumer networking"); - //invoke XPC service (running as r00t) // ->will enumerate network sockets/connections, then invoke reply block so can save into iVar [[xpcConnection remoteObjectProxy] enumerateNetwork:self.pid withReply:^(NSMutableArray* networkItems) { + + //sync + @synchronized(self.connections) + { + + //remove any existing enum'd networking sockets/connections + [self.connections removeAllObjects]; // //NSLog(@"found %d connections", networkItems.count); @@ -558,6 +551,9 @@ bail: //reload bottom pane [((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadBottomPane:self itemView:NETWORKING_VIEW]; + + }//sync + }]; return; diff --git a/TaskEnumerator.h b/TaskEnumerator.h index 3963a10..df6aa35 100644 --- a/TaskEnumerator.h +++ b/TaskEnumerator.h @@ -35,10 +35,6 @@ // ->contains binaries that should be processed @property (nonatomic, retain) Queue* binaryQueue; -//flag indicating tasks (and thus files/dylibs/etc) are being queried -@property BOOL isEnumerating; - - /* METHODS */ //enumerate all tasks diff --git a/TaskEnumerator.m b/TaskEnumerator.m index 1315546..548da4d 100644 --- a/TaskEnumerator.m +++ b/TaskEnumerator.m @@ -22,14 +22,11 @@ @implementation TaskEnumerator - @synthesize files; @synthesize tasks; @synthesize dylibs; @synthesize binaryQueue; @synthesize executables; -@synthesize isEnumerating; - //init -(id)init @@ -73,10 +70,7 @@ //xpc connection NSXPCConnection* xpcConnection = nil; - - //set flag - self.isEnumerating = YES; - + //determine if network is connected // ->sets 'isConnected' flag ((AppDelegate*)[[NSApplication sharedApplication] delegate]).isConnected = isNetworkConnected(); @@ -203,9 +197,6 @@ //TODO: add network connection filtering - //all done! - self.isEnumerating = NO; - return; } diff --git a/TaskExplorer-Info.plist b/TaskExplorer-Info.plist index 06c5280..1e89437 100755 --- a/TaskExplorer-Info.plist +++ b/TaskExplorer-Info.plist @@ -17,11 +17,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0.1 + 1.1.0 CFBundleSignature ???? CFBundleVersion - 1.0.1 + 1.1.0 LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} NSHumanReadableCopyright diff --git a/TaskExplorer.xcodeproj/project.xcworkspace/xcuserdata/patrickw.xcuserdatad/UserInterfaceState.xcuserstate b/TaskExplorer.xcodeproj/project.xcworkspace/xcuserdata/patrickw.xcuserdatad/UserInterfaceState.xcuserstate index 6870862..10eec8c 100644 Binary files a/TaskExplorer.xcodeproj/project.xcworkspace/xcuserdata/patrickw.xcuserdatad/UserInterfaceState.xcuserstate and b/TaskExplorer.xcodeproj/project.xcworkspace/xcuserdata/patrickw.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/TaskExplorer.xcodeproj/xcuserdata/patrickw.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/TaskExplorer.xcodeproj/xcuserdata/patrickw.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index e5da73d..ce427b5 100644 --- a/TaskExplorer.xcodeproj/xcuserdata/patrickw.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/TaskExplorer.xcodeproj/xcuserdata/patrickw.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -6,7 +6,7 @@ @@ -74,11 +74,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "ItemView.m" - timestampString = "461741382.460449" + timestampString = "462061810.500141" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "191" - endingLineNumber = "191" + startingLineNumber = "267" + endingLineNumber = "267" landmarkName = "createLoadedItemView()" landmarkType = "7"> @@ -89,14 +89,14 @@ shouldBeEnabled = "No" ignoreCount = "0" continueAfterRunningActions = "No" - filePath = "ItemView.m" - timestampString = "461741382.460449" + filePath = "AppDelegate.m" + timestampString = "462091427.171131" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "213" - endingLineNumber = "213" - landmarkName = "createLoadedItemView()" - landmarkType = "7"> + startingLineNumber = "1593" + endingLineNumber = "1593" + landmarkName = "-refreshTasks:" + landmarkType = "5"> + startingLineNumber = "323" + endingLineNumber = "323" + landmarkName = "-refresh" + landmarkType = "5"> + + + + + + + + + + + + + + + + + + + + diff --git a/TaskExplorer.xcodeproj/xcuserdata/patrickw.xcuserdatad/xcschemes/TaskExplorer.xcscheme b/TaskExplorer.xcodeproj/xcuserdata/patrickw.xcuserdatad/xcschemes/TaskExplorer.xcscheme index ee52d29..8d3ff25 100644 --- a/TaskExplorer.xcodeproj/xcuserdata/patrickw.xcuserdatad/xcschemes/TaskExplorer.xcscheme +++ b/TaskExplorer.xcodeproj/xcuserdata/patrickw.xcuserdatad/xcschemes/TaskExplorer.xcscheme @@ -59,6 +59,26 @@ + + + + + + + + - + diff --git a/UI/FlaggedItems.xib b/UI/FlaggedItems.xib index 479a8f9..fd25648 100644 --- a/UI/FlaggedItems.xib +++ b/UI/FlaggedItems.xib @@ -17,7 +17,7 @@ - + diff --git a/UI/SearchWindow.xib b/UI/SearchWindow.xib index 5b4ad8b..020d610 100644 --- a/UI/SearchWindow.xib +++ b/UI/SearchWindow.xib @@ -9,6 +9,7 @@ + @@ -241,7 +242,7 @@ - + @@ -292,6 +293,7 @@ + @@ -401,13 +403,16 @@ + + + -