软件环境: IDA Pro 6.4反汇编工具
硬件环境: 电脑、Iphone5手机
最近这几个月,我对Iphone手机感兴趣了,简要地学习了ios的一些基本开发。后来想了想ios6的内核是怎样实现的。于是自己动手研究了。
当然了,有些知识还是请教国外的朋友、网络上的一些知识文章、以及大家的智慧结晶了。 这只能是自己的心得体会。
因为由于IOS内核的代码是不开源的。所以,我必须自己来挖掘和分析。IOS SDK不支持内核的调试。我利用反汇编工具IDA Pro来分析苹果系统的内核。 因为从IDA Pro6.2版本开始,已经完全支持苹果系统的反汇编。经过一些分析,IOS内核和程序开发人员最经常交互的模块是I/O Kit。 从反汇编的角度来看,I/O Kit模块的代码完全就是由C++语言的代码构建而成的。它有一个根类,名叫OSObject类。
从IDA Pro里面看见,I/O Kit模块利用OSObject::new来分配内存空间,然后初始化IOService类,然后调用OSMetaClass::instanceConstructed()函数。OSMetaClass类是:运行时对象类型的检查。IOService类是:为各个类内核扩展定义了接口。 ioreg是:所有附加的IOService列表。在做IOS内核开发的时候,需要修改一个叫着plist的文件,而且需要一个IOKitPersonalities。
在IOS应用层和驱动层相互交互的时候,应用程序可以调用IOServiceOpen函数。这时驱动程序将会接收到DriverClass::NewUserClient方法的调用。在内核中,应用程序到内核程序的每一个连接都由IOUserClient类来表示。如果一个控制请求具有不同类型的参数,那么内核有一个函数,叫着IOConnectCallStructMethod()。IOConnectCallMethod函数也可以用来控制驱动程序。也就是利用IOConnectCallMethod->IOUserClient来找到所有的I/O Kit驱动程序。和Windows驱动程序一样,IOS内核也有派遣函数 IOUserClient::externalMethod()。这个函数是从IOExternalMethodDispatch结构体继承下来的。
在内核中,内存分配函数主要有:IOMalloc、IOFree、IOMallocAligned、IOFreeAligned、IOMallocPageable、IOFreePageable。
当应用层缓冲区映射到内核空间的时候,系统提供了IoMemoryDescriptor类、IOMemoryMap类。
当内核空间映射到用户层的时候,系统使用了IOUserClient类来实现,可以通过这个类的函数ClientMemoryForType来返回。
内核中的网络,网络内存缓冲区主要使用了mbuf数据结构。这个结构体是256字节。在内核中,IONetworkingFamily类:表示内核网络协议栈的底层。在这个类的继承结构中,IONetworkController类用来表示网络硬件的驱动程序,而IONetworkInterface类:用来与数据链路接口层相交互。IOEthernetController类:是所有基于以太网设备的基类。但是经过反汇编,我发现,苹果公司没有发布无线网络驱动程序的开发框架。苹果公司把自己的Airport驱动程序放在IO802Family.kext里面,而且没有源代码和头文件。
Iphone5手机的文件系统缺省分成2个分区,第一个分区是root根文件系统,存放iOS的操作系统文件和MobileMail,MobileSafari的标准应用程序集。
现在root根文件系统接近1GB大小,分区有200MB左右空间剩余。设备的其余存储空间分配给第二个分区,即数据分区, 它装载在/private/var目录下,可以读写。
在根目录的 /etc/fstab文件里有这样的配置:
/dev/disk0s1 / hfs ro 0 1
/dev/disk0s2 /private/var hfs rw,nosuid,nodev 0 2
数据分区的装载配置文件有 nodev标志和nosuid标志。为了防止文件系统层面的攻击,
nodev标志是确保设备节点在可写的数据分区里的存在将会被忽略。nosuid标志是告知内核在数据分区里执行时忽略suid位。
suid位表示执行时需要以超级用户root身份执行,或与当前用户不同的一个用户来执行。这些标志都是iOS内部用来防止权限提升漏洞的防御措施。
在每一架Iphone5手机上都有文件传送服务在运行着。文件传送服务能够通过USB连线存取iPhone的/var/mobile/Media的目录里的文件。文件传送服务由lockdownd守护进程提供,但lockdownd守护进程只提供存取服务,实际由afcd守护进程实现。
在苹果系统上通过MobileDevice.framework,在Windows PC上通过 iTunesMobileDevice.dll来使用。
当从苹果的应用商店安装应用程序时,它们被安装在/var/mobile/Applications目录里,该目录驻留在iPhone的大容量的数据分区里。
由于Iphone手机上的所有应用程序的都是权限较少的用户_wireless,_mdsnresponder,
_securityd角色运行。因此,在内核内部,提升当前运行进程的权限只需要修改进程的proc_t结构的值。这个结构在XNU源代码的/bsd/sys/proc_internal.h文件的proc结构里定义。
得到proc_t结构的地址可以调用current_proc()内核函数,它能取回这个结构的地址。
在调试IOS内核的时候,有一个麻烦的地方,内核里面有一个PE_i_can_has_debugger()函数,内核和一些内核扩展里都用它来决定是否允许调试。如果这个函数返回值是真,那么KDP内核调试器不能使用。
内核函数vm_map_protect()它在映射内存的保护改变时被调用。它不能把内存保护改为同时可写可执行。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!