Daily AlpacaHack Writeup (2026-05-18 ~ 2026-05-24)

Daily AlpacaHack の Writeup.
(2026/5/18 - 2026/5/24)

Flag for Switch (Web, 2026/5/18)

curl http://34.170.146.252:13697/ -H "user-agent:Switch"
        

Small d (Crypto, 2026/5/19)

from Crypto.Util.number import long_to_bytes

n = 111353847434782342577552021595590550258011828841846535858152583507530588771722260002279996578408863620383269850809207716294963798987223718377857807468589048019837035104532011966123698255324737304049629882745865145426217333401985769872460052131723411921295220461420858919693342128249451360271877470431299412631
e = 24535416463309049799324247328967492260372258790953192167956315042327246069286185977587725024528971333528391611263562578561986228715126642586011994924792498076763835710601221847870887310752328685048945207115800606067006433946397499522425453643335216887549768999628574755599652803334025268917547913285044084805
c = 50703818050337116536617131553410132728558556353681003166889460230372336158097688107289097585329177184508245739367286475582331506026328888441167187947148823875004985350563368702349649387915676041889533193939056249122702228179939214260718957322242668719048863890867936693696170949742006007767253492755830780599

def continued_fraction(numerator, denominator):
    a = []
    while denominator != 0:
        a.append(numerator // denominator)
        numerator, denominator = denominator, numerator % denominator
    return a

def convergent(a):
    if len(a) == 1:
            return [a[0], 1]
    else:
        numerator = [a[0], a[0] * a[1] + 1]
        denominator = [1, a[1]]
        for ai in a[2:]:
            numerator[0], numerator[1] = numerator[1], ai * numerator[1] + numerator[0]
            denominator[0], denominator[1] = denominator[1], ai * denominator[1] + denominator[0]
        return [numerator[1], denominator[1]]

def wieners_attack(e, n, ciphertext):
    a = continued_fraction(e, n)
    for i in range(1, len(a)):
        d = convergent(a[:i])[1]
        plaintext = long_to_bytes(pow(ciphertext, d, n))
        if plaintext[:7] == b"Alpaca{":
            print(f"d: {d}\n{plaintext.decode()}")
            break
        
wieners_attack(e, n, c)
        

Kakuzuke (Web, 2026/5/20)

["a", "b", "c"] -> "a,b,c"
        
choice=..%2f..%2f&choice=%2f..%2fflag.txt
        

Python:Impossible (Misc, 2026/5/21)

env> PYTHONOPTIMIZE=1
arg> 1
        

Time Travelers' OTP (Web, 2026/5/22)

  const buf = Buffer.alloc(8);
  buf.writeUInt32BE((counter & 0xffff_ffff_0000_0000) >>> 32, 0);
  buf.writeUInt32BE(counter & 0x0000_0000_ffff_ffff, 4);
        

Even Worse RSA (Crypto, 2026/5/23)

$$c^{d_s} \equiv m^{e \cdot d_s} \equiv m^{s} \mod p$$

p = 8751921425256563367579143227840921849402469143061750238936013324282215699146538047799233649294185141005855739102550788165605861428703197268970229186963997
e = 65538
c = 5947948986109551330433379864390441851954259789762156065124570979131577895849125770689468451948141963015046816934387597958310386264293643862965407787651953

s = gcd(p-1, e)
ds = inverse_mod(e//s, (p-1)//s)
ms = pow(c, ds, p)

F = GF(p)
R.<x> = PolynomialRing(F)

roots = (x^6 - F(ms)).roots()

print(roots)
        
from Crypto.Util.number import long_to_bytes

out = [(8751921425256563367579143227840921849402469143061750238936013324282215699146508455868971569227438191699182987583855507423051406495692586500325392336604064, 1), (7126573897339959323788465857603278061713294396243758437540473331141761726344851828441509900989818118248377183806579046290267698460427051570076614172330847, 1), (7126573897339959323788465857603278061713294396243758437540473331141761726344822236511247820923071168941704432287883765547713243527416440801431777321970914, 1), (1625347527916604043790677370237643787689174746817991801395539993140453972801715811287985828371113972064151306814667022617892617901286756467538451864993083, 1), (1625347527916604043790677370237643787689174746817991801395539993140453972801686219357723748304367022757478555295971741875338162968276145698893615014633150, 1), (29591930262080066746949306672751518695280742554454933010610768644836850359933, 1)]

for tp in out:
    print(long_to_bytes(tp[0]))
        

Counquer Ultimate Device Abyss (Rev, 2026/5/24)

import numpy as np

flag = [
    [0x00000ee698dea1b1, 0x00000e9dd071a07b, 0x00000c1924ac2e63, 0x00000db7c6567969],
    [0x00000cf7dca22a8d, 0x00000d361500d93b, 0x00000a4b9a1df377, 0x00000c43dffefdad],
    [0x000010b0871e1f25, 0x0000108db4c64da3, 0x00000c9baca0e87f, 0x0000100afc00a4b1],
    [0x00000f83590cad41, 0x00000ead68311d37, 0x00000bf80ff254c3, 0x00000e85f5468875],
]

B = [
    [0xde, 0xad, 0xbe, 0xaf],
    [0xab, 0xad, 0x1d, 0xea],
    [0xca, 0xfe, 0xba, 0xbe],
    [0xfe, 0xed, 0xfa, 0xce]]

C = [
    [0x61706c41, 0x61486163, 0x44206b63, 0x796c6961],
    [0x61706c41, 0x61486163, 0x44206b63, 0x796c6961],
    [0x61706c41, 0x61486163, 0x44206b63, 0x796c6961],
    [0x61706c41, 0x61486163, 0x44206b63, 0x796c6961]]

flag = np.array(flag)
B = np.array(B)
C = np.array(C)

rec_A = ((flag - 29*C) @ np.linalg.inv(B)) / 12

print(rec_A)

rounded_A = np.rint(rec_A).astype(np.int32)
recovered = b"".join(int(x).to_bytes(4, "little", signed=True) for x in rounded_A.flatten())

print(recovered)