BuckeyeCTF 2022 Writeup

この大会は2022/11/05 9:00(JST)~2022/11/07 10:00(JST)に開催されました。
今回もチームで参戦。結果は3973点で688チーム中17位でした。
自分で解けた問題をWriteupとして書いておきます。

sanity (misc 1)

Discordに入り、#infoチャネルのトピックを見ると、フラグが書いてあった。

buckeye{0n_ur_m4rk5_937_537_h4ck}

buckeyenotes (web 50)

brutusB3stNut9999ユーザとしてログインする必要がある。以下でログインしてみると、フラグが表示された。

Username: brutusB3stNut9999' -- -
Password: (空)
buckeye{wr1t3_ur_0wn_0p3n_2_pwn}

Sinep (rev 50)

Ghidraでデコンパイルする。

undefined8 main(int param_1,long param_2)

{
  undefined8 uVar1;
  size_t sVar2;
  ulong uVar3;
  undefined4 local_2e;
  undefined2 local_2a;
  char *local_28;
  int local_1c;
  
  if (param_1 == 2) {
    printf("Your plain text: %s\n");
    puts("Applying Sinep Industry\'s Certified unbreakable algorithm.");
    local_2e = 0x656e6973;
    local_2a = 0x70;
    local_28 = *(char **)(param_2 + 8);
    printf("Final: 0x");
    local_1c = 0;
    while( true ) {
      uVar3 = (ulong)local_1c;
      sVar2 = strlen(local_28);
      if (sVar2 <= uVar3) break;
      local_28[local_1c] = *(byte *)((long)&local_2e + (long)(local_1c % 5)) ^ local_28[local_1c];
      printf("%02x");
      local_1c = local_1c + 1;
    }
    putchar(10);
    uVar1 = 0;
  }
  else {
    puts("Please enter the text to apply Sinep\'s patented algorithm.");
    uVar1 = 1;
  }
  return uVar1;
}

問題文に書かれている"111c0d0e150a0c151743053607502f1e10311544465c5f551e0e"を先頭から0x73, 0x69, 0x6e, 0x65, 0x70でXORをすればよい。

#!/usr/bin/env python3

enc = '111c0d0e150a0c151743053607502f1e10311544465c5f551e0e'
key = [0x73, 0x69, 0x6e, 0x65, 0x70]

enc = bytes.fromhex(enc)

flag = ''
for i in range(len(enc)):
    flag += chr(enc[i] ^ key[i % len(key)])
print(flag)
buckeye{r3v_i5_my_p45510n}

megaxord (crypto 60)

1バイト鍵のXORと推測して、ブルートフォースで復号する。CyberChefでXOR Brute Forceで見ると、key = 58のときに復号できているようだ。XORで0x58をKeyにして、復号する。

Power Rangers is an American entertainment and merchandising franchise built around a live-action superhero television series, based on the Japanese tokusatsu franchise Super Sentai. Produced first by Saban Entertainment, second by BVS Entertainment, later by Saban Brands, and today by SCG Power Rangers LLC and its parent company, Hasbro, the Power Rangers television series takes much of its footage from the Super Sentai television series, produced by Toei Company.[1] The first Power Rangers entry, Mighty Morphin Power Rangers, debuted on August 28, 1993, and helped launch the Fox Kids programming block of the 1990s, during which it catapulted into popular culture along with a line of action figures and other toys by Bandai.[2] By 2001, the media franchise had generated over $6 billion in toy sales.[3]

Despite initial criticism that its action violence targeted child audiences, the franchise has been commercially successful. As of 2022, Power Rangers consists of 29 television seasons of 21 different themed series and three theatrical films released in 1995, 1997, and 2017.

In 2010, Haim Saban, creator of the series, regained ownership of the franchise. It was previously owned for eight years by The Walt Disney Company. In 2018, Hasbro was named the new master toy licensee. Shortly afterwards, Saban Brands and Hasbro announced that the latter would acquire the franchise and the rest of the former's entertainment assets in a $522 million deal, with the first products from Hasbro becoming available in early 2019.[4][5]

Since Power Rangers derives most of its footage from the Super Sentai series, it features many hallmarks that distinguish it from other superhero series. Each series revolves around a team of youths recruited and trained by a mentor to morph into the eponymous Power Rangers, able to use special powers and pilot immense assault machines, called Zords, to overcome the periodic antagonists. In the original series Mighty Morphin, the wizard Zordon recruits "teenagers with attitude" against Rita Repulsa.[6]

When "morphed," the rangers become powerful superheroes wearing color-coded skin-tight spandex suits and helmets with opaque visors; identical except in individual rangers' color, helmet design, and minor styling such as incorporating a skirt. Morphed Rangers generally possess enhanced strength, durability, agility and combat prowess. Some possess superhuman or psychic abilities such as super-speed, element manipulation, extra-sensory perception or invisibility.[7] In addition, each individual ranger has a unique weapon, as well as common weaponry used for ground fighting.[note 1] When enemies grow to incredible size (as nearly all do), Rangers use individual Zords that combine into a larger Megazord.

Rangers teams operate in teams of three to five, with more Rangers joining the team later. Each team of Rangers, with a few exceptions, obeys a general set of conventions, outlined at the beginning of Mighty Morphin and implied by mentors throughout many of the other series: Power Rangers may not use their Ranger powers for personal gain or for escalating a fight (unless the enemy does so), nor may the Power Rangers disclose their identities to the general public.[note 2] The penalty for disobeying these rules is the loss of their power.

As in Super Sentai, the color palette of each Power Rangers team changes every series.[note 3] Only Red and Blue appear in every Ranger team, while a Yellow Ranger has been present in every series except Power Rangers Dino Charge and Power Rangers Dino Fury. Other colors and designations also appear throughout the series.[note 4] A Rangers' color designation also influences their wardrobe throughout the series: civilian clothing often matches Ranger color.[note 5]

The idea of adapting Sentai series for America emerged in the late 1970s after the agreement between Toei Company and Marvel Comics to exchange concepts to adapt them to their respective audiences. Toei, with Marvel Productions, created the Japanese Spider-Man television series, and produced three Super Sentai series, which had great success in Japan. Marvel and Stan Lee tried to sell the Sun Vulcan series to American television stations including HBO, but found no buyers and the agreement ended.[8][9]

Several years later, another idea to adapt Super Sentai began in the 80s when Haim Saban made a business trip to Japan, in which, during his stay at the hotel, the only thing that was being transmitted on his television was the Japanese series Choudenshi Bioman. At that time, Saban was fascinated by the concept of 5 people masked in spandex suits fighting monsters, so in 1985, he produced the pilot episode of Bio-Man, an American adaptation of Choudenshi Bioman, which was rejected by several of the largest American television stations.[10][11] His idea only took off in 1992, as Saban came to Fox Kids, whose president Margaret Loesch had previously helmed Marvel Productions and thus was familiar with Super Sentai.[12]

Production of Power Rangers episodes involves extensive localization of and revision of original Super Sentai source material to incorporate American culture and conform to American television standards. Rather than making an English dub or translation of the Japanese footage, Power Rangers programs consist of scenes featuring English-speaking actors spliced with scenes featuring either Japanese actors dubbed into English or the action scenes from the Super Sentai Series featuring the Rangers fighting monsters or the giant robot (Zord and Megazord) battles with English dubbing. In some series, original fight scenes are filmed to incorporate characters or items unique to the Power Rangers production.[13] Like many of Saban Entertainment previous ventures in localizing Japanese television for a Western audience, the plot, character names, and other names usually differ greatly from the source footage, though a few seasons have stayed close to the story of the original Super Sentai season. The American arm of Bandai, who co-produced the Sentai shows and manufactured its toys, worked with the adaptation of the Japanese names. A brainstorming among executives led to "Power Rangers", and for the specific show that would be made, Mighty Morphin Power Rangers, evoking the transformation sequences. The meeting also brought up the term "Zord" for the giant robots, to invoke both the sword that the Megazord carried, and the dinosaurs that were the team's theme.[12] Along with adapting the villains from the Super Sentai counterparts, most Power Rangers series also feature villains with no Sentai counterpart. Generally, the primary antagonist of a Power Rangers series (for example, Lord Zedd, Divatox, etc.) are not adapted from the Sentai. Exceptions to this includes Mighty Morphin, Zeo, Lightspeed Rescue and a few others which only use villains adapted from the Japanese shows.

The franchise began with Mighty Morphin Power Rangers (an American adaptation of the 1992 Japanese Super Sentai Series, Kyōryū Sentai Zyuranger), which began broadcasting as part of the Fox Broadcasting Company's Fox Kids programming block.[14]

In honour of Mighty Morphin Power Rangers's broadcast premiere, Hasbro announced "National Power Rangers Day" to be celebrated annually on August 28, 2018.[15][16]

Saban Entertainment produced and distributed Power Rangers from 1993 until the end of 2001, with Fox Kids broadcasting the series in the United States until the Fall of 2002. The Walt Disney Company acquired the franchise as part of a larger buyout of Fox Family Worldwide that took place in 2001.[14][17][18][19] Fox Family Worldwide subsequently became ABC Family Worldwide Inc.[19] This buyout also saw Saban Entertainment become BVS Entertainment in 2002, from News Corporation, Fox's parent company, and Haim Saban.[19]

From September 2002, Power Rangers had aired on various Disney-owned networks, including the ABC Kids program block on ABC, the ABC Family and Toon Disney cable networks, and Jetix-branded outlets worldwide.[14] Disney moved production of the franchise from Los Angeles to New Zealand after Wild Force ended, resulting in the closure of MMPR Productions.[citation needed] Several ABC affiliate broadcasting groups, including Hearst Television, declined to air the series due to the lack of FCC-compliant educational and informational content.[20]

2008's Power Rangers Jungle Fury was originally set to be the final season, but due to obligations with Bandai, Disney would produce 2009's Power Rangers RPM.[21] An article in The New Zealand Herald published on March 7, 2009, identified RPM as the last season of the Power Rangers run. Production manager Sally Campbell stated in an interview, "...at this stage we will not be shooting another season."[buckeye{m1gh7y_m0rph1n_w1k1p3d14_p4g3}][23] A September 1, 2009, revision to Disney A to Z: The Official Encyclopedia by Disney's head archivist Dave Smith states that "production of new episodes [of Power Rangers] ceased in 2009".[24] Production of Power Rangers ceased and the last series by BVS Entertainment, RPM, ended on December 26, 2009.[22]

On October 1, 2009, Bandai released a press release stating that Disney would re-broadcast Mighty Morphin Power Rangers in January 2010 on ABC Kids in lieu of producing a new season. A new toy line accompanied the broadcast and appeared in stores in the later part of 2009.[14][25][26]

On May 12, 2010, Haim Saban bought back the Power Rangers franchise from Disney for $43 million and announced plans to produce a new season of the television series.[27][28][29] Beginning with the eighteenth season, Samurai (using footage from the 2009 Super Sentai series, Samurai Sentai Shinkenger) the series would be produced under Saban Capital Group's new Saban Brands subsidiary and premiere on Nickelodeon on February 7, 2011.[28][30] Reruns of previous seasons and episodes would also begin airing on sister channel Nicktoons later that year.[30][31][32] In addition to Samurai, Saban announced plans to make a new Power Rangers movie.[33]

On July 2, 2012, Saban Brands announced that would it launch a new Saturday morning cartoon block on The CW, called Vortexx, on August 25, 2012, with reruns of Power Rangers Lost Galaxy to air on the block.[34][35][36][37][38]

On October 1, 2013, Saban Brands announced that it had extended agreements for the franchise with Nickelodeon and Bandai America Incorporated through 2016.[39] In January 2016, Saban and Nickelodeon extended their broadcast partnership through 2018.[40] In February 2018, it was announced that Power Rangers would continue airing on Nickelodeon through 2021.[41] That same month, Saban Brands appointed Hasbro as the global master toy licensee for Power Rangers in April 2019 with a future option to purchase the franchise.[42] On May 1, 2018, Saban would agree to sell Power Rangers and other entertainment assets to Hasbro for US$522 million in cash and stock.[43][44] The Saban Brands subsidiary ended operations upon the closure of the deal on July 2, 2018.[45]

The twenty-sixth and twenty-seventh seasons, Power Rangers Beast Morphers, would produced by Hasbro's Allspark studio. Beginning with the twenty-eighth season, Power Rangers Dino Fury, the series is being produced by Entertainment One (which was acquired by Hasbro on December 30, 2019, and merged with Allspark in October 2020).

In late April 2021, actor Chance Perez announced in an interview that the second season of Power Rangers Dino Fury (the twenty-ninth season overall) would premiere on Netflix in 2022; making it the first season of the show to air exclusively online through a streaming service. Meanwhile, new episodes of the series moved to the streaming service on June 15, 2021.[46][47][48][49]

この文章の中にフラグが含まれていた。

buckeye{m1gh7y_m0rph1n_w1k1p3d14_p4g3}

owl (web 70)

Discordでowl#9960にDMを送ると、ボットとして返す。スクリプトを見ると、"owl"と入力すると、以下の反応があることがわかる。

✨🦉 hoot hoot 🦉✨

試してみると、想定通り反応があった。
以下の正規表現を満たすURLを指定すると、クッキーにフラグをセットして、該当するURLにリクエストが飛ぶ。

/https?:\/\/(www\.)?([-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b)([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/i

RequestBinで待ち受け、以下のURLをDMでメッセージとして投げる。

https://eoa58n346ohhiaa.m.pipedream.net/owl

すると、RequestBinで受信したリクエストの情報が確認できる。

クッキーにはフラグが設定されていた。

buckeye{7h3_m0r3_17_5335_7h3_1355_17_h0075}

textual (web 75)

以下のように入力して、flag.texを読み込むと、フラグが表示された。

\documentclass{article}
\begin{document}
\input{flag}
\end{document}

buckeye{w41t_3v3n_l4t3x_15_un54f3}

Twin prime RSA (crypto)

RSA暗号で、pとqの値が近いことから、Fermat法で素因数分解する。あとは通常通り復号する。

#!/usr/bin/env python3
from Crypto.Util.number import *

def isqrt(n):
    x = n
    y = (x + n // x) // 2
    while y < x:
        x = y
        y = (x + n // x) // 2
    return x

def fermat(n):
    x = isqrt(n) + 1
    y = isqrt(x * x - n)
    while True:
        w = x * x - n - y * y
        if w == 0:
            break
        elif w > 0:
            y += 1
        else:
            x += 1
    return x - y, x + y

e = 0x10001
n = 20533399299284046407152274475522745923283591903629216665466681244661861027880216166964852978814704027358924774069979198482663918558879261797088553574047636844159464121768608175714873124295229878522675023466237857225661926774702979798551750309684476976554834230347142759081215035149669103794924363457550850440361924025082209825719098354441551136155027595133340008342692528728873735431246211817473149248612211855694673577982306745037500773163685214470693140137016315200758901157509673924502424670615994172505880392905070519517106559166983348001234935249845356370668287645995124995860261320985775368962065090997084944099
c = 786123694350217613420313407294137121273953981175658824882888687283151735932871244753555819887540529041840742886520261787648142436608167319514110333719357956484673762064620994173170215240263058130922197851796707601800496856305685009993213962693756446220993902080712028435244942470308340720456376316275003977039668016451819131782632341820581015325003092492069871323355309000284063294110529153447327709512977864276348652515295180247259350909773087471373364843420431252702944732151752621175150127680750965262717903714333291284769504539327086686569274889570781333862369765692348049615663405291481875379224057249719713021

p, q = fermat(n)
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)
flag = long_to_bytes(m).decode()
print(flag)
buckeye{B3_TH3R3_OR_B3_SQU4R3__abcdefghijklmonpqrstuvwxyz__0123456789}

scanbook (web)

適当な文字列を入力し、POSTすると、QRコードがチケットとして払い出される。デコードすると、32913163となった。また同じことをしたら、次のチケットのQRコードのデコード結果は32913168となった。
https://www.cman.jp/QRcode/qr_make/で 0 のQRコードを作成して、そのファイルをScanすると、フラグが表示された。

buckeye{4n_1d_numb3r_15_N07_4_p455w0rd}

fastfor (crypto)

check_hash関数でTrueを返す画像ファイルを送信すればよいらしい。
条件は以下の通り。

・IMG.pngと画像の縦、横のサイズが同じで、RGBAのデータを持つ。
・IMG.pngと同じ画像はNG
・im_alt: IMG.pngのピクセルデータのフーリエ変換
・in_alt: アップロードした画像のピクセルデータのフーリエ変換
・im_hash: im_altの標準偏差
・in_hash: in_altの標準偏差
・im_hash - in_hash < 1 かつ im_hash - in_hash > -1の場合にTrueを返す。

フーリエ変換標準偏差を使っていることから、一番頻度の高い色をわずかに変更して試す。

#!/usr/bin/env python3
from PIL import Image

img = Image.open('IMG.png').convert('RGBA')
w, h = img.size

output_img = Image.new('RGBA', (w, h), (255, 255, 255, 255))

dic = {}
for y in range(h):
    for x in range(w):
        rgba = img.getpixel((x, y))
        if rgba == (0, 0, 0, 0):
            rgba = (0, 0, 0, 1)
        output_img.putpixel((x, y), rgba)

output_img.save('try.png')

一番頻度の高い色は(0, 0, 0, 0)。これを(0, 0, 0, 1)にした画像をアップロードすると、フラグが表示された。

buckeye{D33p_w0Rk_N07_WhY_574ND4RD_d3V}

powerball (crypto)

サーバの処理概要は以下の通り。

・modulus: 128ビット素数
・multiplier = 2 ** 127 - 1
・seed = 2
・1024回以下繰り返し
 ・seed = (multiplier * seed) % modulus
・winningBalls = seedToBalls(seed)
 ・balls: seedを下から2桁ずつ入れた10個の配列
 ・ballsを返却
・seed = (multiplier * seed) % modulus
・winningBalls = seedToBalls(seed)

表示されている10個のボールはseedの下20桁の数字を下から2桁ずつ取り出したもの。予測する次の10個のボールは以下の計算をした後のseedの下20桁の数字を下から2桁ずつ取り出したもの。

seed = (multiplier * seed) % modulus

ブラウザのデベロッパーツールのコンソールを見ていると、全桁がわかるので、観察する。

{
    "last_winning_seed": "207085795274272794089636325975379145992",
    "flag": ""
}

{
    "last_winning_seed": "208113439439593207431218578529057570561",
    "flag": ""
}

{
    "last_winning_seed": "96236074504036443611070370555480962227",
    "flag": ""
}

{
    "last_winning_seed": "85288486979435612758169205395827308554",
    "flag": ""
}

{
    "last_winning_seed": "176413516664624173385053577793275165492",
    "flag": ""
}

{
    "last_winning_seed": "180588078520042388764140592665258796321",
    "flag": ""
}
{
    "last_winning_seed": "35459288262239978408513110903896220484",
    "flag": ""
}

{
    "last_winning_seed": "242069480937173469010146653925729324553",
    "flag": ""
}

LCGになっているので、その性質からmodulusを求める。あとはコンソールの最後の"last_winning_seed"の値から次の値を求める。

#!/usr/bin/ev python3
from Crypto.Util.number import *
from functools import reduce

multiplier = (2 ** 127) - 1

X = [
    207085795274272794089636325975379145992,
    208113439439593207431218578529057570561,
    96236074504036443611070370555480962227,
    85288486979435612758169205395827308554,
    176413516664624173385053577793275165492,
    180588078520042388764140592665258796321,
    35459288262239978408513110903896220484
]

p_mul = [X[i] * X[i+2] - X[i+1] * X[i+1] for i in range(len(X) - 2)]
p = reduce(GCD, p_mul)
print('[+] p =', p)
assert isPrime(p)

seed = 242069480937173469010146653925729324553
next_seed = seed * multiplier % p
print('[+] Next Seed =', next_seed)

print('[*] Next Balls:', end = ' ')
for i in range(10):
    ball = next_seed % 100
    print(ball, end=' ')
    next_seed //= 100

今回のセッションでのパラメータを使った実行結果は以下の通り。

[+] p = 271725303640457487194263865268491373983
[+] Next Seed = 212283984281179022309642184395089368487
[*] Next Balls: 87 84 36 89 50 39 84 21 64 9

次の値の下20桁をボールの値にして入力したら、フラグがメッセージ画面としてポップアップされた。

buckeye{y3ah_m4yb3_u51nG_A_l1N34r_c0nGru3Nt1al_G3n3r4t0r_f0r_P0w3rB4lL_wA5nt_tH3_b3st_1d3A}

SSSHIT (crypto)

サーバの処理概要は以下の通り。

・N_SHARES = 3
・MESSAGE: b"qxxxb, BuckeyeCTF admins, and NOT YOU"を数値化したもの
・p: 512ビット素数
・polynomial = [MESSAGE] + [2個の1以上p未満のランダム整数]
・points = [(1, polynomial[0] * pow(1, 0, p) + polynomial[1] * pow(1, 1, p) + polynomial[2] * pow(1, 2, p)),
            (2, polynomial[0] * pow(2, 0, p) + polynomial[1] * pow(2, 1, p) + polynomial[2] * pow(2, 2, p)),
            (3, polynomial[0] * pow(3, 0, p) + polynomial[1] * pow(3, 1, p) + polynomial[2] * pow(3, 2, p))]
・points[0]~points[2]を表示
・your_input: タプル入力(数値要素2個、1個目は1)
・points[0] = your_input
・xs: pointsの各要素の1個目のリスト
・ys: pointsの各要素の2個目のリスト
・y_intercept = 0
・product = 1
・product = (product * xs[1] * pow(xs[1] - xs[0], -1, p)) % p
・product = (product * xs[2] * pow(xs[2] - xs[0], -1, p)) % p
・y_intercept = (y_intercept + ys[0] * product) % p
・product = 1
・product = (product * xs[0] * pow(xs[0] - xs[1], -1, p)) % p
・product = (product * xs[2] * pow(xs[2] - xs[1], -1, p)) % p
・y_intercept = (y_intercept + ys[1] * product) % p
・product = 1
・product = (product * xs[0] * pow(xs[0] - xs[2], -1, p)) % p
・product = (product * xs[1] * pow(xs[1] - xs[2], -1, p)) % p
・y_intercept = (y_intercept + ys[2] * product) % p
・reconstructed_message: y_interceptのバイト文字列化したもの
・reconstructed_message が b"qxxxb, BuckeyeCTF admins, and ME"と一致している場合、フラグを表示

まず、pを算出したい。

(MESSAGE + polynomial[1] * 1 + polynomial[2] * 1) % p = c0
(MESSAGE + polynomial[1] * 2 + polynomial[2] * 4) % p = c1
(MESSAGE + polynomial[1] * 3 + polynomial[2] * 9) % p = c2

上記のように定義し、式を変形していく。

(c0 * 2 - c1) % p = (MESSAGE - polynomial[2] * 2) % p
(c0 * 3 - c2) % p = (MESSAGE * 2 - polynomial[2] * 6) % p
        ↓
((c0 * 2 - c1) * 3) % p = (MESSAGE * 3 - polynomial[2] * 6) % p
(c0 * 3 - c2) % p = (MESSAGE * 2 - polynomial[2] * 6) % p
        ↓
polynomial[2] * 6 = (MESSAGE * 3 - (c0 * 2 - c1) * 3) % p
polynomial[2] * 6 = (MESSAGE * 2 - (c0 * 3 - c2)) % p

(MESSAGE * 3 - (c0 * 2 - c1) * 3)と(MESSAGE * 2 - (c0 * 3 - c2))はpで割った値が同じため、差を因数分解し、大きい素数がpとなる。ただし、差が0の場合、素数を割り出せない場合は、もう一度接続しなおす。
次に行列にして計算する。

[pow(1, 0, p), pow(1, 1, p), pow(1, 2, p)]   [polynomial[0]]   [points[0][1]]
[pow(2, 0, p), pow(2, 1, p), pow(2, 2, p)] * [polynomial[1]] = [points[1][1]]
[pow(3, 0, p), pow(3, 1, p), pow(3, 2, p)]   [polynomial[2]]   [points[2][1]]

これを以下のように表す。

A * X = C

すると、以下のようにしてXを求めることができる。

X = A.inverse() * C

新しいpolynomial[0]は b"qxxxb, BuckeyeCTF admins, and ME" を数値化したものにしたい。新しいpolynomial[0]をa、polynomial[1]をb、polynomial[2]をcとする。

[pow(2, 1, p), pow(2, 2, p)]   [b]   [points[1] - a]
                             *     =
[pow(3, 1, p), pow(3, 2, p)]   [c]   [points[2] - a]

これを以下のように表す。

B * Y = D

すると、以下のようにしてY(b, c)を求めることができる。

Y = B.inverse() * D

あとは、以下を計算すれば、新しいpoints[0]がわかる。

points[0][1] = (a + b + c) % p
#!/usr/bin/env sage
import socket
from Crypto.Util.number import *

def recvuntil(s, tail):
    data = b''
    while True:
        if tail in data:
            return data.decode()
        data += s.recv(1)

MESSAGE = bytes_to_long(b'qxxxb, BuckeyeCTF admins, and NOT YOU')

while True:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('pwn.chall.pwnoh.io', 13382))

    points = []
    for _ in range(2):
        data = recvuntil(s, b'\n').rstrip()
        print(data)
    data = recvuntil(s, b'\n').rstrip()
    print(data)
    points.append(eval(data))
    data = recvuntil(s, b'\n').rstrip()
    print(data)
    data = recvuntil(s, b'\n').rstrip()
    print(data)
    points.append(eval(data))
    data = recvuntil(s, b'\n').rstrip()
    print(data)
    points.append(eval(data))

    c0 = points[0][1]
    c1 = points[1][1]
    c2 = points[2][1]

    p = (MESSAGE * 3 - (c0 * 2 - c1) * 3) - (MESSAGE * 2 - (c0 * 3 - c2))
    if p == 0:
        s.close()
        continue
    if p < 0:
        p = - p
    for i in range(4096, 1, -1):
        if p % i == 0:
            p //= i
    if isPrime(p):
        break

print('[+] p =', p)

A = matrix(Zmod(p), [[1, 1, 1], [1, 2, 4], [1, 3, 9]])
C = matrix(Zmod(p), [[c0], [c1], [c2]])
X = A.inverse() * C
assert int(X[0][0]) == MESSAGE

a = bytes_to_long(b'qxxxb, BuckeyeCTF admins, and ME')
B = matrix(Zmod(p), [[2, 4], [3, 9]])
D = matrix(Zmod(p), [[c1 - a], [c2 - a]])
Y = B.inverse() * D

p0_y = (a + Y[0][0] + Y[1][0]) % p
ans = '(1, %d)' % p0_y

data = recvuntil(s, b'>>> ')
print(data + ans)
s.sendall(ans.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)

実行結果は以下の通り。

I wrote down a list of people who are allowed to get the flag and split it into 3 using Shamir's Secret Sharing.
Your share is:
(1, 4012202499957398875137701086458100053606200152431965398724943498339900418491446564656882066806099985431339067004256795952346539431842642763866658480911116)
The other shares are:
(2, 5364916493409941827157269048386092315175499421066542035866312970081666454815146922668610494098746322749065934045393751420301434490107919219831983782949082)
(3, 4058141980357628856058703885783976784707897805903729911424108415281729669147017847776490094783533686676333253085533002026211955693321932623024640285690047)
I wrote down a list of people who are allowed to get the flag and split it into 3 using Shamir's Secret Sharing.
Your share is:
(1, 1855078843404391703437952631904133007090815230125853286048535746468919802615329567149742572858032214352220078315070683324094379031716605435288936893704651)
The other shares are:
(2, 2491779136711761019436247636678577337149116632475574320534013537047050628072858621436070972657159889368445581820235533160470489310859279762087111960617369)
(3, 1910100879922107947994885014323332990174904207049163103456433371790824036548503936600290012302977699771829162477616685131475601355954126235523189580314303)
I wrote down a list of people who are allowed to get the flag and split it into 3 using Shamir's Secret Sharing.
Your share is:
(1, 3559038284431499867308640884648248006456142222863820215296215684538330294710810511294770250286921740003009209918695447037247620319916502934719220925239680)
The other shares are:
(2, 2598345619761451058443310428499144847918431565670573129396091822055763301219835942104951314144833508546426779792111812447259456504244479597943063303977910)
(3, 4697417317158193457759725947945657393058674251220470438367015369841194895551967964901608517190808066763864203353074521428957274047172608889542636139124116)
[+] p = 7579495311168339884355717316392966868671806222800211696067386957232464315848974898729760512711478086410458841770703289576574494975662575644742444623333277

Now submit your share for reconstruction:
>>> (1, 6085536721487613162093879990112570296013410963797224113985344670263674546601846994359253075715517644070734210725807675119280653615491977692083640276936879)
Here's your flag:
buckeye{tH1s_SSS_sch3Me_c0uLd_u5e_s0M3_S1gna7Ur3s}
buckeye{tH1s_SSS_sch3Me_c0uLd_u5e_s0M3_S1gna7Ur3s}

bonce (crypto)

暗号化の処理概要は以下の通り。

・line: sample.txtの内容
・flag: flag.txtの内容
・samples: lineの最後の29バイトを除く、28バイトごとのブロック配列
・samplesのどこかの要素の間にflagを挿入
・i = 0
・samplesの長さが40未満の場合は以下繰り返し実行
 ・samplesにsamples[len(samples) - i - 2]を追加
 ・i: ランダムなsamplesのインデックス
・encrypted = []
・40回、以下繰り返し(i)
 ・x = samples[i]
 ・iが10未満の場合
  ・nonce = str(i) * 28
 ・iが10以上の場合
  ・nonce = str(i) * 14
 ・encryptedに「xの各バイトのASCIIコード ^ nonceの各バイトのASCIIコード」の数値文字列 + ' 'を結合したもの追加
・output.txtに以下を書き込み
 ・iが0~3について、以下の形式で書き込み
  input: <samples[i]>
  output: <encryted[i]>
 ・iが4~について、以下の形式で書き込み
  input: ???
  output: <encrypted[i]>

nonceとXORすれば復号できる。

#!/usr/bin/env python3
with open('output.txt', 'r') as f:
    lines = f.read().splitlines()

encs = [lines[i][8:] for i in range(11, len(lines), 2)]

for i in range(4, 40):
    codes = [int(code) for code in encs[i - 4].split(' ')[:-1]]
    if i < 10:
        nonce = str(i) * 28
    else:
        nonce = str(i) * 14
    sample = ''.join(chr(a ^ ord(b)) for a, b in zip(codes, nonce))
    print(sample)

復号結果は以下の通りで、この中にフラグが含まれていた。

r if now thou not renewest,T
hou dost beguile the world, 
unbless some mother.For wher
e is she so fair whose unear
’d wombDisdains the tillag
e of thy husbandry?Or who is
 he so fond will be the tomb
Of his self-love, to stop po
sterity?Thou art thy motherâ
€™s glass, and she in theeCa
lls back the lovely April of
 her prime:So thou through w
indows of thine age shall se
eDespite of wrinkles this th
y golden time.But if thou li
buckeye{some_say_somefish:)}
ve, remember’d not to be,D
ie single, and thine image d
ve, remember’d not to be,D
r if now thou not renewest,T
Look in thy glass, and tell 
sterity?Thou art thy motherâ
unbless some mother.For wher
e is she so fair whose unear
rm another;Whose fresh repai
ve, remember’d not to be,D
r if now thou not renewest,T
rm another;Whose fresh repai
e of thy husbandry?Or who is
e is she so fair whose unear
e of thy husbandry?Or who is
lls back the lovely April of
e of thy husbandry?Or who is
ve, remember’d not to be,D
€™s glass, and she in theeCa
rm another;Whose fresh repai
buckeye{some_say_somefish:)}

survey (misc 1)

アンケートに答えたら、フラグが表示された。

buckeye{7h4nk5_f0r_p14y1n9_2022}