在iOS上启动root特权的后台进程


接触iOS开发还不到一个星期,看了O’Reilly出版的一本《Cocoa and Objective-C: Up and Running》作为入门书,描述的比较简单,很适合初学者入门。我看书基本上就是找重点看,找疑惑的地方着重理解,边理解也边开着XCode实践一下。所以,还是一天把它吸收了,第一次看至少能消化一半,回头看应该还能再理解透一点。我相信每个人一开始都会觉得objc的扩展语法很奇怪,不过习惯了之后,这种感觉就会消失了。一个拥有C语言的效率,又拥有动态的运行环境以及垃圾回收能力的编译语言,的确挺先进的。

我的软件开发环境是:
OSX 10.7.4
XCode 4.3.2

安装好XCode之后,iOS SDK应该也有了,新版的XCode好像是放在/Application/XCode.app/下的,跟旧版的好像有点不一样,不过无所谓,能用就好!

这次打算写一个在手机上后台运行的代理服务,但是iOS跟Android上的app权限有很大的不同。iOS上的程序放到后台之后,就被系统暂停了,所有的线程都会挂起。所以,不能在后台提供任何的服务(除了例外的,例如播放音乐,记录位置和VOIP,设置app的UIBackgroundModes参数可以实现,但功能有限。)。问过身边搞iOS的一些朋友,也问过一些牛人,都似乎没有这样搞后台服务的经验。而我唯一想到能实现的办法是在越狱的手机上,启动另外一个独立的进程来提供服务。此前我是因为在cydia里安装了OpenSSH之后,发现SSHD进程一直能够以root账户保持在后台运行才想到的。

Xiaoxia-mato-iPhone:~ root# ps aux | grep ssh
root 993 0.1 0.3 274816 1412 ?? S 9:05PM 0:00.29 sshd: root@ttys000
root 1003 0.0 0.0 273932 0 s000 R+ 9:05PM 0:00.00 grep ssh

这里记录在iOS上启动root特权的后台进程的方法,是在Xcode开发的低权限的app里使用NSTask调用系统里的另外一个特权程序。至于如何在Xcode开发app的时候启动另外一个进程呢,Apple好像不允许这样做,因为框架里面的NSTask.h被删除了。但是可以手动恢复这个文件,也就是说可以在spotlight里搜到这个NSTask.h,然后拷贝到iOS的Foundation框架里即可。用法很简单:

[NSTask launchedTaskWithLaunchPath:@”/bin/ls” arguments:[NSArray arrayWithObjects:nil]];

运行后可以看到控制台里输出ls的结果,则说明成功。

因为app运行的账户还是低权限普通用户,如何让启动后的进程获取root权限呢?比较熟悉Linux或者Unix文件系统的用户都会知道,这个可以通过设置后台程序的文件属性来实现。

# chmod +s myservice
# ll
-rw-r–r– 1 user staff 446 7 19 20:39 Makefile
-rw-r–r– 1 user staff 50 7 19 20:32 http_proxy.c
-rwsr-sr-x 1 user staff 12800 7 19 20:39 myservice

而在后台服务程序的源代码里,需要加入 setuid(0); 这个系统调用,才能提升到root权限。

后台服务我不是在Xcode环境下编写的,而是在vim里写好,然后用iOS SDK自带的arm gcc编译,Makefile的内容如下:

XDEV = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer
CC = $(XDEV)/usr/bin/gcc
CFLAGS = -arch armv6 -isysroot $(XDEV)/SDKs/iPhoneOS5.1.sdk
LDFLAGS = -arch armv6 -isysroot $(XDEV)/SDKs/iPhoneOS5.1.sdk
LDID = ldid

all: myservice
ldid -S myservice
echo ‘Done.’

myservice: http_proxy.o
$(CC) $(LDFLAGS) -o $@ $< *.o:*.c $(CC) -c $(CFLAGS) $@ $< .PHONY: clean clean: rm -rf *.o rm -rf myservice

编译之后的可执行文件需要使用saurik提供的ldid签名之后,才可以放到iPhone上运行。否则会遇到下面的错误:

Xiaoxia-mato-iPhone:/tmp root# ./system
Killed: 9

后台服务的程序可以通过deb形式打包,让cydia安装到系统里,因为cydia是以root权限运行安装包的,所以可以在安装完毕后给文件设置权限属性。或者自己通过ssh复制进去测试也行!有了这次经验,我是不是可以写iOS上的病毒了 😀

在iOS上启动root特权的后台进程》有22个想法

  1. Mike

    「一个拥有C语言的效率,又拥有动态的运行环境以及垃圾回收能力的编译语言,的确挺先进的。」這不是 Clay 麽?Clay 的語法非常乾淨,是動態類型語法卻又是靜態類型語言(編譯器智能傷不起!)建議瞭解瞭解。

    回复
    1. Xiaoxia 文章作者

      宿舍多了一台2k的黑苹果主机,用上了!

      很流畅,已经两个星期没有开笔记本了,都在MacOSX下过的 🙂

      回复
      1. Caboo

        淘宝上的黑苹果很畅销啊

        “HDC DIY 黑苹果兼容机 MacPro Xeon E3 Z77 8GB AMD HD 1GB 独显”
        6999 元.

        这种机器怎么样, 显卡HD 58XX的.
        从性能上来比, 入Mac Pro好还是黑苹果主机好?

        回复
        1. Xiaoxia 文章作者

          挺强大的,但是我觉得我目前还没有高配置的需求。一个i3的cpu就已经足够用了。对于我日常工作来说,瓶颈问题永远是在硬盘上,所以买个ssd的比较实际 🙂

          回复
    1. Xiaoxia 文章作者

      投递给你的邮件都失败了。提示
      Your access to this mail system has been rejected due to the sending MTA’s poor reputation

      回复
    2. Xiaoxia 文章作者

      投递给你的邮件都失败了。提示
      SMTPConnectError: (554, “m1pismtp01-033.prod.mesa1.secureserver.net\nYour access to this mail system has been rejected due to the sending MTA’s poor reputation. If you believe that this failure is in error, please contact the intended recipient via alternate means.”)

      回复
  2. 蜗牛

    博主你好 我正在开发一款iOS上openVPN 目前采用中间程序获取root再启动openvpn的方法 虽然能用
    但是遇到了 锁屏在启动 程序崩溃的问题 希望能与您交流QQ是457685143 希望能得到您的回复

    回复
    1. Xiaoxia 文章作者

      锁屏会关闭网络连接,你可以试试用udp的方式配置openvpn。只能说是试试,因为可能ios关闭网络连接后socket也被关闭了。

      回复
      1. 蜗牛

        经过实验 发现 锁屏之后 socket被关闭了 只是 前台程序和 后台程序之间的 socket被关闭了 后台运行的openvpn不受影响 处理下这里就好了

        回复
    1. Xiaoxia 文章作者

      要有root权限,就可以调用。现在发现只要在cydia里以root用户安装就行了,这个chmod的步骤可以省略。

      回复
      1. victox

        调用[NSTask launchedTaskWithLaunchPath:@”/bin/ls” arguments:[NSArray arrayWithObjects:nil]];程序异常退出

        Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘launch path not accessible’

        貌似无法访问到系统路径?

        回复
  3. victox

    调用[NSTask launchedTaskWithLaunchPath:@”/bin/ls” arguments:[NSArray arrayWithObjects:nil]]; 
    程序异常退出

    错误:
    *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘launch path not accessible’

    回复

回复 Xiaoxia 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据