memo46

競プロの精進記録その他。

ICPC2021 国内予選 参加記

結果

弊チームUHISHIRO(suta, siro53, kiyoshi0205)は51位、残念ながら予選落ちでした

f:id:bakamono1357:20211105230055p:plain

これまでのチームでの戦績を考えると今までにないぐらいの冷えだったんですが、悔しさで暴れる前にとりあえず色々冷静に書いてみようと思います。

チームメンバーといつもの戦略

  • kiyoshi0205
    • チームのエース 数学/考察系の問題を担当することが多かった
  • suta
    • 問題埋めのプロ オールラウンダーでねっとり重実装もいける
  • siro53
    • 2人には考察力や解いた問題数で大きく劣るので、解法を聞いて頑張って実装することが多かった

コンテスト前

1ヶ月前あたりから週1で大学に集まってチーム練(国内予選の過去問を解く)をやった

恐らくチーム練は弊学で一番やっていたと思う ↓チーム練の跡

https://onlinejudge.u-aizu.ac.jp/services/room.html#UHISHIRO_virtual2

https://onlinejudge.u-aizu.ac.jp/services/room.html#UHISHIRO_virtual3

https://onlinejudge.u-aizu.ac.jp/services/room.html#UHISHIRO_virtual4

https://onlinejudge.u-aizu.ac.jp/services/room.html#UHISHIRO_virtual5

前日に最後のチーム練をし、練習はしっかりやったぞ!という気持ちで本番に備えて早めに就寝した。

当日

午前から大学に向かい、昨日のチーム練の自分が担当していない問題のupsolveをしたり、坑道数式と格闘したりしていた。

ところでこのチーム練のセット(国内2010)のG問題であるレーザー光の反射、かなり好きな問題です(幾何なのであんまり同意してくれる人は少ないかも...)

ちゃんと方針を立てれば実装はかなり簡潔になります。

本番

近頃はコロナが落ち着いてきたこともあり、ワンチャンオンサイトあるんじゃないかということで絶対勝ちたいという気持ちがありました。

当然バチクソに緊張します。

コンテストのURL、ディレクトリ、ファイルの準備はOKであることをしっかり確認し、A : siro53, B : suta, C : kiyoshi でスタート。

Cは構文解析らしいので、sutaのBとswapしたらしい。

Aを読むとシミュレーションするだけなので書いてAC。

kiyoshiがBをほどなくしてAC。この時点では3位でビビる。

Cはやばそうで、僕がDの概要を2人に伝える。DPっぽいがうまい状態の持ち方がわからない。

しばらくするとkiyoshiが「C、全方位木DPじゃん」と言い出し、sutaと2人で分担して書き始める。

↑今思えばここは完全に役割分担を失敗していた。が、その時はgive usがDを通してたので一刻も早く次のACが欲しいという雰囲気になっていたため、難しい......(完全に本番の緊張感に飲まれていた)

やることがないので僕はDの愚直O(N!)を書いて色々実験してみるも何も糸口がつかめず、苦しい。正直な話、たくさん考えているように見えて実質無な時間を過ごしていたと思う(発想一発の考察ゲーに沼った時、大体無の時間を過ごしがち...)

まずいと思いつつEを読むとかなり典型っぽい見た目をしていて2人に概要を共有しようとするがCの実装が忙しそうで断念する。

やっぱりDを放置するのはまずいということでDを考えるも、やはり無の時間を過ごしてしまう。

1WAの末ようやくCが通る。Eをkiyoshiに共有し、sutaがDの考察をすることになる。

概要を伝えると「こどふぉで見たことある」といい、しばらくすると解法が生えたようなので聞いて、実装できそうなので僕がEの実装にとりかかる。

余談ですが、弊チームでは「kiyoshiの解法を聞いてsuta/siro53のどちらかが実装し、考察に強いkiyoshiのリソースを別の問題に割く」というムーブがいつものという感じで、これがハマっていつもレート以上の結果が出せていたような気がします。

Eを僕が実装している間、sutaとkiyoshiでDにとりかかる。この時点でD, Eの2問通さないとアジアは不可能だったので、Eを実装している間かなり手が震えていてとてもまともなメンタルではありませんでした...

ハチャメチャにEをバグらせた後終了20分前になんとかサンプルが合う。しかしこのサンプルはめちゃくちゃ弱いのでなんとも...今からケースを作る時間はない。

Dはもう完全にお通夜で、嘘解法を投げてWAを出す、をずっとやっていたっぽい。

EもWAで通らず、そのままコンテスト終了。

感想

Eはコンテスト終了後しばらくして1箇所致命的なtypoを見つけたので本当にすまん...という気持ちですが、仮にEが通ったとしてもDがかすりもしていない(3分割すら思いついていない)ため、どうあがいても今回のセットでは勝てなかったのかな...と思っています。

先程も言いましたが弊チームでは「kiyoshiの解法を聞いてsuta/siro53のどちらかが実装し、考察に強いkiyoshiのリソースを別の問題に割く」というムーブが日常となっていたため、僕は知識を入れたり典型を多く身につけたり、実装力を高めるためにAOJ-ICPCを埋めるなど、考察の練習をあまり積んでいませんでした。恐らくsutaも実装の練習に力を入れて、考察ゲーはkiyoshiに頼んだ!という感じだったと思います。そのため、kiyoshiが解けなかったら終わり...みたいになっていたのがよくなかったのかな、と思っています(kiyoshiに頼りすぎていた)

最近の国内予選ではねっとりとした実装問題よりも考察寄りの問題で勝負が決まることが多く、傾向をちゃんと把握できていなかったのかな...という気がしています。なんにせよ本当に練習不足だったなぁと思います。

それでも3月の横浜大会から約半年、またアジアに行くぞ!と練習を頑張ったことはいい経験になったと思います。チームのみなさんお疲れさまでした。

とはいったものの今後の情勢次第では海外regionalに行ける可能性もあるので、まだUHISHIROでチーム練をする機会はあると思います。その時はGive usやMSBの尻に火を付けられるように頑張ります!

Give us、MSBのみなさんアジアおめでとうございます!負けて悔しいですが、それでもこの2チームには真におめでたいと思えたので、良い大学に入ったなあなどと思うなどしました。

余談

ところでこれはこの時期ICPCを頑張るB4にありがちだと思うんですが、卒論がやばいらしいです... ;;

誰か助けて

ICPC2021模擬国内

伝えよう 運営への感謝の気持ち

UHISHIRO(shiro, suta, kiyoshi)で出場。

-3日目 ~ -1日目

研究室のゼミ担当だったことを忘れていて焦る。ABCとPG BATTLE以外全く競プロができなくなる

当日

ABCで大失敗したのを引きずり、睡眠が浅いまま本番へ...(悲しい)

当日の朝、マクドナルドでリハーサルを適当に済ませる 全く頭が働いていないので適当に1問解いて大学へ向かった

大学近辺のごはん処が軒並み休業していて昼飯難民になる

なんとか昼飯を済ませ、チームで雑談をしていると開始時刻に...

コンテスト

Aをやる すぐ書き上がったが問題文の解釈が微妙でまごついているとBが通る

冷静にサンプル3を見ると解釈が一致したのでそのまま出してAが通る(この時間無駄すぎた、、、)

ほどなくしてCが通る この時点で5位でびっくりした(スクショ撮り忘れた、残念)

Eを読む、わからない

Dは簡単らしくそのままsutaが実装を開始する

順位表を見るとMSBがEを通している(!?!?!?) 焦る

とりあえずLISを固定してそれ以外を動かすとサンプルは合う 適当にケースを作るも全然hackできない

kiyoshiに愚直を書いてくれと言われたので書く

Dが通る

「LISを固定してそれ以外をいい感じに左右に動かす」という解法が生える sutaが実装を始める

実装を詰めている途中で「もしかして(転倒数)+N-(LIS長)ですか」とkiyoshiが言う

なんか下界がこれで、実際に達成できるらしいのでsutaがそのまま書く E通る

Fはしばらくすると5乗のDPが生えたらしい

解法を聞いて3人で実装する kiyoshiの書いたものが通る

Gは「直径の端から開始すればいいのでは~」と雑に考えていたけどkiyoshiの作ったやばそうなケースを見て絶望する

最小費用流の負辺除去でできるらしいので人様のライブラリをパクって書く

実行に無限時間かかって全く終わる気配がない(オーダーが悪いのでそれはそう) 終わり

結果

2021/Practice/模擬国内予選/順位 - ICPC OB/OG の会

18位(selected 16位)、チームメイトすごい(僕は何もしていません)

give usがエース不在で6完しているけど...

感想

なにもしていません

本番は万全なコンディションで挑みたいです

追記:JAGのみなさん、コンテスト開催ありがとうございました!(一番これを言いたくて書き始めたのに書き忘れてしまった)

ACPC 2021 参加記

伝えよう 運営への感謝の気持ち

Day1

https://onlinejudge.u-aizu.ac.jp/services/room.html#ACPC2021Day1

suta、Chrisとチームcbio_labで参加した 余談ですが、この3人は同じ研究室で、この日は研究室から参加しました

A:僕が担当した。誤読して1ペナしたけどsubmission見たら無限人WAを出していて察した。問題文をグッと睨むと誤読していたので直してAC

B:sutaが「なるべく少ない個数で全体のORを作りたい」と言っていて、高速ゼータ変換を考えていたけどうまく定式化できなかった。 or_convolutionってこうやって使うんですね... 作れるかどうか <-> 作り方が1通り以上で、高々log(max(A_i))回の畳み込みで出来るの確かに upsolveで319でも通しました

C:やばそうだったので飛ばした

D:読んでない

E:Chrisが粘着していて、僕も概要聞いたけど解ける気がしなかったのでskip

F:一番粘着した。でも解けなかった。こういうの本当に無理... めっちゃいい問題で涙......

G:dp[頂点 i まで見た][行きの最後の頂点][帰りの最後の頂点]で3乗で解けるなあと思っていて、よく考えると行きと帰りの最後に訪れる頂点の片方は必ず i になるから2乗で出来そう、といったらsutaが細部を詰めて実装してくれた 良問

H:全く見ていなかったがコンテストが終わった後に見たら単純な桁DPで涙 桁DPは実装がやばいって言われがちだけど、この実装を真似ると簡潔に実装できます

opt-cp.com

I:見てない

感想

めちゃくちゃ冷えた。典型だけどちゃんと考えないと解けない良問が多くて、農工大はすごい

Day2

https://onlinejudge.u-aizu.ac.jp/services/room.html#ACPC2021Day2

kiyoshi0205, Hiramonとチームmo_ri_fantasyで参加した。

A:Hiramonがやってくれた。少しデバッグを手伝った

B:普通に解けなかった(大反省)今もバグっています(は?)

C:Bを一旦飛ばしてCを見たら自明だったので幾何ライブラリを貼ってすぐ書いてAC。全体2位だったらしい。doubleでやると誤差で死ぬらしいけど、運がよかったのでACできました・・・

D:問題名が答えです 最近類題を解いていたのでCの後にすぐ書いてAC

E:クエリ毎に包除したいけど間に合うわけね~→kiyoshiに投げよ・・・ ところで、distinctだと素数は高々7個までしか取れないのでクエリ毎に包除しても間に合うらしいです 悲しい

F:やばそうと思ったけど二度見したらにぶたんだった。kiyoshiがEを書いたあとに僕が書いてAC

G:kiyoshiが解いてくれた。実装に苦しんでいたようだが終盤にAC

H:kiyoshiが初手で解けたと主張していたけど1hバグっていたので一旦放置することになった。結局最後までAC出ず

I:同じ人が含まれるサークル同士に辺を貼ると最大独立集合問題に帰着。この制約で半分全列挙で解けることは昔ECRバチャでやりました

J, K:見てない

感想

今日のセットは典型詰め合わせセットって感じだった、楽しかった | 会 | 津 | 大 | 学 | はすごい

Day3

https://onlinejudge.u-aizu.ac.jp/services/room.html#ACPC2021Day3

Day1のチームにserpent君が加わって、4人で参加

A:serpent君がやってくれた

B:Chrisがやってくれた

C:僕が担当だったけど全然解けなくて焦った。Bを終えたChrisと相談して解けた気持ちになり僕が実装→AC

D:sutaがなんかエスパーして解いてた

E:こういうのはどうせ鳩ノ巣→そうでした 間に合うか怪しいDPを書いたけど配列を使い回すと爆速になったらしい

F:Chrisとsutaが一生粘着していたけど苦しそうだった

G:こういうのはどうせ知識→KUPC2012Kがヒット→頂点属性で解けるのかこれ・・・

ここでしばらく困っていたけど、よく考えたら距離3の箇所は同時に取れる(C - 3 Steps の考察を使う)ので二部グラフかどうか判定すると、二部グラフじゃないなら完全グラフになるのでXOR基底を取ると解けて、二部グラフなら完全二部グラフになるので困りました...

数列Cから偶数個・奇数個取ったときのxorのmaxが求められなくて困っていたけど、Twitterで教えてもらった方法が天才で感動した

感想

どの問題も見た目は難しいけどちゃんと解きほぐすと解ける感じですごい 良問の既出チェックって難しいんだなぁ... 北大はすごい

全体の感想

Day1~3までフル参加で楽しめました。 運営の皆様、お疲れさまでした & ありがとうございました!

SECCON Beginners CTF 2021 WriteUp

チームM15.(W|X)として参加し、全体23位 / 943、3327ptでした。

チームメンバーは

  • siro53(僕)
  • SUAN
  • Soeki
  • eren53

の4人です。

初めてチームを組みましたが、かなり健闘できたと思います。とても嬉しいです!(本当は他の分野も解きたかったですが、時間が足らず...) f:id:bakamono1357:20210523152059p:plain

個人では、Imaginary以外のCrypto 5問を解きました。ImaginaryはAES暗号なんも分からんって言ってたらeren君が解いてくれました...

以下解いた問題のWrite upです。

Simple RSA[Crypto]

n = 17686671842400393574730512034200128521336919569735972791676605056286778473230718426958508878942631584704817342304959293060507614074800553670579033399679041334863156902030934895197677543142202110781629494451453351396962137377411477899492555830982701449692561594175162623580987453151328408850116454058162370273736356068319648567105512452893736866939200297071602994288258295231751117991408160569998347640357251625243671483903597718500241970108698224998200840245865354411520826506950733058870602392209113565367230443261205476636664049066621093558272244061778795051583920491406620090704660526753969180791952189324046618283
e = 3
c = 213791751530017111508691084168363024686878057337971319880256924185393737150704342725042841488547315925971960389230453332319371876092968032513149023976287158698990251640298360876589330810813199260879441426084508864252450551111064068694725939412142626401778628362399359107132506177231354040057205570428678822068599327926328920350319336256613
from Crypto.Util.number import *
from flag import flag

flag = bytes_to_long(flag.encode("utf-8"))

p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = 3

assert 2046 < n.bit_length()
assert 375 == flag.bit_length()

print("n =", n)
print("e =", e)
print("c =", pow(flag, e, n))

problem.pyとoutput.txtが与えられます。

eが3と小さく、assert文から m3 < nであることがわかるので、二分探索すればよいです。

Flagはctf4b{0,1,10,11...It's_so_annoying.___I'm_done}

from Crypto.Util.number import *

n = 17686671842400393574730512034200128521336919569735972791676605056286778473230718426958508878942631584704817342304959293060507614074800553670579033399679041334863156902030934895197677543142202110781629494451453351396962137377411477899492555830982701449692561594175162623580987453151328408850116454058162370273736356068319648567105512452893736866939200297071602994288258295231751117991408160569998347640357251625243671483903597718500241970108698224998200840245865354411520826506950733058870602392209113565367230443261205476636664049066621093558272244061778795051583920491406620090704660526753969180791952189324046618283
e = 3
c = 213791751530017111508691084168363024686878057337971319880256924185393737150704342725042841488547315925971960389230453332319371876092968032513149023976287158698990251640298360876589330810813199260879441426084508864252450551111064068694725939412142626401778628362399359107132506177231354040057205570428678822068599327926328920350319336256613

ok = 0
ng = 10 ** 375
while ng - ok > 1:
    mid = (ok + ng) // 2
    if mid * mid * mid <= c:
        ok = mid
    else:
        ng = mid
print(long_to_bytes(ok))

Logical_SEESAW[Crypto]

from Crypto.Util.number import *
from random import random, getrandbits
from flag import flag

flag = bytes_to_long(flag.encode("utf-8")) # flagをlong型に変える
length = flag.bit_length() # flagのbit長
key = getrandbits(length) # key = flagと同じbit長のランダムな数字
while not length == key.bit_length():
    key = getrandbits(length)

# 2進数に変換し、['1', '0', '1', ...]みたいなlistを作る
flag = list(bin(flag)[2:])
key = list(bin(key)[2:])

cipher_L = []

for _ in range(16):
    cipher = flag[:]
    m = 0.5
    
    for i in range(length):
        n = random()
        if n > m:
            cipher[i] = str(eval(cipher[i] + "&" + key[i]))
            
    cipher_L.append("".join(cipher))


print("cipher =", cipher_L)

やっていることとしては、flagと同じbit長の乱数keyを生成し、flagとkeyをそれぞれ2進数に変換する

各bitごとに1/2の確率で、flagとkeyのi番目のbit同士をANDを取るということを独立にやる

その要領で生成したbit列を16個生成し、出力(output.txt)、です。

flag[i]が'0' のところは何をやっても0のままですし、flag[i]が'1'のところを全て'0'とANDを取られる確率は非常に低いので、cipherに1つでも'1'が含まれていたらその位置のbitは1、それ以外は0という風に復元すればokです。

Flagはctf4b{Sh3_54w_4_SEESAW,_5h3_54id_50}

GFM[Crypto]

FLAG = b'<censored>'

SIZE = 8
p = random_prime(2^128)
MS = MatrixSpace(GF(p), SIZE)

key = MS.random_element()
while key.rank() != SIZE:
    key = MS.random_element()

M = copy(MS.zero())
for i in range(SIZE):
    for j in range(SIZE):
        n = i * SIZE + j
        if n < len(FLAG):
            M[i, j] = FLAG[n]
        else:
            M[i, j] = GF(p).random_element()

enc = key * M * key

print('p:', p)
print('key:', key)
print('enc:', enc)

8×8行列の$key$と、flagが一部入った$M$が入っています。

$enc=key×M×key$

となっているので、$mod \space p$上で

$M={key}^{-1}×enc×{key}^{-1}$

とすればMが復元できます。逆行列は掃き出し法で求めます。

Mの中身を見ると小さい数字が入ってて明らかに怪しいのでそれらをasciiコードを順番に復元すればokです。

Flagはctf4b{d1d_y0u_pl4y_w1th_m4tr1x_4nd_g4l0is_f1eld?}

Field_trip[Crypto]

from Crypto.Util.number import *
from random import getrandbits
from flag import flag


flag = bytes_to_long(flag.encode("utf-8"))
flag = bin(flag)[2:]
length = len(flag)

A = []
a, b = 0, 0
for _ in range(length):
    a += getrandbits(32) + b
    b += a
    A.append(a)

p = getStrongPrime(512)
q = getStrongPrime(512)

assert q > sum(A)

pub_key = [a * p % q for a in A]
cipher = sum([int(flag[i]) * pub_key[i] for i in range(length)])

f = open("output.txt", "w")
f.write("pub_key = " + str(pub_key) + "\n")
f.write("cipher = " + str(cipher) + "\n")
f.close()

cipherの箇所を見ると、flagを2進数にして、bitが立ってるところのみのpub_key[i]の和を暗号としています。

これを復元するにはDPもしくは半分全列挙などをする必要がありますが(部分和問題)、どう考えてもオーダー的に不可能です。

そこで何かあるだろうとひたすらググり倒すと、

Merkle-Hellmanナップサック暗号 - Wikipedia

が見つかります。これとやってることは同じです。

攻撃法にはシャミアの攻撃法、低密度攻撃などがあるそうですが、今回はググるとSageMathでの実装が見つかった低密度攻撃で解きました。

PlaidCTF CTF 2015: Lazy - うさぎ小屋

今回の問題は密度が0.6ぐらいだったのでこれで解けます。ちなみにSageMathは↓でオンライン実行できます。

Sage Cell Server

2進数 -> 10進数の変換がなぜかバグっていた(?)ので、自分でそこだけ書き直したらフラグが出てきました。

Flagはctf4b{Y35!_I_ju5t_n33d3d_th353_num63r5!}

p-8RSA[Crypto]

from Crypto.Util.number import *
from random import getrandbits
from os import urandom
from flag import flag


def gen_primes(bits, e):
    q = getStrongPrime(bits)
    p = q
    while True:
        p = p-8 # p-8
        phi = (p - 1) * (q - 1)
        if isPrime(p) and GCD(phi, e) != 1:
            break
    return p, q

flag = flag.encode("utf-8") + urandom(64)
flag = bytes_to_long(flag)

e = 17
p, q = gen_primes(512, e)
n = p * q

print("n =", n)
print("e =", e)
print("c =", pow(flag, e, n))

p, qの値がかなり近そうなのでフェルマー法でNを素因数分解でき、p, qが求まります。

しかし、phiとeが互いに素でないので逆元が存在せず、秘密鍵dが求まりません。

ここで、eの値が小さいことに着目します。まず

$c \space mod \space p = m^{e} \space mod \space p$

$c \space mod \space q = m^{e} \space mod \space q$

より、p, qは素数であることからwolfram alphaを使って$mod p, q$上のcのe乗根の候補がそれぞれ求まります。

e乗根の候補はかなり少ないため、これらの候補を全て試して中国剰余定理で復元すれば、答えの候補が求まります。

後は適当にgrepするとflagが見つかりました。

Flagはctf4b{4r3_y0u_up5id3_d0wn?_Fr0m_6310w?_0r_60th?}

(wolfram alphaの使い方を調べるのに苦労...)

感想

Crypto全完して喜んでたらreversingとmiscほぼ全て解かれていてビビった。

WebとPwnはダメダメだったので、なんとかしたい。

おまけ

深夜に16位まで上昇し、上位勢のグラフに自チームの名前が入って興奮する我々 f:id:bakamono1357:20210523160443p:plain f:id:bakamono1357:20210523161212p:plain

気づいたらreversing全部通されててビビる僕

f:id:bakamono1357:20210523160841p:plain

WaniCTF'21-spring writeup

waniCTFと呼ばれる、大阪大学 CTF サークル Wani Hackase が開催する初心者向けの CTF大会に参加しました。

全体60位/433人でした。

wanictf.org

結果は↓な感じで、ほとんどCTFしたことない自分からしたら割と頑張れたのでは、と思います。

ほとんどの分野でEasyぐらいまでしか解けなかったのですが、唯一cryptoは全完出来たので嬉しかったです!(競プロで殴れただけ)

f:id:bakamono1357:20210502200120p:plain f:id:bakamono1357:20210502200202p:plain

以下、writeupです

Crypto

[Begginer] Simple Conversion

convert.pyでフラグを整数に変換した後のoutput.txtが与えられるので、それを逆変換してくださいという問題でした。

from const import flag


def bytes_to_integer(x: bytes) -> int:
    x = int.from_bytes(x, byteorder="big")
    return x


print(bytes_to_integer(flag))
709088550902439876921359662969011490817828244100611994507393920171782905026859712405088781429996152122943882490614543229

int.to_bytes()を使って元に戻せばよいです。引数のlengthは適当にガチャして64を入れたらフラグが出てきました。

with open('output.txt') as f:
    n = int(f.read())
print(n.to_bytes(64, byteorder="big"))

フラグは、FLAG{7h1s_i5_h0w_we_c0nvert_m3ss@ges_1nt0_num63rs}

[Easy] Easy

前問と同じ、encrypt.pyで変換後のoutput.txtが与えられるから逆変換しろという問題。

with open("flag.txt") as f:
    flag = f.read().strip()


A = REDACTED
B = REDACTED

plaintext_space = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_{}"

assert all(x in plaintext_space for x in flag)


def encrypt(plaintext: str, a: int, b: int) -> str:
    ciphertext = ""
    for x in plaintext:
        if "A" <= x <= "Z":
            x = ord(x) - ord("A")
            x = (a * x + b) % 26
            x = chr(x + ord("A"))
        ciphertext += x

    return ciphertext


if __name__ == "__main__":
    ciphertext = encrypt(flag, a=A, b=B)
    print(ciphertext)

読むと、文字'A'~'Z'を0~25に直して、その数字を$x$として$Ax+B (mod \space 26)$に変換していることが分かります。 しかし変換するのに使っている1次式の係数は隠されてしまっています。

そこで、output.txtを見ます。

HLIM{OCLSAQCZASPYFZASRILLCVMC}

最初の4文字はFLAGとなっているはずなので、ここから係数$A, B$がある程度分かるはずです。 実際は2つ分かればよくて、連立合同式を立てて計算してみると、$A=5, B=8$になることが分かります。 よってそれを元に適当に変換するコードを書けばよいです。

with open("output.txt") as f:
    S = f.read().strip()

A = 5
B = 8

def decrypt(s: str, a: int, b: int) -> str:
    res = ""
    for x in s:
        if "A" <= x <= "Z":
            x = ord(x) - ord("A")
            x = (x - b + 26) % 26
            for i in range(26):
                if a * i % 26 == x:
                    x = i
                    break
            x = chr(x + ord("A"))
        res += x

    return res

if __name__ == '__main__':
    res = decrypt(S, A, B)
    print(res)

フラグは、FLAG{WELCOMETOCRYPTOCHALLENGE}

[Hard] Can't restore the flag?

与えられたコマンドnc crt.cry.wanictf.org 50000でサーバーにアクセスすると、Modを入力するように要求されます。

siro53@MyComputer:~/CTF/waniCTF2021/crypto$ nc crt.cry.wanictf.org 50000
Mod > 

サーバーのコードは次のようになっています。(適宜コメントを入れています)

from Crypto.Util.number import bytes_to_long

with open("flag.txt", "rb") as f:
    flag = f.read()
flag = bytes_to_long(flag)

assert flag <= 10 ** 103

upper_bound = 300
while True:
    try:
        mod = int(input("Mod > ")) # modを入力する
        if mod > upper_bound: # mod は 300以下じゃないとだめ
            print("Don't cheat 🤪")
            continue

        result = flag % mod
        print(result) # flagをbytesから整数に直したものを、入力したmodであまりを計算し出力
    except Exception:
        print("Bye 👋")
        break

要するにフラグの300以下のmodを取った値なら教えてあげるから、そこからフラグの値を復元してねということです。

こんなのCRT(中国剰余定理)じゃん...ということで、手打ちでmodを埋め込んでCRTをすればフラグが分かります。完全に競プロ

コードは長いので省略します。実装はここを参考にしました

フラグはFLAG{Ch1n3s3_r3m@1nd3r_7h30r3m__so_u5eful}

[Normal] Extra

encrypt.pyとoutput.txtが与えられます。そこからフラグを復元しろという問題です。

from Crypto.Util.number import getPrime, bytes_to_long

with open("flag.txt", "rb") as f:
    flag = f.read()

p, q = getPrime(1024), getPrime(1024)
N = p * q
M = 2 * p + q
e = 0x10001

def encrypt(plaintext: bytes) -> int:
    plaintext = bytes_to_long(plaintext)
    c = pow(plaintext, e, N)

    return c


if __name__ == "__main__":
    c = encrypt(flag)

    print(f"{N = }")
    print(f"{M = }")
    print(f"{e = }")
    print(f"{c = }")
N = 22255382023772668851018179427844169178508638456713544208965498667359965716247243217931028270320680101854437928939452335472153643094266035953797432826168426002458800906764442624308120284177094975740468163835305872963635678413995878812492729432260346481442092245748885202467992527408086207041964831622724073720751839241897580988210971776031098476500998975223039782371635291859483569580516707907602619018780393060215756966917504096971372578145138070121288608502379649804953835336933545368863853793291348412017384228807171466141787383764812064465152885522264261710104646819565161405416285530129398700414912821358924882993
M = 455054308184393892678058040417894434538147052966484655368629806848690951585316383741818991249942897131402174931069148907410409095241197004639436085265522674198117934494409967755516107042868190564732371162423204135770802585390754508661199283919569348449653439331457503898545517122035939648918370853985174413495
e = 65537
c = 17228720052381175899005296327529228647857019551986416863927209013417483505116054978735086007753554984554590706212543316457002993598203960172630351581308428981923248377333772786232057445880572046104706039330059467410587857287022959518047526287362946817619717880614820138792149370198936936857422116461146587380005750298216662907558653796277806259062461884502203484610534512552197338982682870358910558302016481352035443274153409114492025483995668048818103066011831955626539382173160900595378864729936791103356604330731386911513668727994911216530875480647283550078311836214338646991447576725034118526046292574067040720093

問題文は「いつものRSA?」と書いていて、実際encrypt.pyを眺めるとそんな感じのことをしています。

しかし少し異なるのは$M=2p+q$が与えられている点です。これと$N=pq$を連立して2次方程式を解けば、解の公式から$p$の候補が2つに絞れます。

よって$p$を2通り試してwikiを参考にそこから復号すればよいです。

実装にあたり先程のPythonACL記事を参考にしています。

from Crypto.Util.number import long_to_bytes
from math_lib import *

N, M, e, c = map(int, input().split())

def isqrt(n: int) -> int:
    ok = 0
    ng = n
    while ng - ok > 1:
        mid = (ok + ng) // 2
        if mid * mid <= n:
            ok = mid
        else:
            ng = mid
    
    return ok

s = isqrt(M*M-8*N)
assert (s * s == M*M-8*N)

p = (M + isqrt(M*M - 8*N)) // 4
# p = (M - isqrt(M*M - 8*N)) // 4
q = N // p

assert (p * q == N)

phi = lcm(p-1, q-1)
d = inv_mod(e, phi)
m = pow(c, d, N)

print(long_to_bytes(m))

フラグは、FLAG{@n_ex7ra_param3ter_ru1n5_3very7h1n9}

[Very Hard] OUCS

与えられたコマンドnc oucs.cry.wanictf.org 50010でサーバーにアクセスすると、次の5つのコマンドを使えます。 f:id:bakamono1357:20210502173524p:plain

サーバーのコードも与えられています。(適宜コメントを入れています)

import random

from Crypto.Util.number import bytes_to_long, getPrime, long_to_bytes

from const import description, flag, logo

# nc oucs.cry.wanictf.org 50010

class OkamotoUchiyamaCryptoSystem:
    def __init__(self, bits: int):
        p, q = getPrime(bits), getPrime(bits)
        n = p * p * q

        while g := random.randrange(2, n):
            if pow(g, p - 1, p * p) != 1:
                break
        h = pow(g, n, n)

        self.p = p
        self.n = n
        self.g = g
        self.h = h

    def encrypt(self, plaintext: bytes) -> bytes:
        plaintext = bytes_to_long(plaintext)
        n, g, h = self.n, self.g, self.h
        r = random.randrange(2, n)

        ciphertext = pow(g, plaintext, n) * pow(h, r, n) % n
        ciphertext = long_to_bytes(ciphertext)

        return ciphertext

    def decrypt(self, ciphertext: bytes) -> bytes:
        ciphertext = bytes_to_long(ciphertext)
        p, g = self.p, self.g

        a = (pow(ciphertext, p - 1, p ** 2) - 1) // p
        b = (pow(g, p - 1, p * p) - 1) // p
        b_ = pow(b, -1, p)
        plaintext = a * b_ % p
        plaintext = long_to_bytes(plaintext)

        return plaintext

    def get_publickey(self) -> tuple[int, int, int]:
        return self.n, self.g, self.h

# フラグは毎回異なる

if __name__ == "__main__":
    print(logo)
    cipher = OkamotoUchiyamaCryptoSystem(bits=1024)

    while True:
        print()
        print(description)
        while not (choice := input("> ")) in "12345":
            print("Invalid choice.")

        choice = int(choice)

        # 1. Encrypt the flag
        # フラグを暗号化して、暗号文(int)を返す
        if choice == 1:
            ciphertext = cipher.encrypt(flag)
            ciphertext = bytes_to_long(ciphertext)
            print(f"{ciphertext = :#x}")

        # 2. Encrypt
        # 平文(int)を入れると、暗号文(int)が出てくる
        elif choice == 2: 
            print("Enter your plaintext")
            plaintext = int(input("> "), 0)
            plaintext = long_to_bytes(plaintext)

            ciphertext = cipher.encrypt(plaintext)
            ciphertext = bytes_to_long(ciphertext)
            print(f"{ciphertext = :#x}")

        # 3. Decrypt
        # 暗号文(int)を入れると、平文(int)が出てくる
        # ただし平文がフラグと一致した場合、何も表示されない
        elif choice == 3:
            print("Enter your ciphertext")
            ciphertext = int(input("> "), 0)
            ciphertext = long_to_bytes(ciphertext)

            # ... except for the flag
            plaintext = cipher.decrypt(ciphertext)
            if flag == plaintext:
                print("Decryption succeeded, but we won't tell you the result :P")
                continue
            plaintext = bytes_to_long(plaintext)
            print(f"{plaintext = :#x}")

        # 4. Show public key
        elif choice == 4:
            n, g, h = cipher.get_publickey()
            print(f"{n = :#x}")
            print(f"{g = :#x}")
            print(f"{h = :#x}")

        # 5. Exit
        else:
            print("Bye :)")
            break

これを用いてフラグを得る問題です。

とりあえず見たことない計算をしているので、クラス名を頼りに岡本 内山 暗号とかで検索してみます。するとWikipediaのページがヒットします。

EPOC (暗号) - Wikipedia

wikiの式とserver.pyをにらめっこして比べると、どうやらこの暗号で間違いないようです。秘密鍵素数$p, q$なので、これらが分からないことには復号できません。

しばらく考えましたが素数$p, q$が分からないことにはどうしようもないので、色々writeupを漁ってみます。

すると、どうやら岡本・内山暗号は準同型暗号であることを知りました。(そういえば問題文にも「OUによるHomomorphicなCryptoSystemです」と書いてあったな...とwriteupを書きながら気づきました)

この暗号は特に、暗号化する関数を$E$とすると、平文$a, b$に対し$E(a)E(b) = E(a+b)$が成り立つようです。これはめちゃくちゃ使えそうです。

実際、次のような手順で解けます。

  1. コマンド1で、フラグを暗号化した値$C$を教えてもらう。
  2. コマンド2で、適当に決めた定数$T$(私は1にしました)を暗号化した値$E_T$を教えてもらう。
  3. コマンド4で、公開鍵$n, g, h$を教えてもらう。
  4. $C * E_T (mod \space n)$を計算し、それをコマンド3でdecryptしてもらう。
  5. 4で得た値から定数$T$を引いた値がフラグ!

よって、5で得た値をbytes型に直すことでフラグが得られました。

フラグは、FLAG{OU_d0es_n0t_repre53nt_Osaka_University_but_Okamoto-Uchiyama}

Forensics

[Beginner] presentation

zipを解凍すると中にはpowerpointファイルが入っています。開いてみるとこうなっています。 f:id:bakamono1357:20210502175933p:plain よってこの四角い図形をどければフラグが分かります。 f:id:bakamono1357:20210502180115p:plain

[Very Hard] MixedUSB

与えられたMixedUSB.imgというイメージファイルをダウンロードします。とりあえずマウントしようとしてみると失敗します。

このイメージファイル壊れてそう...という気持ちになるのでなんとか中身を見る方法はないか調べると、TestDiskというツールがあることを知りました。

qiita.com

より詳しい使い方はこのサイトがわかりやすかったです。rootまでイメージファイルを移動させてからやらないといけなくて面倒だった。

blog.goo.ne.jp

f:id:bakamono1357:20210502181057p:plain
こんな感じで起動
f:id:bakamono1357:20210502181129p:plain
こんな画面になる

すると、dummyファイルが沢山ある中にflag.txtを発見することが出来ました。これを適当なディレクトリにコピーして中身を見ればフラグゲットです。 f:id:bakamono1357:20210502181343p:plain

フラグはFLAG{mixed_file_allocation_table}

[Easy] secure document

zipファイルにはパスワード付きのzipファイルとpassword-generatorというテキストファイルが入っていました。

::the::
Send, +wani
return

::password:: Send, +c+t+f return

::for:: Send, {home}{right 3}{del}1{end}{left 2}{del}7 return

::today:: FormatTime , x,, yyyyMMdd SendInput, {home}{right 4}_%x% return

::is:: Send, _{end}{!}{!}{left} return

:*?:ni:: Send, ^ac{Esc}{home}password{:} {end} return

zipファイルの中にはflag.jpgが入っており、パスワードを得ることが課題のようです。

とりあえずpassword-generatorが何なのか理解する必要があるので、必死にググると(自分はFormatTimeが関数っぽいなと思ってこれでググりました。)これはAutoHotKeyというキーボードの割当をカスタマイズするための言語で書かれたスクリプトであることが分かります。

問題には次のような説明文があったので、このスクリプトを動かしてメモ帳などに「the password for today is nani」とタイプすると、password: Wan1_20210502_C7F!na!と変換されます。

日付の部分はzipファイル名と同じ20210428に直してセミコロン以降をパスワードに入力してみると、zipファイルが空きました。

フラグは↓

f:id:bakamono1357:20210502182338p:plain

ブラウザのURL入力するところで試していたらスクリプトが変な挙動をして一生パスワードが出てこず、大量に時間を溶かしてしまった...

[Normal] slow

zipファイルには.wavファイルが入っています。audacityとかで波形を見てみても何もわかりませんでした。

色々writeupを漁ってみると、どうやらSSTV(低速度走査テレビ)ってやつに聞かせてみる方法もあるらしい

実際RX-SSTVをインストールして試してみると...

f:id:bakamono1357:20210502183144p:plain

...うわあああなんか浮かび上がってきたあああああああああああ

というわけでフラグは、FLAG{encoded_by_slow-scan_television}でした。

(ちなみに音は結構不快なので注意)

Misc

[Beginner] binary

sample.pyと01だけ書かれたbinary.csvが与えられるので複号せよという問題。

s = "WANI"
bits = []
for i in range(len(s)):
    val = s[i]
    for j in range(8):
        b = (ord(val) >> (7 - j)) & 0x01
        bits.append(b)

print(bits)

s = "" c = 0 for i in range(len(bits)): val = int(bits[i]) c = (c << 1) | val if i % 8 == 7: s = s + chr(c) c = 0

print(s)

適当に復元する。
bits = []

with open('binary.csv') as f: for line in f: line = line.rstrip('\r\n') bits.append(int(line))

s = "" c = 0 for i in range(len(bits)): val = int(bits[i]) c = (c << 1) | val if i % 8 == 7: s = s + chr(c) c = 0

print(s)

フラグは、FLAG{the_basic_knowledge_of_communication}

Pwn

[Beginner] 01 netcat

与えられたコマンドnc netcat.pwn.wanictf.org 9001で問題サーバにアクセスするとlsコマンドを打てと言われます。

仰せのままに実行すると当該ディレクトリにflag.txtがあることがわかるので、cat flag.txtを実行することでフラグを得ます。 f:id:bakamono1357:20210502190702p:plain

[Easy] 03 rop machine easy

nc rop-easy.pwn.wanictf.org 9003で問題サーバにアクセスします。 f:id:bakamono1357:20210502191058p:plain rop machineという予め用意されたプログラムを使ってROP (Return Oriented Programming)を行い、system("/bin/sh")を実行する問題のようです。

ROPを僕は知らなかったので色々調べました。↓のwriteupがわかりやすかったです。

blog.8f-nai.net

要するにこのrop machineというやつは命令列を上から順に実行します。pop rdi; retという命令は、stackのtopにある値をpopしてrdiレジスタにセットし、次にstackのtopにある値をリターンアドレスとみなして飛びます。

よってstackに"/bin/sh"のアドレス、system関数のアドレスを順にpushしておき、pop rdi; retを実行することでsystem("/bin/sh")が実行できます。

f:id:bakamono1357:20210502192029p:plain
フラグは↑

[Easy] 04 rop machine normal

全問に加えて実行できる命令が増えています。

目標はexecve("/bin/sh", 0, 0)を実行することであり、execveのsyscall番号が0x3bであることがわかっています。

f:id:bakamono1357:20210502192245p:plain

やることは前問とほぼ同じで、第1引数に渡す値をrdiレジスタにセット、第2引数に渡す値をrsiレジスタにセット、第3引数に渡す値をrdxレジスタにセットし、syscall命令に渡すsyscall番号をraxレジスタにセットし、実行してあげればよいです。

f:id:bakamono1357:20210502192728p:plain
渡す命令順はこんな感じ

フラグは、FLAG{now-you-can-call-any-system-calls-with-syscall}

reversing

[Beginner] secret

zipファイルには実行ファイルのみが入っています。

実行権限を与えて実行してみると、パスワードを要求されます。 f:id:bakamono1357:20210502193411p:plain

そこでヒントにある表層解析というのを試してみると、

$ strings -a secret > out
f:id:bakamono1357:20210502193518p:plain

なんかwani_is_the_coolest_animals_in_the_world!というのがパスワードっぽく見えます。実際正しくて、これを入れるとフラグが出てきました。 f:id:bakamono1357:20210502193632p:plain

[Easy] execute

zipを解凍するとファイル構成は次のようになっています。 f:id:bakamono1357:20210502193803p:plain 説明文に「コマンドを間違えてソースコードを消しちゃった!」とある通り、Makefileを見てみると

all:
        gcc --version > version.txt
        gcc -S main.c
        gcc -shared -o libprint.so print.c
        rm main.c
        rm print.c

ガッツリ消してて笑う

main.sとlibprint.soというやつがあるなら普通になんらかの方法でコンパイルできるんじゃないか?と思い必死にググると、ありました。

sleepy-yoshi.hatenablog.com

これを参考に次のようにコンパイルして実行すると、フラグを得ることが出来ました。

$ export LD_LIBRARY_PATH=.
$ gcc -I./ -L./ main.s -o main -lprint
$ ./main
Flag is "FLAG{c4n_y0u_execu4e_th1s_fi1e}"

Web

[Beginner] fake

https://fake.web.wanictf.org/ というサイトからフラグを得る問題です。デベロッパーツール開けばなんかあるでしょと思い開くと、謎のhtmlファイルがありました。 f:id:bakamono1357:20210502194710p:plain これを開くとフラグを得ます。 f:id:bakamono1357:20210502194748p:plain

[Easy] Wani Request 1

https://request1.web.wanictf.org/

↑のwebサイトが与えられています。

自前のサーバを用意もしくはRequestBinなどのサービスを使えと言われているので、RequestBinを使ってみます。

与えられたサイトに発行されたURLを入れて送信し、httpヘッダーを見るとそれっぽいリンクがあります。 f:id:bakamono1357:20210502195418p:plain 実際アクセスするとフラグをゲットできます。 f:id:bakamono1357:20210502195445p:plain

ICPC2020 アジア地区 横浜大会 参加記

早稲田大学のチームUHISHIROは、6完21位でした。

f:id:bakamono1357:20210317195353p:plain

Day -n

割とそこそこの頻度でチーム練をしていました。

同大学のB2チームGive_us_sociabilityと一緒に走って感想戦をしたりしていた。かなり楽しかったです。

Day 1

13:00頃に指定のZoomに入り、学生証を見せたり誓約書を書くなどの諸々の手続きを済ませる。

practiceでは色んなverdictが出ることを確認したり、clarを投げてみたりした。

また、practiceのD問題が普通に難しかったので全員でそれの考察をして3人同時に実装したりした(僕はclarで投げる英語の文章が恥ずかしくないようにちょっと推敲してたりしたら普通に時間内に終わらなかったので、後でAOJで通した)

day1終了後、コーチのyamadさんがslackに貼って下さったこの問題を通して明日の起床成功を確信(?)

また、1週間前にJAG開催の模擬地区予選でA問題の読解に手間取りそれが模擬地区の冷えに繋がったと反省したので、少し英語問題文の読解の練習をしていた。

日付が変わるぐらいに就寝。

Day2

緊張してたのか分からないけど5:00に目が覚める。n度寝して起きたら7:30だった。天才。

飲み物の買い出しついでに散歩したりして頭をスッキリさせ、コンテストに備えた。開会式後、コンテストがスタート。

0~1h

AB難易度順C以降randomizedされているので、僕A、suta B、kiyoshi C以降の解けそうなやつを探す、という方針でスタート。

Aがすぐ読める。ナイス反省、ありがとうJAGさん...

しかし1分ぐらい考えて、俺がやるよりkiyoshiにやってもらった方が爆速で通ると思ったのでkiyoshiに問題概要を伝えてバトンタッチ。

しばらくするとAが通る。

sutaもBを読み終わりすでに実装を開始していた。僕は後ろから適当にKを読む。kiyoshiはHとかGを読んでた気がする。

Bの実装が終わり出すがWA。順位表を見るとそこそこWAが出ていたのは知ってたのでそこまで動揺しなかった。

少し考えるとhackケースが生えたので、それを元にこういう実装をしてほしいとsutaにお願いし、書いてもらう。少しバグっていたがなんとかBをAC。

sutaとkiyoshiがJの相談を始める。ここで他の問題の読解をしようとKの続きを読もうとするが、なんか全然解かれてないので読むのをやめ(は?)て順位表を見ると、阪大のonionsがCを通しているのを見つける。Cを読んでみたらヤバそうなので一旦放置する。

1~2h

なんかsutaがJができそうと言って実装を開始する。kiyoshiがG読めないと言っていたので読解を手伝う。

Jが通る。 僕もG読めなかったので(は?)3人でGを読む。割とすぐ読解が終わってGの相談を2人でし始めていたので、3人で1つの問題に固まるのはまずいと思い、Iを読み、考える。

Gはもう少しで詰められそうな雰囲気が出ている。一方僕は「二部グラフ 完全マッチング 数え上げ」で検索してNP困難であることを知り、ため息をついていた。(????)

Gがkiyoshi担当になったようなのでsutaにI問題の概要を伝えると、割とすぐ「箱根DPっぽいね」という。検索するとたしかにな~となる。

2~4h

2人で1hほどIを考えるけど全く生えない。ここらへんで自分はIに絶望を感じてCに浮気する。(え?)

kiyoshiがGをoff-by-oneでバグらせ泣き叫んでいた。

Cのサンプルをぼんやり眺めていたらoutput4の出力が割と賢いことに気づく。「もしかして高々5行で済むのでは???」となるがお気持ちでしかないのでちゃんと考察する。

とりあえず仮説をもとにCの全探索を書くことにする。

Gと格闘していたkiyoshiがGをついに通す。

4~5h

Cが書き上がったが盛大にバグらせていたのでkiyoshiに介護してもらう。

途中で、そういえばsuta大丈夫か?となり様子を聞くと

suta「実はI解けててこっそり実装してます」

本当にびっくりした かっこよすぎて草

その後もCのバグと格闘していると、

suta「あの」

suta「ご報告があります」











suta「I通りました

チーム通話は称賛の嵐であった。Cを絶対に通そうと言う気持ちになる。

その後は無事Cのバグが見つかり、凡ミスで1WAしたもののCが通る。

最後は3人でHを考えていたけど、こんなん無理じゃんって言ってたらコンテストが終わってしまった。あっという間...

その後

コンテストが終わった後はgatherに入って色々な人たちと交流させていただいた。 UHISHIRO+Lorentさん+じゅぴろさんで解説やyes/noを観戦したり、懇親会もTwitterでよくお見かけする有名な方と沢山お話させていただいた。

毎回NOSSさんとは懇親会でお話させていただいているような気がする。いつもありがとうございます。

皆さんが気さくに話しかけて下さり、温かみを感じました

感想

途中何もしてなかったけどCの考察実装ができてホッとした。

横浜大会はめちゃくちゃレベルが高いなと感じた。

実はUHISHIROは来年で解散になってしまうので、来年もアジアに行けるように頑張ります。

コーチのyamadさんを始め、早稲田大学の方々、ICPCの運営をして下さったすべての方々、模擬国内や地区予選を準備して下さったJAGの方々等にこの場を借りて(?)感謝の意を申し上げます、本当にありがとうございました!!!

来年は早稲田2チーム以上進出してオンサイトでわいわいしたいです!それまでにまた精進を頑張ろうと思います(卒論さん...?)

CLionを色々インストール、設定したメモ(自分用)

WSL(Ubuntu18.04 LTS)上のコンパイラを使ってWindows側からCLionが使えるようになった(多分)

CLionは本来は有料ですが、学生ならStudent Packの申請をすることで無料で使えます。

CLionのインストールは済んでいるものとします。以下やったことをメモします。

①CLionにWSLを設定

ここに書いてあることをやれば良い

pleiades.io

次のコマンドをWSL上で順にコピペして実行する。

$ sudo apt-get update
$ sudo apt-get install cmake gcc clang gdb build-essential

インストールが終わったら次のコマンドをコピペして実行する。

$ wget https://raw.githubusercontent.com/JetBrains/clion-wsl/master/ubuntu_setup_env.sh && bash ubuntu_setup_env.sh

実行が終わったらCLionを起動 f:id:bakamono1357:20201111144605p:plain

Configure→Settings→Build,Execution,Deployment→Toolchains と選択。

ドラッグしてWSLを一番上にもってくるとdefaultになる。下の画像では全部チェックついてるけど、最初はなんか赤で警告出てた。

f:id:bakamono1357:20201111144844p:plain
WSLがこのリストになかったら+から追加

Credentialsの項の歯車マークを選択する。

f:id:bakamono1357:20201111145239p:plain

  • Hostlocalhost
  • Port:2222
  • User name: WSLでのuser名
  • Authentication type:Password
  • Password:WSLのパスワード

これらを入力したらTest ConnectionボタンをポチってSuccessみたいなメッセージが出たら完了

②ターミナルもWSLのものを使いたい

Configure→Settings→Tools→Terminal と選択。

f:id:bakamono1357:20201111145721p:plain

Shell pathにwsl.exeと入力する。再起動するとちゃんとWSLのターミナルが開かれている。

Hello World

使い方正しくない気がするけどHello Worldした、補完も正しく動いた!

f:id:bakamono1357:20201111150003p:plain

また何か詰まったらここに追記します