文章目录
混淆函数名原理
代码混淆替换函数名的主要原理是用宏定义#define来替换代码里的函数名或者变量民
代码例子没混淆的函数名
ViewController.h文件
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (assign,nonatomic)int money;
-(void)showMoney;
@end
@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];
}
这个代码就是点击按钮以后再界面上显示函数名,显示结果,如下图
label1的文字被改成了函数名:-[ViewController showMoney]
把上面的代码进行函数名混淆
新建一个pch文件 PrefixHeader.pch ,然后在xcode->target->build settings 搜索prefix header,里面输入pch文件的路径
pch文件里面就加了一行代码: 把 showMoney 宏定义成 AFAdsaf123
#define showMoney AFAdsaf123
这样编译之后手机显示结果如下图:
显示的label1变成了 -[ViewController AFAdsaf123]
因为宏定义替换了函数名
使用class-dump查看导出的头文件ViewController.h ,因为只混淆了ViewController这个类,注意看函数 - (void)AFAdsaf123; 就是我们写的showMoney方法
@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
注意事项
替换变量名时要把set方法替换
下面代码是比上面多了一个setMoney方法,还有在viewDidLoad里面给money变量赋值,调用了 setMoney方法
@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
当点击按钮以后,结果是money = 101因为 set方法把money = 100+ 1了,执行结果如下图,label2显示money = 101:
现在我们给money变量进行代码混淆
pch文件中添加一行
#define money xadsf32
编译报错:
Use of undeclared identifier '_money'
因为_money这个变量已经没有了,现在有的是_xadsf32
代码改成这样才能编译过
_xadsf32 = money + 1;
下面的_money也要改成self.money:
self.label2.text = [NSString stringWithFormat:@"money = %d",self.money];
手机运行结果如下图,money = 100,因为没有调用setMoney方法:
变量已经变成了_xadsf32 ,对应的set方法应该是 setXadsf32这样才能配对,所以原来的setMoney方法每调用
正确的变量set方法也要跟着改,在pch中把变量名和 set方法一起改,如下
#define money xadsf32
#define setMoney setXadsf32
这样调用就能调用变量 xadsf32的set方法了
_下划线成员变量要一起define混淆
自定义的init开头方法代码混淆会会报错,不能混淆
pch文件中添加deine
#define _money _xadsf32
调用的时候可以直接写_money
- (void)setMoney:(int)money{
_money = money + 1;
}
如下定义了一个CA类
CA.h
@interface CA : NSObject
@property (assign,nonatomic)int money;
-(instancetype)initWithMoney:(int) money;
@end
CA.m
#import "CA.h"
@implementation CA
-(instancetype)initWithMoney:(int) money{
self = [super init];
if (self) {
self.money = money;
}
return self;
}
@end
调用代码:
CA * ca1 = [[CA alloc]initWithMoney:50];
NSLog(@"ca1.money=%d",ca1.money);
运行结果:ca1.money=50
但是如果我们把 initWithMoney 函数名混淆
在pch里添加一行:
#define initWithMoney adsf456
编译报错: 不能在init方法之外给self 赋值
Cannot assign to 'self' outside of a method in the init family
因为自定义的init必须调用super的init,并且给self成员变量赋值,混淆以后就不是init开头了,编译器不让用init之外的方法名给self赋值,所以无法混淆init开头的函数名
系统方法和类名不能混淆
例如下面把 UIViewController混淆就会编译报错:
pch中添加:
#define UIViewController asdfadfs123
编译报错如下图,报错,没有找到ViewController的父类asdfadfs123的声明 :
Cannot find interface declaration for 'asdfadfs123', superclass of 'ViewController'
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 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>
可以看到最后2行的label1 label2,而且xml没有读取pch文件,所以不会被#define替换
class-dump导出混淆后的头文件,验证函数和变量已经被混淆
最后我们看一下混淆之后用class-dump导出头文件里面的函数名变量名如下:
可以看到
money变成了xadsf32
showMoney变成了 AFAdsaf123
#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