# Pentest DVIA-v2 for IOS # Basicsa https://github.com/ivan-sincek/ios-penetration-testing-cheat-sheet#1-basics ### Install/Uninstall an IPA ``` ideviceinstaller -i someapp.ipa ``` ### SSH to Your iOS Device ``` iproxy 2222 22 ssh root@192.168.1.10 / root@127.0.0.1 ``` Default password is `alpine`. ### Download/Upload Files and Directories Tilde `~` is short for the root directory. Download a file or directory from your iOS device: ``` scp root@192.168.1.10:~/somefile.txt ./ scp -r root@192.168.1.10:~/somedir ./ ``` Upload a file or directory to your iOS device: ``` scp somefile.txt root@192.168.1.10:~/ scp -r somedir root@192.168.1.10:~/ ``` Use `nano` to edit files directly on your iOS device. Подключился к мобиле Перешел в /var/containers/Bundle/Application/ Грепнул ls * | grep -i DVIA-v2 -B2 Узнал бандл приложения ## 2. Inspect an IPA https://github.com/ivan-sincek/ios-penetration-testing-cheat-sheet#2-inspect-an-ipa ### Pull a Decrypted IPA Pull a decrypted IPA from your iOS device: git clone https://github.com/AloneMonkey/frida-ios-dump && cd frida-ios-dump && pip3 install -r requirements.txt python3 dump.py -o decrypted.ipa -P alpine -p 22 -H 192.168.1.10 com.someapp.dev If you want to pull an encrypted IPA from your iOS device, see section [9. Repackage an IPA](https://github.com/ivan-sincek/ios-penetration-testing-cheat-sheet#8-repackage-an-ipa) and [iMazing](https://github.com/ivan-sincek/ios-penetration-testing-cheat-sheet#imazing). To unpack e.g. `someapp.ipa` or `decrypted.ipa` (preferred), run: ``` unzip decrypted.ipa ``` unzip DVIA-v2-swift.ipa смотрим что содержит файл app `ls -1 DVIA-v2.app` ![](https://hackmd.io/_uploads/rkBlA0K82.png) ### Интересные файлы: ```ad-info Info.plist содержит информацию о конфигурации приложения, такую как его идентификатор пакета, номер версии и отображаемое имя. ``` /var/containers/Bundle/Application/750D395C-9391-4042-AAB6-5A233836BEF6/DVIA-v2.app #### Идентификатор пакета CFBundleIdentifier ```<key>CFBundleIdentifier</key <string>com.highaltitudehacks.DVIAswiftv2</string>``` в iOS идентификатор пакета используется в проверке подписи приложения. Launch Services использует идентификатор пакета для определения местоположения приложения, способного к открытию определенного файла ``` #### Имя пакета CFBundleName ```<key>CFBundleName</key> <string>DVIA-v2</string> ``` #### Номер версии CFBundleVersion ```<key>CFBundleVersion</key> <string>1</string> ``` - Разрешения приложения plistutil -i Info.plist| grep -i UsageDescription ` <key>NSCameraUsageDescription</key>` - Custom URL schemes: `CFBundleURLTypes` plistutil -i Info.plist| grep -i CFBundleURLTypes -A20 ``` <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLName</key> <string>com.highaltitudehacks.DVIAswiftv2</string> <key>CFBundleURLSchemes</key> <array> <string>dvia</string> <string>dviaswift</string> </array> </dict> </array>` ``` - App Transport Security (ATS) configuration: `NSAppTransportSecurity` plistutil -i Info.plist| grep -i NSAppTransportSecurity -A10 ``` <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict> Установите значение этого ключа в `YES`, чтобы отключить ограничения App Transport Security (ATS). Отключение ATS означает, что разрешены незащищенные HTTP-соединения. ``` ```ad-info _CodeSignature/ содержит файл plist с подписью над всеми файлами в пакете. ``` ```ad-info Frameworks/ содержит собственные библиотеки приложений в виде файлов .dylib или .framework. ``` # 3. Search for Files and Directories ssh -p 2222 root@127.0.0.1 password: alpine Узнаем процесс айди в фрида ``` frida-ps -Uai - показывает все приложения ``` frida-ps -Ua - показывает запущенные приложения ID 4633 Подключаемся к процессу приложения `objection -g 4633 explore` Изучаем информацию о каталогах приложения `env` ![](https://hackmd.io/_uploads/S1TSARtLn.png) BundlePath - файлы приложения, так же как и в Payload. Cодержит основные данные приложения, статическое содержимое, а также скомпилированный двоичный файл приложения.содержит основные данные приложения, статическое содержимое, а также скомпилированный двоичный файл приложения. CachesDirectory - Содержит полупостоянные кэшированные файлы. - Невидимый для пользователей, и пользователи не могут писать на него. ![](https://hackmd.io/_uploads/r1x9kyc8n.png) Documents #local_data_storage # LOCAL DATA STORAGE ## LOCAL DATA STORAGE - plist прочитали значения введеные пользователем ![](https://hackmd.io/_uploads/B1lj1k9In.png) **Library/Preferences/** - Используется для хранения свойств, которые могут сохраняться даже после перезапуска приложения. - Информация сохраняется в незашифрованном виде в песочнице приложения в файле plist под названием [BUNDLE_ID].plist. - Все пары ключ/значение, хранящиеся с помощью `NSUserDefaults`, можно найти в этом файле. ## LOCAL DATA STORAGE - NSUserDefaults ios nsuserdefaults get Прочитали значение введенное пользователем![](https://hackmd.io/_uploads/rynayy9I2.png) ## LOCAL DATA STORAGE - Keychain ios keychain dump com.highaltitudehacks.DVIAswiftv2.3JW2H263BC ![](https://hackmd.io/_uploads/rkjAkJ5In.png) ## LOCAL DATA STORAGE - CoreData iPhone:/var/mobile/Containers/Data/Application/9E66C4E1-83F5-42E0-9FFF-FB025DF03DCB/Library/Application Support root# sqlite3 Model.sqlite ![](https://hackmd.io/_uploads/HyTyl1583.png) sqlite connect Model.sqlite `select * from zuser` ![](https://hackmd.io/_uploads/rkpZlJc8n.png) (cохранились данные предыдущих вводов) ## LOCAL DATA STORAGE - WebKit (сохраняет запросы и ответы для ускорения загрузки страницы) Cкачали Сache.db на комп (файл Cache.db в iOS-приложениях, в который по умолчанию попадает кэш всех сетевых запросов, отправленных через NSURLSession.) ``scp root@192.168.1.2:/var/mobile/Containers/Data/Application/9E66C4E1-83F5-42E0-9FFF-FB025DF03DCB/Library/Caches/com.highaltitudehacks.DVIAswiftv2.3JW2H263BC/Cache.db /Users/martun/Desktop/IB/Mobile_Security/IOS\ pentest/DVIA-v2/ ![](https://hackmd.io/_uploads/H1V7lJ5Ln.png) Рекомендации что именно необходимо сделать, чтобы предотвратить кэширование запросов. https://help.stingray-mobile.ru/2022.12/rg/ru/ios/enabled_caching_of_network_requests_ios/ ## LOCAL DATA STORAGE - Realm скачал файл default.realm из Documents - открываю браузером realm - показывает пустые значения ## LOCAL DATA STORAGE - Couchbase Lite `` /var/mobile/Containers/Data/Application/9E66C4E1-83F5-42E0-9FFF-FB025DF03DCB/Library/Application Support/CouchbaseLite/dvcouchbasedb.cblite2 objection - > sqlite connect db.sqlite3 select * from revs![[Снимок экрана 2023-05-16 в 21.39.56.png]] ## LOCAL DATA STORAGE - Yap ``Database/Library/Application Support/ objection -> sqlite connect YapDatabase.sqlite select * from database2 Бинарный файл ![](https://hackmd.io/_uploads/ryGHlyqLn.png) # Jailbreak Detection objection - ios jailbreak disable ![](https://hackmd.io/_uploads/B12Ll1qUn.png) ## Jailbreak test 1 Поищем какие функции использует приложение по похожему ключу ``` frida-trace -U -i "*jail*" DVIA-v2 ``` В приложении протыкаем кнопки Выведется в консоль ![](https://hackmd.io/_uploads/r1AulJ9I2.png) Каждая функция вызывается при нажатии на кнопку. Функция Swift определяется по `_T` в начале. Если бы это была функция Objective-C, мы могли бы подключитьcя к ней objection. Однако мы не можем сделать то же самое со Swift. Дизасемблируем бинарь. #ghidra_run Запустим гидру ./ghidraRun ( у меня она в пути IB/tools/ghidra/build/dist/ghidra_10.4_DEV/ т.к. была пересобрана под арм) ![](https://hackmd.io/_uploads/rkzql1qLn.png) Анализируем Мы видим, что функция проходит, а затем вызывает другую функцию с инструкцией bl (ссылка на ветвь). По сути, это эквивалент инструкции jmp. Если вы наведите курсор на вызов функции `__T07DVIA_v213DVIAUtilitiesCMa`, мы также увидим эту сборку для этого. ![](https://hackmd.io/_uploads/rkVAlkqUh.png) Первая инструкция - загрузка значения в регистре sp, на которое ссылается как #local_38. Это загружается в регистр x8. Затем значение записывается в регистр x0 (возможно, очищает его). Затем инструкция mov перемещает значение с x8 на x0. Затем есть инструкция bl к другой функции. После этого он закрывается. Таким образом, мы можем предположить, что x0 содержит интересующую нас значение по этому адресу. Перейдем к Frida, чтобы проверить что инструкция, которую мы хотим подключить, на самом деле так называется. Создаем файл под названием DVIAcheckmeminuse.js и введите следующий код: ``` var targetModule = 'DVIA-v2'; var addr = ptr(0x192c64); var moduleBase = Module.getBaseAddress(targetModule); var targetAddress = moduleBase.add(addr); Interceptor.attach(targetAddress, { onEnter: function(args) { console.log('Address Entered'); }, }); ``` Целевой модуль необходимо будет изменить для приложения, которое вы просматриваете. Адресный указатель, который мы меняем на адрес, который мы хотим проанализировать. В настоящее время он находится в инструкции ldr. База модулей статична и заставит Фриду рассчитать для нас смещение, что очень приятно. Затем он перехватит вызов на этот адрес памяти, и просто поместит Entered в консоль. frida -U -l DVIAcheckmeminuse.js DVIA-v2 - кликаем на тест 1 в приложении ![](https://hackmd.io/_uploads/r1ygWkc8n.png) Итак, теперь мы знаем, что адрес памяти используется, когда мы нажимаем Test 1. Мы также можем нажать на других и увидеть, что ничего не напечатано. Это показывает нам, что мы примерно в нужном месте. Теперь мы хотим знать, какое значение загружается в регистр x8. Итак, давайте используем код ниже: ``` var targetModule = 'DVIA-v2'; var addr = ptr(0x192c64); var moduleBase = Module.getBaseAddress(targetModule); var targetAddress = moduleBase.add(addr); Interceptor.attach(targetAddress, { onEnter: function(args) { console.log('At the address ' + addr + ' the value is currently ' + this.context.x0); }, }); ``` Это то же самое, что и последний сценарий, только с изменением функции console.log для печати адреса, который мы просматриваем, и значения, которое возвращается в регистре x0. frida -U -l DVIAreturnvalueJBTest1.js DVIA-v2 - кликаем на тест 1 в приложении ![](https://hackmd.io/_uploads/Skt9Wk5Ln.png) Таким образом, мы знаем, что адрес попадает и что значение в регистре x0 равно 1. Теперь для этой функции мы еще не знаем, что это такое, но давайте попробуем изменить ее на 0 и предположим, что это какой-то логический (истинный или ложный) результат. Это будет предполагать, что первая функция, вызванная, выполнила некоторую проверку, результат возврата возвращается либо как 1 для взлома, либо 0 для не взлома. Затем он загружается в x8 для сравнения, чтобы оценить, какое всплывающее окно должно появиться. ``` var targetModule = 'DVIA-v2'; var addr = ptr(0x192c64); var moduleBase = Module.getBaseAddress(targetModule); var targetAddress = moduleBase.add(addr); Interceptor.attach(targetAddress, { onEnter: function(args) { if(this.context.x0 == 0x01){ this.context.x0=0x00 console.log("Bypass Test1"); } }, }); ``` Код перехватывает адрес памяти, проверяет, равно ли значение регистра x0 0x01, и если да, то изменить его на 0x0 и распечатать консоль, чтобы мы знали, что она отработала. Примечание: Чтобы обойти, нам нужно изменить значение в регистре x0, а не в регистре x8! frida -U -l DVIAbypassJBtest1.js DVIA-v2 - кликаем в приложении test 1 - теперь приложение не jailbreake ![](https://hackmd.io/_uploads/rkcjZ1qL3.png) ## Jailbreak Test 2 ### Frida Узнаем процесс с помощью Frida и подключаемся к приложению ``` frida -U DVIA-v2 ``` Создадим скрипты для запуска : 1. Первое, что мы хотим сделать, это определить классы в DVIA-v2, которые отвечают за обнаружение джейлбрейка. Давайте создадим сценарий с именем DVIAclassesJB.js и введем следующее. ``` for (var className in ObjC.classes){ if (ObjC.classes.hasOwnProperty(className)) {console.log(className);} } ``` Выполняем скрипт на устройстве ``` frida -U -l DVIAclassesJB.js DVIA-v2 | grep Jailbreak ``` ![](https://hackmd.io/_uploads/rkkp-J5Ih.png) Нашли имя класса jailbreakDetection 2. Перечисляем методы класса cоздаем скрипт DVIAclassmethodsJB.js ``` console.log("[*] Started: Find All Methods of a Specific Class"); if (ObjC.available) { try { var className = "JailbreakDetection"; var methods = eval('ObjC.classes.' + className + '.$methods'); for (var i = 0; i < methods.length; i++) { try { console.log("[-] "+methods[i]); } catch(err) { console.log("[!] Exception1: " + err.message); } } } catch(err) { console.log("[!] Exception2: " + err.message); } } else { console.log("Objective-C Runtime is not available!"); } console.log("[*] Completed: Find All Methods of a Specific Class"); ``` ``` frida -U -l DVIAclassmethodsJB.js DVIA-v2 | grep -i 'jailbreak\|jailbroken' ``` ![](https://hackmd.io/_uploads/ryC0bJ9In.png) Нашли метод isJailBroken Таким образом, у нас есть приложение, класс и метод. Теперь мы можем начать видеть, что отправляется на этот метод, но нам нужно будет подключить его и заставить отображать то, что возвращается. 3. Cоздаем скрипт DVIAreturnvalueJB.js ``` if (ObjC.available) { try { var className = "JailbreakDetection"; var funcName = "+ isJailbroken"; var hook = eval('ObjC.classes.' + className + '["' + funcName + '"]'); Interceptor.attach(hook.implementation, { onLeave: function(retval) { console.log("[*] Class Name: " + className); console.log("[*] Method Name: " + funcName); console.log("\t[-] Type of return value: " + typeof retval); console.log("\t[-] Return Value: " + retval); } }); } catch(err) { console.log("[!] Exception2: " + err.message); } } else { console.log("Objective-C Runtime is not available!"); } ``` ``` frida -U -l DVIAreturnvalueJB.js DVIA-v2 ``` В приложении нажимаем на test 2. (Та отображает device is Jailbroken) а в фриде выдает результат value метода isJailbroken ![](https://hackmd.io/_uploads/B1GgMyq83.png) Теперь мы знаем, что когда мы нажимаем тест джейлбрейка 2, логическое значение 1 возвращается в метод + isJailbroken. Так что теперь давайте захукаем его и изменим. 4. Создадим скрипт на хук значения DVIAoverwriteJB.js ``` if (ObjC.available) { try { var className = "JailbreakDetection"; var funcName = "+ isJailbroken"; var hook = eval('ObjC.classes.' + className + '["' + funcName + '"]'); var newretval = ptr("0x0"); Interceptor.attach(hook.implementation, { onLeave: function(retval) { console.log("[*] Class Name: " + className); console.log("[*] Method Name: " + funcName); console.log("\t[-] Type of return value: " + typeof retval); console.log("\t[-] Original Return Value: " + retval); retval.replace(newretval) console.log("\t[-] New Return Value: " + newretval) } }); } catch(err) { console.log("[!] Exception2: " + err.message); } } else { console.log("Objective-C Runtime is not available!"); } ``` С помощью этого кода нам нужно определить класс, метод и новое возвращаемое значение. Поскольку мы видели 0x1 раньше, противоположное в логическое было бы 0x0. Таким образом, возвращаемое значение (newretval) указывается как 0x0. Запускаем скрипт ``` frida -U -l DVIAoverwriteJB.js DVIA-v2 ``` Нажимаем в приложении на test2 уведомление - Device is Not Jailbroken (нужный результат получен) ![](https://hackmd.io/_uploads/r1EZM1583.png) ### Objection 1. ``objection -g DVIA-v2 explore 2. ``ios jailbreak disable - отключит все тесты 3. Начнем с поиска классов приложения, которые могут быть связаны с обнаружением джейлбрейка следующим: ``ios hooking search classes jailbreak ![](https://hackmd.io/_uploads/SJtGMJq82.png) Найдено 2 класса 4. Теперь нам нужно найти методы этого класса, которые могут быть актуальны. Мы найдем их со следующей командой: ``` ios hooking watch class JailbreakDetection ``` ![](https://hackmd.io/_uploads/HyHmGJ583.png) найден метод isJailBroken Нажимаем на тест2 в приложении ![](https://hackmd.io/_uploads/B1-4f1cL2.png) Мы знаем что тест 2 использует этот метод класса 5. Следим за методом. + или - может меняться в зависимости от приложения, а затем в квадратных скобках это просто имя класса, за которым следует имя метода ``` ios hooking watch method "+[JailbreakDetection isJailbroken]" --dump-return ``` Нажимаем на тест 2 в приложении. Видим в консоли возвращаемое значение ![](https://hackmd.io/_uploads/HJuHfycL3.png) 6. Меняем значение 0х1 на 0х0 ``` ios hooking set return_value "+[JailbreakDetection isJailbroken]" 0x0 ``` В приложении при нажатии тест2 отображается Device is Not Jailbroken ![](https://hackmd.io/_uploads/S1wIzk5Uh.png) ## Jailbreak Test 3 1. Поищем какие функции использует приложение по похожему ключу ``` frida-trace -U -i "*jail*" DVIA-v2 ``` В приложении нажимаем на тест 3 ![](https://hackmd.io/_uploads/B1c2zJ5U2.png) 2. В гидре ищем имя функции для теста 3 ![](https://hackmd.io/_uploads/B1Q6GJ5Un.png) Сначала мы видим, что он проверяет, существует ли приложение Cydia, так как это обычное приложение, установленное с джейлбрейками по умолчанию. ![](https://hackmd.io/_uploads/BktAMJ5Ln.png) Затем он проверяет файл для MobileSubstrate. Это может относиться к Substrate Cydia, который также распространен с джейлбрейками. ![](https://hackmd.io/_uploads/ryYJmkq8h.png) Затем он проверяет присутствие bash на телефоне. Это то, что обычно устанавливается пользователями с взломанными телефонами. ![](https://hackmd.io/_uploads/ByOlQ1qU2.png) Затем он проверяет наличие SSH. ![](https://hackmd.io/_uploads/Hy4Zm1cL3.png) Затем он проверяет наличие /etc/apt ![](https://hackmd.io/_uploads/rkelMQkqU3.png) Затем он пишет “This is a test” и пытается поместить его в файл по адресу /private/jailbreak.txt. Это проверка того, может ли приложение взаимодействовать с файлами за пределами песочницы приложения, что невозможно на не взломанном устройстве. ![](https://hackmd.io/_uploads/SJbmmyc8n.png) Затем он проверяет, возвращает ли схема URL cydia:// что-либо. Даже если местоположение Cydia перемещено, если оно находится на устройстве, схема URL-адреса будет присутствовать и может быть проверена. ![](https://hackmd.io/_uploads/BJRQQkcUh.png) Далее мы видим функцию, которая выполняет фактическое сравнение, и мы можем увидеть сообщение об ошибке во всплывающем окне в виде строки. Мы также видим, что есть jump перед неудачей, который проходит мимо него.! ![](https://hackmd.io/_uploads/rJp47ycI3.png) Jump переходит к этой функции, показывая сообщение об успехе. ![](https://hackmd.io/_uploads/HJirQkqIn.png) Итак, теперь у нас есть приблизительное представление о том, как работает эта функция. Он выполняет каждую из этих проверок и должен хранить результат, затем, когда он доходит до конца, он оценивает все результаты, а затем решает, является ли устройство взломанным. Мы могли бы использовать метод из теста 1, чтобы изменить результат каждой отдельной проверки. Тем не менее, нам не нужно делать это здесь, потому что есть только один jump. Если после каждой проверки он прыгал, если не удался, то нам нужно будет изменить их все. Так что, зная, что нам нужно найти только одну вещь для изменения, давайте посмотрим на jump. ![](https://hackmd.io/_uploads/rk58XJcUh.png) Здесь мы можем увидеть, что происходит непосредственно перед прыжком. Мы видим, что ключевой инструкцией является операция для регистра w8. В инструкции и он выполняет операцию AND с регистром 8 и значением 0x1. Инструкция tbz определяется как тестовый бит и ветвь, если ноль. Таким образом, инструкция tbz проверяет, равен ли регистр 8 0x0 или 0x1. Если он равен 0x0, то он branch (jump). Это означает, что если мы сможем сделать так, чтобы регистр 8 имел значение 0x0, то он перейдет к функции успеха. 3. Мы можем проверить это с помощью наших скриптов из теста 1, чтобы убедиться, что это вызывается, и убедиться, что это значение в настоящее время 0x1. Обратите внимание, что для этого вам нужно будет изменить регистр, потому что мы больше не смотрим на регистр 0, как для теста 1. Приведенный ниже script выведет значение этой инструкции. DVIAreturnvalueJB3.js ``` var targetModule = 'DVIA-v2'; var addr = ptr(0x1959d8); var moduleBase = Module.getBaseAddress(targetModule); var targetAddress = moduleBase.add(addr); Interceptor.attach(targetAddress, { onEnter: function(args) { console.log('At the address ' + addr + ' the value is currently ' + this.context.x8); }, }); ``` frida -U -l DVIAreturnvalueJB3.js DVIA-v2 ![](https://hackmd.io/_uploads/BJ-OX15In.png) 4. DVIA2bypassjailbreak3.js Вы можете видеть, что это то же самое, что и тест 1, просто с другим указателем и другим регистром. ``` var targetModule = 'DVIA-v2'; var addr = ptr(0x1959d8); var moduleBase = Module.getBaseAddress(targetModule); var targetAddress = moduleBase.add(addr); Interceptor.attach(targetAddress, { onEnter: function(args) { if(this.context.x8 == 0x01){ this.context.x8=0x00 console.log("Bypass Test3"); } }, }); ``` Нажимаем на тест 3 в приложении ![](https://hackmd.io/_uploads/B1QFm1c83.png) Device is Not Jailbroken ## Jailbreak Test 4 1. В ghidra ищем функцию test4 ![](https://hackmd.io/_uploads/ByatXk5In.png) 2. При прокрутке мы видим, что это то же самое, что и тест 3. Он выполняет те же тесты джейлбрейка, а затем имеет ту же логику теста и jump в конце, что и 3. Это означает, что мы можем прокручивать вниз, пока не увидим сообщение об ошибке, затем найти jump, а затем изменить значение в регистре. ![](https://hackmd.io/_uploads/BkLjmkqU2.png) 3. Меняем значение 0х1 на 0х0 в скрипте DVIAbypassjailbreak4.js ``` var targetModule = 'DVIA-v2'; var addr = ptr(0x1936e0); var moduleBase = Module.getBaseAddress(targetModule); var targetAddress = moduleBase.add(addr); Interceptor.attach(targetAddress, { onEnter: function(args) { if(this.context.x8 == 0x01){ this.context.x8=0x00 console.log("Bypass Test4"); } }, }); ``` ``` frida -U -l DVIAbypassjailbreak4.js DVIA-v2 ``` ![](https://hackmd.io/_uploads/H162QJ98n.png) Нажимаем на тест4 в приложении - device is Not Jailbroken ## Jailbreak Test 5 1. Найдем функцию в Ghidra ![](https://hackmd.io/_uploads/ByTp715Un.png) 2. Прокрутите вниз, и мы увидим небольшую разницу. Теперь вместо того, чтобы быть строками, которые мы можем прочитать, чтобы увидеть, что он проверяет, он вызывает другие функции и, кажется, каким-то образом запутан. ![](https://hackmd.io/_uploads/SJ0AQ1cU3.png) 3. Мы видим, что та же логика происходит при проверке, а затем она сообщает, что файл существует, но мы не знаем, какой именно файл. Мы могли бы немного покопаться (и пришлось бы, если бы он прыгал после каждого сбоя), но если мы продолжим прокручивать, мы на самом деле увидим, что конечная логика похожа.![](https://hackmd.io/_uploads/BkqJ4y5Lh.png) 4. Теперь он выделен, он будет сохраняться на нашем экране, пока мы не найдем точку входа. Если мы не выделим, то он упадет, и ему станет трудно следовать. Если мы прокрутим вверх, чтобы увидеть, где начинается этот прыжок, мы увидим следующую функцию. ![](https://hackmd.io/_uploads/HkCe4JqLh.png) Здесь мы можем увидеть функцию, аналогичную предыдущей. 5. создадим скрипт для замены значения DVIAbypassjailbreak5.js ``` var targetModule = 'DVIA-v2'; var addr = ptr(0x197028); var moduleBase = Module.getBaseAddress(targetModule); var targetAddress = moduleBase.add(addr); Interceptor.attach(targetAddress, { onEnter: function(args) { if(this.context.x8 == 0x01){ this.context.x8=0x00 console.log("Bypass Test5"); } }, }); ``` ``` frida -U -l DVIAbypassjai lbreak5.js DVIA-v2 ``` ![](https://hackmd.io/_uploads/BJuGEkcIn.png) Нажимаем тест5 в приложении и device is Not jailbroken # Excessive Permissions пользователи, как правило, не знают о последствиях предоставления определенных разрешений приложению. После предоставления разрешения оно может использоваться приложением в любое время и, в зависимости от разрешения, может позволить приложению шпионить за пользователем. эти разрешения также можно использовать без какого-либо предупреждения или указания пользователю. Тут реализовано camera permission # Runtime manipulation Все нативные приложения IOS написаны на языке Objective-C, ориентированном на среду выполнения. Эта функция делает все собственные приложения уязвимыми для анализа и манипулирования во время выполнения. ваша задача состоит в том, чтобы обойти проверку входа в следующие задачи, используя методы манипулирования во время выполнения Есть две проблемы для обхода экрана входа в систему, одна задача для изменения URL-адреса и другая задача для обхода 6-значного пин-кода. ## Login Method 1 ### Objection 1. Узнаем какие методы использует приложение ``frida-trace -U -i "*login*" DVIA-v2 в приложении нажимем Login method 1 и Login method 2 ![](https://hackmd.io/_uploads/HkvHEycI3.png) Можем найти в гидре эти методы 2. Воспользуемся objection - подключимся к приложению ``` objection -g DVIA-v2 explore ``` 3. Поищем классы Login ![](https://hackmd.io/_uploads/Bkd8VJ9L2.png) Найдено более 30 классов , но мы обратим внимание на LoginValidate 4. Поищем методы класса ios hooking watch class LoginValidate ![](https://hackmd.io/_uploads/r19_EyqI3.png) 5. Нажмем в приложении на Login Method 1 Нам выведет в консоль ![](https://hackmd.io/_uploads/Bk8t4Jq8n.png) Итак, теперь мы знаем, что при нажатии метода входа 1 вызывается метод isLoginValidated из класса LoginValidate. Итак, теперь давайте посмотрим на метод и посмотрим, какое значение возвращается. 7. ``` ios hooking watch method "+[LoginValidate isLoginValidated]" --dump-args --dump-return ``` Нажмем в приложении на Login Method 1 ![](https://hackmd.io/_uploads/HkmiE15Ln.png) 8. Изменим возвращаемое значение меняем на 0х1 ``` ios hooking set return_value "+[LoginValidate isLoginValidated]" 0x1 ``` Почему-то значение не изменилось. Попробуем поменять на true ``` ios hooking set return_value "+[LoginValidate isLoginValidated]" true ``` ![](https://hackmd.io/_uploads/ryY3NkqL2.png) Нажмем в приложении Login Method 1 - Congratulated! Мы обошли проверку ### LLDB 1. Узнаем процесс в фриде frida-ps -Ua 2. Подключившись к айфону - в терминале запускаем lldb 3. Подключаемся к приложению (lldb) attach 14298 4. ```image dump sections DVIA-v2``` 5. Для начала нам нужно рассчитать смещение ASLR. Поскольку применяется ASLR, адреса в памяти будут случайными каждый раз, когда мы начинаем. Поэтому каждый раз, когда мы перезапускаем DVIA-v2, нам нужно будет повторять это. В LLDB дамп разделов изображения. ![](https://hackmd.io/_uploads/r1f1Hk9L3.png) ``0x0000000102efc000 - 0x0000000100000000(2**32) = 0x2efc000 ![](https://hackmd.io/_uploads/SyzgB15U3.png) 6. Теперь, когда мы знаем смещение, мы можем посмотреть на функцию в Гидре и найти сравнение, которое нас интересует. ![](https://hackmd.io/_uploads/SyzWHk9L2.png) 0x1001bd300 7. Cчитаем смещение dis -s 0x2efc000+0x1001bd300 ![](https://hackmd.io/_uploads/Sy1MrkqLh.png) 8. Ставим брейкпоинт (предварительно нажимаем в приложении Login Metod 1) br set -a 0x1030b9314 ![](https://hackmd.io/_uploads/H1oGSk9Ln.png) 9. register read -читаем регистры ![](https://hackmd.io/_uploads/rJRQBkcIn.png) Учитывая, что мы хотим изменить логику инструкции по прыжку, нам нужно посмотреть на регистр x0, так как он сравнивает x0 с 0x0, и если он равен 0x0, то он сделает jump и отправит нас к неудачному сообщению. 10. Меняем регистр на 0х1 ``` register write x0 0x1 ``` 11. Отпускаем приложение `c` ![](https://hackmd.io/_uploads/Hy3EryqUn.png) Congratulations - обошли проверку Login Method 1 ## Login Method 2 1. Мы знаем название функции из frida-trace, поэтому мы можем найти это в Ghidra и найти функцию для нажимаемой кнопки Login Method 2. ![](https://hackmd.io/_uploads/B1jrry583.png) 2. Прокрутим страницу, найдем строку admin13412, которая, кажется, выполняет инструкцию добавления с этой статической строкой и некоторым другим значением. Это очень многообещающее поведение, поскольку нас интересует имя пользователя или пароль. ![](https://hackmd.io/_uploads/H1-PSk98n.png) admin13412 Прокрутим ниже, найдем строку похожую на пароль ![](https://hackmd.io/_uploads/r16dSk9I2.png) S@g@rm@7h@8848 Ввели данные в приложении и Congratulation! ## Validate Code При вводе 4 значного числа мы видим уведомление с введеным числом и ошибкой. 1. Выведем вызываемую функцию с помощью frida ``frida-trace -U -i "*validateCode*" DVIA-v2 ![](https://hackmd.io/_uploads/S16Frk58h.png) 2. Перейдем в гидру. Проанализируем функции Ничего похожего на предыдущий анализ не было найдено. Воспользовался поиском - ввел incorrect code и увидел необходимый код 8848 ![](https://hackmd.io/_uploads/HydqBkqU2.png) исследуем в обратную сторону - нашли функцию ![](https://hackmd.io/_uploads/HJSjrJqUn.png) Этот b.ne - это ветвь, если не равная инструкции, и прыжок, который он делает, отправляет нас на неправильное кодовое сообщение. Если этот прыжок не будет сделан, мы в конечном итоге получим сообщение об успехе. ![](https://hackmd.io/_uploads/B1g2HkcLn.png) Непосредственно перед b.ne находится инструкция cmp, которая сравнивает значение того, что хранится в x9, с тем, что хранится в x8. Результат этого определит, будем ли мы прыгать. Если они равны, мы не будем прыгать, и у нас все получится. Если они не равны, то он перескочит, и мы потерпим неудачу. Инструкция ldur перемещает значение в x9 из #local_28. Мы не знаем, что это такое, но, вероятно, это значение, возвращенное какой-то другой функцией. Инструкция mov перемещает шестнадцатеричное значение 0x2290 в регистр x8. Итак, теперь мы знаем, что это показывает, что 0x2290 находится в x8 и сравнивается с каким-то другим значением в x9, а затем на основе результата мы пройдем или потерпим неудачу. Это означает, что x9, вероятно, будет нашим кодом. Поскольку 0x2290 является шестнадцатеричное, а значение, которое мы вводим, является десятичным значением, нам нужно преобразовать его. Конвертируем 0x2290 и оно равно десятичному значению 8848. Вводим код 8848 в приложение, и успех! ### Frida Мы можем использовать следующий сценарий Frida для проверки значений в регистрах x9 и x8 в этом указателя, чтобы показать нам значения в режиме реального времени и подтвердить, что мы ожидаем от x9 и x8. 1. Cоздадим скрипт DVIARuntimeCodereturnmemvalue.js ``` var targetModule = 'DVIA-v2'; var addr = ptr(0x15e3e0); var moduleBase = Module.getBaseAddress(targetModule); var targetAddress = moduleBase.add(addr); Interceptor.attach(targetAddress, { onEnter: function(args) { console.log('At the address ' + addr + ' the value of x9 is currently ' + this.context.x9 + ' and the value of x8 is currently ' + this.context.x8); }, }); ``` ``` frida -U -l DVIARuntimeCodereturnmemvalue.js DVIA-v2 ``` в приложении нажали кнопку validate Code и в окно frida нам вывелась инфа ![](https://hackmd.io/_uploads/HJPTHJ5Uh.png) Введем другое значение кода ![](https://hackmd.io/_uploads/BJRpH1qIh.png) Понимаем что значение х9 - это вводимая строка 2. Итак, теперь мы можем создать скрипт frida, который будет смотреть на этот адрес, а затем, если значение x9 не равно 0x2290, он его изменит так, чтобы он был 0x2290. Это будет означать, что независимо от того, какой код мы введем, он будет успешным! DVIARuntimecodebypass.js ``` var targetModule = 'DVIA-v2'; var addr = ptr(0x15e3e0); var moduleBase = Module.getBaseAddress(targetModule); var targetAddress = moduleBase.add(addr); Interceptor.attach(targetAddress, { onEnter: function(args) { if(this.context.x9 != 0x2290){ this.context.x9=0x2290 console.log("Bypass Code Validation"); } }, }); ``` ``` frida -U -l DVIARuntimecodebypass.js DVIA-v2 ``` Success! # Anti Anti Hooking/Debugging ## Defeating Anti-Debugging 1. Мы можем найти в Ghidra функцию, которая запускается при нажатии кнопки Disable Debugging ![](https://hackmd.io/_uploads/SJCyIk5Ih.png) В этой функции мы видим, что она вызывает другую функцию. 2. Нажимаем на эту функцию ![](https://hackmd.io/_uploads/SyAlIyqI2.png) В этой функции мы видим, что есть строка для ptrace. Если вы погуглить о мерах по борьбе с отладкой на iOS, можно найти несколько документов, включая OWASP и Apple, подробно описывающих использование ptrace для предотвращения отладки в приложениях iOS. Ptrace на iOS имеет уникальную функцию, которой является флаг PT_DENY_ATTACH, который позволяет установить его только для предотвращения подключения других отладчиков. Если другой попытается подключиться, процесс завершится. 3. Подключаем LLDB 4. Подключаемся к приложению attach id ![](https://hackmd.io/_uploads/ryQMLJ98n.png) 5. Cтавим брейкпоинт введя b ptrace ![](https://hackmd.io/_uploads/HkzX8y5In.png) 6. Ошибки можно игнорировать, так как это все еще сработало. Теперь, установив точку останова, нажмите кнопку "Disable Debugging". Приложение должно сделать паузу, и увидим, что точка останова была поражена.![](https://hackmd.io/_uploads/rkk4LJcU2.png) 7. register read ![](https://hackmd.io/_uploads/HktNIkqU3.png) Отпускаем процесс - и видим что приложение закрылось 8. Это показывает, что отладка была отключена. Теперь перезапустим приложение и снова установим точку останова на ptrace. Нажмем кнопку, а затем, когда будет нажата точка останова, на этот раз измените регистр x0 с 0x1f на 0x0. b ptrace reg read reg write x0 0x0 Всплывающее окно появится в приложении, но ошибки в отладчике не будет. Теперь продолжаем отладку приложения и обходим защиту отладки! ## Defeating Anti-Hooking Могут быть приняты меры по борьбе с крючками, чтобы попытаться остановить такие вещи, как Frida, Cydia Substrate и SSL KillSwitch. 1. в гидре найдем эту функцию ![](https://hackmd.io/_uploads/S1SULkq8n.png) Находим сообщение об ошибке ![](https://hackmd.io/_uploads/Bk7DLJ5Lh.png) frida-trace -U -i "*Injection*" DVIA-v2! ![](https://hackmd.io/_uploads/BJCPIy9Ln.png) **lldb** image dump sections DVIA-v2 0x00000001027cc000 - 0x0000000100000000 = 0x27cc000 dis -s 0x27cc000+0x1001f0b44 ![](https://hackmd.io/_uploads/H11FL1c8h.png) 0x1029bcb44 br set -a 0x1029bcb44 reg read ![](https://hackmd.io/_uploads/S19FUJcI2.png) reg write x9 0x0 безуспешно Изучили исходный код, нашли название функции ![](https://hackmd.io/_uploads/H1698J9U3.png) Попробуем изменить значение в строке 1001690d8 dis -s 0x27cc000+0x1001690d8![](https://hackmd.io/_uploads/r1AoU1cLn.png) br set -a 0x1029350d8 reg read reg write x9 0x0 po $x0 image dump section DVIA-v2 0x0000000100000000 0x00000001042e4000 0x42e4000 0x1001690d8+0x42e4000 0x1001690e4+0x42e4000 0x100169064+0x42e4000 0x100169068+0x42e4000 Понимаю что через изменение значений по брейкпоинту я ниче не добъюсь. Уже перебробовал разные брейкпоинты. Функция сравнивает w8 и w9 и перепрыгивает на проверку ![](https://hackmd.io/_uploads/r1XaIk5L2.png) Когда цикл происходит, он переходит в эту часть кода со строкой с инструкцией b.cs и делает прыжок, который обходит все проверки, поэтому я бы предположил, что именно тут заканчивается цикл. Я использовал следующий сценарий frida, чтобы посмотреть на регистры x8 и x9 в месте. Это выводит огромное количество выходных данных, так как эта функция постоянно повторяется, а затем, если она обнаруживает их в любое время, она завершает работу. DVIAreturnmvalueInjection.js ``` var targetModule = 'DVIA-v2'; var addr = ptr(0x169060); var moduleBase = Module.getBaseAddress(targetModule); var targetAddress = moduleBase.add(addr); Interceptor.attach(targetAddress, { onEnter: function(args) { console.log('At the address ' + addr + ' the value of x8 and x9 is currently ' + this.context.x8 + this.context.x9); }, }); ``` Frida -U -l DVIAreturnmvalueInjection.js DVIA-v2 Нажмем на Disable Injection в приложении ![](https://hackmd.io/_uploads/r1BCLJ5U2.png) Идет сравнение х8 и х9 Если мы сможем сделать значение x8 равным или больше x9, то b.cs будет взят, и цикл будет завершен. С моими тестами казалось, что значение x9 изменилось в различных циклах высечения, поэтому я сделал скрипт Фриды ниже, который должен делать x8 и x9 всегда равными. DVIAbypassInjection.js ``` var targetModule = 'DVIA-v2'; var addr = ptr(0x169060); var moduleBase = Module.getBaseAddress(targetModule); var targetAddress = moduleBase.add(addr); Interceptor.attach(targetAddress, { onEnter: function(args) { if(this.context.x8 != this.context.x9){ this.context.x8=this.context.x9 console.log("Bypass Injection Checks"); } }, }); ``` Frida -U -l DVIAbypassInjection.js DVIA-v2 ![](https://hackmd.io/_uploads/Byw1D1qIn.png) Видно что скрипт отработал и работает циклом. Предполагаю что работа завершена, т.к. в приложении не удается это как-то проверить # Binary protection Отсутствие бинарной защиты в мобильном приложение может помочь злоумышленнику проанализировать приложение, перепроектировать его и подделать его, а также. Проверьте следующие средства защиты. Lack of Binary protection within a mobile app can help an adversary analyze the app, reverse engineer it and tamper it as well. Check for the following protections. ## а) Проверьте, включены ли защиты PIE , ARC и защита от stack smashing (защита стека от переполнения) (a) Check whether PIE, ARC and stack smashing protection is enabled in the app) PIE (Position Independent Executable) - это механизм защиты, который обеспечивает случайное размещение исполняемого файла в памяти. ARC (Automatic Reference Counting) - это механизм управления памятью в Objective-C и Swift, который автоматически отслеживает количество ссылок на объект и освобождает память, когда объект больше не используется. Запустим скрипт на фриде для PIE & ARC ``` // Проверка наличия защиты от PIE function checkPIE() { var mainModule = Process.enumerateModulesSync()[0]; return mainModule.base.toString().startsWith("0x1000"); } // Проверка наличия защиты от ARC function checkARC() { var classes = ObjC.classes; for (var i = 0; i < classes.length; i++) { var className = classes[i].$className; if (className === "NSObject") { return true; // Если класс NSObject доступен, это указывает на использование ARC } } return false; } // Вызов функций проверки и вывод результатов function checkProtection() { console.log("PIE enabled:", checkPIE()); console.log("ARC enabled:", checkARC()); } // Запуск проверки checkProtection(); ``` ![](https://hackmd.io/_uploads/ryC-PyqL3.png) Запустим скрипт на фриде для stack smashing ``` // Проверка наличия защиты от stack smashing function checkStackSmashing() { // Получаем адрес функции __stack_chk_guard var stackGuardAddr = Module.findExportByName(null, "__stack_chk_guard"); // Если адрес найден, то защита от stack smashing включена return stackGuardAddr !== null; } // Вызов функции проверки и вывод результата function checkProtection() { console.log("Stack smashing protection enabled:", checkStackSmashing()); } // Запуск проверки checkProtection(); ``` ![](https://hackmd.io/_uploads/S1YGPk5Ln.png) ## б) Проверьте, поставляется ли приложение с раздетые символы или нет b) Check whether the app comes with stripped symbols or not "Stripped symbols" в iOS означает, что символы (например, имена функций и переменных) были удалены из исполняемого файла приложения. Это делается с целью уменьшить размер исполняемого файла и скрыть информацию о внутренней реализации приложения. ``` // Загрузка модуля var module = Process.enumerateModulesSync()[0]; // Проверка наличия символов if (module !== undefined && module !== null) { if (module.path.includes("DVIA-v2")) { console.log("Symbols are present in the app."); } else { console.log("Symbols are stripped from the app."); } } else { console.log("Failed to enumerate modules."); } ``` ![](https://hackmd.io/_uploads/B1EEP1q82.png) Символы присутствуют в приложении ## c) Найдите общие библиотеки, используемые приложением c) Find the shared libraries used by the app shared_libraries.js Frida -U -l shared_libraries.js DVIA-v2 ``` // Получение списка используемых общих библиотек function getSharedLibraries() { // Получение модуля приложения var mainModule = Process.enumerateModulesSync()[0]; // Получение списка используемых общих библиотек var libraries = mainModule.enumerateImports(); // Вывод списка общих библиотек libraries.forEach(function(library) { console.log(library.name); }); } // Запуск поиска общих библиотек getSharedLibraries(); ``` ![](https://hackmd.io/_uploads/rycrDJ98h.png) и еще куча всего ## d) Проверьте, может ли приложение быть самоподписанным и развернуто на взломанном устройстве d) Check whether the app can be self-signed and deployed on a jailbroken device Перейдем в папку приложения где исполняемый файл ``` iPhone:/var/containers/Bundle/Application/750D395C-9391-4042-AAB6-5A233836BEF6/DVIA-v2.app ldid -e DVIA-v2 ``` ![](https://hackmd.io/_uploads/B11vwJ5U3.png) 1. `application-identifier` содержит значение `3JW2H263BC.com.highaltitudehacks.DVIAswiftv2.3JW2H263BC`. Это идентификатор приложения, который должен быть уникальным для каждого приложения в экосистеме iOS. Он указывает на то, что приложение с идентификатором `com.highaltitudehacks.DVIAswiftv2.3JW2H263BC` должно быть самоподписанным. 2. `com.apple.developer.team-identifier` содержит значение `3JW2H263BC`. Это идентификатор команды разработчика, связанный с приложением. Он указывает на то, что приложение связано с командой, имеющей идентификатор `3JW2H263BC`. 3. `get-task-allow` имеет значение `<true/>`. Это означает, что приложение разрешает отладку, что может быть полезно при разработке и тестировании на джейлбрейкнутых устройствах. 4. `keychain-access-groups` содержит элемент `<string>3JW2H263BC.*</string>`. Это указывает на группы доступа к ключам, к которым приложение имеет доступ. ## e) Проверьте, является ли двоичный файл приложения толстым двоичный или нет e) Check whether the app binary is a fat binary or not ``` iPhone:/var/containers/Bundle/Application/750D395C-9391-4042-AAB6-5A233836BEF6/DVIA-v2.app file DVIA-v2 ``` ![](https://hackmd.io/_uploads/SypYDkqU2.png) Этот вывод означает, что исполняемый файл приложения не является "fat binary" и поддерживает только одну архитектуру `arm64`. ## f) Проверьте, являются ли имена классов обфусцирован в приложении или нет f) Check whether the class names are obfuscated in the application or not objection ios hooking list classes ![](https://hackmd.io/_uploads/S1-jw1cL2.png) Замаскированные имена классов могут быть случайными, непонятными или использовать нестандартные шаблоны именования. Обратите внимание, что классы, связанные с системными фреймворками iOS, могут иметь стандартные имена, в то время как классы, специфичные для приложения, могут быть более замаскированными. Я считаю что имена классов не обфусцированы ## g) Найдите подпись, использованную для подписания приложение g) Find the signature used for signing the app ``` /var/containers/Bundle/Application/750D395C-9391-4042-AAB6-5A233836BEF6/DVIA-v2.app ldid -e DVIA-v2 ``` ![](https://hackmd.io/_uploads/BkH3v15U3.png) ## h) Найдите права, используемые приложением h) Find the entitlements used by the app то же самое что и вывод сверху # Touch/Face ID Bypass ``objection -g 23504 explore `` ios ui biometrics_bypass ![](https://hackmd.io/_uploads/SJh6wJ9In.png) Класс `LAContext` отвечает за локальную аутентификацию. Он не выполняет никаких внешних проверок и полагается на iOS для представления соответствующего диалога и подтверждения. Метод `evaluatePolicy в классе LAContext` дает iOS возможность представить соответствующее диалоговое окно (отпечаток пальца, сканирование лиц, пароль для входа в систему, пароль) и аутентифицировать пользователя. В зависимости от результатов проверки блок ответов вызывается из метода и отправляется обратно в приложение. Это содержит логическое значение, диктующее, было ли оно успешным или нет. Когда `ios ui biometrics_bypass` выполняется в Objection, он создает хук на ``-[LAContext evaluatePolicy:localizedReason:reply:]``. В этом можно увидеть, что это класс `LAContext`, метод `evaluatePolicy` и блок ответов. Это изменит его с ложного на истинный, что означает, что он был успешным. Это не сработает в тех случаях, когда необходимы дальнейшие проверки. В этих случаях вы можете использовать это для обхода первой части, затем вам нужно будет вручную подключить последующие проверки. Это также не сработает, если он будет проверен удаленно в качестве локального механизма аутентификации. Это также не будет работать в тех случаях, когда элементы связки ключей защищены флагами контроля доступа, такими как `kSecAccessControlTouchIDAny или kSecAccessControlTouchIDCurrentSet`. доп пример команды ``` ios hooking set return_value "-[LAContextevaluatePolicy:localizedReason:reply:]" true ``` ![](https://hackmd.io/_uploads/S1Gy_kcUh.png) # iOS Side Channel Data Leakage ## Device Logs При вводе значений у меня вылетает из приложения. Но логи введеные мы можем посмотреть idevicesyslog ## App Screenshot Когда приложение для телефона фоновое, вы все равно можете «видеть» экран при захождении в меню, чтобы выбрать между открытыми приложениями. На самом деле это всего лишь скриншот. Приложение делает снимок экрана при фоновом режиме, затем сохраняет его на устройстве, и это то, что вы видите. Затем, когда вы снова открываете приложение, оно сохраняет этот скриншот, пока загружает приложение, это обеспечивает более плавный опыт. Однако, если вы фоновое приложение при вводе банковской информации, это означает, что снимок экрана содержит конфиденциальные данные. Скриншоты сохраняются в `/var/mobile/Containers/Data/Application/9E66C4E1-83F5-42E0-9FFF-FB025DF03DCB/Library/SplashBoard/Snapshots` можно скачать на комп с помощью scp и открыть скрин Но я сделаю проще - зайду через filza и там открою скрин ![](https://hackmd.io/_uploads/Skezgg5U2.png) ## Pasteboard Когда текст копируется в iOS, он попадает внутрь "pasteboard". Так что это то же самое, что и буфер обмена Windows. Здесь хранятся введеные данные для вставки позже. Это может включать в себя имена пользователей, пароли и любую другую конфиденциальную информацию. Задача здесь состоит в том, чтобы ввести имя, номер кредитной карты и значение CVV, скопировать их, а затем увидеть на pasteboard. В нем говорится, что мы должны создать отдельное приложение, чтобы сделать это, но я буду использовать objection. ``` objection --gadget DVIA-v2 explore ``` ``` ios pasteboard monitor ``` Теперь зайдите в заявку, заполните значения, а затем скопируйте их все по одному. Мы должны видеть, как они появляются в консоли, когда мы их копируем! ![](https://hackmd.io/_uploads/rk0LxgqUn.png) # Keystroke Logging При прохождении приложения устройство по умолчанию регистрирует нажатия клавиш на каждом вводе. Он не делает этого, если поле ввода помечено как безопасное `secure` в приложении. Разработчики также должны отключить автокоррекцию конфиденциальных полей, чтобы предотвратить это. Телефоны собирают эту информацию, чтобы они могли использовать прогнозный текст и предложения по автокоррекции. Поскольку это значения, хранящиеся на устройстве, мы (или вредоносное приложение) можем найти их на взломанном устройстве и прочитать содержимое! Находится это в ``` /private/var/mobile/Library/Keyboard/ ``` Перейдем в каталог В Интернете я видел, что местоположение должно быть en_GB-dynamic-text.dat в этой папке. Но у меня этого не было. Однако, просматривая папки и другие файлы .dat, я нашел следующий файл: `/private/var/mobile/Library/Keyboard/en-dynamic.lm/dynamic-lexicon.dat` скопируем по SCP файл ``` scp root@127.0.0.1:/private/var/mobile/Library/Keyboard/en-dynamic.lm/dynamic-lexicon.dat . ``` У меня connection refused, по этому я скачаю файл через Filza xxd /dynamic-lexicon.dat | less тут что-то непонятное. Попробовал через саму филзу прочитать файл и нашел там введенное значение. ![](https://hackmd.io/_uploads/BJO2lx582.png) ## Cookies Некоторые приложения создают файлы cookie и хранят их на устройстве, чтобы обеспечить сохранение в приложении (оставясь в системе, поэтому пользователям не нужно вводить аутентификацию каждый раз). Хотя это удобно, это может позволить учетным данным находиться на устройстве. Можем воспользоваться objection ``` objection --gadget DVIA-v2 explore ``` ``` ios cookies get ``` ![](https://hackmd.io/_uploads/r110xe5Ln.png) Так же можем найти данные значения в ghidra! ![](https://hackmd.io/_uploads/HyCRlx58n.png) # IPC Issues Звонок из приложения с помощью deeplink Как узнать что приложение использует диплинки ? diplink В проперти лист 1. переходим в папку установки приложения cd /private/var/containers/Bundle root# cd Application/ ls * | grep -i "DVIA-v2" -B 2 cd 750D395C-9391-4042-AAB6-5A233836BEF6/DVIA-v2.app 2. файлик Info.plist 3. plistutil -i Info.plist - раскодируем проперти лист 4. грепаем по ключу url chema - ``plistutil -i Info.plist | grep -i "<key>CFBundleURLName</key>" -A 6 ![](https://hackmd.io/_uploads/ByQQbe9Un.png) 5. Определяем что приложен использует `<string>dvia</string> ``<string>dviaswift</string>` 6. берем гидру ищем метод приходящей ссылки обработки ccылка обработки функции (url схема) прилетает в application - appdelegate ![](https://hackmd.io/_uploads/SJhEWxcU3.png) 7. в браузере телефона можем ввести url . предварительно нашли в гидре значения dvia://aaa.com/phone/call_number/12345678 Calling - Ring Ring - с помощью DVIA звонит по введеному номеру # Broken Criptography криптография Уязвимость которая происходит, когда хранилище данных в приложении не зашифровано должным образом, что позволяет злоумышленнику получить доступ к данным. 1. В исходном коде на гитхабе - видно что данные шируются с помощью SHA256 и пароля @daloq3as$qweasdlasasjdnj от файла ![](https://hackmd.io/_uploads/rJQOWlc8n.png) 2. переходим в папку приложения /var/mobile/Containers/Data/Application/9E66C4E1-83F5-42E0-9FFF-FB025DF03DCB/Documents 3. надо скачать secret-data и расшифровать (я скачал с помощью филзы) 4. Напишем скрипт на питоне ``` import rncryptor data = open("secret-data", 'rb').read() password = '@daloq3as$qweasdlasasjdnj' cryptor = rncryptor.RNCryptor() decrypted_data = cryptor.decrypt(data, password) print(decrypted_data) ``` Расшифровал ![](https://hackmd.io/_uploads/SkUK-xcLn.png) # Webview Issues Попробуем XXS ![](https://hackmd.io/_uploads/BJSoWg5U3.png) Символы фильтруются, а числа нет. Попробуем Перевести слово Hello world в ASCII ``<script>alert(String.fromCharCode(72,101,108,108,111,32,87,111,114,108,100))</script> ![](https://hackmd.io/_uploads/SJ_pbxcL3.png) 1 таск удалось пройти # Network Layer Security Перехват трафика Man in the Middle ## HTTP Включаем burp 1.Настраиваем прокси на порт 9999 на все интерфейсы 2. включаем прокси на телефоне Настройки -> WiFi - Proxy-> ручной -> пишем сервер (ip хоста) и порт (9999) 3. переходим в приложение dvia-v2 и нажимем на кнопку SEND OVER HTTP ![](https://hackmd.io/_uploads/rkvxGx582.png) ## HTTPS 1. На iPhone запустите веб-браузер и перейдите на http://burp. Нажмите кнопку CA Certificate в правом верхнем углу представления и разрешите загрузку. 2. Переходим в настройки телефона -> Основные -> Профиль -> PortSwigger CA -> установить 3. Настройки > Основные > Об этом устройстве > Доверие к сертификатам > Активировать сертификаты 4. Нажимаем SEND OVER HTTPS ![](https://hackmd.io/_uploads/rkFWMl5Ih.png) ## Certificate/SSL Pinning objection 1. objection -g 35216 explore 2. ios sslpinning disable 3. нажимаем на send using certificate pinning и на send using public key pinning ![](https://hackmd.io/_uploads/BklHfgcU2.png) Пиннинг отключили - запрос прилетел в бурп Оба этих запроса выглядят одинаково и являются запросами GET. Это означает, что они не включают данные POST из приложения, поэтому мы не можем видеть конфиденциальные данные. Однако, поскольку мы обошли проверку сертификата. ## App Transport Security перейдем в файл Info.plist ``` /private/var/containers/Bundle/Application/750D395C-9391-4042-AAB6-5A233836BEF6/DVIA-v2.app ``` plistutil -i Info.plist ![](https://hackmd.io/_uploads/HJ4vMg9I2.png) ключ NSAllowsArbitraryLoads Данная настройка разрешает HTTP-связь. ключ `<key>NSExceptionAllowsInsecureHTTPLoads</key>` разрешает только связь HTTPS Более подробно можно изучить тут https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33 # Sensitive information in memory ![](https://hackmd.io/_uploads/SJHtMx98n.png) - Некоторые приложения хранят важную информацию в памяти приложений, даже если она им не нужна • Происходит потому, что разработчик не удалил атрибут или переменную экземпляра после его использования, которые могут содержать важную информацию Скачиваем утилиту для дампа памяти Fridump3 #Fridump3    [https://github.com/rootbsd/fridump3](https://github.com/rootbsd/fridump3) python3 fridump3.py -u -r -s DVIA-v2 -U = USB-устройство -R = Выбрасывает часть памяти, доступную только для чтения, и использует эту опцию для получения большего количества данных -S = Проверьте, извлекая только строки, введенные из сброшенных данных. 1. Переходим в Runtime Manipulation - вбиваем данные Юзернейм и пароль - Login method 1 2. Дампим память 3. python3 fridump3.py -u DVIA-v2 -r -s 4. ![](https://hackmd.io/_uploads/S1GiGx5I3.png) 5. Открываем файл strings.txt ![](https://hackmd.io/_uploads/rJ_TMgqIh.png) ![](https://hackmd.io/_uploads/HkL17g9U2.png) # Data leakage to third parties Утечка данных третьим лицам Утечка данных третьим лицам Много приложений, использующих сторонние услуги по разным причинам. Конфиденциальные данные может просочиться на эти стороны, если нет должным образом заботятся. В некоторых случаях нарушение стороннего поставщика услуг может закончиться высвобождением большого количества информации о своих клиентах. Flurry — самая популярная мобильная аналитика услуга. Авторизация осуществляется через используя единый ключ API. Ваши задачи – это следующий. а) Определите ключ API б) Зафиксировать утечку данных во Flurry, когда информация вводится в текстовое поле ниже. Введите фиктивный номер телефона 1. Переходим в директорию /var/mobile/Containers/Data/Application/9E66C4E1-83F5-42E0-9FFF-FB025DF03DCB/Library/Application Support/FlurryFiles 2. Тут архивные файлы. 3. А еще есть info файл 4. Но там прописывется инфа о созданных архивах Flurry 5. Дальше не понимаю куда двигаться.... # Application patching ## Login Method 1 ![](https://hackmd.io/_uploads/ryX-XlqUh.png) Нам надо сделать так чтобы - при вводе любого значения было Sucsess найдем в гидре функцию ![](https://hackmd.io/_uploads/BJfMml9L3.png) находим функцию - в которой получаем Sucsess ![](https://hackmd.io/_uploads/H1-mQecU2.png) находим функцию проверки ![](https://hackmd.io/_uploads/B1l4QgcU2.png) Мы видим что 1001ac1b8 ведет к Sucsess Теперь в гидре меняем значение проверки LAB_1001ac270 на LAB_1001ac1bc ![](https://hackmd.io/_uploads/Hkrr7l98h.png) выделяем нужный адрес - нажимаем правой кнопкой Patch и меняем на необходимое значение ![](https://hackmd.io/_uploads/BkQL7e9U2.png) Теперь экспортируем программу ![](https://hackmd.io/_uploads/BkGPmxcU2.png) ![](https://hackmd.io/_uploads/Hyhw7g9Ln.png) перекидываем получившийся бинарь на телефон в папку scp -P 2222 DVIA-v2 root@localhost:/private/var/containers/Bundle/Application/750D395C-9391-4042-AAB6-5A233836BEF6/DVIA-v2.app/ Открываем приложение и должно быть все ок. Но у меня больше не открывается приложение, я предполагаю что проблема в подписи))