BsBsこうしょう

これは考えたことではなく思ったことです。

Salt and Pepper[writeup][Crypto CTF 2021]

問題

  • システムにログインしてね
  • usernameは n3T4Dm1n、passwordは P4s5W0rd
  • ただしそのハッシュも一緒につける必要があるよ
  • ハッシュは sha1(salt + password + md5(pepper + username)) だよ
  • saltとpepperのハッシュと文字数は分かっているよ

解説

salt、pepperがハッシュ関数で前についていることから、このハッシュにはLendth Extension Attack(身長攻撃)が可能。しかし、ややこしく本当にできるかどうかは疑問が残る(できます)。

伸長攻撃についてはこちら a8pfactory.hatenablog.com

このハッシュ関数において、自由に操作できる文字列はpasswordとusername。md5()の部分が操作できないため難しいように見えるが、(伸長攻撃が salt + originalMessage + padding + addMessage のハッシュを 事前に 求められることに注目すれば、)md5を事前に求めておくことができるため addMessage = password + md5hash とし、後でmd5hashを取り除くことで伸長攻撃が可能である。

では実装するだけ……と思いきや、伸長攻撃ツールhashpumpはoriginalMessageの長さが0の場合、エラーを吐いてしまうため、うまく実装できない。そこで、saltの最後の1byteをoriginalMessageとし、その1byteを全探索する。もちろん最終的に得られるmessageには余計なものがあるので取り除く。md5sha1でそれぞれ調べる必要があるので、全体で65536回くらいの試行が必要となる。実装したものが以下である。

from pwnlib.util.packing import pack
import hashpumpy
import pwn
md5salt = '5f72c4360a2287bc269e0ccba6fc24ba'
sha1pepper = '3e0d000a4b0bd712999d730bc331f400221008e0'
saltpepper = 19

USERNAME = b'n3T4Dm1n'
PASSWORD = b'P4s5W0rd'
f = False

for s in range(0,256):
    for p in range(0,256):
        md5digest, user = hashpumpy.hashpump(md5salt, s.to_bytes(1, 'big'), USERNAME, saltpepper-1)
        sha1digest, word = hashpumpy.hashpump(sha1pepper, p.to_bytes(1, 'big'), PASSWORD+md5digest.encode(), saltpepper-1)
        socket = pwn.remote('02.cr.yp.toc.tf', 28010)
        socket.recvuntil('uit')
        socket.sendline('l')
        socket.recvuntil('comma: ')
        name = hex(int.from_bytes(user[1:], 'big'))[2:] + ',' + hex(int.from_bytes(word[1:-32], 'big'))[2:]
        socket.sendline(name)
        socket.recvuntil('hash: \n')
        socket.sendline(sha1digest)
        packet = socket.recv(1024)
        # print(packet)
        if b'flag' in packet:
            f = True
            socket.close()
            break
        socket.close()
    if f:
        break

これでFLAGを得ることができた。

疑問点

ところでこのプログラムを動かすと、すべてのケースでFLAGを獲得できることが分かった。なぜだろう?

実際に伸長攻撃ライブラリを動かしたことがある人ならお分かりかもしれないが、addMessageを変えない場合、saltの文字数を変えてもライブラリが出力するハッシュは変わらない。変わるのはmessageだけだ。なぜならば、saltの文字情報がすべて含まれている既知ハッシュの情報は何も変わらないためである。

今回のケースもこれと同じことが起きている。saltの最後の文字を全探索して、saltの文字数を1文字引いたとしても、saltの情報が変わる=既知ハッシュが変わるわけではない。既知ハッシュが変わらないということは、うまく辻褄を合わせられる範囲であれば、 文字数と既知ハッシュさえ合っていれば伸長攻撃ライブラリ は正しく動作するということになる。

これが個人的に非自明だったので、今回このwriteupを残した。

ポピュラー和声のダイアトニックコードと代理和音

この記事は何

Wikipediaの記事「ポピュラー和声」を、自分が理解できる形で読解したノートである。基本的な和声に関する法則、用語などへの理解を前提とする。

ja.wikipedia.org

と言ってもこの記事自体、初心者が書いた初心者向けの記事ではある……。

続きを読む

ハッシュ関数の伸長攻撃

まとめ

ハッシュ関数の中には、SHA256のように伸長攻撃(Length Extension Attack)ができるものがある。

これがよく分からなかったので、伸長攻撃を行うライブラリHashPumpの実装を読むことで、 伸長攻撃がどのようにして行われるかを調査した。

調査の結果、以下のリンクに書いてあることが正しかった。(めっっっっっちゃ遠回りした……)

ptr-yudai.hatenablog.com

続きを読む

OUPC開催後記

まとめ

// 内部連絡
// Writer, Testerをしてくださった方のなかで不足を見つけた方がいらっしゃれば、適宜指摘してください。

  • 全体に、(AOJでの)経験の少なさが響いた。
    • AOJはノックアウト形式なので、サンプルを最初に置く(clarで来た)
      • clarで来たし、感想ツイートで突っ込まれた
    • 剰余を求める問題が複数ある場合、MODは揃える
    • 前半の軽い問題はマルチテストケースにする
    • テストケースはできるだけ削る(Pythonなどで大量提出する人がいる)
      • C++ / C言語系 / その他 みたいなジャッジの構成なので、大量提出が出るとスクリプト言語系ユーザー全体に影響が出る
    • チーム戦をする場合、ひとりチーム(ソロ参加)についてルールを明文化する
  • 外部に情報を出すときは、全員(コアメンバー)に確認を取ってからにする
    • ルールについては、完全に厳密でなくても大丈夫だと思う
  • 本番中の役割分担は、あらかじめ決めておく

個人的反省

  • 実力がないからと言って逃げない
    • 僕が思っているほど僕の周りの人は怖い人じゃない、はず
  • 成果物は成果物だけを見て評価する
    • 「この変更点は変更がめんどくさいからな……」と言わずに放置しても、結局Testerに指摘される
      • されないこともある。その場合地獄
  • 簡単な問題もある程度作る
    • 簡単な問題を作るのは難しい

// 本当は当時の状況を振り返りながらお気持ち表明をしたかったが、めんどくさいのでやめた

バイキングに勝つ。

大食いアドベントカレンダー17日目の記事です。

小野原のカーネルバフェ行きたい。Badlylucky ( @small_rakkyoes )です。つたない文章ですが、お手柔らかにお願いします。

みなさんバイキング(ビュッフェスタイルのレストラン)は好きですか? 私は大好きです。好きなものを好きなだけ食べられる、食欲の極致のひとつなのではないか、と思います。

ところで、バイキング中にまだ途中なのにお腹がいっぱいになってしまったり、想像していたように食べ進められなかったことはありませんか? ……なるほど、ある。……とてももったいない!

本日は、そのような悲劇を起こしにくい食べ方(のひとつ)、を紹介いたします。

続きを読む

OUPC2020 解説記事のまとめ

コンテストページ

onlinejudge.u-aizu.ac.jp

ご参加いただき、ありがとうございました!

解説ページ

A. Times Square

Writer: Badlylucky ( @small_rakkyoes )

FA: S0_1115

a8pfactory.hatenablog.com

B. グリコ on Line

Writer: octo ( @octocoder24 )

FA: S0_1115

kawamochi-kpr.hatenablog.com

C. Symmetric Nbase Number

Writer: ningenMe( @ningenMe )

FA: nvip62

ningenme.hatenablog.com

D. 仲良しスライム

Writer: furuya1223 ( @furuya1223 )

FA: ptr3oesmat

www.creativ.xyz

E. Xor Mart

Writer: fine ( @refine_P )

FA: WA_syndrome

refine-p.hatenablog.com

F. Alternating Path

Writer: furuya1223 ( @furuya1223 )

FA: beet

www.creativ.xyz

G. Construction Set

Writer: ningenMe ( @ningenMe )

FA: ptr3oesmat

ningenme.hatenablog.com

H. ラブラブデート大作戦スギノキさん

Writer: fine ( @refine_P )

FA: beet

refine-p.hatenablog.com

I. カフェオレ

Writer: furuya1223 ( @furuya1223 )

FA: NyaanNyaan

www.creativ.xyz

OUPC2020 A. Times Square

問題

onlinejudge.u-aizu.ac.jp

解説

問題を解く際に行う計算を、式で表すと以下のようになります。

この解を \(S\) と置きます。

$$ S = a \times b + a \times (b+1) + ... + (a+1) \times b + (a+1) \times (b+1) + ... + c \times (d-1) + c \times d $$

この式は、以下のように因数分解できます。

$$ S = (a + (a+1) + ... + c) \times (b + (b+1) + ... + d) $$

\(a\) から \(c\) まで、 \(b\) から \(d\) まではそれぞれ連続する自然数区間なので、 等差数列の和を求める方法を使って \(O(1)\) で求めることができます。

よってこの問題を \(O(1)\) で解くことができました。

別解

\( T := a + (a+1) + ... + c\) と置きます。 \(T\) を累積和、等差数列の和などを使ってあらかじめ求めておきます。

\(S\) は \(T\) を使って以下のように表すことができます。

$$ S = T \times b + T \times (b+1) + ... + T \times d $$

\( T \) をあらかじめ求めておけば、 \(S\) は \( O(N) \) で求めることができ、 \(T\) も \( O(N) \) で求めることができるため、全体の計算量は \( O(N) \) となります。

制約が十分小さいため、この方法でも求めることができます。

表の縦、あるいは横に注目して、まとめて足していくイメージです。これを縦横両側から行うと、最初の解法になります。

Writer解

Python、 \( O(N) \) 。

onlinejudge.u-aizu.ac.jp

余談

  • 「九九の和」で検索すると、解法を得られます。サンプルには、九九の和を求める入力例があったのですが、これを受けて削除しました。

gakusyu.shizuoka-c.ed.jp

  • 自分が一番最初に作った競技プログラミングの問題です。AtCoderで累積和を使うほぼ同じ問題が出たり、yukicoderに爆破されかけたりと色々ありましたが、簡単な問題なのでお目こぼしにあずかりました。