小标
2019-04-22
来源 :
阅读 1841
评论 0
摘要:本文主要向大家介绍了C/C++知识点之MachOView源码(AppController.mm),通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。
本文主要向大家介绍了C/C++知识点之MachOView源码(AppController.mm),通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。
//AppController.h
/*
* AppController.h
* MachOView
*
* Created by psaghelyi on 15/06/2010.
*
*/#import @class MVPreferenceController;@interface MVAppController : NSObject {
MVPreferenceController * preferenceController;
}//偏好设置- (IBAction)showPreferencePanel:(id)sender;//附加- (IBAction)attach:(id)sender;@end//AppController.mm
/*
* AppController.mm
* MachOView
*
* Created by psaghelyi on 15/06/2010.
*
*/#import ""Common.h""#import ""AppController.h""#import ""DataController.h""#import ""Document.h""#import ""PreferenceController.h""#import ""Attach.h""// counters for statisticsint64_t nrow_total; // number of rows (loaded and empty)int64_t nrow_loaded; // number of loaded rows//============================================================================@implementation MVAppController//----------------------------------------------------------------------------- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
{ return NO;
}//----------------------------------------------------------------------------- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{ return NO;
}//----------------------------------------------------------------------------//new 方式 没写- (IBAction)newDocument:(id)sender
{ NSLog(@""Not yet possible"");
}//----------------------------------------------------------------------------//是否在运行- (BOOL)isOnlyRunningMachOView
{ //获取进程的相关信息 NSProcessInfo * procInfo = [NSProcessInfo processInfo]; //获取程序程序包(app包就是一个mainBundle) NSBundle * mainBundle = [NSBundle mainBundle]; //获取当前进程的CFBundleShortVersionString //返回指定键关联的接收器中的属性信息列表 NSString * versionString = [mainBundle objectForInfoDictionaryKey:@""CFBundleShortVersionString""]; NSUInteger numberOfInstance = 0; //返回一个工作空间 //提供服务 //1)打开,操作文件/设备,获取文件/设备信息 //2)跟踪文件,设备以及数据库的变动 //3)设置或获取文件的 Finder 信息 //4)操作应用程序 NSWorkspace * workspace = [NSWorkspace sharedWorkspace]; //获取当前运行的 apps for (NSRunningApplication * runningApplication in [workspace runningApplications])
{ //检查进程名称是否匹配 //executableURL获取bundle 类实例的 可执行的URL //lastPathComponent获取路径中的最后一个文件名 NSString * fileName = [[runningApplication executableURL] lastPathComponent]; //判断名称是否相等 if ([fileName isEqualToString: [procInfo processName]] == NO)
{ continue;
} //检查版本字符串是否匹配 //通过 url 获取bundle NSBundle * bundle = [NSBundle bundleWithURL:[runningApplication bundleURL]]; //判断是否与当前进程的相等 if ([versionString isEqualToString:[bundle objectForInfoDictionaryKey:@""CFBundleShortVersionString""]] == YES && ++numberOfInstance > 1)
{ return NO;
}
} return YES;
}//----------------------------------------------------------------------------//附加方式打开同时解析 mach-o header- (IBAction)attach:(id)sender
{ //alert NSAlert *alert = [NSAlert alertWithMessageText:@""Insert PID to attach to:""
defaultButton:@""Attach""
alternateButton:@""Cancel""
otherButton:nil
informativeTextWithFormat:@""""]; //初始化一个文本框 NSTextField *input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)]; //设置默认字符串
[input setStringValue:@""""]; //设置弹框的 view为input
[alert setAccessoryView:input]; //返回按钮值 NSInteger button = [alert runModal]; if (button == NSAlertDefaultReturn)
{ //设置为不可编辑
[input validateEditing]; //获取 pid
pid_t targetPid = [input intValue]; NSLog(@""Attach to process %d"", targetPid); //入口地址
mach_vm_address_t mainAddress = 0; //找到入口地址 if (find_main_binary(targetPid, &mainAddress))
{ NSLog(@""Failed to find main binary address!""); return;
}
uint64_t aslr_slide = 0;
uint64_t imagesize = 0; //获取镜像大小 if ( (imagesize = get_image_size(mainAddress, targetPid, &aslr_slide)) == 0 )
{ NSLog(@""[ERROR] Got image file size equal to 0!""); return;
} //分配macho所需要的缓冲区大小(文件)
uint8_t *readbuffer = (uint8_t*)malloc(imagesize); if (readbuffer == NULL)
{ NSLog(@""Can't allocate mem for dumping target!""); return;
} //最后读取这些部分并将它们的内容转储到缓冲区中 if (dump_binary(mainAddress, targetPid, readbuffer, aslr_slide))
{ NSLog(@""Main binary memory dump failed!"");
free(readbuffer); return;
} //将缓冲区内容转储到临时文件以使用NSDocument model //拼接临时文件名+进程名 如:""/var/folders/l8/3kn0r51s3qdbbnxb9ng2gvb40000gn/T/MachOView_2.4.XXXXXXXXXXX"" const char *tmp = [[MVDocument temporaryDirectory] UTF8String]; //用于保存数数据的临时文件绝对路径名的缓冲区 char *dumpFilePath = (char*)malloc(strlen(tmp)+1); if (dumpFilePath == NULL)
{ NSLog(@""Can't allocate mem for temp filename path!"");
free(readbuffer); return;
} //拷贝
strcpy(dumpFilePath, tmp); int outputFile = 0; //在系统中以唯一的文件名创建一个文件并打开 if ( (outputFile = mkstemp(dumpFilePath)) == -1 )
{ NSLog(@""mkstemp failed!"");
free(dumpFilePath);
free(readbuffer); return;
} //写入 if (write(outputFile, readbuffer, imagesize) == -1)
{ NSLog(@""[ERROR] Write error at %s occurred!\n"", dumpFilePath);
free(dumpFilePath);
free(readbuffer); return;
} NSLog(@""\n[OK] Full binary dumped to %s!\n\n"", dumpFilePath);
close(outputFile); //打开文件
[self application:NSApp openFile:[NSString stringWithCString:dumpFilePath encoding:NSUTF8StringEncoding]]; //删除临时转储文件 NSFileManager * fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:[NSString stringWithCString:dumpFilePath encoding:NSUTF8StringEncoding] error:NULL];
free(dumpFilePath);
free(readbuffer);
} else if (button == NSAlertAlternateReturn)
{ //
} else
{ NSAssert1(NO, @""Invalid input dialog button %ld"", button);
}
}//----------------------------------------------------------------------------//open方式打开- (IBAction)openDocument:(id)sender
{ //打开文件查看 NSOpenPanel *openPanel = [NSOpenPanel openPanel]; //是否显示面板封装的文件的目录
[openPanel setTreatsFilePackagesAsDirectories:YES]; //设置为多选模式
[openPanel setAllowsMultipleSelection:YES]; //不可选择文件夹
[openPanel setCanChooseDirectories:NO]; //设置可以选择文件
[openPanel setCanChooseFiles:YES]; //设置代理为自身 调用 shouldShowFilename过滤打开面板中的文件
[openPanel setDelegate:self]; //告警风格窗口 //completionHandler参数为事件响应
[openPanel beginSheetModalForWindow:nil
completionHandler:^(NSInteger result)
{ //判断点击 ok if (result != NSOKButton)
{ return;
} //关闭面板之前,可能会出现错误 //移除窗口
[openPanel orderOut:self]; //遍历所选的文件路径 for (NSURL * url in [openPanel URLs])
{ //全部打开(通过多文档模式)
[self application:NSApp openFile:[url path]];
}
}];
}//----------------------------------------------------------------------------//协议-----过滤文件- (BOOL)panel:(id)sender shouldShowFilename:(NSString*)filename
{ //文件 url NSURL * url = [NSURL fileURLWithPath:filename]; // 判断是否为文件夹 NSNumber * isDirectory = nil;
[url getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:NULL]; if ([isDirectory boolValue] == YES)
{ return YES;
} // 跳过符号链接等 //判断是否为一些符号链接 NSNumber * isRegularFile = nil;
[url getResourceValue:&isRegularFile forKey:NSURLIsRegularFileKey error:NULL]; if ([isRegularFile boolValue] == NO)
{ return NO;
} // 检查文件的magic //文件句柄 NSFileHandle * fileHandle = [NSFileHandle fileHandleForReadingAtPath:filename]; // NSLog(@""fileHandleForReadingAtPath----- %@!\n\n"", filename); //读取指定的字符数 NSData * magicData = [fileHandle readDataOfLength:8]; // NSLog(@""magicData----- %@!\n\n"", magicData); //关闭句柄
[fileHandle closeFile]; //判断长度 if ([magicData length] < sizeof(uint32_t))
{ return NO;
} //比较
uint32_t magic = *(uint32_t*)[magicData bytes]; //NSLog(@""magic----- %8x!\n\n"", magic); if (magic == MH_MAGIC || magic == MH_MAGIC_64 ||
magic == FAT_CIGAM || magic == FAT_MAGIC)
{ return YES;
} if ([magicData length] < sizeof(uint64_t))
{ return NO;
} if (*(uint64_t*)[magicData bytes] == *(uint64_t*)""!\n"")
{ return YES;
} return NO;
}//----------------------------------------------------------------------------//程序将启动- (void)applicationWillFinishLaunching:(NSNotification *)aNotification
{ BOOL isFirstMachOView = [self isOnlyRunningMachOView]; //禁用状态恢复功能,这对MachOView来说不是很有用 if([[NSUserDefaults standardUserDefaults] objectForKey: @""ApplePersistenceIgnoreState""] == nil)
[[NSUserDefaults standardUserDefaults] setBool: YES forKey:@""ApplePersistenceIgnoreState""]; // load user's defaults for preferences// if([[NSUserDefaults standardUserDefaults] objectForKey: @""UseLLVMDisassembler""] != nil)// qflag = [[NSUserDefaults standardUserDefaults] boolForKey:@""UseLLVMDisassembler""]; //获取一个文件管理者 NSFileManager * fileManager = [NSFileManager defaultManager]; NSString * tempDir = [MVDocument temporaryDirectory];
__autoreleasing NSError * error; //删除以前被遗忘的临时文件 if (isFirstMachOView && [fileManager fileExistsAtPath:tempDir isDirectory:NULL] == YES)
{ //移除 if ([fileManager removeItemAtPath:tempDir error:&error] == NO)
{
[NSApp presentError:error];
}
} //为临时文件创建占位符 //返回一个布尔值,该值指示一个文件或目录是否存在于指定路径 if ([fileManager fileExistsAtPath:tempDir isDirectory:NULL] == NO)
{ //创建一个带有给定属性的指定目录路径 if ([fileManager createDirectoryAtPath:tempDir
withIntermediateDirectories:NO
attributes:nil
error:&error] == NO)
{ //调用错误对话框
[NSApp presentError:error];
}
}
}//----------------------------------------------------------------------------//程序已启动- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{#ifdef MV_STATISTICS
nrow_total = nrow_loaded = 0; //开线程开始打印(用于调试忽视)
[NSThread detachNewThreadSelector:@selector(printStat) toTarget:self withObject:nil];#endif //默认一开始就打开文件对话框 if ([[NSUserDefaults standardUserDefaults] objectForKey:@""OpenAtLaunch""] != nil)
{ if ([[NSUserDefaults standardUserDefaults] boolForKey:@""OpenAtLaunch""] == YES)
{ if ([[[NSDocumentController sharedDocumentController] documents] count] == 0)
{
[self openDocument:nil];
}
}
}
}//----------------------------------------------------------------------------//程序将结束- (void)applicationWillTerminate:(NSNotification *)aNotification
{ BOOL isLastMachOView = [self isOnlyRunningMachOView]; if (isLastMachOView == YES)
{ //删除临时文件 NSFileManager * fileManager = [NSFileManager defaultManager]; //返回当前用户的临时目录 NSString * tempDir = [MVDocument temporaryDirectory]; //NSLog(@""Can't allocate mem for temp filename path! %@"",tempDir); //删除
[fileManager removeItemAtPath:tempDir error:NULL];
}
}//----------------------------------------------------------------------------//回调函数 打开文件- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
{ NSLog (@""open file: %@"", filename);
__autoreleasing NSError *error; //获取一个多文档控制器 NSDocumentController * documentController = [NSDocumentController sharedDocumentController]; //NSDocumentController 创建管理多个MVDocument //MVDocument 创建管理多个NSWindowController //NSWindowController //通过文件路径创建一个文档 同时显示(通过代理实现细节) //MVDocument必须实现的函数有: //窗口名称 //- (NSString *)windowNibName; //指定窗口控制器 //- (void)windowControllerDidLoadNib:(NSWindowController *)aController; //必须实现创建和返回受支持类型的文档数据,通常是将数据写入NSData对象的文件。 //- (NSData *)dataRepresentationOfType:(NSString *)aType; //必须实现将NSData对象(包含特定类型的文档数据)转换为文档的内部数据结构,以便文档准备显示其内容。NSData对象通常是从读取文档文件的文档中产生的。 //- (BOOL)loadDataRepresentation:(NSData *)data:(NSString *)aType;
MVDocument * document = [documentController openDocumentWithContentsOfURL:[NSURL fileURLWithPath:filename]
display:YES
error:&error]; //判断是否能打开文档 if (!document)
{
[NSApp presentError:error]; return NO;
} return YES;
}//----------------------------------------------------------------------------//线程回调-(void) printStat
{ for (;;)
{ NSLog(@""stat: %lld/%lld rows in memory\n"",nrow_loaded,nrow_total);
[NSThread sleepForTimeInterval:1];
}
}//----------------------------------------------------------------------------//系统偏好设置 (显示一个nib)- (IBAction)showPreferencePanel:(id)sender
{ if (!preferenceController)
{
preferenceController = [[MVPreferenceController alloc] init];
}
[preferenceController showWindow:self];
}@end本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!
喜欢 | 0
不喜欢 | 0
您输入的评论内容中包含违禁敏感词
我知道了

请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号