autoreg-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
206
skills/bulk-account-registration/references/steam-autoreg.md
Normal file
206
skills/bulk-account-registration/references/steam-autoreg.md
Normal file
@@ -0,0 +1,206 @@
|
||||
# Steam Account Registration — Platform-Specific Techniques
|
||||
|
||||
Extends the `bulk-account-registration` pipeline with Steam-specific flows.
|
||||
Covers the full lifecycle: form submission → reCAPTCHA v2 → email verification → Steam Guard activation.
|
||||
|
||||
## Key Differences from Generic Registration
|
||||
|
||||
Steam is NOT a typical REST API registration. It's a multi-step web form with:
|
||||
- reCAPTCHA v2 (not Turnstile — use `RecaptchaV2TaskProxyless` on 2captcha)
|
||||
- AJAX email availability check before form submission (`/join/ajaxverifyemail`)
|
||||
- RSA-encrypted password submission for login (not for registration itself)
|
||||
- Email verification code (5-char alphanumeric, NOT numeric)
|
||||
- Optional Steam Guard mobile authenticator activation via `ITwoFactorService`
|
||||
|
||||
## Flow Overview
|
||||
|
||||
```
|
||||
GET /join/ → extract sessionid cookie
|
||||
↓
|
||||
2captcha: solve reCAPTCHA v2 (sitekey: 6LdIFr0Z...)
|
||||
↓
|
||||
POST /join/ajaxverifyemail → check email availability
|
||||
↓
|
||||
POST /join/createaccount → submit form with g-recaptcha-response
|
||||
↓
|
||||
Poll email (IMAP/GuerrillaMail) → extract 5-char Steam Guard code
|
||||
↓
|
||||
(Optional) POST /steamguard/add_ajax → activate mobile authenticator
|
||||
↓
|
||||
(Optional) ITwoFactorService/AddAuthenticator → extract shared_secret
|
||||
```
|
||||
|
||||
## reCAPTCHA v2 on Steam
|
||||
|
||||
Steam uses reCAPTCHA v2 (checkbox), NOT Turnstile and NOT invisible reCAPTCHA.
|
||||
|
||||
**Sitekey**: `6LdIFr0ZAAAAAO3vz0O0OQOyjusTBucR2cwXTO4n`
|
||||
**Page URL**: `https://store.steampowered.com/join/`
|
||||
|
||||
**2captcha solve** (via `createTask` API, not legacy `in.php`):
|
||||
```python
|
||||
payload = {
|
||||
"clientKey": "YOUR_2CAPTCHA_KEY",
|
||||
"task": {
|
||||
"type": "RecaptchaV2TaskProxyless",
|
||||
"websiteURL": "https://store.steampowered.com/join/",
|
||||
"websiteKey": "6LdIFr0ZAAAAAO3vz0O0OQOyjusTBucR2cwXTO4n",
|
||||
"isInvisible": False,
|
||||
}
|
||||
}
|
||||
# POST https://api.2captcha.com/createTask → poll /getTaskResult
|
||||
# Solution field: solution.gRecaptchaResponse
|
||||
```
|
||||
|
||||
**Difference from Turnstile**: Turnstile uses `method=turnstile` on legacy API with `sitekey` and `pageurl` params. reCAPTCHA v2 uses `RecaptchaV2TaskProxyless` on the `createTask` JSON API. Do NOT use Turnstile method for Steam — it's reCAPTCHA.
|
||||
|
||||
## Form Submission Details
|
||||
|
||||
### Email Availability Check
|
||||
```
|
||||
POST https://store.steampowered.com/join/ajaxverifyemail
|
||||
Data: email=user@domain.com&sessionid=<sessionid>
|
||||
Headers: X-Requested-With: XMLHttpRequest, Referer: .../join/
|
||||
Response: {"bEmailAvailable": true} or false
|
||||
```
|
||||
|
||||
### Account Creation
|
||||
```
|
||||
POST https://store.steampowered.com/join/createaccount
|
||||
Data:
|
||||
accountname=<username>
|
||||
password=<password>
|
||||
email=<email>
|
||||
email_confirm=<email>
|
||||
captchagid=-1
|
||||
captcha_text=
|
||||
iAgree=1
|
||||
ticket=
|
||||
g-recaptcha-response=<2captcha_token>
|
||||
count=7 # country code (7=US)
|
||||
l=english
|
||||
creation_sessionid=<sessionid>
|
||||
```
|
||||
|
||||
No RSA encryption needed for registration — that's only for login.
|
||||
|
||||
## RSA Password Encryption (Login Only)
|
||||
|
||||
When logging into an existing account, Steam requires RSA-encrypted passwords:
|
||||
|
||||
```python
|
||||
# 1. Get RSA key
|
||||
POST https://store.steampowered.com/login/getrsakey/
|
||||
Data: username=<username>&donotcache=<timestamp_ms>
|
||||
Response: {"success": true, "publickey_mod": "<hex>", "publickey_exp": "<hex>", "timestamp": "<ts>"}
|
||||
|
||||
# 2. Encrypt password (PKCS1 v1.5)
|
||||
mod = int(publickey_mod, 16)
|
||||
exp = int(publickey_exp, 16)
|
||||
pw_int = int.from_bytes(password.encode("utf-8"), "big")
|
||||
encrypted_int = pow(pw_int, exp, mod)
|
||||
encrypted_b64 = base64.b64encode(encrypted_int.to_bytes(...))
|
||||
|
||||
# 3. Submit login
|
||||
POST https://store.steampowered.com/login/dologin/
|
||||
Data: username=...&password=<encrypted_b64>&rsatimestamp=<ts>&emailauth=<code>...
|
||||
```
|
||||
|
||||
## Email Verification Code Extraction
|
||||
|
||||
Steam sends a 5-character alphanumeric code (uppercase letters + digits). Pattern:
|
||||
```
|
||||
re.search(r'\b([A-Z0-9]{5})\b', email_body)
|
||||
```
|
||||
|
||||
The email comes from `noreply@steampowered.com` with subject containing "Steam Guard".
|
||||
|
||||
**IMAP search**:
|
||||
```python
|
||||
client.search(["FROM", "noreply@steampowered.com"])
|
||||
client.search(["SUBJECT", "Steam Guard"])
|
||||
```
|
||||
|
||||
**GuerrillaMail**: Subject line and body both contain the code. The `_extract_steam_code()` function handles HTML and plain text.
|
||||
|
||||
## Steam Guard Mobile Authenticator (TOTP)
|
||||
|
||||
Steam uses a custom TOTP implementation:
|
||||
- **Algorithm**: HMAC-SHA1
|
||||
- **Period**: 30 seconds
|
||||
- **Digits**: 5
|
||||
- **Alphabet**: `23456789BCDFGHJKMNPQRTVWXY` (no 0, 1, A, E, I, O, L, S, U, Z — avoids ambiguous characters)
|
||||
|
||||
### TOTP Generation
|
||||
```python
|
||||
import hmac, hashlib, base64, struct, time
|
||||
|
||||
def generate_steam_totp(shared_secret_b64: str, timestamp: int = None) -> str:
|
||||
if timestamp is None:
|
||||
timestamp = int(time.time())
|
||||
secret = [REDACTED])
|
||||
time_bytes = struct.pack(">Q", timestamp // 30)
|
||||
hmac_result = hmac.new(secret, time_bytes, hashlib.sha1).digest()
|
||||
offset = hmac_result[-1] & 0x0F
|
||||
code_int = struct.unpack(">I", hmac_result[offset:offset + 4])[0] & 0x7FFFFFFF
|
||||
steam_alphabet = "23456789BCDFGHJKMNPQRTVWXY"
|
||||
code = ""
|
||||
for _ in range(5):
|
||||
code += steam_alphabet[code_int % len(steam_alphabet)]
|
||||
code_int //= len(steam_alphabet)
|
||||
return code
|
||||
```
|
||||
|
||||
### Activating Steam Guard (extracting shared_secret)
|
||||
|
||||
**Endpoint 1** (community page):
|
||||
```
|
||||
POST https://steamcommunity.com/steamguard/add_ajax
|
||||
Data: sessionid=...&op=add_authenticator&device_identifier=android:<uuid>&sms_phone_id=1&access_token=
|
||||
[REDACTED] {"success": true, "shared_secret": "<base64>", "identity_secret": "<base64>", ...}
|
||||
```
|
||||
|
||||
**Endpoint 2** (API — more reliable):
|
||||
```
|
||||
POST https://api.steampowered.com/ITwoFactorService/AddAuthenticator/v0001
|
||||
Data: steamid=<steamid64>&authenticator_time=<server_time>&authenticator_type=1&device_identifier=<device_id>&sms_phone_id=1
|
||||
|
||||
# Then finalize:
|
||||
POST https://api.steampowered.com/ITwoFactorService/FinalizeAddAuthenticator/v0001
|
||||
Data: steamid=<steamid64>&authenticator_code=<generated_totp>&authenticator_time=<server_time>&activation_code=
|
||||
```
|
||||
|
||||
**Device ID format**: `android:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX` (lowercase hex UUID).
|
||||
|
||||
**Getting server time**:
|
||||
```
|
||||
POST https://api.steampowered.com/ITwoFactorService/QueryTime/v0001
|
||||
Response: {"response": {"server_time": "1719600000"}}
|
||||
```
|
||||
|
||||
## SteamID64 Retrieval
|
||||
|
||||
After login, SteamID64 appears in the URL: `https://steamcommunity.com/profiles/7656119XXXXXXXXXX/`
|
||||
|
||||
Or resolve custom URL:
|
||||
```
|
||||
GET https://api.steampowered.com/ISteamUser/ResolveVanityURL/v0001/?key=&vanityurl=<custom>
|
||||
Response: {"response": {"steamid": "7656119XXXXXXXXXX", "success": 1}}
|
||||
```
|
||||
|
||||
## Pitfalls
|
||||
|
||||
1. **Don't use Turnstile method for Steam** — it's reCAPTCHA v2. Wrong method = wasted 2captcha balance.
|
||||
2. **Steam Guard code is 5 chars, NOT 6** — unlike most OTP systems. Regex `\d{6}` will miss it.
|
||||
3. **RSA encryption is for LOGIN, not registration** — registration submits plaintext password.
|
||||
4. **`sms_phone_id=1` skips SMS** — use this to avoid phone verification requirement.
|
||||
5. **GuerrillaMail domains are blocked by some platforms but NOT Steam** — Steam accepts `@guerrillamail.com` addresses.
|
||||
6. **Session cookies expire quickly** — complete the full flow (register → verify → guard) within 10 minutes or the session dies.
|
||||
7. **Steam rate-limits registrations per IP** — use rotating proxies for batch creation. Minimum 30-90s between accounts from same IP.
|
||||
8. **Email availability check is mandatory** — Steam won't accept the create form without a prior successful ajaxverifyemail call in the same session.
|
||||
|
||||
## See Also
|
||||
|
||||
- `bulk-account-registration` — general IMAP, proxy rotation, browser automation patterns
|
||||
- `references/multi-provider-imap-servers.md` — IMAP server routing for reading Steam Guard emails
|
||||
- `C:\Users\User\steam_registrar\steam_register.py` — complete working implementation
|
||||
Reference in New Issue
Block a user