get process name (from app bundle)

delete sample's output file
made find camera/mic instance methods
fixed icons for main app
code cleanup/TODOs
This commit is contained in:
Patrick Wardle 2016-09-18 11:10:44 -10:00
parent c356077600
commit 78ea2d11c4
9 changed files with 202 additions and 137 deletions

View File

@ -34,7 +34,11 @@
if(YES == [self isInstalled])
{
//dbg msg
logMsg(LOG_DEBUG, @"already installed, so uninstalling...");
logMsg(LOG_DEBUG, @"already installed, so stopping/uninstalling...");
//stop
// ->kill login item/XPC service
[self stop];
//uninstall
if(YES != [self uninstall])
@ -43,10 +47,6 @@
goto bail;
}
//and stop
//TODO: erorr checking
[self stop];
//dbg msg
logMsg(LOG_DEBUG, @"uninstalled");
}
@ -81,16 +81,9 @@
//dbg msg
logMsg(LOG_DEBUG, @"stopping login item");
//stop login item/XPC service
if(YES != [self stop])
{
//err msg
logMsg(LOG_ERR, @"stopping failed");
//bail
goto bail;
}
//stop
// ->kill login item/XPC service
[self stop];
//dbg msg
logMsg(LOG_DEBUG, @"uninstalling...");
@ -228,22 +221,13 @@ bail:
}
//stop
-(BOOL)stop
-(void)stop
{
//flag
BOOL bStopped = NO;
//kill it
// pkill doesn't provide error info, so...
execTask(PKILL, @[APP_HELPER_NAME]);
//happy
bStopped = YES;
//bail
bail:
return bStopped;
return;
}
//uninstall

View File

@ -14,67 +14,6 @@
#import "../Shared/XPCProtocol.h"
//TODO: make instance methods?!
//grab first apple camera
AVCaptureDevice* findAppleCamera()
{
//apple camera
// ->likely FaceTime camera
AVCaptureDevice* appleCamera = nil;
//list of cameras
NSArray *cameras = nil;
//get cameras
cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for(AVCaptureDevice* camera in cameras)
{
//check if apple
if(YES == [camera.manufacturer isEqualToString:@"Apple Inc."])
{
//save
appleCamera = camera;
//exit loop
break;
}
}
return appleCamera;
}
//grab built-in mic
AVCaptureDevice* findAppleMic()
{
//built-in mic
AVCaptureDevice* appleMic = nil;
//list of mics
NSArray *mics = nil;
//get mics
mics = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
for(AVCaptureDevice* mic in mics)
{
//check if apple
// ->also check input source
if( (YES == [mic.manufacturer isEqualToString:@"Apple Inc."]) &&
(YES == [[[mic activeInputSource] inputSourceID] isEqualToString:@"imic"]) )
{
//save
appleMic = mic;
//exit loop
break;
}
}
return appleMic;
}
@implementation AVMonitor
@synthesize mic;
@ -96,6 +35,54 @@ AVCaptureDevice* findAppleMic()
return self;
}
//grab first apple camera
// ->saves into iVar 'camera'
// note: could maybe use defaultDeviceWithDeviceType method() to default device...
-(void)findAppleCamera
{
//get cameras
// ->look for one that belongs to apple
for(AVCaptureDevice* currentCamera in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo])
{
//check if apple
if(YES == [currentCamera.manufacturer isEqualToString:@"Apple Inc."])
{
//save
self.camera = currentCamera;
//exit loop
break;
}
}
return;
}
//grab first apple mic
// ->saves into iVar 'mic'
-(void)findAppleMic
{
//get mics
// ->loof for one that belongs to app
for(AVCaptureDevice* currentMic in [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio])
{
//check if apple
// ->also check input source
if( (YES == [currentMic.manufacturer isEqualToString:@"Apple Inc."]) &&
(YES == [[[currentMic activeInputSource] inputSourceID] isEqualToString:@"imic"]) )
{
//save
self.mic = currentMic;
//exit loop
break;
}
}
return;
}
//initialiaze AV notifcations/callbacks
-(BOOL)monitor
{
@ -155,13 +142,12 @@ AVCaptureDevice* findAppleMic()
methodSelector = NSSelectorFromString(@"connectionID");
//find (first) apple camera
self.camera = findAppleCamera();
// ->saves camera into iVar, 'camera'
[self findAppleCamera];
//find built in mic
self.mic = findAppleMic();
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found mic: %@", self.mic]);
//find (first) apple mic
// ->saves mic into iVar, 'mic'
[self findAppleMic];
//got camera
// ->grab connection ID and invoke helper functions
@ -522,7 +508,7 @@ bail:
if(noErr != status)
{
//err msg
//TODO: add
logMsg(LOG_ERR, [NSString stringWithFormat:@"CMIOObjectAddPropertyListenerBlock() failed with %d", status]);
//bail
goto bail;
@ -737,23 +723,22 @@ bail:
// ->for activatated video; allow/block
else
{
//get process name
processName = getProcessName([event[EVENT_PROCESS_ID] intValue]);
//set other button title
notification.otherButtonTitle = @"allow";
//set action title
notification.actionButtonTitle = @"block";
//get process name
// TODO: see 'determineName' in BB (to get name from bundle, etc)
processName = [getProcessPath([event[EVENT_PROCESS_ID] intValue]) lastPathComponent];
//set pid in user info
// ->allows code to try kill proc (later) if user clicks 'block'
notification.userInfo = @{EVENT_PROCESS_ID:event[EVENT_PROCESS_ID]};
//set details
// ->name of process using it / icon too?
[notification setInformativeText:[NSString stringWithFormat:@"%@ (%@)", processName, event[EVENT_PROCESS_ID]]];
[notification setInformativeText:[NSString stringWithFormat:@"process: %@ (%@)", processName, event[EVENT_PROCESS_ID]]];
}
//log event?
@ -772,11 +757,11 @@ bail:
}
//process
// ->add title / details / process
// ->add title / details / process path
else
{
//add
[logMsg appendFormat:@"%@ (%@, %@)", title, details, processName];
[logMsg appendFormat:@"%@ (process: %@, %@)", title, details, getProcessPath([event[EVENT_PROCESS_ID] intValue])];
}
//write it out to syslog

View File

@ -6,8 +6,6 @@
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
@ -24,12 +22,12 @@
<string>1.0.0</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>LSUIElement</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Copyright (c) 2016 Objective-See. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>LSUIElement</key>
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>

View File

@ -33,6 +33,7 @@
7D9A7DE81D893E4F0091C1AF /* InfoWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D62458C1D87D38400870565 /* InfoWindow.xib */; };
7D9A7DEC1D8BE1E00091C1AF /* Exception.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C5311D659E580066232A /* Exception.m */; };
7D9A7DEE1D8CACE30091C1AF /* libbsm.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D9A7DED1D8CACE30091C1AF /* libbsm.tbd */; };
7D9A7DF21D8F2C900091C1AF /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7D6245841D87C43900870565 /* Images.xcassets */; };
7DAF4B7F1D657192000DA31A /* StatusBarMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DAF4B7D1D656FD3000DA31A /* StatusBarMenu.m */; };
7DC9C8171D641A350017D143 /* OverSightXPC.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DC9C8161D641A350017D143 /* OverSightXPC.m */; };
7DC9C8191D641A350017D143 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DC9C8181D641A350017D143 /* main.m */; };
@ -166,7 +167,7 @@
7D17C5131D658FE20066232A /* Images */ = {
isa = PBXGroup;
children = (
7D17CFE21D81121E0017B475 /* AVMonitor.h */,
8B5755C819DA3F9300799E6B /* AppDelegate.h */,
7D17C5141D658FEB0066232A /* statusIcon.png */,
7D17C5151D658FEB0066232A /* statusIcon@2x.png */,
);
@ -276,11 +277,11 @@
isa = PBXGroup;
children = (
7D17C5131D658FE20066232A /* Images */,
8B5755C919DA3F9300799E6B /* AppDelegate.m */,
7D17CFE21D81121E0017B475 /* AVMonitor.h */,
7D17CFE11D81121E0017B475 /* AVMonitor.m */,
7DAF4B7C1D656FD3000DA31A /* StatusBarMenu.h */,
7DAF4B7D1D656FD3000DA31A /* StatusBarMenu.m */,
8B5755C819DA3F9300799E6B /* AppDelegate.h */,
8B5755C919DA3F9300799E6B /* AppDelegate.m */,
7D17CFE11D81121E0017B475 /* AVMonitor.m */,
8B5755CD19DA3F9300799E6B /* MainMenu.xib */,
8B5755C419DA3F9300799E6B /* Supporting Files */,
);
@ -419,6 +420,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
7D9A7DF21D8F2C900091C1AF /* Images.xcassets in Resources */,
7D6245921D87D46800870565 /* InfoWindow.xib in Resources */,
7D17C53C1D659E580066232A /* icon.png in Resources */,
8B5755A919DA3E9500799E6B /* MainMenu.xib in Resources */,
@ -629,6 +631,7 @@
8B5755B919DA3E9500799E6B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "Developer ID Application";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
COMBINE_HIDPI_IMAGES = YES;
@ -644,6 +647,7 @@
8B5755BA19DA3E9500799E6B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "Developer ID Application";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
COMBINE_HIDPI_IMAGES = YES;

View File

@ -309,7 +309,6 @@ bail:
}
//parse on '()'
// TODO: improve this!
subStrings = [line componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"()"]];
if(subStrings.count < 3)
{
@ -371,10 +370,10 @@ bail:
videoProcs = [NSMutableArray array];
//invoke 'sample' on each
// TODO: delete tmp file? 'Sample analysis of process 37370 written to file /tmp/FaceTime_2016-09-10_081703_TAwB.sample.txt' (written 2 std err?)
for(NSNumber* processID in currentSenders)
{
//exec 'sample' to get threads/dylibs
// ->uses 1.0 seconds for sampling time
results = [[NSString alloc] initWithData:execTask(SAMPLE, @[processID.stringValue, @"1"]) encoding:NSUTF8StringEncoding];
if( (nil == results) ||
(0 == results.length) )
@ -383,6 +382,10 @@ bail:
continue;
}
//sampling a process creates a temp file
//->delete it!
[self deleteSampleFile:getProcessPath(processID.intValue)];
//for now, just check for 'CMIOGraph::DoWork'
// ->TODO: could look for dylibs, other calls, etc
if(YES != [results containsString:@"CMIOGraph::DoWork"])
@ -398,6 +401,66 @@ bail:
return videoProcs;
}
//'sample' binary creates a file
// ->this looks for that file and deletes it
-(void)deleteSampleFile:(NSString*)processPath
{
//error
NSError* error = nil;
//files
NSArray* files = nil;
//grab all files in /tmp
files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/tmp/" error:&error];
if(nil != error)
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to enumerate files in /tmp, %@", error]);
//bail
goto bail;
}
//find/delete file
for(NSString* file in files)
{
//skip non-sample files
if(YES != [file hasSuffix:@".sample.txt"])
{
//skip
continue;
}
//ignore files that don't contain process name
if(YES != [file containsString:[processPath lastPathComponent]])
{
//skip
continue;
}
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"deleting sample file: %@", file]);
//delete
if(YES != [[NSFileManager defaultManager] removeItemAtPath:[@"/tmp" stringByAppendingPathComponent:file] error:&error])
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to delete %@ (%@)", file, error]);
//bail
goto bail;
}
}//all files
//bail
bail:
return;
}
//set status of video
-(void)updateVideoStatus:(BOOL)isEnabled
{

View File

@ -11,12 +11,10 @@
#import "Exception.h"
#import "Utilities.h"
//TODO: renenable
/*
#ifdef IS_INSTALLER_APP
#import "AppDelegate.h"
#endif
*/
//global
// ->only report an fatal exception once
@ -98,9 +96,8 @@ void exceptionHandler(NSException *exception)
// ->agent should exit
errorInfo[KEY_ERROR_SHOULD_EXIT] = [NSNumber numberWithBool:YES];
//TODO: renable
//display error msg
//[((AppDelegate*)[[NSApplication sharedApplication] delegate]) displayErrorWindow:errorInfo];
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) displayErrorWindow:errorInfo];
//need to sleep, otherwise returning from this function will cause OS to kill agent
// ->instead, we want error popup to be displayed (which will exit agent when closed)
@ -178,9 +175,8 @@ void signalHandler(int signal, siginfo_t *info, void *context)
// ->agent should exit
errorInfo[KEY_ERROR_SHOULD_EXIT] = [NSNumber numberWithBool:YES];
//TODO: renable
//display error msg
//[((AppDelegate*)[[NSApplication sharedApplication] delegate]) displayErrorWindow:errorInfo];
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) displayErrorWindow:errorInfo];
//end app-specific code
#endif

View File

@ -42,8 +42,5 @@ void logMsg(int level, NSString* msg)
//log to syslog
syslog(level, "%s: %s\n", [logPrefix UTF8String], [msg UTF8String]);
//TODO: remove
NSLog(@"%s: %s", [logPrefix UTF8String], [msg UTF8String]);
return;
}

View File

@ -14,8 +14,6 @@
/* FUNCTIONS */
//TODO: cleanup/remove un-needed
//get app's version
// ->extracted from Info.plist
NSString* getAppVersion();
@ -36,13 +34,6 @@ SInt32 getVersion(OSType selector);
// parse it back up to find app's bundle
NSBundle* findAppBundle(NSString* binaryPath);
//given a directory and a filter predicate
// ->return all matches
NSArray* directoryContents(NSString* directory, NSString* predicate);
//hash (sha1/md5) a file
NSDictionary* hashFile(NSString* filePath);
//get app's version
// ->extracted from Info.plist
NSString* getAppVersion();
@ -54,15 +45,15 @@ NSString* getLatestVersion();
// -1, YES or NO
NSInteger isNewVersion(NSMutableString* versionString);
//exec a process and grab it's output
NSData* execTask(NSString* binaryPath, NSArray* arguments);
//get process's path
NSString* getProcessPath(pid_t pid);
//given a pid
// ->get the name of the process
NSString* getProcessName(pid_t pid);
//wait until a window is non nil
// ->then make it modal
void makeModal(NSWindowController* windowController);
#endif

View File

@ -254,7 +254,7 @@ NSData* execTask(NSString* binaryPath, NSArray* arguments)
//launch
[task launch];
}
@catch(NSException *exception)
@catch(NSException* exception)
{
//bail
goto bail;
@ -412,6 +412,53 @@ bail:
return taskPath;
}
//given a pid
// ->get the name of the process
NSString* getProcessName(pid_t pid)
{
//task path
NSString* processName = nil;
//process path
NSString* processPath = nil;
//app's bundle
NSBundle* appBundle = nil;
//get process path
processPath = getProcessPath(pid);
if( (nil == processPath) ||
(0 == processPath.length) )
{
//default to 'unknown'
processName = @"<unknown>";
//bail
goto bail;
}
//try find an app bundle
appBundle = findAppBundle(processPath);
if(nil != appBundle)
{
//grab name from app's bundle
processName = [appBundle infoDictionary][@"CFBundleName"];
}
//still nil?
// ->just grab from path
if(nil == processName)
{
//from path
processName = [processPath lastPathComponent];
}
//bail
bail:
return processName;
}
//determine if there is a new version
// -1, YES or NO
NSInteger isNewVersion(NSMutableString* versionString)