注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

熊猫正正的博客

熊猫正正的天空

 
 
 

日志

 
 

launchd, I'm coming for you  

2015-12-20 17:47:31|  分类: IOS安全 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

Force open sourcing launchd and libxpc, one binary at a time

Jonathan Levin, @Technologeeks, http://newosxbook.com/ - 10/07/15

Changelog:

  • 11/09/15 - Added commpage for ARM64, "dumpjpcategory" command and fixed "lookup" for iOS + 32 bit support for iOS, OS X
  • 11/14/15 - Added interpose for libxpc, for anyone wanting to try BYOL

About

Apple woke up one day with OS X 10.10, and decided to take launchd off the opensource lists. This is surprising, since launchd was one of the first projects to go on the Mac OS Forge, since its advent in 10.4. The last known source version seen in the wild is 842-92.1 for OS X 10.9.something, but as of 10.10 launchd's project affiliation is moved to (the closed source) libXPC, and its version number is renumbered:

# In 10.9:
morpheus@Ergo (~)$ what /sbin/launchd
/sbin/launchd
	PROGRAM:launchd   PROJECT:launchd-842.92.1
# In 10.10.4:
morpheus@Zephyr (~) what /sbin/launchd
/sbin/launchd
	PROGRAM:launchd  PROJECT:libxpc-559.20.9
	VERSION:Darwin Bootstrapper Version 2.0.2: Mon Mar  2 23:27:57 PST 2015; root:libxpc_executables-559.20.9~1/launchd/RELEASE_X86_64
# In iOS 9 (and also 10.11)
morpheus@Phontifex (~) what /sbin/launchd
/sbin/launchd
	PROGRAM:launchd  PROJECT:libxpc-756.1.1
	VERSION:Darwin Bootstrapper Version 3.0.0: Wed Aug  5 23:03:24 PDT 2015; root:libxpc_executables-756.1.1~3/launchd/RELEASE_ARM64

Similarly, launchctl(1), the interface utility, has been rewritten from scratch, made non-interactive (which is kind of a shame) and augmented with many more useful commands - primarily those that finally provide information on Mach ports. But, alas, where's the source??

The source

(download link)

I had to do a lot of extensive reversing for MOXiI 2, wherein I delve for the first time into Apple's private frameworks and user-mode daemons. launchd obviously fits into that important category - it already commanded chapter 7 of the first edition ("Alpha and Omega") - but that was before the rewrite. Add to that a gaping hole in MOXiI's 1's coverage - which barely touched on XPC (as it was just out and my (former) publisher wouldn't let me write about deep internals). Top that off with the arrogant (but funny :) rascal actively challenging me on Twitter* and@bruienne reminding me of my commitment to expose it.

So what I decided to share with the world for now is not launchd itself - that will wait for MOXiI 2's release - but launchctl's source. launchctl is used quite a bit in Jailbreaks to communicate with launchd(8) and ensure Daemons continue normal system startup after the jailbreak occurs. Apple knows that, and has in fact relocated the utility to the RAM Disk as of 9.0 (which obviously still doesn't work, since Pangu9 uses it). With this, you won't need the real launchctl, as this works exactly the same. Additionally, I'm releasing the source clearly with the intent people use it. Feel free to build/integrate in your own code.

As with the original, jlaunchctl provides help.

Usage: jlaunchctl  ... | help [subcommand]
	kill            Sends a signal to the service instance.
	blame           Prints the reason a service is running.
	print           Prints a description of a domain or service.
	print-cache     Prints information about the service cache.
	print-disabled  Prints a description of a domain or service.
	procinfo        Prints port information about a process.
	hostinfo        Prints port information about the host.
	limit           Reads or modifies launchd's resource limits.
	runstats        Prints performance statistics for a service.
	examine         Runs the specified analysis tool against launchd in a non-reentrant manner.
	dumpstate       Dumps launchd state to stdout (iOS 9 only)
	list            Lists information about services.
	start           Starts the specified service.
	stop            Starts the specified service.
	asuser          Execute a program in the bootstrap context of a given user.
	submit          Submit a basic job from the command line.
	error           Prints a description of an error.
	version         Prints the launchd version.
	variant         Prints the launchd variant.
# On iOS, these two commands are visible
	dumpjpcategory   Dumps the jetsam properties category for all services.
	lookup          Lookup Mach/XPC endpoint by name (new command, for iOS).
	help            Prints the usage for a given subcommand.

This is the 64-bit version of jlaunchctl

That "64-bit" or "32-bit" is just for my own purposes, since I recently updated the code to work well with 32-bit as well. I've packaged a (really) fat binary, so you can use arch to take your pick as to which architecture to run.

Compiling & Running

Normally I do a full writeup, wherein I explain the process of reversing. I'm skipping it this time in favor of just providing the source, for your compilation pleasure, and leaving the XPC internals, etc for the book. The source I've provided will compile neatly (-Wall) on both OS X and iOS, and you can find a fat binary for all architectures in the source bundle as well (The iOS version is obviously more useful than the OS X one, for purposes of jailbreaking/reverse engineering).

Do note - It's NOT the full source of launchctl, but only of the interesting commands - primarily the procinfolist, and such. I was also quite lazy here, and didn't implement the launchctlconvention of a "full path" to a service (e.g. system/com.apple.kextd or user/501/something...). Instead, you can pass uid=.. as an environment variable. For example:

# Default: Print for system (user 0). This does the same as  launchctl print-disabled system
Zephyr:~ morpheus$ ~/Documents/shared/10.11/launchd/jlaunchctl print-disabled
disabled services = {
        "com.apple.AEServer" => true
        "com.apple.ManagedClientAgent.enrollagent" => true
        "com.apple.usbmuxd" => false
        "com.apple.rpmuxd" => false
        "com.apple.ftpd" => true
        "com.apple.mrt" => false
        "com.apple.stackshot" => false
        "com.apple.dynamic_pager" => false
        "org.ntp.ntpd" => false
        "com.apple.pacemaker" => true
}
# This does the same as  launchctl print-disabled user/501
Zephyr:~ morpheus$ uid=501 ~/Documents/shared/10.11/launchd/jlaunchctl print-disabled
disabled services = {
        "com.apple.TMHelperAgent.SetupOffer" => false
        "com.apple.FileStatsAgent" => true
}
login item associations = {
}
# uid= is required when looking for a per-user service:
Zephyr:~ morpheus$ jlaunchctl print com.apple.tccd
Error:  113 - Could not find specified service
Zephyr:~ morpheus$ uid=501 ./jlaunchctl print com.apple.tccd
com.apple.tccd = {
	active count = 2
	path = /System/Library/LaunchAgents/com.apple.tccd.plist
	...
	...

Likewise try uid=501 jlaunchctl print and jlaunchctl print (implicitly does the same as launchctl print system), and remember uid=... when printing a per-user service, as without it you will get error 113. While I was at it, I added a simple command - lookup - which will enable you to see if a Mach port is reachable or not (by name). Super useful for iOS. If a port isn't reachable, expect error 3.

If you read the source..

You'll see that I have #if 0 blocks showing the Mach messages used in each of the launchctl requests. You are encouraged to get to them yourself, and it's quite easy to reproduce:

  • Start launchctl with no arguments under lldb
  • Set a breakpoint on xpc_pipe_routine
  • Run with whatever request argument you want to test
  • When the breakpoint hits, set another breakpoint on mach_msg
  • continue on the first two hits of mach_msg - these are the setup messages of the XPC pipe
  • mem read $rdi to see the content of the third message. You'll see something like:
    (lldb) mem read $rdi
    # Note the mach_msg header
    0x100200118: 13 15 13 80 b8 00 00 00 1b 03 00 00 13 04 00 00  ....?...........
    0x100200128: 07 0b 00 00 00 00 00 10 01 00 00 00 03 0a 00 00  ................
    #                                    XPC Magic
    0x100200138: 00 00 00 00 00 00 11 00 21 43 50 58 05 00 00 00  ........!CPX....
    0x100200148: 00 f0 00 00 80 00 00 00 06 00 00 00 73 75 62 73  .?..........subs
    0x100200158: 79 73 74 65 6d 00 00 00 00 40 00 00 02 00 00 00  ystem....@......
    0x100200168: 00 00 00 00 66 64 00 00 00 b0 00 00 68 61 6e 64  ....fd...?..hand
    0x100200178: 6c 65 00 00 00 40 00 00 00 00 00 00 00 00 00 00  le...@..........
    0x100200188: 72 6f 75 74 69 6e 65 00 00 40 00 00 c4 02 00 00  routine..@..?...
    0x100200198: 00 00 00 00 6e 61 6d 65 00 00 00 00 00 90 00 00  ....name........
    0x1002001a8: 10 00 00 00 63 6f 6d 2e 61 70 70 6c 65 2e 6b 65  ....com.apple.ke
    0x1002001b8: 78 74 64 00 74 79 70 65 00 00 00 00 00 40 00 00  xtd.type.....@..
    0x1002001c8: 01 00 00 00 00 00 00 00 03 0a 00 00 00 00 00 00  ................
    

    and the serialization is readily evident. And interesting if ,say, you wanted to fuzz it to find faults in launchd's handling.

Note that most methods actually require you to pass a file descriptor (via file ports) to launchd. This is clever, but sucks, because it means there's no easy way (convoluted popen()notwithstanding) to get the data in a machine-friendly format which can be digested programmatically.

Update: I added a small XPC snooping library in the snoop/ directory inside the tar. Super simple, and really nothing fancy - the ages-old DYLD_INSERT_LIBRARIES trick, etc. But useful, since it uses xpc_copy_description() to dump XPC messages aplenty. Fascinating stuff. Expect more - much more - when I get to the XPC explication in MOXiI 2.

Speaking of MOXiI 2..

Both launchd and libxpc would benefit from more transparency - you know, just in case there is a certain 0-day vulnerability (or two three) in the implementation of XPC. The 2nd edition of MOXiI will therefore have a lot more than this. launchd now has a dedicated chapter (I'm kicking SpringBoard and WindowServer to their own chapter), and XPC is covered in depth likewise in a chapter. 

Update: And I'm glad to say I have libxpc.dylib fully reversed :-) Anyone interested in OpenXPC? ;-)

Yes, I know I promised MOXiI will see print by October/November. I'm sort of on track, but as with Parkinson's law, there's always more and more to detail and explain - especially with the many under-the-hood changes AAPL put into iOS 9/10.11. I'm also now in "Android Mode", with Marshamllow FINALLY out, and the second volume of Android Internals due very soon. And I have real life to try and squeeze in every now and then. But once AIvII is out of the picture, MOXiI will once again command my full undivided attention. Stay tuned, (still aiming by end of year) and I promise you the wait will be over soon enough - and it will have been worth it. 

.. and Technologeeks' Training

If you're reading this and following my articles, check out Technologeeks' Training on OS X and iOS Internals. This reverse-engineering oriented course is delivered by yours truly and goes even deeper than MOXiI 2 does, with practical and hands-on exercises. Our 2015 dates are full, but they tell me we're planning more training right around January 18th, 2016! Updates through@Technologeeks, or emailing info@you.know.where.

Comments/Feedback

Through the website forum please. Technologeeks' Twitter doesn't normally respond to Twitter conversations or questions, but you can follow them for more updates on my work, as well as training

Greets

windknown, qwupz, and - how can I forget - launchderp :)

  评论这张
 
阅读(360)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017