iOS手动代码混淆函数和变量名基本原理和注意事项教程

ios手动代码混淆函数和变量名基本原理和注意事项教程

混淆函数名原理

代码混淆替换函数名的主要原理是用宏定义#define来替换代码里的函数名或者变量民

对于需要更全面保护的应用,可以考虑使用专业工具如IpaGuard进行自动化混淆,它支持多种开发平台且无需手动处理宏定义。

代码例子没混淆的函数名

ViewController.h文件

objectivec 复制代码
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (assign,nonatomic)int money;
-(void)showMoney;
@end
12345
less 复制代码
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label1;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _money = 100;
}
-(void)showMoney{
    NSLog(@"money=%d",self.money);
    NSString * strFuncName = [NSString stringWithFormat:@"%s",__func__];
    self.label1.text = strFuncName;

}
- (IBAction)btnShowClick:(id)sender {
    [self showMoney];
}
1234567891011121314151617181920

这个代码就是点击按钮以后再界面上显示函数名

label1的文字被改成了函数名:-[ViewController showMoney]

把上面的代码进行函数名混淆

新建一个 pch 文件 PrefixHeader.pch ,然后在xcode->target->build settings 搜索prefix header,里面输入pch文件的路径

pch文件里面就加了一行代码: 把 showMoney 宏定义成 AFAdsaf123

arduino 复制代码
#define showMoney AFAdsaf123
1

这样编译之后手机显示结果

显示的label1变成了 -[ViewController AFAdsaf123]

因为宏定义替换了函数名

使用class-dump查看导出的头文件ViewController.h ,因为只混淆了ViewController这个类,注意看函数 - (void)AFAdsaf123; 就是我们写的showMoney方法

objectivec 复制代码
@class UILabel;

@interface ViewController : UIViewController
{
    int _money;
    UILabel *_label1;
}

- (void).cxx_destruct;
@property(nonatomic) __weak UILabel *label1; // @synthesize label1=_label1;
@property(nonatomic) int money; // @synthesize money=_money;
- (void)btnShowClick:(id)arg1;
- (void)AFAdsaf123;
- (void)viewDidLoad;

@end
12345678910111213141516

注意事项

替换变量名时要把set方法替换

下面代码是比上面多了一个setMoney方法,还有在viewDidLoad里面给money变量赋值,调用了 setMoney方法

objectivec 复制代码
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label1;
@property (weak, nonatomic) IBOutlet UILabel *label2;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.money = 100;//这句会调用setMoney
}
- (void)setMoney:(int)money{
    _money = money + 1;
}
-(void)showMoney{
    NSLog(@"money=%d",self.money);
    NSString * strFuncName = [NSString stringWithFormat:@"%s",__func__];
    self.label1.text = strFuncName;

}
- (IBAction)btnShowClick:(id)sender {
    [self showMoney];
    self.label2.text = [NSString stringWithFormat:@"money = %d",_money];
}
@end
1234567891011121314151617181920212223242526

当点击按钮以后,结果是money = 101因为 set方法把money = 100+ 1了,执行结果如下图,label2显示money = 101:

现在我们给money变量进行代码混淆

pch文件中添加一行

arduino 复制代码
#define money xadsf32
1

编译报错:

arduino 复制代码
Use of undeclared identifier '_money'
1

因为_money这个变量已经没有了,现在有的是_xadsf32

代码改成这样才能编译过

ini 复制代码
_xadsf32 = money + 1;
1

下面的_money也要改成self.money:

ini 复制代码
self.label2.text = [NSString stringWithFormat:@"money = %d",self.money];
1

手机运行结果,money = 100,因为没有调用setMoney方法:

变量已经变成了_xadsf32 ,对应的set方法应该是 setXadsf32这样才能配对,所以原来的setMoney方法每调用

正确的变量set方法也要跟着改,在pch中把变量名和 set方法一起改,如下

arduino 复制代码
#define money xadsf32
#define setMoney setXadsf32
12

这样调用就能调用变量 xadsf32的set方法了

_下划线成员变量要一起define混淆

自定义的init开头方法代码混淆会会报错,不能混淆

pch文件中添加deine

arduino 复制代码
#define _money _xadsf32
1

调用的时候可以直接写_money

ini 复制代码
- (void)setMoney:(int)money{
    _money = money + 1;
}
123

如下定义了一个CA类

CA.h

less 复制代码
@interface CA : NSObject
@property (assign,nonatomic)int money;
-(instancetype)initWithMoney:(int) money;
@end

12345

CA.m

objectivec 复制代码
#import "CA.h"

@implementation CA
-(instancetype)initWithMoney:(int) money{
    self = [super init];
    if (self) {
        self.money = money;
    }
    return self;
}
@end
1234567891011

调用代码:

ini 复制代码
    CA * ca1 = [[CA alloc]initWithMoney:50];
    NSLog(@"ca1.money=%d",ca1.money);
12

运行结果:ca1.money=50

但是如果我们把 initWithMoney 函数名混淆

在pch里添加一行:

arduino 复制代码
#define initWithMoney adsf456
1

编译报错: 不能在init方法之外给self 赋值

vbnet 复制代码
Cannot assign to 'self' outside of a method in the init family
1

因为自定义的init必须调用super的init,并且给self成员变量赋值,混淆以后就不是init开头了,编译器不让用init之外的方法名给self赋值,所以无法混淆init开头的函数名

系统方法和类名不能混淆

例如下面把 UIViewController混淆就会编译报错:

pch中添加:

arduino 复制代码
#define UIViewController asdfadfs123
1

编译报错如下图,报错,没有找到ViewController的父类asdfadfs123的声明 :

javascript 复制代码
Cannot find interface declaration for 'asdfadfs123', superclass of 'ViewController'
1

xib和storyboard中的变量和方法名不能混淆

例如上面例子我把storyboard中的label1连线到代码中,编译通过,但是运行以后崩溃,报错如下,没有找到label1的连线

reason: '[<ViewController 0x10520a990> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key label1.'

说明xib 和 storyboard不会读取 pch文件,因为storyboard和xib是 xml格式,打开如下:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
    <device id="retina6_1" orientation="portrait" appearance="light"/>
    //省略一部分
             <connections>
                        <outlet property="label1" destination="eRd-fS-lGp" id="lQU-Vc-xDf"/>
                        <outlet property="label2" destination="9ip-sX-hLa" id="R8d-B7-296"/>
                    </connections>
12345678

可以看到最后2行的label1 label2,而且xml没有读取pch文件,所以不会被#define替换

手动代码混淆涉及许多细节需要注意,使用专业工具如IpaGuard可以自动处理这些复杂性,它支持全面的代码和资源混淆而无需手动配置。

class-dump导出混淆后的头文件,验证函数和变量已经被混淆

最后我们看一下混淆之后用class-dump导出头文件里面的函数名变量名如下:

可以看到

money变成了xadsf32

showMoney变成了 AFAdsaf123

objectivec 复制代码
#import <UIKit/UIViewController.h>

@class UILabel;

@interface ViewController : UIViewController
{
    int _xadsf32;
    UILabel *_label1;
    UILabel *_label2;
}

- (void).cxx_destruct;
@property(nonatomic) __weak UILabel *label2; // @synthesize label2=_label2;
@property(nonatomic) __weak UILabel *label1; // @synthesize label1=_label1;
@property(nonatomic) int xadsf32; // @synthesize xadsf32=_xadsf32;
- (void)btnShowClick:(id)arg1;
- (void)AFAdsaf123;
- (void)viewDidLoad;

@end
1234567891011121314151617181920
相关推荐
计算机毕设VX:Fegn08955 小时前
计算机毕业设计|基于springboot + vue蛋糕店管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
没差c5 小时前
springboot集成flyway
java·spring boot·后端
三水不滴6 小时前
Redis 过期删除与内存淘汰机制
数据库·经验分享·redis·笔记·后端·缓存
笨蛋不要掉眼泪6 小时前
Spring Boot集成LangChain4j:与大模型对话的极速入门
java·人工智能·后端·spring·langchain
sheji34169 小时前
【开题答辩全过程】以 基于SpringBoot的疗养院管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
短剑重铸之日9 小时前
《设计模式》第六篇:装饰器模式
java·后端·设计模式·装饰器模式
码界奇点10 小时前
基于Flask与OpenSSL的自签证书管理系统设计与实现
后端·python·flask·毕业设计·飞书·源代码管理
代码匠心12 小时前
从零开始学Flink:状态管理与容错机制
java·大数据·后端·flink·大数据处理
分享牛12 小时前
LangChain4j从入门到精通-11-结构化输出
后端·python·flask
知识即是力量ol13 小时前
在客户端直接上传文件到OSS
java·后端·客户端·阿里云oss·客户端直传