00:00
好了同学们,那么接下来的话呢,我们刚刚啊了解完了这个分析后果的一个简单使用了之后,对吧?里面呢,就是这个函数和这个结构体对不对,那么接下来呢,我们来讨论讨论非机户口的一个原理。非机啊,可以后我们的C函数,但是我们知道函数是什么,是静态的呀,也就是说在编译的时候,我们编译器就知道了它的实线的地址对不对啊,这也就是为什么C函数只写函数的声明,调用的时候就会报错对吧?你生命一个函数,你不写函数的实现,你调用它是不是会报错,OC不会,OC最终运行才会crash,才会崩掉,说找不到方法对吧?那么为什么分析如果还能改变C函数的调用呢?难道函数也有动态的特性吗?啊,难道还是有动态特性吗?那么关于Facebook的原理呢?这里有张图,这个是什么呢?这个就是咱们Facebook这个网站上面的read里面的一个图啊,这个图呢,大家可能看不清楚是吧。这张图我把它放大一点。
01:01
这样子就应该看的清楚了,对吧,就这么一张图啊,然后呢,怎么去它是怎么工作的,这后面有解释啊,那么呢,这个图现在一看呢,大家也挺懵逼,没关系,我跟大家先解释一下,等一下呢,我们再回过头来看这张图,你就能完全理解这张图了,知道吗?好,首先我在这里做个小小的笔记,OK,我在这里做笔记啊,因为这里面呢,鬼画胡一样注意。我现在不带大家去分析源码啊,关于分析源码的分析的网上有一大堆的文章,你可以自己去看,好吧,我今天呢,分析它的原理,它到底是怎么做到的,首先我们知道我问大家一个问题。咱们的可执行文件是不是ma o是吧?咱们的ma o它是怎么进入到内存的?啊。他是不是被一个东西叫做DYLD啊,是不是这个们给加载到内存的。是还是不是?是不是的,它是不是被DLD加载进来的,对吧?然后呢,我们通过LDB调试的时候,通过image list等一下我会用到啊,我们是可以看到它加载麦克欧之后还加载了哪些依赖库,然后注意这里呢,就要提到一个技术,这里注意啊,咱们有一个技术叫做as s lr啊。
02:09
ALR,这个今天介绍一下啊,VIP里面讲到的过,它是什么呢?翻译过来就是地址空间布局随机化哈,说白了这是什么技术呢?这个技术就是当DYLD加载你每一个可执行文可执行文件的时候,加载你每一个APP的时候,它的地址前面加了一个偏移地址。知道吧,前面加的这个偏移地址,它是一个随机值。明白吗?好,有了这几个这有了这几个概念之了,有了这几个概念之后,接下来我们来看一下它会有什么变化,我们思考一个问题。我在PPT里面呢,我在PPT里面呢,再给大家画个图好吧,我在这里面画个图啊。那我画,我画个图。呃,那首先啊看着。我这里呢,画个画个内存,这咱们的内存啊,这咱们内存啊,注意看啊,咱们的这个内存的话呢,颜色呢,就搞浅一点好吧,啊颜色浅一点好,然后呢,紧接着呢,咱们这个操作系统啊。
03:04
是不是里面有一个东有咱们的这个iOS操作系统啊,在内存里面肯定有一个应用程序在里面的,这个应用程序叫什么呢?这个应用程序就叫做DLD。这这个门DYLD。这方面是不是专门用来加载的,对吧。他专门用来加载别人的,对不对是吧,我刚刚说了好,那么紧接着注意看啊。咱们除了有这个DYLD之外呢,咱们有一个APP,这个这个APP有一个叫做ma对吧,这个APP啊里面就有一个可执行文件,这个可执行文件目前在磁盘里面,它要被DYLD这个。程序给加载到内存里面去,是不是这么一个过程,每次都是这样一个过程,对不对,好,那么注意听好了,那么首先啊,咱们did在内存里面它有一个地址对吧,这前面有一个内存地址的,那么注意,由于我们麦克O每次加载的时候,你的地址是不是不一样的,随机的是吧,前面会有一个随机值,随机的偏移值,所以说注意,所以说我们的ma o呢,在这个内存当中的地址它是不确定的,好,这是第一个,这是第一个,第二个有一个问题,什么问题我现在问大家,我现在问大家。
04:13
我刚刚写的那个fun c和ns log,他在内存里面的地址是不是不一样的?它有绝对的不一样,它的位置就不一样,什么位置不一样,我问你fun c在不在这个ma o里面。我自己自定义的那个C语言的函数在不在这个ma o里面。在不在,在不在,你这个可执行文件里面在不在,不在吗?诶再思考一下在不在,思考思考我说的是fun c,我自己定义的那个函数,我自己写的那个函数方法实现是我自己写的,在不在。在吧,对不对,在啊,我自己定义的函数,它一定是在我自己的这个ma o可执行文件里面的,对不对,因为他把它编译了之后变成了二进制文件,所以说自己的定义的这个fun c,它一定是在这个麦里面的,好,那么紧接着我再问大家一个问题,A lock在不在?
05:02
NS洛,在不在你的麦克风里面?NS在你的Mac里面吗?不在,对不对,这一下就想明白了,哦,NS不在,那NS在哪里呢?注意NS在很多的啊,在不是在很多,我们系统有很多的什么动态库。这些系统的动态库,这就是我们系统的一个,这是我们系统的动态库,它在某一个系统的动态库里面,这个系统的动态库它一定是在系统启动的时候,当别人用到的时候,对它加载进内存的,而这个东西它有一个共享缓存区,公用的大家都用它,你用ns log,我也用,你的APP有,我的APP也有,但是其实它就只有一份内存,对吧?它在这个内存里面,好,那么接下来注意听好了,当我的麦克O被DYLD加载进内存的时候,我的这个放C里面有一句代码,什么呢?叫做ns log,那么请问这个时候我去调用ns log的时候,是不是要找到这个系统的动态库?
06:02
是还是不是,是的,给我打打个一。是不是的。是的吧,要找到系统的函数地址对不对。那我的Mac里面怎么找到系统的函数地址的呢?我有可能知道吗?我告诉你,在你的程序启动之前,你绝对都不知道,没有人知道。你的手机和我的手机。里面的n log的地址是绝对不一样的。你每次启动的时候都不一样的。明白吗?明白了,敲个一,那谁知道呢?谁知道呢?谁知道咱们的ns log在哪里呢?注意,他知道。他是谁?它是DYLD。所有的可持文件都由它加载的。能理解吗?真正调用的系统库函数的真实地址。DYLD最清楚在程序运行的时候,是通过DYLD加载了咱们的ma o,它一旦加载ma o,注意啊,它一旦加载了马克欧。
07:09
我们我们的苹果的Mac文件呢,它采用了一个技术,我这里给大家讲一下,采用了一个什么技术呢?叫做pic技术,叫做。位置独立代码。叫做位置独立代码。比如说,当你的程序要调用一个麦克外部的系统函数的时候,它首先会在哪里呢?注意听好了啊,这里讲的就是技术点了啊。它首先会在哪里呢?当如果说啊,当我的麦克欧要调用我麦克欧外部的一个函数,也就是说,比方说系统的库函数NX log啊,要调用这样的函数,那么它会在注意咱们的麦克有很多的段,它会在贝塔段。Data,这是数据段建立,注意它会建立创建一个指针。注意它会创建一个指针,在data塔段里面去创建一个数据,相当于而给这个空间八个字节的空间,因为八个字节足够保存一个内存地址了,知道吗?给八个字节的一个空间,这个空间放什么呢?就专门用来放外部函数的地址,但是前期他知道吗?他不知道,注意他不知道,那么诶老我们知道有两个特别经常用到的段,一个是data段,一个是什么,放代码在哪个段,T段。
08:23
TT端是干嘛?T端是只读的,知道吗?T是只读的啊,Data端放数据的,那么它会在这里面建立一个指针,知道吗?T端是只读的,所以说它不会修改好,它会在对大端上建立一个指针,这个指针呢?这个指针由谁来操作呢?由我们的DYLD,当DYLD加载了咱们的ma o之后。他知道咱们的ns log在哪里,所以说DD呢,就会找到你的ma o啊,看一下A哥们,你要依赖哪些库啊,咱们的ma o里面是不是会有很多的依赖的库啊,我们是不是在前面在load commands里面,我上次讲过啊,如果不了解的没关系,你就知道ma克O这个文件呢,前面它有个load commands这里面呢,会告诉别人,诶我需要依赖哪些库啊,DLD知道了啊,你要依赖这个库,这个库啊,你要依赖这个,OK,没问题,接下来它干什么,它进行绑定。
09:10
把这个DYLD的什么,这个这个这个库里面的ns log的地址,哎,给你的这个data塔段里面的那个指针给它复制进去知道吗?所以说为什么叫做DYLD,叫做dynamic loader,就这个意思,因为它就是用来动态进行加载的。明白了吗?动态加载的这些个库的地址是动态告诉你的,明白了吗?所以也就是为什么我今天一开始就问你们同学们,你知道C。是静态的,但是C语言的函数有没有动态的性质呢?今天你就发现了,原来C函数它依然也有动态的性质,知道了吗?这是系统。造就的。明白的同学来个一。明白的同学来能想能想清楚吧。这是系统造就的。明白吧,啊,这个东西大家一定要知道,所以说CC语言是静态的,是的,这个语言特性是静态的,但是也不代表着所有的C函数都是静态的,知道吗?啊,不代表所有的实验速度,所以说你学完了之后,你也会发现哦,原来C的底层也有动态的事情,好吧,好,那么呢,注意将这个注意看咱们的这个。
10:17
DLD就会绑定这个函数,知道吗?绑定函数绑定里面的一个符号,也就是塔段里面的这个指针,我们称之为符号,它和外部的函数就绑在一起了,也就是为什么分析后的那个函数的名字,你仔细看一下,我们那个函数的名字叫什么?不叫做一个陷阱,不叫做改变呢?不叫做改变叫什么呢?叫做rebo。重新绑定申报符号,重新绑定符号就是这个原因,因为他是要重新绑定你之前DYLD去绑定的那个符号,明白了没有,所以说也就是为什么分hook只能修改系统的函数,不能够hook自己的函数。知道吗?明白了没有?所以只能获OOK系统的C级别函数,是的非后只能去修改系统的C级别函数,明白了啊,修改不了自己的函数,知道吧,OK,大家理解了吧。
11:05
好的好,那么刚刚汉克老师说了这么多的原理和底层的东西是吧啊。到底是真的吗?是真的吗?是吧?万一骗你的呢?是不是吧?杨里面,那么接下来是不是要证明一下是吧?讲的挺像那么一回事的,是不是讲的真的像那么一回事啊,万一错的呢?是吧?错的你也下是吧?你信吗?是吧?那么接下来我们验证一下好吧,验证一下啊,要证明一下嘛,不证明这个东西大家也记不住,刚刚讲了那么多,其实也没用好,那么看着啊。我们就使用第一个工程啊,第一个工程,这个工程没变的,是不是这个工程啊,001FACEBOOK DEMO啊,就用这个就用这个,注意看啊,我我既然要验证这个东西啊。我要验证这个东西,我就必须要操作咱们的麦克O,而现在此时此刻呢,它是叉八六架构的,为什么模拟器嘛,我现在把它调成真机。调增剂啊,调真剂的话呢,这个。版本号要改一下,嗯,好,然后呢,接下来注意看啊,调整真机我不需要运行,我只要build啊,只要build当然运行也可以啊,我们先看一个东西,在这里呢,我有一个细节我先跟大家讲一下,在这个地方我先敲一个n log。
12:08
不然的话,等一下你看不到效果啊,为什么呢?诶刚刚我说的有两张表,我刚刚提到了一个词,叫做懒加载和非懒加载,还记得吗?我刚刚是不是提到了这么一个东西啊,叫做懒加载和非懒加载符号表啊对我们的这个符号表呢,又分为两个,一个是懒加载的,一个是非懒加载,懒加载是什么意思啊,永导我才加载嘛,所以说如果说注意N在哪里呢?诶,你猜对了,就在懒加代表里面知道吧,啊,因为如果说我不调用,那它就没用啊,所以说你等一下看不到它的指针知道吧?嗯。好,我在这里呢,注意这个地方进行。交换的是吧,啊进行重绑定的,所以说在这后面呢,我写一个函数啊完毕了。看着啊。在这上面我敲个断点,这就和咱们的master Switch一样的,我也在这里敲个断点,我们先运行,我们先运行啊看着。
13:01
我来看一看,这个地方修改了之后,咱们的地址是不是真的发生了变化,发生了改变,对吧,我们是可以看到。代码他是不会骗人的,对不对,汉克老师刚刚说的,有可能老师老糊涂了,记错了呢,对不对?好,我们先这样先先build完了是吧。手机等一下手机的这个。屏幕打开。然后我看一下这个WiFi是不是连的这个。WiFi式的,WiFi式的好,没关系,给它慢慢运行好吧,我手机现在已经屏幕解锁了,我先看什么呢?我先看它的Mac o。点击它。刘辉。这个鼠标还不灵呢。怎么只有open只能修一翻的呢?看守。犯的。好,然后呢,我在卡加运行好看着啊。麦克在哪里,是不是在这里面?这是我们的可执行文件吧,我今天就要分析它了啊,就就要分析它了,卡加杯,好,这是我们的黑不溜秋的可执行文件,看着啊,我来这里。
14:03
在跑着。然后呢,打开咱们的Mac o u,这个是方便我们查看Mac的这个工具,我之前给过大家。卡加O,然后呢,找到咱们的这个飞机,后果好,我现在呢。好看着啊。接下来。我刚刚是不是说了,咱们有一个符号表啊,一个是懒加载,一个是非懒加载,对不对,那么咱们的符号表在哪里呢?在注意在咱们的。T端吗?不在T端是代码,它里面是什么?只读的data端是咱们的数据,那么注意这里呢,就有一个,哎,把它展开这个god展开,这里面就有一个什么,诶非懒加载的一个符号表,下面这个呢,就是lazy symbol,它是懒加载的符号表,那注意看在懒加载符号表里面第一个是不是就是ns log看到了吗?看到了打个一。看到吧,所以说ns log呢,它是一个属于加载的啊,如果你不调用这个ns log的这里面它就不会值,知道吗?它就不会负值,当然ma克O里面本来就不可能有值啊,Ma克O里面的值是没有用的,因为你没运行我们这个它这个符号里面的值是谁给的,谁给的,DYLD给的,什么时候给啊,运行的那一刻给知道吧,好,那么接下来我们知道啊这个原理好,那么接下来啊。
15:15
快走。呃,我来看看什么呢?我现在是不是到了这个函数啊,这个函数现在还没开始执行对不对,也就还没有开始绑定咱们的ns log对吧,还没有开始绑定咱们的,那么接下来我怎么找到咱们的ns log的地址呢?注意啊,我的这个ns log的函数地址我怎么找到呢?注意咱们就可以通过借助Mac o了咱们的这个ns log。啊不,我不找函数的例子,我我我要找函数的例子,那函数例子怎么找呢?首先通过符号来找。我说了,这里面保存的是什么?啊,这里面保存的是什么,是不是咱们NS洛的。真实地址啊,是不是啊。这是占八个字节的。是不是占八个字节,我要找到这个指针,这是个指针嘛,它占八个字节对不对,这个指针里面保存的就是ns log的地址了,所以说那我现在要找到这个指针呢?这个指针在哪里呢?注意这里有一个offset,这个指针呢,在咱们O文件偏移一个0X8018这样一个地址,知道吧?啊,也就是在咱们的ma o文件的地址上面加上一个8018就可以了啊,这就能找到我这个指针了,好,那么接下来注意看啊,那我的ma文件现在是。
16:27
在内存的哪块区域呢?咱们可以通过LDB来查看一列,来一个list,注意这个是模块的列表回车,这个时候呢,他就会告诉你啊,咱们加载了哪些模块,你看非常多是不是,你看非常之多啊,非常多好第一个加载的是什么呢?注意看这个位置是不是飞机后果DEMO这个是什么?Ma o文件也就第一个加载的是咱们的可执行文件,加载了你之后呢,第二个就加载咱们的DYLD,然后呢,再加载咱们的function是吧,Function啊,咱们的这个呃,Foundation foundation foundation对吧,再加上foundation,他这样子加载的好吧。
17:01
好,那么所谓符号是什么,符号是什么意思呢?符号是因为啊咱们的我刚刚我刚刚这里的提到了是吧?我刚这里给大家讲了,符号的产生是因为啊咱们的苹果啊,它使用了这个pic技术,这个pic技术呢,就是位这个代码独立啊位置代码独立,那么这个技术是干嘛的?这个技术就是咱们的慢O里面去,因为它有共享缓存库,所以说咱们调用这个ns log的时候,你能找到ns log吗?找不到,所以说它就需要一个符号在哪里呢?在你的可执行文件里面。知道吗?它就需要一个符号记号告诉咱们的加载的这个DYLD,哦,你要调用n log,好,我告诉你它在哪里。这个符号就是起这个作用,明白了没有道法自然同学明白了吗?这个符号的作用就是这个。所谓符号就是我这里写的是ns log少啊,Ns log就是一个指针,那这个指针指向的是谁呢?指向的是真正的那个ns log,但是你前面你不知道ns log在哪里啊,因为它是系统的函数,在你运行的那一刻,DYLD就赋值给这个指针,就告诉你n log在这里,符号的作用就是这个作用,明白了给老师敲个一好吧。
18:07
明白了吧,啊,就这个作用,好吧,嗯,好,那么紧接着我们再往下走啊对,好,那么接下来我们来看到这里呢,有我们的麦克O的地址,对不对啊,麦欧的地址在哪里呢?注意这就是咱们ma克O这个文件的加载的到内存里面的这个内存地址,这是内存地址,知道吗?好,我卡梦加C复制一下干掉它,那么接下来注意我读内存,按照16进制来读它的数据卡加V,这是咱们的ma克O,注意这是咱们的ma o,那么我刚刚说了咱们的这一个。来到麦克O文件这里啊,咱们的ns log这个符号在哪里啊,是不是ma克O偏移一个0X8018呀,所以说这个符号再加上一个0X8018,明白吧,就是在麦克O的基础上加上一个0X8018回车,这个时候它八个字节就是咱们的指针里面的指了,这个就是读的指针啊,指针的位置在这里。
19:02
指针里面的值是哪个呢?是这个,看明白了吗?这个值是谁?我先问你。告诉我。这个指是谁,指向了谁?觉得指向的是ns log的敲个一,觉得指向的是my ns log的敲个二。思考一下。是ns log还是my ns log?Ns log嘛,为什么它在绑定之前嘛,对不对,所以说它指向的是ns log,那怎么证明呢?看一下呗,是不是我们看一下什么,看一下汇编好吧,看一下汇编啊看汇编的话怎么看呢?我这里给大家介绍一个指令叫做汇编是什么December吧,所以说Dis。杠S就是打印汇编代码,那么呢,这个地址是什么呢?由于咱们注意咱们的iOS它是小端序的啊,这个CPU小端序的,这个我也会讲的啊,这个小端序的,所以说你要从从这里读啊,从这边往这边读,知道吧,好,那么零该是01859DB074是从右往左读的啊,从右往左读的知道吧,这么读的好,那么就是这个地址好,那么呢,我们来看一下。
20:01
回车注意看这个是不是在方方这个foundation里面的n log,看到同学咱们来走向话好吗?这个时候咱们就找到了这个什么,找到了这个ns log的地址了,看到了吗?就这个就这个看到了没有,你看这个地址值是不是其四,那么接下来怎么验证它是ns log了,注意看我这个地方哦,还没绑定,还没绑定,那现在还看不到,还看不到,好吧,这就是ns log,知道吗?N log好那么呢,接下来知道了,现在它是指向的ns work了,注意啊,现在咱们这一个什么,这个符号就是这个地址。咱们这个符号指向的还是ns log对不对?是的吧,指向的还是ns log,接下来咱们做一件事情,单步走一步。现在是不是走到了啊。这个时候改变了,没修改了吧,修改了让我的人是不是要看一下啦,是不是要看一下啦,那么我们照样是看这个例子。看我们的符号吧,好,符号里面的值你看发生变化了没有。
21:00
是不是发生变化了,之前是什么七四,现在是什么九四了,对不对,而且前面也变了啊,前面也变了,那这个值是谁呢。你觉得是谁来December查看一下吧,来零幺多少0102171D94回车注意看谁。看同看到同学咱们那种情况是不是修改成功了,在你的分析这个DEMO ma o文件里面的my ns log看到了吧。改了吧。符号被修改了知道吗?就是我刚刚这里演示的过程,大家应该看懂了吧,就是在这个函数之前,哎,咱们是不是有一个符号地址就是这个就是这个这个个们是吧,就这个们n log这个这个门之前它保存的确实是n s log的值,现在重绑定的这个函数一定要玩重绑定,绑定在哪里呢?绑定在了MY。N log格了,所以说修改什么,所以说它内部做了什么事情,就是非修后格改变了。
22:02
这个东西说白了就是他改变了这个东西。他其实就是改变了他知道吗?就是改变了他,这就是他做的事情啊,那么刚才我这里为什么要写上n log,这个大家应该也知道了,对吧?我为什么要写上n log,是因为啊,咱们这个属于lazy symbol,如果我刚刚不写这个n log,注意听好了,如果我不写结果会是怎样的?刚刚的调试大家猜想一下,我断点断到这个地方,断点断到这个地方,我问你。就是我刚刚如果不写这个,刚才说我断点断的这个地方,那么我获取到这个这个什么,这个符号我能获取吧,能获取,但是这个符号里面首先保存的这个值是谁。一定不是ns log,知道吗?它保存的就是一段垃圾值,它绝对不是ns log,因为什么呢?因为你系统没有调用过,所以说它就不会保存,知道吧,它就不保存,它一直是个垃圾值,然后直到我们要用了啊,这个时候它就保存了,明白了吧,就这么一个过程,好吧,就这么一个过程,好,这就是非行后的原理的一个探究,明白了没有,明白的同学打个一好不好,这里明白了的同学咱们敲个一好不好,明白的同学敲个一啊。
23:09
干掉,然后呢,把这个保存。
我来说两句