如何实现批量自动化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("------ 全部数据检测完毕,请按任意键退出!------")
posted @ 2026-03-12 23:41  知秋's  阅读(3)  评论(0)    收藏  举报