如何从swift访问Objective C混淆类

时间:2017-09-22 06:07:09

标签: ios objective-c swift

我有一个项目,我同时使用Objective C和Swift。 出于安全原因,对于使用Objective C编写的一些类和方法,我使用了混淆。

这是我的代码:

#ifndef AccessManager_h

#define AccessManager ySbIXoscpewLLSwVacDpZvPvQeNDtG
#define loginWithUsername TEWhYyXaCdGrCViPbZZHWXoBiUPvPn

#endif

@interface AccessManager : AFHTTPSessionManager

-(void)loginWithUsername:(NSString*)username password:(NSString*)password success:(WSSuccessBlock)success failure:(WSFailureBlock)failure;

@end

这是我试图访问混淆类的快速代码

AccessManager.instance().login(withUsername: "my_user", password: "password", success: { (response) in
        //TODO
    }) { (error) in
        //TODO
    }

这是我在构建项目时得到的错误

Undefined symbols for architecture armv7:
"_OBJC_CLASS_$_AccessManager", referenced from:
      objc-class-ref in MySwiftClass.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

如何访问从Swift中混淆的Objective C类?

2 个答案:

答案 0 :(得分:0)

通过使用宏,您更改了类的名称和方法名称。这是一种简单的混淆方法。

但是,如果您尝试使用原始类名及其方法,那也会破坏Swift-Objective-C的互操作性。

当然,您仍然可以通过Swift类中的重新定义的名称使用您的obj-c类(为简单起见,将块参数更改为简单的BOOL):

let accessManager = ySbIXoscpewLLSwVacDpZvPvQeNDtG()
accessManager.teWhYyXaCdGrCViPbZZHWXoBiUPvPn("", password: "", success: true, failure: true)

答案 1 :(得分:0)

下面是一个非常基本的例子,但是可以了解你可以做什么:

通过可从Swift代码调用的全局C函数,为您的类和方法的运行时表示提供接口。

与Objective-C方法不同,后者使用动态分派,并且其名称因此作为普通字符串(选择器)存在于二进制文件中,C函数调用被编译为跳转指令到相应的内存地址;函数名称不存在于二进制文件中,供黑客反编译/检查。

<强> AccessManager.h:

#import <Foundation/Foundation.h>

#ifndef AccessManager_h
#define AccessManager ySbIXoscpewLLSwVacDpZvPvQeNDtG
#define loginWithUsername TEWhYyXaCdGrCViPbZZHWXoBiUPvPn
#endif

/// Provides the class object at runtime
Class accessManagerClass();

/// Provides the method name at runtime
SEL loginMethodName();

@interface AccessManager : NSObject

- (instancetype) init;
- (void) loginWithUsername:(NSString*) userName;

@end

<强> AccessManager.m:

#import "AccessManager.h"

Class accessManagerClass() {
    return [AccessManager self];
}

SEL loginMethodName() {
    return @selector(loginWithUsername:);
}

@implementation AccessManager

- (void) loginWithUsername:(NSString*) userName {
    // Dummy implementation, for demonstration purposes:
    NSLog(@"%s", __func__);
    NSLog(userName);
}

@end

桥接标题:

#import "AccessManager.h"

ViewController.swift(省略了大部分类):

override func viewDidLoad() {
    super.viewDidLoad()

    if let managerClass: AnyClass = accessManagerClass(), let methodName = loginMethodName() {

        // Instantiate the manager from the class:
        let manager = (managerClass as! NSObject.Type).init()

        // (I'm still a bit fuzzy about metatypes on Swift,
        //  perhaps the line above can be improved)

        // Call the obfuscated method: 
        manager.perform(methodName, with: "AAAA")
    }
}

运行时,会打印:

% -[ySbIXoscpewLLSwVacDpZvPvQeNDtG TEWhYyXaCdGrCViPbZZHWXoBiUPvPn:]
% AAAA

......证明:

  1. 类和方法名称在运行时进行模糊处理。
  2. 该方法实际上称为
  3. 我将示例项目on GitHub上方的所有代码放在一起。