WeChall - Inka

Challenge

题面是一首诗歌,以及一个"weird formula"链接 inka.php

访问 inka.php 会得到随机的三个二进制数组成的表达式

1
A * B + C

其中 A ≈ 593 位、B/C ≈ 33 位,每次请求都重新生成。提示"some 3rd party lib"。

提交答案有严格限制:每个问题只能提交 1 次(错误/正确都会消耗该问题),提交错误会泄露正确答案(Correct would have been: XXX),但无法再提交;需重新 GET 才有新问题。答案固定 15 个大写字母。

另有响应时限:GET 到提交的间隔超限会返回 You are slow, slow, slow! You took Xs but your limit is Y.。limit 每次随机(实测出现过 0.50s 与 >5.3s),保险做法是单进程内 GET→解码→POST (本地解码仅需 0ms,zxingcpp scale=1 即可)。

Solution

关键洞察N = A * B + C 恰好是 625 位 = 25×25 = QR 码 Version 2。painting 就是一幅"墙上的画"(QR 码)!"3rd party lib" = QR 库(phpqrcode 之流)

解法流程:

  1. GET inka.php(需过 Anubis,用 techaro.lol-anubis-auth cookie jar)拿 painting
  2. 提取 A、B、C 三个二进制数
  3. N = A*B + C,转 625 位二进制,排成 25×25 矩阵
  4. 反色(painting 中 1=白 0=黑,zxing 需 inverted 才能解)
  5. QR 解码 → 15 字符答案
  6. 立即提交 inka.php?answer=<ANSWER>

Solve Script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/env python3
"""WeChall Inka fast submit: GET painting -> decode QR -> POST answer within limit."""
import re, subprocess, sys, time
import numpy as np
from zxingcpp import read_barcode

URL = 'https://www.wechall.net/challenge/inka/inka.php'
JAR = '/tmp/anubis_inka_jar.txt' # anubis cookie jar
WC = 'WC=<your-session-cookie>'
UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'

def curl(url):
return subprocess.run(['curl', '-s', '--max-time', '30', '-b', JAR, '-b', WC,
'-A', UA, '-H', f'Referer: {URL.rsplit("/", 1)[0]}/index.php', url],
capture_output=True, text=True).stdout

def decode_qr(A, B, C):
N = int(A, 2) * int(B, 2) + int(C, 2)
s = bin(N)[2:].rjust(625, '0')
mat = np.array([[1 if c == '1' else 0 for c in s[i * 25:(i + 1) * 25]] for i in range(25)], dtype=np.uint8)
img = np.pad(255 - mat * 255, 4, constant_values=255) # 1=white, quiet zone
res = read_barcode(img)
return res.text if res else None

for attempt in range(10):
body = curl(URL)
if 'Making sure' in body or not body:
time.sleep(2); continue # anubis 挡,重试
A, B, C = re.findall(r'[01]+', body.strip())
ans = decode_qr(A, B, C)
resp = curl(f'{URL}?answer={ans}') if ans else 'DECODE FAIL'
print(f'[{attempt}] answer={ans} | resp: {resp[:120].strip()}')
if 'slow' not in resp and 'DECODE FAIL' not in resp:
break