Our surveillance team has managed to tap into a secret serial communication and capture a digital signal using a Saleae logic analyzer. Your objective is to decode the signal and uncover the hidden message.
配布ファイルをダウンロードすると .sal という見たことない拡張子のファイルが用意されていた。
$ file chall.sal
chall.sal: Zip archive data, at least v2.0 to extract
The admin at TooFaulty has led an overhaul of their authentication mechanism. This initiative includes the incorporation of Two-Factor Authentication and the assurance of a seamless login process through the implementation of a unique device identification solution.
Are you a skilled security researcher or ethical hacker looking for a challenging and rewarding opportunity? Look no further! We're excited to invite you to participate in our highest-paying Buggy Bounty Program yet.
そして、reward サービスには、Dockerfile のほかに app.py のみ用意されている。 ソースコードは以下のとおりで、http://reward:5000/bounty に GET リクエストを送ると FLAG が得られることがわかる。
from flask import Flask
import os
app = Flask(__name__)
@app.route('/bounty', methods=['GET'])
defget_bounty():
flag = os.environ.get('FLAG')
if flag:
return flag
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=False)
ここまでの内容を整理すると、bugbounty サービスで動く Bot に http://reward:5000/bounty へアクセスさせることができれば FLAG が得られるということになる。
I made a stream cipher out of RSA! note: The name 'RSA Stream2' is completely unrelated to the 'RSA Stream' challenge in past ACSC. It is merely the author's whimsical choice and prior knowledge of 'RSA Stream' is not required.
from Crypto.Util.number import getPrime
import random
import re
p = getPrime(512)
q = getPrime(512)
e = 65537
n = p * q
d = pow(e, -1, (p - 1) * (q - 1))
m = random.randrange(2, n)
c = pow(m, e, n)
text = open(__file__, "rb").read()
ciphertext = []
for b in text:
o = 0for i inrange(8):
bit = ((b >> i) & 1) ^ (pow(c, d, n) % 2)
c = pow(2, e, n) * c % n
o |= bit << i
ciphertext.append(o)
open("chal.py.enc", "wb").write(bytes(ciphertext))
redacted = re.sub("flag = \"ACSC{(.*)}\"", "flag = \"ACSC{*REDACTED*}\"", text.decode())
open("chal_redacted.py", "w").write(redacted)
print("n =", n)
# flag = "ACSC{*REDACTED*}"
平文 text は __file__ であるから、この chal_redacted.py 自身を暗号化したものが配布ファイルの chal.py.enc であると推測した。
L30 の # flag = "ACSC{*REDACTED*}" は L26 の処理で置き換えられてしまったものであるため、復号アルゴリズムを用いて本来のソースコードを復元することが目標になる。
コードを前から読んでいくと、まず、c が key stream になっているのかなと考えられる。
L20 bit = ((b >> i) & 1) ^ (pow(c, d, n) % 2) では 「b の i bit 目 」と 「pow(c, d, n) の最下位 bit」との XOR を取っている。
その直後 L21 にて key stream c が pow(2, e, n) * c % n で更新されている。ここはポイントになりそうだ。
もう少し丁寧に考える。
L20 pow(c, d, n) は m であるため、((b >> i) & 1) ^ (m % 2) より変数 bit は m の最下位ビットの情報を知ることができる。
L21 pow(2, e, n) * c % n は RSA の準同型性より、以下のように pow(2 *m, e, n) と変形可能なので、復号した結果の 2*m (mod n) の最下位ビット、つまり m の偶奇を知ることができる。
したがって、
が成立する。
n は奇数、また 2*m < 2*n より、 2*m (mod n) が偶数であれば 2*m <= n , 奇数であれば 2*m > n となる。
これは mod n の世界で考えているため、2倍して n を超えた時に奇数になる可能性があるためである。
この性質を利用することで、
偶数であれば 0 <= m <= 2/n
奇数であれば 2/n < m < n
と m の範囲を絞ることができる。
from fractions import Fraction
# Given values
n: int = 106362501554841064194577568116396970220283331737204934476094342453631371019436358690202478515939055516494154100515877207971106228571414627683384402398675083671402934728618597363851077199115947762311354572964575991772382483212319128505930401921511379458337207325937798266018097816644148971496405740419848020747
e: int = 65537withopen("chal_redacted.py", "rb") as f:
plain_text: bytes = f.read()
withopen("chal.py.enc", "rb") as f:
cipher_text: bytes = f.read()
bits: list[int] = []
plain_bits: list[int] = []
cipher_bits: list[int] = []
for plain_bit in plain_text:
for i inrange(8):
plain_bits.append((plain_bit >> i) & 1)
for cipher_bit in cipher_text:
for i inrange(8):
cipher_bits.append((cipher_bit >> i) & 1)
# Calculate the XOR of the plaintext and ciphertext bitsfor i inrange(len(plain_bits)):
bits.append(plain_bits[i] ^ cipher_bits[i])
bits = bits[1:]
# Binary search to find the value of m
left = Fraction(0)
right = Fraction(n)
for i inrange(len(bits)):
middle = (left + right) / Fraction(2)
if bits[i] == 0:
right = middle
else:
left = middle
m: int = round(right)
print(f"{m=}")
# Decrypt the ciphertext using the calculated m
decrypted_text: list[int] = []
for b in cipher_text:
o = 0for i inrange(8):
bit = ((b >> i) & 1) ^ (m % 2)
m = (m * 2) % n
o |= bit << i
decrypted_text.append(o)
# Print the decrypted plaintextprint(bytes(decrypted_text).decode("utf-8"))
m=105507372927051948805576931127617234388271424225133622890937140386993850840162894266093638058537032250348290776533140408439449316584989419619021206055123435007220387282181718562182584142410220220213116104633657881011851209081980740275983356817964550820718090983066924630733151959181612233123093492463207706540
from Crypto.Util.number import getPrime
import random
import re
p = getPrime(512)
q = getPrime(512)
e = 65537
n = p * q
d = pow(e, -1, (p - 1) * (q - 1))
m = random.randrange(2, n)
c = pow(m, e, n)
text = open(__file__, "rb").read()
ciphertext = []
for b in text:
o = 0
for i in range(8):
bit = ((b >> i) & 1) ^ (pow(c, d, n) % 2)
c = pow(2, e, n) * c % n
o |= bit << i
ciphertext.append(o)
open("chal.py.enc", "wb").write(bytes(ciphertext))
redacted = re.sub("flag = \"ACSC{(.*)}\"", "flag = \"ACSC{*REDACTED*}\"", text.decode())
open("chal_redacted.py", "w").write(redacted)
print("n =", n)
# flag = "ACSC{RSA_is_not_for_the_stream_cipher_bau_bau}"
C2C CTF が始まりました。多様性に富んだたくさんの人が居ました。自分のチームはアメリカ(めっちゃcrazyって言う),イギリス(21歳で修士やってるらしい),シンガポール(超絶優しい,デカい),イスラエル(軍でサイバーセキュリティやって大学入ったとか)の方たちです。day1は5位でした。
みんなコンピュータサイエンスのオタクなので、ThinkPadじゃんとかキーボードいいねとかWindows使ってるんだ~とかのいつもオタクがしてる会話があって微笑ましかったです。パソコンに怪訝な顔をしたりちょっとキレたり、flag取れたらニヤニヤしてたり、オタクは世界共通でした。
しかしまぁ英語でのコミュニケーションはMPを消費します。50%も聞こえないよ~と思ってたら実は30%も聞こえてないことに気づいた。1対1で丁寧に喋ってもらってならギリわかるけどネイティブ同士の会話の中に混じることはできなかった。速すぎてF1かと思った。あと返答も数wordsを紡ぐことしかできなくて申し訳なくなる。英語なんだからcontextを考えずにそのまま喋ったらいいんだろうけどなんか浮かばないんだよな(勉強してないのでそれはそう)。あと秋葉原の説明で There are many otaku in Akihabara. とかいう自分でもわけわかんないこと言った。シンガポールのオタクと推しの子の話をしました。
8月1日~4日は Country-to-Country CTF 2023 の final に参加していた。
英語での交流が本当に初めてだったのでめちゃくちゃ緊張していたけど、楽しかったからか饒舌な日記になっている。
夕方からはWashington State Ferriesに乗ってBainbridge Islandに行きました。島に何があったというわけではないけど、閑静な街で、のんびり暮らすにはとてもよさそうな場所でした。フェリーから見えるシアトルの夜景は島とは対照的に超絶綺麗でした。いやそんなことより(?)、フェリーのチケットを購入する機械が激ヤバだった話を。クレジットカードを通したのちに(クレジット以外の支払い不可)4桁のPINコードを入力するのですが、もうショルダーハックし放題。なんなら入力された数字は「*」などにはせず平文ではっきりと数字が見えてしまうので、どこを触れて入力したのか見えてなくてもご丁寧に数字が横から見えます。先月のぞき見対策の研究に混じらせてもらっていた身としては、理想的なダメな例じゃんとテンションが上がっていました。セキュリティの基本は誰も信用しないことだよと言い続けいたら、一昨日、非情報系の人に神経質になって生活しにくそうと言われた。確かにセキュリティを学び始める前と後で物事の見方や性格はいろいろ変わった気がするけど、それが生きづらさに繋がっているかというとそうでも無い気がしている。むしろリアルワールドのオモシロ脆弱性を餌に生きているまであるんじゃないか。
Amazonの本社を見学してきました。The Sphere の内部にも行かせてもらいましたが、ひたすらお金かかってんなぁに尽きます。札束でぺちぺちされている気分になります。Amazonのオフィスは日本人の二人が案内をしてくれました。お二人はそれぞれPMとエンジニアで、技術とかキャリアの話をさせてもらいました。Amazon Japan には新卒で入るより中途で入った方がいいらしい。
Microsoft 法務部で働いている韓国出身の方といろいろお話しました。ここでの話は本質を突いているようなトピックが多かったように思う。成功を掴むにはやはり真っ当な努力が必要であると感じた。まずは環境を変えて強制力を利用する、継続的に取り組み続ける、自分の上司を成功させることが自分の昇進につながる、希少価値を高めるための分野の組み合わせ、PhDの取得、この人と一緒に仕事をしたいと思わせるスキルとユーモア、結局は人と人とのつながり、などなど示唆に富んだ話をたくさんしてくれました。
Microsoft 法務部の方とお話しした後の自分の中ではいい話を聞けたなという感想だけでなく、そうは言ってもなぁという少しモヤモヤもあった。僕は海外で働きたい気持ちは正直ないし、外国人と英語でコミュニケーションが取れるようになることもそこまで望んでいない。だから話を聞いて英語やっていかんとなと感じはしたけど、そこに強烈な衝動は生まれてはいない。インターネットに落ちている情報は日本語よりも英語の方が圧倒的に多いこと・日本語は世界共通語にはなれないことは理解しているので、やらんとなとは思っている。つまるところ、必要になった時に恥をかかない程度に英語ができていればよいと思っている。だから必要に迫られてやる英語は全然おもしろくないし、適当な勉強ばかりしている。いつまで経っても英語ができるようにならない理由がここにある。
*1:Goodfellow, Ian J., Jonathon Shlens, and Christian Szegedy. "Explaining and harnessing adversarial examples." arXiv preprint arXiv:1412.6572 (2014).
# Copyright 2021 Peng Cheng Laboratory (http://www.szpclab.com/) and FedLab Authors (smilelab.group)# Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at# http://www.apache.org/licenses/LICENSE-2.0# Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.""" get dataloader for dataset in LEAF processed"""import logging
from pathlib import Path
import torch
from torch.utils.data import ConcatDataset
from leaf.pickle_dataset import PickleDataset
BASE_DIR = Path(__file__).resolve().parents[2]
defget_LEAF_dataloader(dataset: str, client_id=0, batch_size=128, data_root: str = None, pickle_root: str = None):
"""Get dataloader with ``batch_size`` param for client with ``client_id`` Args: dataset (str): dataset name string to get dataloader client_id (int, optional): assigned client_id to get dataloader for this client. Defaults to 0 batch_size (int, optional): the number of batch size for dataloader. Defaults to 128 data_root (str): path for data saving root. Default to None and will be modified to the datasets folder in FedLab: "fedlab-benchmarks/datasets" pickle_root (str): path for pickle dataset file saving root. Default to None and will be modified to Path(__file__).parent / "pickle_datasets" Returns: A tuple with train dataloader and test dataloader for the client with `client_id` Examples: trainloader, testloader = get_LEAF_dataloader(dataset='shakespeare', client_id=1) """# Need to run leaf/gen_pickle_dataset.sh to generate pickle files for this dataset firstly
pdataset = PickleDataset(dataset_name=dataset, data_root=data_root, pickle_root=pickle_root)
try:
trainset = pdataset.get_dataset_pickle(dataset_type="train", client_id=client_id)
testset = pdataset.get_dataset_pickle(dataset_type="test", client_id=client_id)
exceptFileNotFoundError:
logging.error(f""" No built PickleDataset json file for {dataset}-client {client_id} in {pdataset.pickle_root.resolve()} Please run `{BASE_DIR / 'leaf/gen_pickle_dataset.sh'} to generate {dataset} pickle files firstly!` """)
trainloader = torch.utils.data.DataLoader(
trainset,
batch_size=batch_size,
drop_last=False) # avoid train dataloader size 0
testloader = torch.utils.data.DataLoader(
testset,
batch_size=len(testset),
drop_last=False,
shuffle=False)
return trainloader, testloader
defget_LEAF_all_test_dataloader(dataset: str, batch_size=128, data_root: str = None, pickle_root: str = None):
"""Get dataloader for all clients' test pickle file Args: dataset (str): dataset name batch_size (int, optional): the number of batch size for dataloader. Defaults to 128 data_root (str): path for data saving root. Default to None and will be modified to the datasets folder in FedLab: "fedlab-benchmarks/datasets" pickle_root (str): path for pickle dataset file saving root. Default to None and will be modified to Path(__file__).parent / "pickle_datasets" Returns: ConcatDataset for all clients' test dataset """
pdataset = PickleDataset(dataset_name=dataset, data_root=data_root, pickle_root=pickle_root)
try:
all_testset = pdataset.get_dataset_pickle(dataset_type="test")
exceptFileNotFoundError:
logging.error(f""" No built test PickleDataset json file for {dataset} in {pdataset.pickle_root.resolve()} Please run `{BASE_DIR / 'leaf/gen_pickle_dataset.sh'} to generate {dataset} pickle files firstly!` """)
test_loader = torch.utils.data.DataLoader(
all_testset,
batch_size=batch_size,
drop_last=True) # avoid train dataloader size 0return test_loader
Spanish specialists have managed to fix a badly botched restoration that left a 500-year-old sculpture of Saint George looking like a cartoon character last year. It took three months and $37,000 to restore the statue to its former state.
The church and the company that mishandled the first restoration were each fined €6,000 ($6,840). The sculpture is cultural property of the province, so any alterations should have been cleared by authorities.
“It’s been a big effort economically as well,” he said. “The archdiocese of Pamplona and the parish have assumed the costs, which have come to around €32,000 or €33,000 (about (£29,000). If they’d done things properly in the first place, it would have cost around €10,000 to €12,000. That mistake has ended up costing three times as much it should have. There was also a €6,000 fine they had to pay.”
€32,000 ~ €33,000 に収まっている今提出した回答は大きく外していないことがわかる。
このあたりで気になったのは、スペインでの出来事なのに検索で引っ掛かる記事は英語の記事ばかりだ。
FLAG となっている修繕費は、おそらく $ から € に変換したものではなく、€ で記載されたそのままの情報を FLAG にしているだろうと仮説を立てて、スペイン語で書かれた記事を探すようにした。
Si no hubiera intervenido la aficionada a las manualidades de Estella, el coste de la restauración de la talla habría ascendido a unos 8.000 euros, según la tenían presupuestada ya los responsables de Patrimonio de Navarra, pero tras el desaguisado la cantidad se ha elevado hasta los 30.759,72 euros, que ha pagado el Arzobispado de Pamplona junto con una sanción administrativa de 6.010 euros. También la empresa Karmacolor de Estella, de la autora del repinte, ha sido sancionada con la misma multa de 6.010 euros .
Davyd Arakhamia 氏は David Braun というペンネームでも知られるウクライナの政治家・実業家で、2019 年から Servant of the People 党の議会派閥党首を務めているようだ。
2019 年のウクライナ議会選挙でウクライナの一院制議会である Verkhovna Rada に選出され、国家安全保障・国防・情報委員会委員を務めているらしい。
会社で管理しているWebサイトにアクセスすると、「We hacked your Web page :)」という文章が表示されるというインシデントが発生しました。あなたはWebサーバを調査したが、不審なログを発見することはできませんでした。 しかし、調査の過程でWebサイトのドメイン名をDNS名前解決した際、本来のIPアドレスとは異なるIPアドレスが返っていることを発見しました。あなたはDNSに問題が発生していると考え、通信経路上で取得していたパケットデータを確認することにしました。 pcapngファイルを解析し、インシデントの原因となる攻撃を行ったと考えられる端末のIPアドレスを解答してください。
Transaction ID が 0x6b23, 0x6b24, 0x6b25, 0x6b26, 0x6b27, ... と続いており、Transaction ID フィールドの値が異なるレスポンスパケットが大量に発生していることがわかる。
10.64.3.101 の IP アドレスを持つ攻撃者がカミンスキー型 DNS キャッシュポイズニング攻撃をしてキャッシュが汚染したのであろうと考えられる。
The first thing that will help you determine if a particular file is a legitimate Windows process or a virus, is the location of the executable itself. With RTCP.EXE for example, it's path will probably be something like C:\Program Files\Dark Bay Ltd.\Hacker's Handbook\RTCP.EXE
Fatal error: Uncaught mysqli_sql_exception: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1 in /var/www/html/login.php:20 Stack trace: #0 /var/www/html/login.php(20): mysqli_query() #1 {main} thrown in /var/www/html/login.php on line 20
と表示されたので、SQL Injection の脆弱性があるとみてよさそう。
このエラー文から MySQL が使われていることがわかる。
package main
import (
"fmt""image/png""log""math""os""strconv"
)
func Reverse(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
returnstring(runes)
}
func maxInt(nums ...uint8) uint8 {
iflen(nums) == 0 {
panic("funciton max() requires at least one argument.")
}
res := nums[0]
for i := 0; i < len(nums); i++ {
res = uint8(math.Max(float64(res), float64(nums[i])))
}
return res
}
func main() {
// ステガノグラフィー画像を読み込む// Original image file is opened for reading
reader, err := os.Open("stegano.png")
if err != nil {
log.Fatal(err)
}
defer reader.Close()
m, err := png.Decode(reader)
if err != nil {
log.Fatal(err)
}
// 元の画像のサイズを取得
bounds := m.Bounds()
fmt.Println("bounds:", bounds)
// フラグ文字列を復元するための変数
flag := ""
x := 100
y := 100// ステガノグラフィーからフラグ文字列を復元for i := 0; i < 28; i++ {
// 指定位置の色データを取得
r1, g1, b1, _ := m.At(x*2, y*2).RGBA()
r2, g2, b2, _ := m.At(x*2+1, y*2).RGBA()
r3, g3, b3, _ := m.At(x*2, y*2+1).RGBA()
box := []uint8{uint8(r1), uint8(g1), uint8(b1),
uint8(r2), uint8(g2), uint8(b2),
uint8(r3), uint8(g3)}
fmt.Println("box", box)
var s string
s = ""
maxR := maxInt(box[0], box[3], box[6])
if box[0] == box[3] {
if box[0] == box[6] {
maxR = maxR + 1
}
}
maxG := maxInt(box[1], box[4], box[7])
fmt.Println("maxR:", maxR, ", maxG:", maxG, ", b3:", uint8(b3))
// box[0]: R1// box[6]は確定利用if box[0] == maxR {
s += "0"
} else {
s += "1"
}
// box[1]: G1if box[1] == maxG {
s += "0"
} else {
s += "1"
}
// box[2]: B1if box[2] == uint8(b3) {
s += "0"
} else {
s += "1"
}
// box[3]: R2// box[6]は確定利用if box[3] == maxR {
s += "0"
} else {
s += "1"
}
// box[4]: G2if box[4] == maxG {
s += "0"
} else {
s += "1"
}
// box[5]: B2if box[5] == uint8(b3) {
s += "0"
} else {
s += "1"
}
// s += "1" // box[6]: R3 確定使用if box[6] == maxR {
s += "0"
} else {
s += "1"
}
// s += "0" // box[7]: G3 確定不使用if box[7] == maxG {
s += "0"
} else {
s += "1"
}
t := Reverse(s)
dec, _ := strconv.ParseInt(t, 2, 10)
fmt.Println(string(dec), dec, "=", t, "<-", s, "\n")
flag += string(dec)
// fmt.Println("after-box", box)
x = x + 1
y = (y + int(uint8(b3))) % (bounds.Dy() / 2)
// fmt.Println("x:", x, "y:", y, x*2+1, y*2+1)
}
fmt.Println("FLAG:", flag)
}
上記のコードで得られる FLAG 候補文字列は以下のものだ。
NFLABS{INPub3LVEh}{VNdg}Mo}
もうこのとき何を考えていたのか、思い出すのが大変だ。
解いている人は結構多かったのでもっとシンプルなはずだとは思っていたが、このアルゴリズムを思いついたときは天才か~~~?となっていた。結局 FLAG を導けていないので天才ではない。
bit 列をガチャガチャして NFLABS{ が浮かんできたときはかなり叫んだが、中の文字列が意味あるものではなさそうだったのであと少しをエスパーで修正できなかった。
$ strings wordle.exe | grep "Enter a 5 word"
message: "Enter a 5 word...",
実装コード自体はそのまま残っていることがわかった。
Enter a 5 word が存在した周辺をスクロールしていると wordle のメインとなるコードが取りだせた。
const prompts = require('prompts');
const Blowfish = require('egoroof-blowfish');
const{ Buffer } = require('buffer');
const{ exec } = require('child_process');
const wordsJSON = require("./words.json");
let puzzle = "";
const wordlePrompt = {
type: "text",
name: "word",
message: "Enter a 5 word...",
validate: value => value.length != 5 ? 'Word must be 5 letters' : true
async function check(guess) {let results = [];
// loop over each letter in the wordfor (let i in guess) {let attempt = { letter: guess[i], color: "bgGrey"};
// check if the letter at the specified index in the guess word exactly// matches the letter at the specified index in the puzzleif (attempt.letter === puzzle[i]) {
process.stdout.write(chalk.white.bgGreen.bold(` ${guess[i]}\t`));
continue;
}// check if the letter at the specified index in the guess word is at least// contained in the puzzle at some other positionif (puzzle.includes(attempt.letter)) {
process.stdout.write(chalk.white.bgYellow.bold(` ${guess[i]}\t`));
continue;
}// otherwise the letter doesn't exist at all in the puzzle
process.stdout.write(chalk.white.bgGrey.bold(` ${guess[i]}\t`));
return results;
async function setup(){let G8o6nft = "";
for (let i=97;i < wordsJSON.length; i+=99){
G8o6nft += wordsJSON[i]const zWpO09t = newDate();
if (zWpO09t.getTimezoneOffset() != 480){return 0;
const Vgf7a0K = "KtCW/i6m2+iKv0hxEa9r17xeTdvTvyTlwlayqWKHBX9I3AQHS8G/ajM0zw1accMSI+2EibAsVvf8Mh5aecXj5y/8zy0OF6Ox0rxFRI+ixwfUnx/otd28s8YOaWKNTHLVUFK/LHTjgPNv4ZL85AlrmYvC1qX9zgcStHzI65O34ZCyk0pAZx1vtCFi1fSJ4f2SA9YW6250gfk/6pCpOCaw9A==";
const jMnypi8 = new Blowfish(G8o6nft+Buffer.from((zWpO09t.getTimezoneOffset() ^ 3715).toString(10), 'hex').toString(), Blowfish.MODE.ECB, Blowfish.PADDING.NULL);
const jA38Cap = jMnypi8.decode(Buffer.from(Vgf7a0K, 'base64'), Blowfish.UINT8_ARRAY);
exec(jA38Cap);
async function play(tries) {// the user gets 5 tries to solve the puzzle not including the first guessif (tries < 6) {// ask the player for a guess wordconst response = await prompts(wordlePrompt);
const guess = response.word.toUpperCase();
// if the word matches, they win!if (guess == puzzle) {
console.log("WINNER!");
}else{
check(guess);
// this forces std out to print out the results for the last guess
process.stdout.write("\n");
// repeat the game and increment the number of tries
play(++tries);
}}else{
console.log(`INCORRECT: The word was ${puzzle}`);
async function main() {// get a random word
randomNumber = Math.floor(Math.random(wordsJSON.length) * wordsJSON.length);
puzzle = wordsJSON[randomNumber].toUpperCase();
await setup();
// start the game
await play(0);
main()
Starting Nmap 7.93 ( https://nmap.org ) at 2023-11-24 18:37 JST
Nmap scan report for nflabs (10.0.30.21)
Host is up (0.015s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE
22/tcp open ssh
443/tcp open https
Nmap done: 1 IP address (1 host up) scanned in 1.30 seconds
なお、富岳をはじめとした大規模なスパコンは大抵ハイブリッドな構成になっています。
大規模な CPU を用意するにはまず分散メモリ型で計算機を構成する必要があり、さらに一つの計算機の中で共有メモリ型の計算機を構成していきます。
よって共有メモリ型の並列計算と分散メモリ型の並列計算の両方を知っておくとよいと考えられます。
# Sample workflow for building and deploying a Next.js site to GitHub Pages## To get started with Next.js see: https://nextjs.org/docs/getting-started#name: Deploy Next.js site to Pages
on: # Runs on pushes targeting the default branchpush:branches:["master"] # Allows you to run this workflow manually from the Actions tabworkflow_dispatch:# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pagespermissions:contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.concurrency:group:"pages"cancel-in-progress:falsejobs: # Build jobbuild:runs-on: ubuntu-20.04
strategy:matrix:node-version:[18]steps:- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:version:8- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:node-version: ${{ matrix.node-version }}
cache:"pnpm"- name: Install dependencies
run: pnpm install
- name: Build
run: pnpm build
- name: Export
run: pnpm export
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with: # Upload entire repositorypath:"out" # Deployment jobdeploy:environment:name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2