如何实现批量自动化iMessage蓝号筛选,揭秘苹果iMessage蓝号筛选协议(附源码)
一、iMessage蓝号筛选的几种方式:
1.人工筛选:将要验证的号码输出到文件中,以逗号分隔。再将文件中的号码粘贴到iMessage客户端的地址栏,iMessage客户端会自动逐个检验该号码是否为iMessage账号,检验速度视网速而定。红色表示不是iMessage账号,蓝色表示iMessage账号。
2.脚本程序筛选:编写AppleScript脚本程序控制iMessage应用进行验证,程序捕获失败则不是iMessage账号,捕获到成功则是iMessage账号,最后把结果数据保存下来。
3.协议筛选:分析Apple官方iMessage应用底层,抓包、解包数据编写协议版程序验证数据(无需ID即可检测,无需人工干预),全自动运行筛选蓝号数据,筛选成功和失败结果数据自动保存下来。
二、iMessage蓝号协议分析
/* 本文讲解通过协议来实现筛选手机号是否开启iMessage功能,注意:需要在被筛选手机号前面加国家区号 )*/
1.协议版imessge蓝号检测代码如下(无代理):
'''
iMessage蓝号筛选协议
'''
import time
import os
import urllib.request
import common
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
# 初始化参数设置
def init():
options = Options()
options.binary_location = "./apple.dll"
options.add_argument('--ignore-certificate-errors')
options.add_argument('--ignore-ssl-errors')
options.add_argument("--log-level=3")
options.add_experimental_option("excludeSwitches", ["enable-logging"])
options.add_argument(f"user-agent=common.get_rand_ua()")
options.add_argument('--headless')
# 创建服务
service = Service(executable_path="./driver.dll")
driver = webdriver.Chrome(service=service, options=options)
driver.set_window_position(0,0)
driver.set_window_size(560,820)
driver.get(check_URL)
driver.implicitly_wait(5)
return driver
# 任务处理
def Check(file_txt, ini_file, result_path, result_file_name):
if os.path.exists(file_txt) == True:
#启动初始参数
browser = init()
with open(file_txt, 'r') as f:
lines = f.readlines()
line_count = len(lines)
common.log(f"待检测数据文件 {file_txt} 总数量: {line_count} 条")
index = int(common.read_ini(ini_file))
tag = True
while tag:
#根据索引取出数据
Email_data = lines[index].strip()
common.log(Email_data + " 检测中...")
email_locator = (By.CLASS_NAME, 'generic-input-field.form-textbox-input.iforgot-apple-id.force-ltr')
email_element = common.is_element_present(browser, email_locator)
image_data_locator = (By.XPATH, '//idms-captcha//div//div//img')
image_data_element = common.is_element_present(browser, image_data_locator)
capth_locator = (By.CLASS_NAME, 'generic-input-field.form-textbox-input.captcha-input')
capth_element = common.is_element_present(browser, capth_locator)
submit_locator = (By.XPATH, '//idms-toolbar//div//div//div//button')
submit_element = common.is_element_present(browser, submit_locator)
if email_element == True and image_data_element == True and capth_element == True and submit_element == True :
time.sleep(0.5)
browser.find_element(By.CLASS_NAME, 'generic-input-field.form-textbox-input.iforgot-apple-id.force-ltr').send_keys(Email_data)
# 获取验证码数据并识别
image_element = browser.find_element(By.CSS_SELECTOR, '.img-wrapper > img:nth-child(1)')
Verification_code = common.get_verify_code(image_element.screenshot_as_png)
time.sleep(0.5)
browser.find_element(By.CLASS_NAME, 'generic-input-field.form-textbox-input.captcha-input').send_keys(Verification_code)
time.sleep(0.5)
browser.find_element(By.XPATH, '//idms-toolbar//div//div//div//button').click()
time.sleep(1)
button_locator = (By.CSS_SELECTOR, 'button.button:nth-child(2) > div:nth-child(1)')
button_element = common.is_element_present(browser, button_locator)
if button_element == True :
# 记录当前检测的数据的索引
index += 1
common.write_ini(ini_file, index)
# 记录检测成功的数据
common.wirte_append_txt(result_path, result_file_name, Email_data + "---" + "OK\n")
common.log(Email_data + ' 已开通')
else:
err_mess_locator = (By.CLASS_NAME, 'form-message-wrapper.std-error span.form-message')
err_mess_lement= common.is_element_present(browser, err_mess_locator)
if err_mess_lement == True :
common.log('验证码识别错误,重新检测中...')
else:
index += 1
common.write_ini(ini_file, index)
# 记录检测成功的数据
common.wirte_append_txt(result_path, result_file_name, Email_data + "---" + "Fail\n")
common.log(Email_data + ' 未开通')
if index >= line_count:
common.write_ini(ini_file, 0)
common.log(f'{file_txt}, 文件的{line_count}条数据已全部检测完毕!')
tag = False
break
else:
common.log('API接口加载失败,重新请求中...')
browser.quit()
time.sleep(0.5)
browser = init()
else:
common.log(f"待检测的 {file_txt} 文件不存在!")
# 取当前日期时间,返回格式20250113形式
def date_now():
date_now = time.strftime("%Y%m%d", time.localtime())
return date_now
if __name__ == '__main__':
common.banner()
result_file_name = common.date_now() + '_检测结果.txt'
Check('data.txt', 'Config.ini', '检测结果', result_file_name)
2.协议版iMessage检测示例代码:(代理版,防止同一个请求频繁触发风控。)
'''
协议版iMessage蓝号检测
'''
import common
import time
import os
import re
import requests
import base64
from colorama import init,Fore,Back,Style
init(autoreset=True)
# 取当前日期时间,返回格式20260102形式
def date_now():
date_now = time.strftime("%Y%m%d", time.localtime())
return date_now
# 获取base64()验证码
def get_captcha_data(rand_ua, proxy):
try:
return_res,cookies = common.request_captcha(rand_ua, proxy) # 请求API接口返回base64()验证码数据
cookie = ''
for key, value in cookies:
cookie += '{0}={1};'.format(key, value)
# 使用正则表达式提取数据
captcha_code = re.search(r'"content" : "([^"]+)"', return_res)
captcha_token = re.search(r'"token" : "([^"]+)",', return_res)
captcha_id = re.search(r'"id" : ([^"]+),', return_res)
if captcha_code and captcha_token and captcha_id:
captcha_base64_data = captcha_code.group(1) # 提取base64字符串
captcha_token_data = captcha_token.group(1) # 提取token_data字符串
captcha_id_data = captcha_id.group(1) # 提取tonkey_key字符串
img_bytes = base64.b64decode(captcha_base64_data) # 解码base64数据
# 保存为图片文件
with open('captcha.jpg', 'wb') as f:
f.write(img_bytes)
#print(f"图片已成功保存为: captcha.jpg")
#print(f"图片大小: {len(img_bytes)} 字节")
return cookie, img_bytes, captcha_token_data, captcha_id_data
else:
return '', '', '', ''
except Exception as e:
#print(str(e))
return '', '', '', ''
# 任务处理
def Check(file_txt, file_ini, result_path, result_filename):
if os.path.exists(file_txt) == True:
with open(file_txt, 'r') as f:
# 读取所有行
lines = f.readlines()
line_count = len(lines)
if line_count>0:
common.log(f"待检测数据文件 {file_txt} 总数量: {line_count} 条")
#上次检测数据的索引
if int(common.read_ini(file_ini)) >= line_count:
index = int(0)
else:
index = int(common.read_ini(file_ini))
tag = True
while tag:
agent_type = 'socks5' # 代理类型
agent_data = common.rand_agent_data() # 随机取一条socks5代理
if agent_data :
common.log(f"当前代理IP | {agent_type}://{agent_data}")
#根据索引取出数据
phone = lines[index].strip()
if len(phone) > 0:
common.log(phone + " | 检测中...")
rand_ua = common.rand_ua() # 随机ua
phone_number = common.get_return_phone("+", phone) # 去除电话号码中 + 号
cookie, img_bytes, token_data, id_data = get_captcha_data(rand_ua, agent_data) # 取token和验证码数据
if cookie and img_bytes and token_data and id_data:
# 识别验证码图像
Verification_result = common.get_verify_code(img_bytes)
common.log(f"{phone} | 验证码识别结果:" + Verification_result)
try:
# 携带组织好的参数,token, 验证码等提交请求
result = request_api(token_data, Verification_result, phone_number)
# 请求频繁或网络异常
if result.count("Your request could not be completed because of an error. Try again later.") > 0:
common.log(f"{phone} | 当前网络错误或IP被限制,重新检测中...")
continue
# 验证码识别错误
if result.count("Please enter the characters you see or hear to continue.") > 0:
common.log(f"{phone} | 验证码识别错误,重新检测中...")
continue
# 无效账户
if result.count("This Apple Account is not valid or not supported.") > 0:
# 记录当前检测的数据是第几条的索引
index += 1
common.write_ini(file_ini, index)
#保存检测结果数据
common.wirte_append_txt(result_path, result_filename + '_未开通.txt', phone + "---" + "Fail\n")
common.log(f"{phone} | 未开通")
continue
# 账户冻结
if result.count("It looks like the phone number you provided is not registered with iMessage. Please verify the number and try again.") > 0:
# 记录当前检测的数据是第几条的索引
index += 1
common.write_ini(file_ini, index)
#保存检测结果数据
common.wirte_append_txt(result_path, result_filename + '_未开通.txt', phone + "---" + "Locked\n")
common.log(f"{phone} | 已被锁")
continue
# 开通iMessage服务的
if result.count('The SMS text message was sent successfully.') > 0:
# 记录当前检测的数据是第几条的索引
index += 1
common.write_ini(file_ini, index)
#保存检测结果数据
common.wirte_append_txt(result_path, result_filename + '_已开通.txt', phone + "---" + "Scuess\n")
common.log(Fore.RED + phone + ' | 已开通')
else:
# 记录当前检测的数据是第几条的索引
index += 1
common.write_ini(file_ini, index)
#保存检测结果数据
common.wirte_append_txt(result_path, result_filename + '_未开通.txt', phone + "---" + "Fail\n")
common.log(f"{phone} | 未开通!")
except Exception as e:
common.log(f'{phone} | API接口请求失败, 重新请求中...')
#print(e)
finally:
#print(f'索引 : {index}')
if index >= line_count:
common.write_ini(file_ini, 0)
common.log(f'{file_txt}文件的{line_count}条数据已全部检测完毕!')
tag = False # 之后的代码还会运行,下次循环判断条件时才生效
break
else:
common.log(f'{phone} | 验证码数据获取失败!')
else:
# 记录当前检测的数据是第几条的索引
index += 1
common.write_ini(file_ini, index)
#保存检测结果数据
common.wirte_append_txt(result_path, result_filename + '_异常数据.txt', phone + "---" + "Invalid\n")
common.log(phone + ' | 无效数据!')
else:
common.log('代理数据获取失败,已暂停检测!')
exit(0)
else:
common.log(f"待检测的数据文件 {file_txt} 数据量不足!")
else:
common.log(f"待检测的文件 {file_txt} 不存在!")
if __name__ == '__main__':
common.banner()
start_time = time.time()
result_filename = date_now()
Check("data.txt",'Config.ini', '筛选结果', result_filename)
seconds = time.time() - start_time
hours, minutes, seconds = common.convert_seconds(seconds)
common.log(f"运行总时长:{hours}小时 {minutes}分钟 {seconds}秒")
input("------ 全部数据检测完毕,请按任意键退出!------")

浙公网安备 33010602011771号