mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-24 20:00:37 +00:00
feature: App 逆向防护
This commit is contained in:
@@ -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`
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user