接触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 = ldidall: 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上的病毒了 😀
「一个拥有C语言的效率,又拥有动态的运行环境以及垃圾回收能力的编译语言,的确挺先进的。」這不是 Clay 麽?Clay 的語法非常乾淨,是動態類型語法卻又是靜態類型語言(編譯器智能傷不起!)建議瞭解瞭解。
非常关注iOS和Android的代理,期待…
另外推荐几个项目做参考3proxy, polipo, privoxy
小虾大神入mac了?
宿舍多了一台2k的黑苹果主机,用上了!
很流畅,已经两个星期没有开笔记本了,都在MacOSX下过的 🙂
淘宝上的黑苹果很畅销啊
“HDC DIY 黑苹果兼容机 MacPro Xeon E3 Z77 8GB AMD HD 1GB 独显”
6999 元.
这种机器怎么样, 显卡HD 58XX的.
从性能上来比, 入Mac Pro好还是黑苹果主机好?
挺强大的,但是我觉得我目前还没有高配置的需求。一个i3的cpu就已经足够用了。对于我日常工作来说,瓶颈问题永远是在硬盘上,所以买个ssd的比较实际 🙂
哦, 对了, 小虾大神, 你的回复邮件通知功能不工作了.
应该可以工作的吧,我的gmail天天都收到评论通知邮件的。
投递给你的邮件都失败了。提示
Your access to this mail system has been rejected due to the sending MTA’s poor reputation
投递给你的邮件都失败了。提示
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.”)
博主你好 我正在开发一款iOS上openVPN 目前采用中间程序获取root再启动openvpn的方法 虽然能用
但是遇到了 锁屏在启动 程序崩溃的问题 希望能与您交流QQ是457685143 希望能得到您的回复
锁屏会关闭网络连接,你可以试试用udp的方式配置openvpn。只能说是试试,因为可能ios关闭网络连接后socket也被关闭了。
经过实验 发现 锁屏之后 socket被关闭了 只是 前台程序和 后台程序之间的 socket被关闭了 后台运行的openvpn不受影响 处理下这里就好了
嗯。可以在收到解锁事件后,重新建立socket。
chmod +s 只能在ssh通过额,那 app 自身无法解决这个问题咋办?
要有root权限,就可以调用。现在发现只要在cydia里以root用户安装就行了,这个chmod的步骤可以省略。
博主,我把NSTask.h拷贝到iOS的Foundation框架里,但是依然还是编译报错“NSTask未定义”
应该是没有拷贝到正确位置。
调用[NSTask launchedTaskWithLaunchPath:@”/bin/ls” arguments:[NSArray arrayWithObjects:nil]];程序异常退出
Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘launch path not accessible’
貌似无法访问到系统路径?
调用[NSTask launchedTaskWithLaunchPath:@”/bin/ls” arguments:[NSArray arrayWithObjects:nil]];
程序异常退出
错误:
*** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘launch path not accessible’
你换一个可以访问到的路径就可以了吧!可能 /bin/ls 这个文件的确不存在的。
确实是存在的,可以在mobile terminal中直接运行