相信本书的绝大部分读者从接触iOS开发的第一天起,就不断被苹果灌输这样一个观念——iOS中没有真正的后台多任务,你的App在后台将被大大限制。如果你是一个纯粹的App Store 开发者,坚信并坚守这个观念,那么它将是你的App通过苹果审核的助推剂;但既然你阅读了这本书,想要在学习逆向工程的同时了解一些官方文档没有阐述的事实,那么你就要保持冷静,理性思考。让我们一起回想一下iPhone上的一些现象。
1)当我们正在用iPhone上网或刷微博时来了一个电话,所有其他操作会立即中断,iOS第一时间将接听电话的界面呈现在我们面前。如果iOS中没有真正的后台多任务,系统是如何实时处理这个来电的呢?
2)对于那些经常收到垃圾短信和骚扰电话的朋友来说,类似于SMSNinja这样的防火墙软件必不可少。如果它不能常驻iOS后台,怎么能够实时地处理并过滤收到的每一条短信呢?
3)Backgrounder是一款iOS 5时代的插件,它能够帮助App实现真正的后台运行。有了它,我们再也不用担心因为push功能的不给力而漏收QQ消息啦!如果iOS中没有真正的后台多任务, Backgrounder怎么会存在呢?
这些现象无一不说明iOS实际上存在真正的后台多任务。那么难道是苹果说错了?并不是!对于StoreApp来说,当用户按下home键时,进程就进入后台了,大多数功能都会被暂停;也就是说,对于遵纪守法的App Store开发者来说,可以把iOS看作是没有真正后台多任务的系统,因为你唯一能干的事不支持后台多任务。但iOS源于OSX,后者又跟所有类UNIX操作系统一样,有 daemon(即守护进程,Windows称Service)的概念。越狱开放了iOS全文件系统,daemon也得以展现在我们面前。
Daemon为后台运行而生,给用户提供了各种“守护”,如imagent保障了iMessage的正确收发,mediaserverd处理了几乎所有的音频、视频,syslogd则用于记录系统日志等。iOS中的daemon主要由一个可执行文件和一个plist文件构成。iOS的根进程是launchd,它会在开机时检查/System/Library/LaunchDaemons和/Library/ LaunchDaemons下所有格式符合规定的plist文件,然后启动对应的daemon。这里的plist文件与App中的Info.plist文件作用类似,即记录daemon的基本信息,如下:
snakeninnys-MacBook:~ snakeninny$ plutil -p /Users/snakeninny/Code/iOSSystemBinaries/ 8.1.1_iPhone5/System/Library/LaunchDaemons/com.apple.imagent.plist
{
"WorkingDirectory" => "/tmp"
"Label" => "com.apple.imagent"
"JetsamProperties" => {
"JetsamMemoryLimit" => 3000
}
"EnvironmentVariables" => {
"NSRunningFromLaunchd" => "1"
}
"POSIXSpawnType" => "Interactive"
"MachServices" => {
"com.apple.hsa-authentication-server" => 1
"com.apple.imagent.embedded.auth" => 1
"com.apple.incoming-call-filter-server" => 1
}
"UserName" => "mobile"
"RunAtLoad" => 1
"ProgramArguments" => [
0 => "/System/Library/PrivateFrameworks/IMCore.framework/imagent.app/imagent"
]
"KeepAlive" => {
"SuccessfulExit" => 0
}
}
相对于App,daemon提供的功能要底层得多,逆向难度也要大得多,随意改动造成的后果当然也就严重得多,所以白苹果的惨案才会时有发生。在iOS逆向工程初学阶段,请不要把daemon当作练习目标;当你逆向了几个App,有了一定的心得和积累后再挑战这些daemon才是比较明智的选择。相比App,逆向daemon花费的时间和精力会更多,但更多的付出一定会带来更丰厚的回报。例如,“ iOS 上的第一款电话录音软件”Audio Recorder就是通过逆向mediaserverd这个daemon实现的。