#mbltdev: Знакомство с codesign (e-legion)
DESCRIPTION
#MBLTdev: Конференция мобильных разработчиков Спикер: Руслан Гуменный iOS-разработчик, e-Legion http://mbltdev.ru/TRANSCRIPT
Знакомство с codesign
Гуменный Руслан
Подписывание кода
• гарантировать то, что код не был изменен
• идентифицировать источник кода (разработчика или того, кто его подписал)
• определить, что код имеет право выполнять определенные задачи (доступ в keychain, доступ в iCloud, …)
Public Key CryptographyСуть шифрования с открытым ключом заключается в том,
что для шифрования данных используется один ключ (открытый), а для расшифрования другой (закрытый)
(поэтому такие системы часто называют ассиметричными).
Сертификат
Сертификатпубличный ключ + описание
Сертификат
RSA
• данные зашифрованные при помощи открытого ключа, могут быть расшифрованы только при помощи закрытого
• данные зашифрованные при помощи закрытого ключа, могут быть расшифрованы только при помощи открытого
Цифровая подписьСочетание зашифрованной контрольной суммы (digest) и
цифрового сертификата
Проверка цифровой подписи
Provisioning profile
• связывает разработчиков и устройства c командой (Development Team)
• определяет, что может делать код (entitlements)
• формируется Apple и изначально подписан
Назначение — не допустить запуск кода не разрешенного Apple
Provisioning profile
cms -D -i embedded.mobileprovision
Внутри лежит xml, который можно извлечь командой:
Provisioning profile <key>DeveloperCertificates</key> <array> <data>…</data> </array> <key>Entitlements</key> <dict> <key>com.apple.developer.team-identifier</key> <string>6TWG7MTXRP</string> <key>get-task-allow</key> <true/> </dict> <key>ProvisionedDevices</key> <array> <string>324a5b08c19f3f8f3c2d65e9432be21069e47e41</string> </array>
developer/distribution certificates (.cer file) в base64
Поле DeveloperCertificates
openssl x509 -text -in tmp.pem.
-----BEGIN CERTIFICATE----- MIIFmTC....
-----END CERTIFICATE-----
Что нужно для подписи
• developer или distribution сертификат
• приватный ключ для сертификата
• provisioning profile в котором есть используемый сертификат
Что подписываем
• бинарник основного приложения
• динамические библиотеки
IPAunzip Orders -d Payload
IPA
• embedded.mobileprovision
• PkgInfo
• _CodeSignature/CodeResources
• ResourcesRules.plist
Интересные файлы:
PkgInfo
Содержит байты {65, 80, 80, 76, 63, 63, 63, 63} или строку "APPL????"
Является наследием OS X
CodeResources… <dict> <key>files</key> <dict> <key>[email protected]</key> <data> LuxPgpygBTlxoj9r3S14ZCEdwU8= </data> <key>Assets.car</key> <data> dJ4xkjYAgGJQMKMCXZOe3q8FgBA= …. </dict> <key>rules</key> <dict> <key>.*</key> <true/> <key>Info.plist</key>
SHA-1 hashes
ResourceRules.plist… <dict> <key>rules</key> <dict> <key>.*</key> <true/> <key>Info.plist</key> <dict> <key>omit</key> <true/> <key>weight</key> <real>10</real> </dict> <key>ResourceRules.plist</key> <dict> <key>omit</key> <true/> <key>weight</key> <real>100</real> </dict> </dict> </dict> …
Бинарный файл
• Fat binary (склейка нескольких архитектур, armv7, armv7s, arm64)
• Мach-O (описывает одну архитектуру)
• Каждая архитектура подписывается отдельно
Fat
Mach-O
• mach-O состоит из секций
• подпись лежит в секции LC_CODE_SIGNATURE
• подпись тоже состоит из секций, которые называются blobs
Blobs
• Requirements
• Entitlements
• Code Directory
• CMS
Requirements Blob
• размер 12 байт
• хранит magic-строку
Entitlements Blob<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.developer.team-identifier</key> <string>6TWG7MTXRP</string> <key>keychain-access-groups</key> <array> <string>6TWG7MTXRP.*</string> </array> <key>application-identifier</key> <string>6TWG7MTXRP.*</string> <key>get-task-allow</key> <true/> </dict> </plist>
Code Directory Blob• хеш от entitlements blob
• хеш от requirements blob
• хеш файла CodeResources
• хеш файл Info.plist
• набор хешей бинарника разбитого на секции по 4096 байт
CMS Blob
• Цифровая подпись (зашифрованный хеш + сетрификат) для Code Directory Blob
Команда codesignКоманда codesign используется для создания,
проверки и отображения подписей кода.
• security_systemkeychain/
• libsecurityd
• libsecurity_utilities
• libsecurity_cdsa_client
• libsecurity_cdsa_utilities
• libsecurity_codesigning
http://opensource.apple.com/tarballs/
Утилита codesign
codesign -f -s DEEF9D402F5FFC986C86FCDC236090C6186FE6E9 "Payload/Apts.app/Apts"
-f удалять существующую подпись -s идентификатор сертификата (developer/distribution)
security find-identity -v -p codesigning
1) D5B28E0000920A4C86ED025CBEA94AF8FA88755D "iPhone Developer: Ruslan Gumenniy (J362LCRMQS)" 2) 60855F0569C7595362202CDDE4E5B1671A1E86CC "iPhone Distribution: e-Legion (96GT47C53G)" 3) 5BB0183A7B66911A2E36D75E26137456B3A90258 "iPhone Developer: Ruslan Gumenniy (9P8FPFW4PQ)"
Получить список идентификаторов:
Подписать сборку:
Типовые задачи
• проверить, что AdHoc сборка может запускаться на устройстве
• переподписать сборку с новым сертификатом
• внедрить свой код
Проверка IPA• распаковать ipa как zip файл
• открыть файл embedded.mobileprovision и найти секцию ProvisionedDevices
• убедиться, что в секции ProvisionedDevices есть UDID устройства на которое производится установка
Проверка IPAУстановить плагин для Quick Look
https://github.com/chockenberry/Provisioninghttps://github.com/ealeksandrov/ProvisionQL
Переподписывание сборки• распаковать IPA
• заменить файл embedded.mobileprovision тем, который будет подходить для приватного ключа используемого при переподписи
• удалить файл CodeResources
• взывать codesign
• запаковать в ZIP и изменить расширение на IPA
Переподписывание сборки#!/bin/sh
rm Application.resigned.ipa rm -rf output mkdir output
unzip ipa/Apts.ipa -d output/extracted > /dev/null 2>&1
rm -rf Payload/*.app/_CodeSignature 2> /dev/null | true
/usr/bin/codesign -f -s DEEF9D402F5FFC986C86FCDC236090C6186FE6E9 "Payload/Apts.app/Apts"
/usr/bin/xcrun -sdk iphoneos PackageApplication -v Payload/*.app -o “Application.resigned.ipa" --embed ../../support_files/embedded.mobileprovision
Внедрение кода• 6-й xCode позволяет собирать динамические библиотеки для iOS (раньше надо было править конфигурационные файлы xCode)
• можно собрать динамическую библиотеку dylib и сделать так, чтобы приложение загружало ее при старте
https://github.com/fanruten/mach-patcher/
Внедрение кода
@executable_path/inferno.dylib
Чтобы не указывать абсолютный путь, можно использовать
Внедрение кода• распаковать IPA
• заменить файл embedded.mobileprovision тем, который будет подходить для приватного ключа используемого при переподписи
• удалить файл CodeResources
• скопировать dylib в бандл
• модифицировать бинарник (внедрить dylib)
• взывать codesign для бинарника и dylib
• запаковать в ZIP и изменить расширение на IPA
Внедрение кода#!/bin/sh
rm Application.resigned.ipa rm -rf output mkdir output
unzip ipa/Apts.ipa -d output/extracted > /dev/null 2>&1
rm -rf Payload/*.app/_CodeSignature 2> /dev/null | true
mach-patcher Payload/*.app/Artique @executable_path/inferno.dylib cp ../../support_files/inferno.dylib Payload/*.app/
/usr/bin/codesign -f -s DEEF9D402F5FFC986C86FCDC236090C6186FE6E9 Payload/*.app/inferno.dylib /usr/bin/codesign -f -s DEEF9D402F5FFC986C86FCDC236090C6186FE6E9 "Payload/Apts.app/Apts"
/usr/bin/xcrun -sdk iphoneos PackageApplication -v Payload/*.app -o “Application.resigned.ipa" --embed ../../support_files/embedded.mobileprovision
IPA из AppStore
• зашифрованные
• можно расшифровать при помощи устройства с jailbreak используя Clutch
• после расшифровки получим IPA, который можно подписать и ставить на устройства
IPA из AppStore
Спасибо за внимание