iOS-私有API与runtime

作者: cocoa | 来源:发表于2015-11-28 11:22 被阅读11753次

有朋友在做类似iTool的功能,跟我聊起来,这几天闲,就写了一个demo,不是正经做这个,还很粗略,具体干货诸位等这位朋友自己发文吧。

DEMO

https://github.com/liulishuo/testAppList

思路

iOS9白名单的上限是50个,如果想绕过这个限制,扫描系统中所有app的状态,只有使用私有API,需要用到的类有两个:LSApplicationWorkspace、LSApplicationProxy,知道类的名字我们就可以依靠runtime得到这个类,以及这个类的所有方法,OC的方法望文生义,接下来就可以慢慢尝试。

实现

  • 得到LSApplicationWorkspace、LSApplicationProxy
Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
Class LSApplicationProxy_class = object_getClass(@"LSApplicationProxy");
//获取不到成员变量
    int count = 0;
    Ivar *members = class_copyIvarList([LSApplicationProxy_class class], &count);
    for (int i = 0 ; i < count; i++) {
        Ivar var = members[i];
        const char *memberName = ivar_getName(var);
        const char *memberType = ivar_getTypeEncoding(var);
        NSLog(@"%s: %s",memberType,memberName);
    }
    
    NSLog(@"count: %d",count);
    //获取不到有用的方法
    count = 0;
    Method *memberMethods = class_copyMethodList(LSApplicationProxy_class, &count);
    for (int i = 0; i < count; i++) {
        SEL name = method_getName(memberMethods[i]);
        NSString *methodName = [NSString stringWithCString:sel_getName(name) encoding:NSUTF8StringEncoding];
        NSLog(@"member method:%@", methodName);
    }
    
    NSLog(@"count: %d",count);

因为函数class_copyIvarList、class_copyMethodList有时不能返回有用的结果,所以我们使用class-dump(有朋友反映xcode7的库导不出来,大家用源码自己build一个吧),导出类的头文件。
导出MobileCoreServices.framework的所有头文件:

class-dump -H /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/MobileCoreServices.framework  -o /Users/credit/Desktop/header004

-o后面是输出路径 改成你需要的。

MobileCoreServices.framework的所有头文件 LSApplicationProxy LSApplicationWorkspace
  • 得到app列表

虽然没有注释,但是我们可以猜到这个方法应该可以得到app列表

- (id)allApplications;

但是他是实例方法,我们先要拿到一个LSApplicationWorkspace实例

+ (id)defaultWorkspace;

代码如下

NSObject* workspace = [LSApplicationWorkspace_class performSelector:@selector(defaultWorkspace)];
NSArray *appList = [workspace performSelector:@selector(allApplications)];
  • 遍历app列表
    applist里的每一个元素都是LSApplicationProxy 比对其头文件,把对应的属性打印出来研究,
    属性略多,不想自己写的朋友,请看我的demo


    遍历数组
YY
微信

注意groupContainers数组的内容,我们可以拿到group id,可不可以拿到公共存储区的数据呢?

 NSUserDefaults *share = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.tencent.xin"];
 NSLog(@"%@",share.dictionaryRepresentation);

然而并没有,那有没有共享数据的目录呢?

NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.tencent.xin"];

返回值为nil

app不在group.com.tencent.xin这个组内,咱的冒牌货强写是无效的,因为这个标识符已经被正品占用了。


App Groups

还有什么好玩的? 试试这个

[workspace performSelector:@selector(uninstallApplication:withOptions:) withObject:@"XXX" withObject:nil];

workspace 是LSApplicationWorkspace实例,@"XXX"这里填你获取到的applicationIdentifier

模拟器可以正常卸载app,真机不行。
更多API,大家可以自己尝试一下。

相关文章

网友评论

  • 天空总是很晴朗:ios10 无法卸载?
  • Vxer_Lee:亲测 ios11.3.1 获取不到!
  • 62737ae69891:ios10 直接蹦逼
  • 62737ae69891:楼主请问你好,能不能只获取用户安装的app列表,不显示系统的?
  • 顺其自然2017:您好,你还研究过其他的私有类吗?比如说LSApplicationWorkspaceObserver之类的,是否有私有API可以监控其他APP的运行情况
  • JopiNFlyyy:楼主,急求助,有没有办法去获取用户-隐私-定位服务-系统服务 里面的数据?急问,谢谢
  • 镜花水月cy:楼主,我有个问题要请教下,我现在的LSApplicationProxy文件是xcode8.1beat里的,里面没有_groupIdentifiers这个成员变量,请问怎么办才能获得呢,还有,你的xcode是哪个版本的
  • 城郊慕迪声:楼主你好,我在真机上运行了你的demo,结果点击show info崩溃了,真机是ios10的系统,请问怎么解决?
    cocoa:@isVivian 你已经研究的比我深入啦,恐怕帮不到你了。。
    城郊慕迪声:@cocoa我把崩溃的方法屏蔽掉了,暂时可以运行。请问楼主有没有iOS 9以上获取iPhone前台运行app列表和运行时长的方法?我在网上搜了一些资料,运行时模拟器可以获取到信息,但是真机获取的是null,不知道是不是和系统有关。
    cocoa:@isVivian 嗯,刚看了一下,iOS10 LSApplicationProxy的方法已经变了,崩溃提示是LSApplicationProxy对象找不到指定的方法。
  • 36f4002cd761:请问能获取到app的名字吗
    cocoa:@循环循环循环 你说的是Bundle display name这个字段吗?我没获取到,当时玩票的,没有深挖。
  • 邹浩:Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
    Class LSApplicationProxy_class = object_getClass(@"LSApplicationProxy");
    这个能过审吗?
    邹浩:@cocoa 是的,用runtime获取的私有方法在构建版本时不会打回,开始审核时还是会检测的
    cocoa:@邹浩 object_getClass不是私有API,但是LSApplicationProxy、LSApplicationWorkspace是私有的,应该过不了审。
  • 中峰:您好,请问,使用这个私有API怎么获取已安装app的图标?
    67c9ab5605de:@中峰 问一下,你说的这个方法在模拟器上可行,在真机上获取不到图片。你知道原因吗?
    中峰:@cocoa 通过查阅网上资料,利用该私有API获取app图标的代码如下:
    // 使用私有API
    Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
    NSObject *workspace = [LSApplicationWorkspace_class performSelector:@selector(defaultWorkspace)];

    // 获取已安装app的列表(数组中的对象都是LSApplicationProxy类型的)
    NSArray *appList = [workspace performSelector:@selector(allApplications)];

    // 开始遍历appList数组中每个LSApplicationProxy类型的对象
    [appList enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    // 下面两句代码是重点:利用私有API获取app的图标的路径
    NSDictionary *boundIconsDictionary = [obj performSelector:@selector(boundIconsDictionary)];
    NSString *appIconPath = [NSString stringWithFormat:@"%@/%@.png", [[obj performSelector:@selector(resourcesDirectoryURL)] path], [[[boundIconsDictionary objectForKey:@"CFBundlePrimaryIcon"] objectForKey:@"CFBundleIconFiles"] lastObject]];

    // 判断上述获得的app的图标的路径能不能实例化出图像
    if ([UIImage imageWithContentsOfFile:appIconPath]){
    // 能实例化出图像,则表示该路径上确实存在app图标,接下来的操作...
    }
    }];
    cocoa:@中峰 我没有获取到图标,图标在沙盒里,不越狱不太可能做到哦。
  • cocoa:去他github仓库里拿源码自己编译一个就好,这个问题我说啦
  • 9a6523ec56dc:楼主你好,我用class-dump试着导出这有framework,但是报错: Warning: This file does not contain any Objective-C runtime information.
    怎么办呢
    nikaap:@guakeliao iOS9以上版本不行了
  • 5643eeb7a73a:你好 , 我有个困惑的地方想请教下 , 如果 用私有api来扫描所安app , 提交appStore 会被拒绝么?
    cocoa:@5643eeb7a73a 会的 这个没法直接上线
  • 667a69f9a9e1:我就喜欢这样的文章!
  • Sugar_璟:大牛
  • airron:牛
  • Aeron_Xie:厉害
  • Shumin_Wu:支持
  • 曾樑:iTools现在还是不能轻松把短信导出来,虽然短信用的人少了
  • Resory:卧槽!

本文标题:iOS-私有API与runtime

本文链接:https://www.haomeiwen.com/subject/fzerhttx.html