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
相关推荐
程序员威哥2 小时前
YOLOv8用ConvMixer结构:简化Backbone,速度+20%,mAP仅降0.9%
后端
开心猴爷2 小时前
如何在苹果手机上面进行抓包?iOS代理抓包,数据流抓包
后端
程序员威哥2 小时前
轻量型YOLO入门:在嵌入式设备上跑通目标检测(树莓派实战)
后端
程序员威哥2 小时前
基于YOLOv7的目标检测实战:彻底解决新手常见的「训练不收敛」问题
后端
程序员威哥2 小时前
从数据集标注到模型评估:YOLO完整工作流实战(附避坑清单)
后端
明月_清风2 小时前
模仿 create-vite / create-vue 风格写一个现代脚手架
前端·后端
南囝coding2 小时前
CSS终于能做瀑布流了!三行代码搞定,告别JavaScript布局
前端·后端·面试
Calvad0s2 小时前
application.yml和bootstrap.yml这两个配置文件有什么区别?
后端
aibigdata2 小时前
重塑 LLM 的“第二大脑”——RAG 技术原理与核心价值深度解析
后端