引言
- get 和post 布尔值参数处理( 使用NSNumber 传BOOL值)https://blog.csdn.net/z929118967/article/details/105138207
- 全局的const常量代替宏常量,节省内存空间。
敏感逻辑的保护: 把函数名隐藏在结构体里,以函数指针成员的形式存储。
编译后,只留了下地址,去掉了名字和参数表,提高了逆向成本和攻击门槛
I 装箱和拆箱
1.1 Java包装类
全部被final修饰,顺便提一下,java.lang.Math,System,String也被final修饰
包装类是使用面向对象的思想把简单的数据类型封装成类
- 特点
包装类把简单的数据类型包装成类。
注:简单数据类型不是类,使用简单数据类型主要为了提高代码的运行效率
装箱和拆箱
把简单数据类型包装成对应的包装类称为boxing
(示例:Integer i=1;将1包装成Integer再使用Object引用Integer对象)
把包装类型转换成简单数据类型称为unboxing
(示例:Integer i=1,int p=i;//将包装类Integer转化成简单数据类型int)
注:Integer的拆箱方法为 int intValue(),其他的包装类以此类推。
1)包装类都重写了toString方法,equals方法,hashCode方法
2)Integer的API:String toBinaryString(int i);
将int类型的数据以二进制字符串形式返回int parseInt(String)
将字符串转化成int类型int parseInt(Stringstr,int i )
将字符串转化成对应的进制 类型,str为被转换的字符串,i为进制类型(10,8,16)Integer valueof(String str)
将字符串转换成Integer类型。
1.2 iOS 装箱
:快速构造数字对象
Objective-C's boxing capability:
The printf function NSLog
offers a number of substitution tokens for printing numbers (%d, %ld, %f, %d, for example). As a convenience, you can use Objective-C's boxing capability to save time and avoid compiler warnings.
- For example
平常也可以使用@
来快速包装数字类型以对象的形式进行存储和传参
[discountArray addObject:[[ self class] mj_objectWithKeyValues:@{@"placeholder":QCTLocal(@"please_input_card_num"),@"btnContent":QCTLocal(@"member_see"),@"EnterModelType":@2,@"isEnabled":@1,@"isLast":@1,@"block":block}]];
II The Truth About NSNumber and BOOL
Name | Typedef | Header | True Value | False Value |
---|---|---|---|---|
BOOL | signed char | objc.h | YES | NO |
bool | _Bool (int) | stdbool.h | true | false |
Boolean | unsigned char | MacTypes.h | TRUE | FALSE |
NSNumber | __NSCFBoolean | Foundation.h | @(YES) | @(NO) |
CFBooleanRef | struct | CoreFoundation.h | kCFBooleanTrue | kCFBooleanFalse |
BOOL不如bool好用
BOOL表示 1是YES , 所以非1是NO. 而bool表示0是false,所以非0是true;
2.1 NSCFBoolean
NSCFBoolean是NSNumber类簇中的一个私有的类,它是通往CFBooleanRef类型的桥梁。NSCFBoolean被用来给Core Foundation的属性列表和集合封装布尔数值。
CFBoolean定义了常量kCFBooleanTrue和kCFBooleanFalse。
NSLog(@"%@", [@(YES) class]);
__NSCFBoolean
2.1 get 和post 布尔值参数处理( 使用NSNumber 传BOOL值)
使用NSNumber 传BOOL值的时候,get 和post对应的参数不一致。get请求对应的0和1,post对应true/false。
[params setValue:[NSNumber numberWithBool:self.viewModel.multipleSwitchCellTableViewCellModel.IsSon] forKey:@"IsSon"];
这个代码使用Post 会将请求参数IsSon 自动转为true/false
若服务端Bool 参数没有支持0和1格式,只支持true false的时候,就需要特殊处理。
//get 需要自己处理
if(self.viewModel.multipleSwitchCellTableViewCellModel.IsSon){
[params setValue:@"true" forKey:@"IsSon"];//
}else{
[params setValue:@"false" forKey:@"IsSon"];//
}
————————————————
版权声明:本文为CSDN博主「iOS逆向」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/z929118967/article/details/105138207
————————————————
版权声明:本文为CSDN博主「iOS逆向」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/z929118967/article/details/105138207
II 常量
2.1 对象常量
随着Apple 的 LLVM 4.0 编译器的发布,让我们欣喜的是NSNumber,NSArray和NSDictionary常量被添加了。
@""
:返回一个由引号内 Unicode 内容初始化的 NSString 对象。@42,@3.14,@YES,@'Z'
:返回一个由相关类构造初始化的 NSNumber 对象
比如 @42 → [NSNumber numberWithInteger:42],或者 @YES → [NSNumber numberWithBool:YES]。支持使用后缀进一步指定类型,如 @42U → [NSNumber numberWithUnsignedInt:42U]。
@[]
:返回一个由冒号分隔的对象列表作为内容的 NSArray 对象。
比如,@[@"A", @NO, @2.718] → [NSArray arrayWithObjects:@"A", @NO, @2.718, nil] (注意在数组常量中结束标记nil是不需要的)。
@{}
:返回一个由特定键-值对初始化作为内容的NSDictionary对象,格式:@{@"someKey" : @"theValue"}
。@():动态评估封装的表达,并返回基于其值的合适的对象常量,这也是使用数字常量和枚举值的指定方式。
(比如,const char*返回NSString,int返回NSNumber。)
2.2 Objective-C 常量
选择器和协议可以作为方法参数。@selector()
和@protocol()
作为伪常量指令返回一个指向特定选择器(SEL)或协议(Protocol *)的指针。
@selector()
:返回一个指向有特定名称的选择器的 SEL 指针。
-performSelector:withObject:
@protocol()
:返回一个指向有特定名称的协议的 Protocol * 指针。
-conformsToProtocol:
2.3 全局的字符串常量代替宏常量,节省内存空间。
应用场景:在声明诸如 userInfo 字典,NSNotification 名称和 NSError 域的时候。
在公共头文件里申明一个 extern 的 NSString const,并在实现文件里定义该 NSString const:
#define KNClientId @""//宏会在编译时,将所有引用宏变量的地方,进行值的替换,造成很多相同的临时字面量,浪费内存
NSString * const KNClientId = @"";// 全局的const常量代替宏常量,节省内存空间。内存只有一份
Consts.h
extern NSString * _Nonnull const KNClientId;//
使用字符串常量来代替宏的使用:
- 定义const 全局常量 ,保证只在一处定义,多处进行引用。
- 全局的const常量代替宏常量,节省内存空间(内存只有一份)。
当 static 使得一个特定的文件中的函数和变量全局可见,extern 则使它们对所有文件可见。
III 扩展:敏感逻辑的保护
https://blog.csdn.net/z929118967/article/details/115857706
3.1 把函数名隐藏在结构体里,以函数指针成员的形式存储
把函数名隐藏在结构体里,以函数指针成员的形式存储。
编译后,只留了下地址,去掉了名字和参数表,提高了逆向成本和攻击门槛
#import <Foundation/Foundation.h>
@interface KNUtil : NSObject
/**
把函数名隐藏在结构体里,以函数指针成员的形式存储。
编译后,只留了下地址,去掉了名字和参数表,提高了逆向成本和攻击门槛
*/
typedef struct _util {
void (*checkKNSign)(char *keys[], unsigned char *output);
}CheckKNSignUtil_t ;
#define ShareKNUtil ([KNUtil sharedUtil])
+ (CheckKNSignUtil_t *)sharedUtil;
- 调用方法
ShareKNUtil->checkKNSign(key, output);
3.2 使用宏进行替换字符串
- 根据前缀搜索出需要混淆的类名、方法名, 生成对应的宏文件
#define run OmWJoTZfCqoPshvr
#define iosre egnjoOFDrFiQVRgr
静态分析时hopper等反汇编工具无法根据string搜索到关键字符