在DEBUG模式下,Objective-C方法的混淆可以正常工作,但在RELEASE模式下会崩溃。

9

我制作了一个Xcode项目,其中进行了一些安全措施,他们要求我混淆方法名称。

例如:

#define specialMethod a9328238
+(void) specialMethod
{
   // do security stuff
}

我从一个项目(项目A)中制作了一个.framework库,并将其包含到另一个项目(项目B)中。
但是,当我使用发布版本的构建配置运行(项目B)时,它总是崩溃,如下所示。
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[SecurityClass a9328238]: unrecognized selector sent to class 0x337cc4'

当它尝试访问该方法时,它会崩溃。

但是,当我使用调试构建配置运行(项目B)时,它运行得很顺利。

(我已将所有构建配置设置保持为默认值)


你的编译器标志是什么? - CarlJ
1
发布版本中,不混淆方法名称,它能正常工作吗? - Klas Lindbäck
4
安全通过深藏不露来实现的说法是什么? - JeremyP
它可以在不混淆的情况下工作。 - Andy Jacobs
也许你应该更详细地说明混淆是如何被使用的——就像你在示例中展示的那样,在方法定义之前(在.m文件中)立即使用#define不会使调用者看到该名称(虽然这显然不是你所看到的错误的原因,所以我怀疑你正在压缩你的代码)。 - Ben Zotto
我和@JeremyP的感觉一样。整件事情与安全毫无关系。它可能会让黑客稍微困难一些,但并不会增加安全性。 - Sulthan
4个回答

7
您把混淆的#define放在哪里了?是在框架的头文件 (.h) 中还是在实现文件 (.m) 中?为使混淆生效,必须将其放置在既被实现文件包含,又被调用者包含的文件中。您还可以通过检查预处理文件来检查预处理是否正常。选择实现文件并转到菜单 Product > Generate Output > Generate Preprocessed File(可以在屏幕底部选择配置)。

通过助理编辑器也可以查看预处理结果。 - Danra

2

我的直觉是 #define 的位置/可见性也有问题。

但你可能想从另一个角度考虑这个问题。你可以改变:

#define specialMethod a9328238
+(void) specialMethod
{
   // do security stuff
}

to:

@interface SecurityClass : NSObject

// private obfuscated interface:
+ (void)a9328238;
// {
//    do security stuff in a9328238's definition
// }

@end

// here is the public interface:
static inline void SecurityClass_LogIn() {
   [SecurityClass a9328238];
}

放弃使用#define

在使用中:

SecurityClass_LogIn();
…

由于这是一个类方法,你可以编写一个混淆的函数并包装在易读的内联中。一个精心制作的C实现将比objc更难拆分。

更完整的示例将帮助我们缩小可能性。

还要验证是否有警告--编译器可能会警告您是否调用了未声明的选择器。可能会在其他情况下看不到#define的方法被调用。


1

看起来导入混淆框架的可执行文件试图访问未混淆的方法。

您应该检查框架中的符号。在框架中的静态库上使用nm命令查看导出的符号(标记为“t”)。确保这些符号已经被混淆。


1
如果您将所有内容都封装到框架中,您是否确保适当的头文件在框架外部公开?框架内部的头文件与普通文件的公开方式不同。请前往您的项目->构建阶段,在右下角您应该看到“添加复制头文件”。这将在您的构建阶段中添加一个新的部分。在此部分内,单击“+”,选择定义您方法名称的头文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接