某音防dump手法

用frida-ios-dump对某音进行dump,然后反汇编分析AwemeCore,发现这个框架里的objc_selrefs区域全是错误地址,导致一个OC类的方法都没解析成功,全是空的。因为AwemeCore是某音的一个framework,而frida-ios-dump只对text段做dump处理,而objc_selrefs的内容是在data段,这部分没dump下来,猜测是不是这个原因导致解析OC类方法名失败呢?这是某音的anti-dump手段?有人踩过坑吗

2 个赞


都是这种异常地址,导致解析出来都是问号

1 个赞

这个有解决吗?我也同求此解

你说的解决指解决到什么程度,完全恢复是吃力不讨好

静态没办法dump,但可以采取动态的方式。

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self classList:NSClassFromString(@"TTNetworkManager") recursion:YES keyWord:@""];
    });
}

+ (void)classList:(Class)defaultClass recursion:(BOOL)recursion keyWord:(NSString *)keyword {
    [self getClassMethods:defaultClass];
    int count = objc_getClassList(NULL, 0);
    Class *classes = (Class *)malloc(sizeof(Class) * count);
    objc_getClassList(classes, count);
    for (int i = 0; i < count; i++) {
        if (defaultClass == class_getSuperclass(classes[i])) {
            NSString * className = NSStringFromClass(classes[i]);
            if (recursion) {
                if ([keyword length] > 0 && ![className containsString:keyword]) {
                    return;
                } else {
                    [self classList:classes[i] recursion: recursion keyWord: keyword];
                }
            }
        }
    }
    free(classes);
}

+ (void)getClassMethods:(Class)defaultClass {
    unsigned int count = 0;
    Ivar *members = class_copyIvarList(defaultClass, &count);
    for(int i = 0; i < count; i++) {
        Ivar ivar = members[i];
        const char *memberName = ivar_getName(ivar);
        const char *memberType = ivar_getTypeEncoding(ivar);
        printf("@property %s %s\n", memberType, memberName);
    }
    free(members);
    
    NSString * className = NSStringFromClass(defaultClass);
    Method *methodList = class_copyMethodList(defaultClass, &count);
    for (int i = 0; i<count; i++) {
        SEL name = method_getName(methodList[i]);
        printf("-[%s %s] %p\n", className.UTF8String, NSStringFromSelector(name).UTF8String, method_getImplementation(methodList[i]));
    }
    free(methodList);
    
    Class metaClass = object_getClass(defaultClass);
    Method *classMethods = class_copyMethodList(metaClass, &count);
    for (int i = 0; i < count; i++) {
        SEL name = method_getName(classMethods[i]);
        printf("+[%s %s] %p\n", className.UTF8String, NSStringFromSelector(name).UTF8String, method_getImplementation(classMethods[i]));
    }
    free(classMethods);
}

通过lldb的image lookup命令,查到IDA中具体对应哪个函数

如果你不嫌慢的话,可以直接传个NSObject进去。

3 个赞

他应该是想IDA分析

好代码 马上集成到frida 里去

已经有了啊。只不过在Aweme上不好使,应用启动会闪退

我这些日子研究终于搞明白 为什么 Aweme 系列不行。这代码我看过

为啥

删除就没意思了。

删了啥,你不是搞明白了吗

我是附和了一个 为啥.回复错人就删了.所以是为啥 :laughing:

这个怎么用啊

写个插件注入进去使用

求解,有人知道怎么实现的么。 现在等保很多使用class-dump扫描的

多年后来回答自己未回答的问题:Aweme使用了动态释放ObjC相关段数据导致,class-dump 这种静态工具所以就失效了,frida-class-dump 为啥不好使呢,因为某音的类太多了,没办法一次性全导出frida也会因为内存膨胀导致卡死,最优解决办法就是找到动态释放segment 地方把解压解密后的段数据恢复到 静态文件中,这样重新用class-dump就没有问题了,aweme还有一个非常有意思的架构就是 aweme是个wapper 项目,aweme-core 核心逻辑以库的依赖形式存在,静态隐藏某些runtime信息 提供了完美的温床,拿张总的话说就是防脚本小子

2 个赞

是segment迁移吗?好像一开始是为了减少包体做的优化

objc相关的 确实是动态释放的,直接从高版本研究,确实压力大了不少,不过frida+lldb,也可以不用考虑他先关的内容,直接统一按c/c++代码考虑即可。如果想加快的,其实可以对 老版本做一些分析,然后两个版本对照。针对 objc相关的内容,直接启动后台启动,然后在+load之前断住,最后对objc相关内存下watch断点,基本能找到相关方法。我习惯了c/c++,直接放弃这个了

至于wapper这种,安全上,我唯一考虑到的是针对 主包的检测,方便上架等等。扩展一下,就是库的检测相对弱一点,然后可做手段就多了点。毕竟iOS系统的性质导致了,能做的范畴只有那么多。不可写权限的地方是写不到的,能写的地方方能搞事。

2 个赞

这种frida脱壳工具其实最早是我开发的,那时候和团队刚接触ios,dumpdecrypt用起来太麻烦了,所以我开发了一个基于frida的js脱壳脚本,后来公司对开源代码查的比较严所以删掉了代码库后来又重建了。monkey不知道啥时候看到我那脚本,加上个python控制,成为frida-ios-dump,多年以后再接触ios才发现

6 个赞