From 51be8da95e070fd63dabf9484da7e1aab00605e0 Mon Sep 17 00:00:00 2001 From: Patrick Wardle Date: Sat, 27 Jun 2015 17:49:31 -1000 Subject: [PATCH] fixed info views removed args from dylib view increased size for signing added file type (via 'file' cmd) to non-binary files added extra logic to handle filtering VT reload is row-only (no more full table!) --- 3rdParty/OrderedDictionary.h | 5 + 3rdParty/OrderedDictionary.m | 1 + AppDelegate.h | 8 +- AppDelegate.m | 217 +++++++++--------- InfoWindowController.h | 7 +- InfoWindowController.m | 101 ++++---- Items/File.h | 29 +-- Items/File.m | 122 +++++----- Queue.m | 3 +- Task.m | 24 +- TaskEnumerator.m | 10 +- .../xcdebugger/Breakpoints_v2.xcbkptlist | 212 +++++++++++------ TaskTableController.m | 3 +- UI/DylibInfoWindow.xib | 33 +-- UI/FileInfoWindow.xib | 96 +++----- UI/TaskInfoWindow.xib | 64 +++--- VirusTotal.m | 54 +---- en.lproj/MainMenu.xib | 62 ++--- remoteTaskService/remoteTaskService.m | 2 +- 19 files changed, 525 insertions(+), 528 deletions(-) diff --git a/3rdParty/OrderedDictionary.h b/3rdParty/OrderedDictionary.h index 506d17d..66e14cb 100644 --- a/3rdParty/OrderedDictionary.h +++ b/3rdParty/OrderedDictionary.h @@ -29,7 +29,10 @@ NSMutableArray *array; } +/* PROPERTIES */ +//@property(nonatomic, retain)NSMutableArray *array; +/* METHODS */ - (void)insertObject:(id)anObject forKey:(id)aKey atIndex:(NSUInteger)anIndex; - (id)keyAtIndex:(NSUInteger)anIndex; - (NSUInteger)indexOfKey:(id)aKey; @@ -40,4 +43,6 @@ // ->by pid, name, etc -(void)sort:(NSUInteger)sortBy; + + @end diff --git a/3rdParty/OrderedDictionary.m b/3rdParty/OrderedDictionary.m index df700b4..15aabb1 100644 --- a/3rdParty/OrderedDictionary.m +++ b/3rdParty/OrderedDictionary.m @@ -24,6 +24,7 @@ #import "Consts.h" #import "OrderedDictionary.h" + NSString *DescriptionForObject(NSObject *object, id locale, NSUInteger indent) { NSString *objectString; diff --git a/AppDelegate.h b/AppDelegate.h index 90fbd43..390dcbb 100755 --- a/AppDelegate.h +++ b/AppDelegate.h @@ -129,9 +129,6 @@ // ->provide mouse over effects -(void)initTrackingAreas; -//callback method, invoked by virus total when plugin's items have been processed -// ->reload table if plugin matches active plugin -//-(void)itemsProcessed:(PluginBase*)plugin; //callback when user has updated prefs @@ -164,7 +161,7 @@ @property (weak) IBOutlet NSTextField *versionString; //reload (to re-draw) a specific row in table --(void)reloadRow:(Task*)task item:(ItemBase*)item pane:(NSUInteger)pane; +-(void)reloadRow:(id)item; //reload task table -(void)reloadTaskTable; @@ -183,5 +180,8 @@ //filter tasks -(void)filterTasks:(NSString*)filterText; +//VT callback to reload a binary +-(void)reloadBinary:(Binary*)binary; + @end diff --git a/AppDelegate.m b/AppDelegate.m index 7ecf9b0..753dcc4 100755 --- a/AppDelegate.m +++ b/AppDelegate.m @@ -16,13 +16,9 @@ #import "Task.h" //TODO: bottom pane's progress indicator: center via autolayout -//TODO: fix bottom icons -//TODO: dylib info view, don't show args -//TODO: SHA1 is NULL -//TODO: Time is NULL -//TODO: Software signing is too long (goes into 'close' buttom -//TODO: only update task row(s) on Task VT result! not full table -//TODO: full VT queue!! +//TODO: full VT queue!! - flush +//TODO: on filter, reset scanning for bottom item (hideDylib) +//TODO: network info window @implementation AppDelegate @@ -44,7 +40,6 @@ @synthesize scannerThread; @synthesize versionString; @synthesize progressIndicator; -//@synthesize filterObj; @synthesize topPane; @synthesize taskEnumerator; @@ -360,54 +355,46 @@ return; } -//reload (to re-draw) a specific row in table --(void)reloadRow:(Task*)task item:(ItemBase*)item pane:(NSUInteger)pane +//smartly reload a specific row in table +// ->arg determines pane (top/bottom) and for bottom pane, the active view the item belongs to +-(void)reloadRow:(id)item; { - //item's task - // ->will use current task if task arg is nil - __block Task* itemTask = nil; - //table view __block NSTableView* tableView = nil; //row __block NSUInteger row = 0; - //segment (for bottom pane - __block NSUInteger segmentTag = 0; - //run everything on main thread // ->ensures table view isn't changed out from under us.... dispatch_async(dispatch_get_main_queue(), ^{ - - //get item's task - // ->use passed in task if non-nil - if(nil != itemTask) - { - //set - itemTask = task; - } - //passed in task is nil - // ->use currently selected one - else - { - //set - itemTask = self.currentTask; - } - + //top table (pane) - if(PANE_TOP == pane) + if(YES == [item isKindOfClass:[Task class]]) { //top table view tableView = [((id)self.taskTableController) itemView]; - //reloadItem + //reload item // ->flat view if(YES != [tableView isKindOfClass:[NSOutlineView class]]) { - //get index where task is - // TODO: doesn't account for filtering, etc!!! - row = [self.taskEnumerator.tasks indexOfKey:itemTask.pid]; + //no filtering + // ->grab row from all tasks + if(YES != self.taskTableController.isFiltered) + { + //get row + row = [self.taskEnumerator.tasks indexOfKey:((Task*)item).pid]; + } + //filtering + // ->grab row from filtered tasks + else + { + //get row + row = [self.taskTableController.filteredItems indexOfObject:item]; + } + + //sanity check if(NSNotFound == row) { //bail @@ -425,20 +412,18 @@ } //reload item - // ->tree view + // ->tree view, so no need to worry about filtering else { //begin updates [tableView beginUpdates]; //reload - [(NSOutlineView*)tableView reloadItem:itemTask]; + [(NSOutlineView*)tableView reloadItem:item]; //end updates [tableView endUpdates]; } - - } //bottom pane else @@ -446,73 +431,21 @@ //bottom table view tableView = [((id)self.bottomViewController) itemView]; - //get segment tag - segmentTag = [[self.bottomPaneBtn selectedCell] tagForSegment:[self.bottomPaneBtn selectedSegment]]; - - //get item - // ->will bail if item isn't in (current) view, etc - switch(segmentTag) + //no filtering + // ->grab row from all items + if(YES != self.bottomViewController.isFiltered) { - //dylibs - case DYLIBS_VIEW: - - //make sure item class/type matches current view - if(YES != [item isKindOfClass:[Binary class]]) - { - //bail - goto bail; - } - - //sync - @synchronized(itemTask.dylibs) - { - //get row - row = [itemTask.dylibs indexOfObject:item]; - } - - break; - - //files - case FILES_VIEW: - - //make sure item class/type matches current view - if(YES != [item isKindOfClass:[File class]]) - { - //bail - goto bail; - } - - //sync - @synchronized(itemTask.files) - { - //get row - row = [itemTask.files indexOfObject:item]; - } - - break; - - //networking - case NETWORKING_VIEW: - - //make sure item class/type matches current view - if(YES != [item isKindOfClass:[Connection class]]) - { - //bail - goto bail; - } - //sync - @synchronized(itemTask.connections) - { - //get row - row = [itemTask.connections indexOfObject:item]; - } - - break; - - default: - break; + //get row + row = [self.bottomViewController.tableItems indexOfObject:item]; } - + //filtering + // ->grab row from filtered item + else + { + //get row + row = [self.bottomViewController.filteredItems indexOfObject:item]; + } + //make sure item was found if(NSNotFound == row) { @@ -520,7 +453,6 @@ goto bail; } - //begin updates [tableView beginUpdates]; @@ -529,7 +461,8 @@ //end updates [tableView endUpdates]; - } + + }//bottom pane //bail bail: @@ -641,6 +574,72 @@ bail: return; } +//VT callback to reload a binary +// ->task binary: reload all instances that match in top pane +// dylib: reload row if dylib is loaded in current/selected task +-(void)reloadBinary:(Binary*)binary +{ + //all tasks + OrderedDictionary* tasks = nil; + + //task + Task* task = nil; + + //task binary + // ->reload all instances that match in top pane + if(YES == binary.isTaskBinary) + { + //when not filtered + // ->use all tasks + if(YES != self.taskTableController.isFiltered) + { + //TODO: sync? + + //get tasks + tasks = self.taskEnumerator.tasks; + for(NSNumber* taskPid in tasks) + { + //extract task + task = tasks[taskPid]; + + //check for match + if(task.binary == binary) + { + //reload + [self reloadRow:task]; + } + } + } + //when filtered + // ->use filtered items + else + { + //filtered items + for(Task* task in self.taskTableController.filteredItems) + { + //check for match + if(task.binary == binary) + { + //reload + [self reloadRow:task]; + } + } + } + + + }//top pane + + //bottom pane + // ->can just invoke 'reloadRow' method (which has logic to handle filtering, ignoring 'not found' items, etc. + else + { + //reload + [self reloadRow:binary]; + } + + return; +} + //display alert about OS not being supported -(void)showUnsupportedAlert { diff --git a/InfoWindowController.h b/InfoWindowController.h index ffb789c..e175601 100644 --- a/InfoWindowController.h +++ b/InfoWindowController.h @@ -27,17 +27,18 @@ @property (weak) IBOutlet NSTextField *arguments; + //file window specific outlets @property(weak)IBOutlet NSTextField *hashes; @property(weak)IBOutlet NSTextField *size; @property(weak)IBOutlet NSTextField *sign; +//file window specific outlets +@property (weak) IBOutlet NSTextField *type; + @property (weak) IBOutlet NSTextField *plist; -//extension window specific outlets -@property (weak) IBOutlet NSTextField *details; -@property (weak) IBOutlet NSTextField *identifier; //window controller @property(nonatomic, strong)InfoWindowController *windowController; diff --git a/InfoWindowController.m b/InfoWindowController.m index af2298a..70426e6 100644 --- a/InfoWindowController.m +++ b/InfoWindowController.m @@ -54,6 +54,14 @@ //load nib self.windowController = [[InfoWindowController alloc] initWithWindowNibName:@"DylibInfoWindow"]; } + //load file info window + else if(YES == [selectedItem isKindOfClass:[File class]]) + { + //load nib + self.windowController = [[InfoWindowController alloc] initWithWindowNibName:@"FileInfoWindow"]; + } + + //TODO: file && network info view /*TODO: delete this and xibs? @@ -102,6 +110,10 @@ // ->when showing info about a dylib Binary* dylib = nil; + //file + // ->when showing info about a file + File* file = nil; + //handle tasks if(YES == [self.itemObj isKindOfClass:[Task class]]) { @@ -139,6 +151,13 @@ //set path [self.path setStringValue:[self valueForStringItem:task.binary.path default:@"unknown"]]; + //hashes could still be, being generated + // ->but don't want to wait, so just created em directly + if(nil == task.binary.hashes[KEY_HASH_MD5]) + { + //save hash + task.binary.hashes = hashFile(task.binary.path); + } //set hash [self.hashes setStringValue:[NSString stringWithFormat:@"%@ / %@", task.binary.hashes[KEY_HASH_MD5], task.binary.hashes[KEY_HASH_SHA1]]]; @@ -149,11 +168,19 @@ //set date [self.date setStringValue:[NSString stringWithFormat:@"%@ (created) / %@ (modified)", task.binary.attributes.fileCreationDate, task.binary.attributes.fileModificationDate]]; + //signing info still being generated? + // ->but don't want to wait, so just created em directly + if(nil == task.binary.signingInfo) + { + //generate signing info + task.binary.signingInfo = extractSigningInfo(task.binary.path); + } + //set signing info [self.sign setStringValue:[self valueForStringItem:[task.binary formatSigningInfo] default:@"not signed"]]; } - //handle tasks + //handle binaries else if(YES == [self.itemObj isKindOfClass:[Binary class]]) { //type cast @@ -165,7 +192,7 @@ //set name [self.name setStringValue:[self valueForStringItem:dylib.name default:@"unknown"]]; - + //TODO: enable?! /* //flagged files // ->make name red! @@ -180,70 +207,66 @@ //set path [self.path setStringValue:[self valueForStringItem:dylib.path default:@"unknown"]]; + //hashes still being generated? + // ->but don't want to wait, so just created em directly + if(nil == dylib.hashes[KEY_HASH_MD5]) + { + //save hash + dylib.hashes = hashFile(dylib.path); + } //set hash - [self.hashes setStringValue:[NSString stringWithFormat:@"%@ / %@", dylib.hashes[KEY_HASH_MD5], task.binary.hashes[KEY_HASH_SHA1]]]; + [self.hashes setStringValue:[NSString stringWithFormat:@"%@ / %@", dylib.hashes[KEY_HASH_MD5], dylib.hashes[KEY_HASH_SHA1]]]; //set size [self.size setStringValue:[NSString stringWithFormat:@"%llu bytes", dylib.attributes.fileSize]]; //set date - [self.date setStringValue:[NSString stringWithFormat:@"%@ (created) / %@ (modified)", dylib.attributes.fileCreationDate, task.binary.attributes.fileModificationDate]]; + [self.date setStringValue:[NSString stringWithFormat:@"%@ (created) / %@ (modified)", dylib.attributes.fileCreationDate, dylib.attributes.fileModificationDate]]; + + //signing info still being generated? + // ->but don't want to wait, so just created em directly + if(nil == dylib.signingInfo) + { + //generate signing info + dylib.signingInfo = extractSigningInfo(dylib.path); + } //set signing info [self.sign setStringValue:[self valueForStringItem:[dylib formatSigningInfo] default:@"not signed"]]; } - //handle File class else if(YES == [self.itemObj isKindOfClass:[File class]]) { + //typecast + file = (File*)self.itemObj; + + //first check if detailed info (such as 'type') was generated yet + // ->when not, do it directly here + if(nil == file.type) + { + //generated detailed info + [file generateDetailedInfo]; + } + //set icon - self.icon.image = getIconForBinary(self.itemObj.path, ((File*)itemObj).bundle); + self.icon.image = itemObj.icon; //set name [self.name setStringValue:self.itemObj.name]; - /* - - //flagged files - // ->make name red! - if( (nil != ((Binary*)self.itemObj).vtInfo) && - (0 != [((File*)self.itemObj).vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue]) ) - { - //set color (light red) - self.name.textColor = [NSColor redColor]; - } - - */ - //set path [self.path setStringValue:self.itemObj.path]; - //set hash - [self.hashes setStringValue:[NSString stringWithFormat:@"%@ / %@", ((File*)self.itemObj).hashes[KEY_HASH_MD5], ((File*)self.itemObj).hashes[KEY_HASH_SHA1]]]; + //set type + [self.type setStringValue:[self valueForStringItem:((File*)self.itemObj).type default:@"unknown"]]; //set size - [self.size setStringValue:[NSString stringWithFormat:@"%llu bytes", ((File*)self.itemObj).attributes.fileSize]]; + [self.size setStringValue:[NSString stringWithFormat:@"%llu bytes", self.itemObj.attributes.fileSize]]; //set date - [self.date setStringValue:[NSString stringWithFormat:@"%@ (created) / %@ (modified)", ((File*)self.itemObj).attributes.fileCreationDate, ((File*)self.itemObj).attributes.fileModificationDate]]; - - //set plist - if(nil != ((File*)self.itemObj).plist) - { - //set - [self.plist setStringValue:((File*)self.itemObj).plist]; - } - //no plist - else - { - //set - [self.plist setStringValue:@"no plist for item"]; - } - - //set signing info - [self.sign setStringValue:[(File*)self.itemObj formatSigningInfo]]; + [self.date setStringValue:[NSString stringWithFormat:@"%@ (created) / %@ (modified)", self.itemObj.attributes.fileCreationDate, self.itemObj.attributes.fileModificationDate]]; } /* diff --git a/Items/File.h b/Items/File.h index a91f529..1d4d01b 100644 --- a/Items/File.h +++ b/Items/File.h @@ -9,7 +9,7 @@ #import "ItemBase.h" #import -#import + @interface File : ItemBase { @@ -18,25 +18,8 @@ /* PROPERTIES */ -//name -@property(nonatomic, retain)NSString* name; - -//path -@property(nonatomic, retain)NSString* path; - -//plist -@property(nonatomic, retain)NSString* plist; - -//bundle -@property(nonatomic, retain)NSBundle* bundle; - -//hashes (md5, sha1) -@property(nonatomic, retain)NSDictionary* hashes; - -//signing info -@property(nonatomic, retain)NSDictionary* signingInfo; - - +//type +@property(nonatomic, retain)NSString* type; /* METHODS */ @@ -48,8 +31,10 @@ // ->only shown to user if they click 'info' so this method is called in the background -(void)generateDetailedInfo; -//format the signing info dictionary --(NSString*)formatSigningInfo; +//set file type +// ->invokes 'file' cmd, the parses out result +-(void)setFileType; + @end diff --git a/Items/File.m b/Items/File.m index a7b0c2a..78a22a8 100644 --- a/Items/File.m +++ b/Items/File.m @@ -14,19 +14,13 @@ @implementation File -@synthesize path; -@synthesize name; -@synthesize plist; -@synthesize bundle; -@synthesize hashes; -@synthesize signingInfo; - -//@synthesize vtInfo; +@synthesize type; //init method -(id)initWithParams:(NSDictionary*)params { + //TODO: why care if dir? //flag for directories BOOL isDirectory = NO; @@ -49,46 +43,15 @@ goto bail; } - //if path is directory - // ->treat is as a bundle - if(YES == isDirectory) - { - //load bundle - // ->save this into 'bundle' iVar - if(nil == (bundle = [NSBundle bundleWithPath:params[KEY_RESULT_PATH]])) - { - //err msg - NSLog(@"OBJECTIVE-SEE ERROR: couldn't create bundle for %@", params[KEY_RESULT_PATH]); - - //set self to nil - self = nil; - - //bail - goto bail; - } - - //extract executable from bundle - // ->save this into 'path' iVar - if(nil == (self.path = self.bundle.executablePath)) - { - //err msg - //NSLog(@"OBJECTIVE-SEE ERROR: couldn't find executable in bundle %@", itemPath); - - //set self to nil - self = nil; - - //bail - goto bail; - } - } - - //save (optional) plist - // ->ok if this is nil - self.plist = params[KEY_RESULT_PLIST]; - //extract name self.name = [[self.path lastPathComponent] stringByDeletingPathExtension]; + + //set icon + self.icon = [[NSWorkspace sharedWorkspace] iconForFile:self.path]; + //grab attributes + self.attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:self.path error:nil]; + } //bail @@ -97,21 +60,62 @@ bail: return self; } +//set file type +// ->invokes 'file' cmd, the parses out result +-(void)setFileType +{ + //results from 'file' cmd + NSString* results = nil; + + //array of parsed results + NSArray* parsedResults = nil; + + //exec 'file' to get file type + results = [[NSString alloc] initWithData:execTask(@"/usr/bin/file", @[self.path]) encoding:NSUTF8StringEncoding]; + + //sanity check + if(nil == results) + { + //bail + goto bail; + } + + //parse results + // ->format: : + parsedResults = [results componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@":\n"]]; + + //sanity check + // ->should be two items in array, and + if(parsedResults.count < 2) + { + //bail + goto bail; + } + + //file type comes second + // ->also trim whitespace + self.type = [parsedResults[1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + +//bail +bail: + ; + + + return; +} + + //get detailed info (which takes a while to generate) // ->only shown to user if they click 'info' so this method is called in the background -(void)generateDetailedInfo { - //grab attributes - //TODO: done elsewhere? - self.attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:self.path error:nil]; - - //computes hashes - // ->set 'md5' and 'sha1' iVars - self.hashes = hashFile(self.path); + //set type + [self setFileType]; return; } + //convert object to JSON string -(NSString*)toJSON { @@ -120,25 +124,26 @@ bail: //json data // ->for intermediate conversions - NSData *jsonData = nil; + //NSData *jsonData = nil; //plist NSString* filePlist = nil; //hashes - NSString* fileHashes = nil; + //NSString* fileHashes = nil; //signing info - NSString* fileSigs = nil; + //NSString* fileSigs = nil; //init file hash to default string // ->used when hashes are nil, or serialization fails - fileHashes = @"\"unknown\""; + //fileHashes = @"\"unknown\""; //init file signature to default string // ->used when signatures are nil, or serialization fails - fileSigs = @"\"unknown\""; + //fileSigs = @"\"unknown\""; + /* //convert hashes to JSON if(nil != self.hashes) { @@ -201,8 +206,11 @@ bail: //init VT detection ratio //vtDetectionRatio = [NSString stringWithFormat:@"%lu/%lu", (unsigned long)[self.vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue], (unsigned long)[self.vtInfo[VT_RESULTS_TOTAL] unsignedIntegerValue]]; + //init json json = [NSString stringWithFormat:@"\"name\": \"%@\", \"path\": \"%@\", \"plist\": \"%@\", \"hashes\": %@, \"signature(s)\": %@", self.name, self.path, filePlist, fileHashes, fileSigs]; + + */ return json; } diff --git a/Queue.m b/Queue.m index 6e36b85..752aa5e 100644 --- a/Queue.m +++ b/Queue.m @@ -35,7 +35,6 @@ //start it [self.qProcessorThread start]; - } return self; @@ -86,7 +85,7 @@ //process //->for now, just hash, etc [binary generateDetailedInfo]; - + //add item for VT processing [vtObject addItem:binary]; diff --git a/Task.m b/Task.m index 99cda40..501332e 100644 --- a/Task.m +++ b/Task.m @@ -399,6 +399,7 @@ bail: //add to task's dylibs [self.dylibs addObject:dylib]; } + } //all dylibs //sync to sort @@ -417,29 +418,30 @@ bail: // ->this will only reload if new task is the currently selected one, etc [((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadBottomPane:self itemView:DYLIBS_VIEW]; - //complete dylib processing + //complete dylib processing for new dylib // ->get signing info, hash, etc, & save into global list + // ...reloads each row (if task is stil current) for(Binary* newDylib in newDylibs) { //generate signing info [newDylib generatedSigningInfo]; + + //no need to reload if task is now longer current/selected + if(((AppDelegate*)[[NSApplication sharedApplication] delegate]).currentTask != self) + { + //skip reload + continue; + } + + //reload row + [((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadRow:newDylib]; } - //any new dylibs? - // ->reload bottom pane to update signing info, etc - if(0 != newDylibs.count) - { - //reload - [((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadBottomPane:self itemView:DYLIBS_VIEW]; - } - }]; return; } - - //enumerate all file descriptors -(void)enumerateFiles:(NSXPCConnection*)xpcConnection { diff --git a/TaskEnumerator.m b/TaskEnumerator.m index 613c81f..ae4dfa7 100644 --- a/TaskEnumerator.m +++ b/TaskEnumerator.m @@ -154,11 +154,19 @@ //get task newTask = newTasks[key]; + //don't need to regerate signing info if its already there + // ->e.g. task is just another instance of the same binary + if(nil != newTask.binary.signingInfo) + { + //skip + continue; + } + //generate signing info [newTask.binary generatedSigningInfo]; //reload task (row) in table - [((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadRow:newTask item:newTask.binary pane:PANE_TOP]; + [((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadRow:newTask]; //reload bottom pane // ->this will only reload if new task is the currently selected one, etc diff --git a/TaskExplorer.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/TaskExplorer.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index d1f802f..33fa188 100644 --- a/TaskExplorer.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/TaskExplorer.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -20,11 +20,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "TaskEnumerator.m" - timestampString = "456903878.108936" + timestampString = "457149043.732031" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "348" - endingLineNumber = "348" + startingLineNumber = "356" + endingLineNumber = "356" landmarkName = "-removeTask:" landmarkType = "5"> @@ -36,11 +36,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "AppDelegate.m" - timestampString = "456993845.79535" + timestampString = "457155963.943682" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "771" - endingLineNumber = "771" + startingLineNumber = "775" + endingLineNumber = "775" landmarkName = "-reloadTaskTable" landmarkType = "5"> @@ -116,7 +116,7 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "AppDelegate.m" - timestampString = "456992198.722928" + timestampString = "457149043.732031" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" startingLineNumber = "320" @@ -167,22 +167,6 @@ landmarkType = "5"> - - - - @@ -206,11 +190,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "AppDelegate.m" - timestampString = "456993845.79535" + timestampString = "457155963.943682" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "559" - endingLineNumber = "559" + startingLineNumber = "497" + endingLineNumber = "497" landmarkName = "-reloadBottomPane:itemView:" landmarkType = "5"> @@ -311,22 +295,6 @@ landmarkType = "5"> - - - - @@ -366,11 +334,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "AppDelegate.m" - timestampString = "456993845.79535" + timestampString = "457155963.943682" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "1464" - endingLineNumber = "1464" + startingLineNumber = "1468" + endingLineNumber = "1468" landmarkName = "-selectBottomPaneContent:" landmarkType = "5"> @@ -382,7 +350,23 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "AppDelegate.m" - timestampString = "456993845.79535" + timestampString = "457155963.943682" + startingColumnNumber = "9223372036854775807" + endingColumnNumber = "9223372036854775807" + startingLineNumber = "1460" + endingLineNumber = "1460" + landmarkName = "-switchView:" + landmarkType = "5"> + + + + - - - - @@ -446,11 +414,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "AppDelegate.m" - timestampString = "456994072.431204" + timestampString = "457155963.943682" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "1647" - endingLineNumber = "1647" + startingLineNumber = "1651" + endingLineNumber = "1651" landmarkName = "-controlTextDidChange:" landmarkType = "5"> @@ -471,5 +439,101 @@ landmarkType = "5"> + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TaskTableController.m b/TaskTableController.m index ae147c7..085fef8 100644 --- a/TaskTableController.m +++ b/TaskTableController.m @@ -1361,10 +1361,9 @@ bail: //bail bail: - + ; return; - } diff --git a/UI/DylibInfoWindow.xib b/UI/DylibInfoWindow.xib index a7f96d1..7bcc830 100644 --- a/UI/DylibInfoWindow.xib +++ b/UI/DylibInfoWindow.xib @@ -7,7 +7,6 @@ - @@ -45,7 +44,7 @@ - + @@ -53,7 +52,7 @@ - + @@ -61,7 +60,7 @@ - + @@ -69,7 +68,7 @@ - + @@ -77,7 +76,7 @@ - + @@ -85,7 +84,7 @@ - + @@ -93,7 +92,7 @@ - + @@ -101,7 +100,7 @@ - + @@ -128,22 +127,6 @@ - - - - - - - - - - - - - - - - diff --git a/UI/FileInfoWindow.xib b/UI/FileInfoWindow.xib index 15b412e..c2f57ea 100644 --- a/UI/FileInfoWindow.xib +++ b/UI/FileInfoWindow.xib @@ -1,20 +1,18 @@ - + - + - - - + @@ -22,14 +20,14 @@ - + - + - + @@ -37,31 +35,15 @@ - + - - - - - - - - - - - - - - - - - + @@ -69,31 +51,15 @@ - + - - - - - - - - - - - - - - - - - + @@ -101,41 +67,25 @@ - + - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + - + diff --git a/UI/TaskInfoWindow.xib b/UI/TaskInfoWindow.xib index d78588e..ada1991 100644 --- a/UI/TaskInfoWindow.xib +++ b/UI/TaskInfoWindow.xib @@ -22,14 +22,14 @@ - + - + - + @@ -37,7 +37,7 @@ - + @@ -45,7 +45,7 @@ - + @@ -53,7 +53,7 @@ - + @@ -61,7 +61,7 @@ - + @@ -69,7 +69,7 @@ - + @@ -77,7 +77,7 @@ - + @@ -85,7 +85,7 @@ - + @@ -93,7 +93,7 @@ - + @@ -101,7 +101,7 @@ - + @@ -109,17 +109,33 @@ - + - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + diff --git a/VirusTotal.m b/VirusTotal.m index eb94a48..ee5522f 100644 --- a/VirusTotal.m +++ b/VirusTotal.m @@ -649,11 +649,7 @@ bail: { //queried binary obj Binary* queriedItem = nil; - - //flag for top pane reload - // ->will be set if any of the queried binaries are a task executable - BOOL reloadTopPane = NO; - + //process all results // ->save VT result dictionary into File obj for(NSDictionary* result in results[VT_RESULTS]) @@ -672,56 +668,14 @@ bail: //save VT results into item queriedItem.vtInfo = result; - //for task executables - // ->set flag to reload top - if(YES == queriedItem.isTaskBinary) - { - //set - reloadTopPane = YES; - } - //for dylibs - // ->no dups, update each via row reload - else - { - //update - [self updateUI:queriedItem]; - } + //callback to smartly reload + [((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadBinary:queriedItem]; + //TODO: do something with detections!? //if(0 != [result[VT_RESULTS_POSITIVES] unsignedIntegerValue]) } - //reload top pane - // ->do full since there might be dups (e.g. Chrome Helper) - if(YES == reloadTopPane) - { - //reload - [self updateUI:nil]; - } - - return; -} - -//call back up to update item in UI -// ->will either reload task table (top), or just row in item (bottom) table --(void)updateUI:(Binary*)item -{ - //handle case where item is a task (top) - // ->fully reload task table (since there can be dups) - if( (nil == item) || - (YES == item.isTaskBinary) ) - { - //reload - [((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadTaskTable]; - } - //handle case where item is a dylib (bottom) - // ->just reload row - else - { - //reload row - [((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadRow:nil item:item pane:PANE_BOTTOM]; - } - return; } diff --git a/en.lproj/MainMenu.xib b/en.lproj/MainMenu.xib index 3110bbe..784f1f3 100755 --- a/en.lproj/MainMenu.xib +++ b/en.lproj/MainMenu.xib @@ -45,37 +45,27 @@ - + - + - - + @@ -88,8 +78,22 @@ + + + + + + + + + + + + + + - + - + @@ -121,20 +125,16 @@ - - - - - - - - - - + @@ -211,7 +211,7 @@ - + diff --git a/remoteTaskService/remoteTaskService.m b/remoteTaskService/remoteTaskService.m index 892142d..6347e0a 100644 --- a/remoteTaskService/remoteTaskService.m +++ b/remoteTaskService/remoteTaskService.m @@ -191,7 +191,7 @@ struct dyld_image_info_32 { // ->32bit mode else { - //hack, can use 64bit version of struct (since 'infoArray' is first pointer + //hack, can use 64bit version of struct (since 'infoArray' is first pointer) // ->but zero out top bits remoteReadAddr = (vm_address_t)allImageInfo->infoArray & 0xFFFFFFFF;