目标分析
豆包(com.lemon.lv)是字节跳动的 AI 助手 App,用户名称(昵称)可以绑定一个唯一 ID。「抢 ID」的意义在于:豆包早期有大量简短、有意义的 ID 未被注册,可以批量检测并注册。
协议抓包
使用 mitmproxy + 证书固定绕过,抓到关键接口:
设备注册
POST https://passport.bytedance.com/api/v3/passport/user/login/new_device
aid=497858 (豆包的 AppID)
用户名检测
GET https://alice.doubao.com/alice/profile/check_username
?username=target_id&aid=497858
设置用户名
POST https://alice.doubao.com/alice/profile/update_profile
{
"username": "target_id",
"session_id": "<session>"
}
device_id 生成
字节系 device_id 是一个 18-19 位数字,通过设备注册接口获取:
import uuid, requests, time
DOUBAO_AID = 497858
DEVICE_REGISTER_URL = "https://passport.bytedance.com/api/v3/passport/user/login/new_device"
def gen_device_info() -> dict:
return {
"openudid": uuid.uuid4().hex,
"device_type": "Pixel 7",
"os_version": "14",
"resolution": "1080*2400",
"dpi": "420",
"language": "zh",
"timezone": "Asia/Shanghai",
}
def register_device(aid: int = DOUBAO_AID) -> dict:
info = gen_device_info()
headers = {
"User-Agent": f"com.lemon.lv/1.0.0 (Linux; Android 14)",
"Content-Type": "application/x-www-form-urlencoded",
}
payload = {"aid": aid, **info}
r = requests.post(DEVICE_REGISTER_URL, data=payload, headers=headers, timeout=10)
return r.json() # {"device_id": "...", "install_id": "..."}
唯一性检测
import requests
ALICE_CHECK_URL = "https://alice.doubao.com/alice/profile/check_username"
def check_username(username: str, session_token: str) -> bool:
# 返回 True 表示该用户名可用
r = requests.get(
ALICE_CHECK_URL,
params={"username": username, "aid": DOUBAO_AID},
headers={
"Cookie": f"sessionid={session_token}",
"User-Agent": "doubao/1.0 (iPhone; iOS 17.0)",
},
timeout=5
)
data = r.json()
return data.get("data", {}).get("available", False)
批量检测脚本
from concurrent.futures import ThreadPoolExecutor
import itertools, string
def gen_candidates(length: int = 4):
# 生成所有 length 位纯字母+数字组合(演示)
chars = string.ascii_lowercase + string.digits
for combo in itertools.product(chars, repeat=length):
yield "".join(combo)
def batch_check(session_token: str, candidates, max_workers: int = 20):
available = []
with ThreadPoolExecutor(max_workers=max_workers) as pool:
futures = {
pool.submit(check_username, uid, session_token): uid
for uid in candidates
}
for f in futures:
uid = futures[f]
try:
if f.result():
available.append(uid)
print(f"[+] 可用: {uid}")
except Exception as e:
print(f"[-] 检测 {uid} 失败: {e}")
return available
if __name__ == "__main__":
TOKEN = "your_session_token_here"
# 检测 4 字母短 ID
candidates = list(gen_candidates(4))[:1000] # 只测试前1000个
available = batch_check(TOKEN, candidates)
print(f"
共找到 {len(available)} 个可用 ID")
注意事项
- 频率限制:豆包有接口调用频率限制,并发不宜过高(建议 ≤10)
- 账号封禁:批量注册违反服务条款,生产使用请评估合规性
- 验证码:注册流程可能触发图形验证码,需对接识别服务
免责声明:本文仅供安全学习研究使用,请勿用于违法目的。