feature: App 逆向防护

This commit is contained in:
杭城小刘
2024-07-15 20:03:01 +08:00
parent 13f7457be9
commit 83fefff66b
109 changed files with 2549 additions and 672 deletions

View File

@@ -28,7 +28,7 @@ NSInteger age = 27;
用指令`xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转为 c++
<img src="./../assets/BlockViaClangC.png" style="zoom:25%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockViaClangC.png" style="zoom:25%">
`ViewController.m` 的 `viewDidLoad` 函数为 `_I_ViewController_viewDidLoad`
@@ -200,7 +200,7 @@ struct __ViewController__viewDidLoad_block_desc_0 {
}
```
<img src="./../assets/MockBlockDemo.png" style="zoom:25%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/MockBlockDemo.png" style="zoom:25%">
@@ -214,7 +214,7 @@ struct __ViewController__viewDidLoad_block_desc_0 {
<img src="./../assets/block-structure.png" style="zoom:40%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-structure.png" style="zoom:40%">
@@ -237,11 +237,11 @@ printBlock();
用 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++
<img src="./../assets/SimpleBlockExploreDemo.png" style="zoom:40%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/SimpleBlockExploreDemo.png" style="zoom:40%">
概括如下:
<img src="./../assets/SimpleSimpleBlockCaptureStructure.png" style="zoom:40%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/SimpleSimpleBlockCaptureStructure.png" style="zoom:40%">
@@ -257,7 +257,7 @@ printAgeBlock();
用指令 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++ 代码
<img src="./../assets/AutoVariableCaptureByBlock.png" style="zoom:25%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/AutoVariableCaptureByBlock.png" style="zoom:25%">
代码分析:
@@ -293,7 +293,7 @@ printInfoBlock();
用指令 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++ 代码
<img src="./../assets/StaticVariableCaptureByBlock.png" style="zoom:25%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/StaticVariableCaptureByBlock.png" style="zoom:25%">
@@ -334,7 +334,7 @@ age is 28, height is 176
用指令 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++ 代码
<img src="./../assets/GlobalVariableWillNotCaptureByBlock.png" style="zoom:25%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/GlobalVariableWillNotCaptureByBlock.png" style="zoom:25%">
@@ -409,7 +409,7 @@ block 截获变量可以分为:
用指令 `xcrun --sdk iphoneos clang -arch arm64 Person.m -rewrite-objc -o Person-arm64.cpp` 转换为 c++ 代码
<img src="./../assets/BlockWillCaptureMethodSelfVariable.png" style="zoom:25%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockWillCaptureMethodSelfVariable.png" style="zoom:25%">
@@ -442,13 +442,13 @@ block 截获变量可以分为:
我们知道 block 可以看成是一个 oc 对象,所以它有类型,写个 Demo1 验证下
<img src="./../assets/BlockClassType.png" style="zoom:40%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockClassType.png" style="zoom:40%">
也就是说: `__NSGlobalBlock__` -> `NSBlock` -> `NSObject`。
继续验证Demo2
<img src="./../assets/OCBlockType.png" style="zoom:40%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/OCBlockType.png" style="zoom:40%">
同时利用指令 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++
@@ -473,7 +473,7 @@ block 的类型可以通过 isa 或者 class 方法查看,最终都是继承
这3种 block 在内存中的排布如下图:
<img src="./../assets/block-memorylayout.png" style="zoom:40%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-memorylayout.png" style="zoom:40%">
@@ -485,7 +485,7 @@ Demo
由于 ARC 默认会做一些优化,我们将工程的 ARC 关掉Build Setting 里 Automatic Reference Counting 设置为 No
<img src="./../assets/OCStackBlockCrash.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/OCStackBlockCrash.png" style="zoom:30%">
分析:
@@ -497,7 +497,7 @@ Demo
当 `__NSStackBlock__` 调用 copy 方法后会变为 `__NSMallocBlock__`。如下图:
<img src="./../assets/FixStackBlockIssueWithCopy.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/FixStackBlockIssueWithCopy.png" style="zoom:30%">
@@ -531,7 +531,7 @@ Demo 也同时发现,当对 `__NSGlobalBlock__` 调用 copy ,不会变为 `
MRC 下 block 作为函数的返回值是比较危险的。在方法内部,也就是栈上定义的 block函数调用结束后可能一些相关数据就释放了存在潜在风险。
<img src="./../assets/BlockAsFunctionReturnValueIsDangerous.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockAsFunctionReturnValueIsDangerous.png" style="zoom:30%">
@@ -539,13 +539,13 @@ MRC 下 block 作为函数的返回值是比较危险的。在方法内部,也
MRC 下如果函数返回值是 block且 block 内做了 auto 变量捕获的逻辑,编译器会报错:`Returning block that lives on the local stack`。此时 block 应该为 `__NSStackBlock__`
<img src="./../assets/MRCCompileFailedWhenBlockCaptureAutoVarsiableAndAsReturnValue.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/MRCCompileFailedWhenBlockCaptureAutoVarsiableAndAsReturnValue.png" style="zoom:30%">
改为 ARC看看
<img src="./../assets/CompileWillCallCopyWhenBlockCaptureAutoVarsiableAndAsReturnValueInARC.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/CompileWillCallCopyWhenBlockCaptureAutoVarsiableAndAsReturnValueInARC.png" style="zoom:30%">
也就是说ARC 模式下,当 block 捕获了 auto 变量并且作为函数返回值的时候ARC 会自动调用 copy 方法,将 `__NSStackBlock__` 变为 `__NSMallocBlock__`
@@ -624,11 +624,11 @@ ARC 下:如果 block 调用 copy 方法,则 block 仍旧为 `__NSMallocBloc
MRC 下,栈内捕获了 auto 变量的 block 为 `__NSStackBlock__`
<img src="./../assets/LocalBlockInMRC.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/LocalBlockInMRC.png" style="zoom:30%">
改为 ARC
<img src="./../assets/LocalBlockInARCWillCallCopy.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/LocalBlockInARCWillCallCopy.png" style="zoom:30%">
@@ -656,31 +656,31 @@ MRC 下,栈内捕获了 auto 变量的 block 为 `__NSStackBlock__`
ARC 下block 对象捕获了 auto 外部变量,是一种 `__NSMallocBlock__`,捕获的对象将会在 block 销毁后销毁
<img src="./../assets/ARCObjectWillReleasedWhenLeaveScope.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ARCObjectWillReleasedWhenLeaveScope.png" style="zoom:30%">
MRC 下block 对象捕获了 auto 外部变量,是一种 `__NSMallocBlock__`,因为是 MRC所以需要手动管理内存。会发现对象将在离开作用域后立马销毁不会被 block 所捕获。
<img src="./../assets/MRCObjectCannotCaptureByMallocBlock.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/MRCObjectCannotCaptureByMallocBlock.png" style="zoom:30%">
MRC对 block 加 copy变为 `__NSMallocBlock__` 呢?
<img src="./../assets/MRCObjectWillReleaseWhenBlockIsReleased.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/MRCObjectWillReleaseWhenBlockIsReleased.png" style="zoom:30%">
ARC 下对 block 引用的对象加 `__weak` 修饰呢?
<img src="./../assets/ARCWeakObjectWillReleaseWhenLeaveScope.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ARCWeakObjectWillReleaseWhenLeaveScope.png" style="zoom:30%">
用指令 `xcrun --sdk iphoneos clang -arch arm64 main.m -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 -o main-arm64.cpp` 转换为 c++ 进行分析看看。注意,因为 weak 涉及运行时,需要在 clang 后添加 runtime 参数
<img src="./../assets/WeakObjectCapturedByBlock.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/WeakObjectCapturedByBlock.png" style="zoom:30%">
如果对 Person 不加 `__weak` 修饰block 结构体内部将会是`__strong`。
<img src="./../assets/StrongObjectCapturedByBlock.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/StrongObjectCapturedByBlock.png" style="zoom:30%">
@@ -724,11 +724,11 @@ static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_objec
Demo1:
<img src="./../assets/ObjectWillReleaseWhenGCDTimeout.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ObjectWillReleaseWhenGCDTimeout.png" style="zoom:30%">
Demo2
<img src="./../assets/WeakObjectWillReleaseWhenLeaveScope.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/WeakObjectWillReleaseWhenLeaveScope.png" style="zoom:30%">
@@ -738,13 +738,13 @@ Demo2
Demo3
<img src="./../assets/DoubleGCDMainQueueTaskObjectWillReleaseAfterTotalTime.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/DoubleGCDMainQueueTaskObjectWillReleaseAfterTotalTime.png" style="zoom:30%">
因为 GCD 是给 MainQueue 添加任务的所以是串行2个任务前后按照3s、1s 后打印。由于最晚的一个任务是访问强指针对象,所以不会释放。等到 GCD 全部执行完后Person 才释放。
Demo4
<img src="./../assets/DoubleGCDMainQueueTaskObjectWillReleaseAfterStrongReference.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/DoubleGCDMainQueueTaskObjectWillReleaseAfterStrongReference.png" style="zoom:30%">
@@ -829,7 +829,7 @@ MyBlock block = ^{
转为 C++
<img src="./../assets/BlockChangeVariableUse__Block.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockChangeVariableUse__Block.png" style="zoom:30%">
```c++
struct __Block_byref_age_0 {
@@ -873,7 +873,7 @@ block 内部的函数在修改 age 的时候其实就是通过 `__main_block_imp
<img src="./../assets/block-forwarding.png" style="zoom:40%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-forwarding.png" style="zoom:40%">
@@ -885,7 +885,7 @@ QA为什么`__block` 变量的 `__Block_byref_age_0` 结构体并不在 block
看个有趣的例子,验证下 __block 的效果
<img src="./../assets/Block__BLOCKAssignObject.png" style="zoom:30%" />
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/Block__BLOCKAssignObject.png" style="zoom:30%" />
转换成 c++ 可以看到
@@ -930,7 +930,7 @@ __attribute__((__blocks__(byref))) __Block_byref_num2_0 num2 = {(void*)0,(__Bloc
对` __block` 修饰的对象clang 转换为 c++ 后如下:
<img src="./../assets/BlockChangeVariableUse__BlockOnObject.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockChangeVariableUse__BlockOnObject.png" style="zoom:30%">
@@ -943,7 +943,7 @@ __attribute__((__blocks__(byref))) __Block_byref_num2_0 num2 = {(void*)0,(__Bloc
注意:
<img src="./../assets/NSMutableArrayDonotNeedBlockToUseArray.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/NSMutableArrayDonotNeedBlockToUseArray.png" style="zoom:30%">
@@ -1013,7 +1013,7 @@ int main(int argc, const char * argv[]) {
我们将断点设置到 NSLog 这里,打印出自定义结构体 `__main_block_impl_0` 中的 age 。
<img src="./../assets/Block-variableAddress.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/Block-variableAddress.png" style="zoom:30%">
```c
// 0x0000000105231f70
@@ -1100,7 +1100,7 @@ in block: age = 28, address is 0x600000464938
<img src="./../assets/BlockChangeOuterValue.png" style="zoom:100%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockChangeOuterValue.png" style="zoom:100%">
分析:
@@ -1150,7 +1150,7 @@ in block: age = 28, address is 0x600000464938
那么` __forwarding` 的作用是什么?为什么这么设计
<img src="./../assets/block_forwarding.png" style="zoom:15%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block_forwarding.png" style="zoom:15%">
@@ -1168,17 +1168,17 @@ in block: age = 28, address is 0x600000464938
Demo1
<img src="./../assets/BlockVariableDemo1.png" style="zoom:20%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockVariableDemo1.png" style="zoom:20%">
<img src="./../assets/block-strong-object-memoery.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-strong-object-memoery.png" style="zoom:30%">
Demo2
<img src="./../assets/BlockVariableDemo2.png" style="zoom:20%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockVariableDemo2.png" style="zoom:20%">
<img src="./../assets/block-weak-object-memoery.png" style="zoom:30%" >
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-weak-object-memoery.png" style="zoom:30%" >
@@ -1304,7 +1304,7 @@ p.block();
`__unsafe_retained` 因为不安全所以不推荐,`__block` 因为使用繁琐,且必须等到调用 block 才会释放内存所以不推荐。ARC 下最佳用 `__weak`
![](./../assets/block_object_cycle.png)
![](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block_object_cycle.png)