yoshikingのがんばる日記

あたまよくないけどがんばります

SECCON Quals 2019 Writeup

 SECCON Quals 2019 にHarekazeとして出ていました.結果はチームで14位でした.

 僕は、welcome, thank you問とCryptoのZKPayを解きました. CryptoのCRC問についても考えていたのですが、st98さんがパワーで解いてくれました. ここでは、復習も兼ねてCRCについても書きたいと思います.

チームメンバーのwriteup

SECCON 2019 Online CTF の write-up - st98 の日記帳

SECCON 2019 Online CTF Writeup - /var/log/hikalium

writeups/secconctf/2019 at master · hnoson/writeups · GitHub

[Crypto] ZKPay

 ソースコードも何も貰えません.URLのみです.Web問か何かですか. 中身はQR決済?でお金を$1,000,000以上に増やすとflagを得ることができます. 手持ちはadminから与えられた$500のみです.

 お金を送るときにQRコードを発行するのですが、送るお金を入力フォームでは数値以外は弾かれます(エスケープされるaa100 -> 100). しかし、QRコードのデコード・エンコードは適当なツールでできるので、QRコードの金額にマイナスの値を入れることが可能です.

 お金の受取では、マイナスの金額のQRコードは弾かれないので、-$1,000,000のQRを作ることでflagを得ることができました.

 めちゃめちゃ時間を使いました... はじめはproofやhashの偽造・解析あたりの問題かな〜とチームメンバーとともにやっていたのですが、proofやhash一切使いませんでしたね(そもそもソースコードが無いのでしんどい). NaruseJunの方曰く、想定解の目処があるそうなので気になる方は調べてみてください.そしてあわよくば教えて...ください.

[Crypto] Crazy Repetition of Codes

 CRC問題です.問題コードは読みやすくて、crc32をとんでもない数繰り返していて、その結果がAESの鍵となっています. とんでもない数繰り返しているので、当然とんでもなく時間がかかります. 困ったものですが、crc32は2^{32}-1しか状態をもたないので、とんでもない数に比べると圧倒的に小さく、ぎりぎり現実的です. これでも行けるのですが、もう少し頑張って行列と戯れると爆速に計算できます.

 CRC32について、Mを32×32行列、cを32bitsのベクトルとしたとき、


CRC32 _ s (x) = M \times x \oplus c

となります. sは、与える文字列です.cは、x=0を代入すれば求めることができ、Mcが分かればただの表現行列なので、単位ベクトルを与えると求めることができます. ここで、 CRC32 _ s (x)n乗してみましょう.


\begin{aligned}
{CRC32 _ s (x)}^{n}   &=  M \times ( ... M \times (M \times x \oplus c) \oplus c) ... ) \oplus c \\
&= M^{n} \times x \oplus M^{n-1} \times c \oplus M^{n-2} \times c \oplus ... \oplus M \times c \oplus c \\
&= M^{n} \times x \oplus (M^{n-1} \oplus M^{n-2} \oplus ... \oplus M \oplus E) \times c
\end{aligned}

  E単位行列です.入力xに関係しない  (M^{n-1} \oplus M^{n-2} \oplus ... \oplus M \oplus E) 等比数列の和の公式を用いることで、以下のようになります.


(M^{n-1} \oplus M^{n-2} \oplus ... \oplus M \oplus E) = (E - M^{n})(E - M)^{-1} = (M^{n} + E)(M + E)^{-1}

 ここで、(M+E)は正則であるので、計算が可能です. 流れとしては、

  1. 入力文字に対するCRC _ s (x)M, cを求める.
  2.  (M^{n} + E)(M + E)^{-1}を計算する.
  3. 2.とcをかけた結果が、n乗したもの(最初は x=0から始めるので、M^{n} \times xの項は無視です.)

といった感じです.

from binascii import hexlify
from struct import pack

def crc32(crc, data):
  crc = 0xFFFFFFFF ^^ crc
  for c in data:
    crc = crc ^^ ord(c)
    for i in range(8):
      crc = (crc >> 1) ^^ (0xEDB88320 * (crc & 1))
  return 0xFFFFFFFF ^^ crc

def bin2vec(v):
    return ZZ(tuple(map(int, v))[::-1], base=2)

def vec2bin(v, n):
    return tuple(ZZ(v).digits(2, padto=n))[::-1]

n = int("1" * 10000) % (2**32-1)
E = identity_matrix(GF(2), 32, 32)

def calc(s):
    print("[*] Computing for", repr(s))
    c = crc32(0, s)

    M = matrix(GF(2), 32, 32)
    for i in range(32):
        v = [0] * 32
        v[i] = 1
        v = bin2vec(tuple(v))
        v = crc32(v, s) ^^ c
        v = vec2bin(v, 32)
        M.set_column(i, v)
    c = vector(GF(2), vec2bin(c, 32))

    Msum = (M**n + E) * (M + E).inverse()
    res = Msum * c
    return pack(">I", int(bin2vec(res)))

key = b""
key += calc("TSG")
key += calc("is")
key += calc("here")
key += calc("at")
key += calc("SECCON")
key += calc("CTF!")

print(hexlify(key))
$ time sage solver.sage
('[*] Computing for', "'TSG'")
('[*] Computing for', "'is'")
('[*] Computing for', "'here'")
('[*] Computing for', "'at'")
('[*] Computing for', "'SECCON'")
('[*] Computing for', "'CTF!'")
b09bc54fe4a5927b8d3fef85b345bf3f5af656b0db496954

real    0m1.383s
user    0m1.129s
sys 0m0.212s

 これは、速い.鍵が手に入ったので、復号してあげるとflagを得ることができます. (from sage.all import *を使ってpythonですべてをやりたかったんだけど、僕の環境ではCryptoパッケージがあるのに認識されない...悲しい...)

SECCON{Ur_Th3_L0rd_0f_the_R1NGs}

 もともとは、zkpayしか解いてないから書くつもりなかったんですが、TwitterのTLにきれいなwriteupが流れたので、僕も書く気分になりました. これは賢いですね.

セキュリティミニキャンプ in 愛知 2019 参加記

 10/5にミニキャンプが開かれていたので、参加しました.学んだことや感想を書いていきます.

www.security-camp.or.jp

 今回のキャンプでは、分散システム(ブロックチェーン)や機械学習といった流行り?(語弊がありそう)の技術についてのセキュリティがメインになっています.

午前:分散システムで学ぶセキュリティ

 主にブロックチェーンを実装してみようといった感じでした.ブロックチェーンは昔少し嗜んでいたので、事前知識としては十分でした.(CTFで去年の冬あたりブロックチェーン問流行りそうだったけど、最近見ないですね)今まではsolidityを用いたスマートコントラクト関連しかやったことがなく、基盤となるブロックチェーンの実装はしたことがなかったので、非常に楽しかったです.また、言語がpythonだったのも、一番慣れ親しんだ言語なのでプログラムで困るということがないのはよかったです(午後の講義も同じことが言えますが).

 やったこととしては、署名の検証やPoWの実装をしました.PoWはすぐかけたので、10秒に合わせるのを頑張ってました. ただ、時間の関係でDNS関連の話を聞けなかったのが残念です.講義資料と戯れます...

お昼ご飯

 お弁当でした.これがめちゃめちゃおいしかった.ほんとに.

午後:実践 機械学習セキュリティ

 前半に講義をして、残りは演習をひたすらしました.機械学習はAndrew Ng先生の有名なやつを6か7章まで進めた記憶があるので、さっぱりということはなかったです.機械学習に対する攻撃をいくつか挙げられていたのですが、画像に対する攻撃とかpicoCTF2018であったじゃんと思いました(picoマジですごいな...).

 今回は、同一IPからの集中アクセス(パスワード総当たり)を想定した攻撃検知の実装を行い、作ったモデルを自ら攻撃することをしました.ロジスティクス回帰を用いて決定境界を定めました.攻撃者は特徴量の任意の値からモデルの出力(攻撃か否かの確率)を知ることができるという仮定で攻撃します.ここで、未知の変数を解くためにデータをとってきて、連立方程式を解くことにより、決定境界の関数を導きます(ちょっと専門用語の使い方に自信がないです...).これにより、攻撃者は実際のモデルに近しいものを手に入れることができます.モデルを手に入れると、攻撃者の手元でモデルについて研究することができます.今回は50%に近い値となる手元のモデルで見つけ、実際のモデルに投げてみました.プログラムで探索したろ、と思ったのですが、うまく書けなくて泣いちゃいました(2変数なので手動でも全然見つかる).

 連立方程式を解くところとか、いくつ方程式をとればいいか実際はわからなくね?と思いました.次元削除や高次の特徴追加の影響でエスパーするの結構厳しそうに見えるんですが、実際はどうするんですかね(OSINTとか?).詳しい話は以下の論文に乗っているようなので、興味のある方はぜひ.

arxiv.org

さいごに

 めちゃめちゃ楽しかったです.やっぱり実際に動かして遊ぶのは楽しいですね. 最後になりましたが、運営・講師・参加者の皆様ありがとうございました.

yoshi-camp 参加記

はじめに

 2日間行われたyoshi-campを無事終了したので、参加記を書きます. 内容としては、angr講座、マルウェア解析・フォレンジック講座を主にしました. 2日目には少々早く終わったので、pwnを解く時間もありました.

事の発端

 僕がセキュキャンに落ちたんですが、なんとptr-yudaiも(チューターに)落ちてました.

 こんな感じから、どっかでやるか!となりました. その会場が運悪く用意できなくて困り果てていたところを、阪大の教授、学生の方々のご厚意という形で部屋を貸していただきました.(ありがとうございますっっっっっ) yoshi-campは9時~18時だったのですが、家が少々遠くて早起きがしんどかったです. 早起きもセキュキャンっぽさがあって、また一興ということでよいとします.

day1 angr講座(シンボリック実行入門)

 yoshi-campの開幕を飾るのは、ふるつきが講師のangr講座でした. この講義では、主にCTFの問題をangrで解ける範囲を増やそうという目的で行われました. 基本的には、angrの機能解説→問題解くの流れでした. 問題はharekazeCTF, InterKosenCTF, angr_ctfの問題を用いて練習しました.

 簡単な使い方や制約のつけ方、アドレスや関数に対してフックする方法を学びました. angrは得意な形かどうかを見極めて使ってあげることが大切ですね.

 今回の講義で生み出された簡単なanti angrをptr-yudaiが公開しているので、そちらもぜひ.

ptr-yudai.hatenablog.com

day1, 2 マルウェア解析・フォレンジック講座

 1日目の後半ちょっと+2日目にかけて行われたのは、ptr-yudaiが講師のマルウェア解析・フォレンジック講座でした. (実際に使われた)マルウェアに感染した疑いのあるマシンのディスクダンプがあるので、重要ファイルの復元、マルウェア抽出、マルウェア挙動解析をすることを目的に行われました.

 vmの容量が足りなくて、10Gのディスクダンプが取れなかったりしましたが、メインのマルウェアの挙動解析は一通りできました.

 ディスクダンプは先頭0x20e00バイト壊されていて、謎の文字(PRINCPES)やごみで埋められています. ファイルの復元には、先頭だけ壊されているので、ファイルの真ん中や後ろにあるメタデータを用いるMetadata Carvingで復元します. その後、マルウェアを抽出する作業に移るのですが、今回は謎の文字でgrepするとマルウェアっぽいexeファイルを見つけることができます.(ここまで1時間くらい)

 このマルウェアを静的解析していくのですが、ひたすらidaさんで読んでいきます. これがまた、CTFのrevと違って読みにくい...(号泣)関数の呼び出しとかが気持ち悪くて、アドレスで呼んでいてidaが認識できないです. そのため、アドレスの先を計算して、ジャンプ、idaに認識させる、という作業をします. これで、idaは関数を認識することができましたが、callが死ぬほど読みにくくて何の関数を読んでるか(ぱっと見では)わからないです. これを解決するため、構造体を定義してidaに定義した名前を認識できるようにしてあげます. idaで構造体を定義して読みやすくするのは、とても勉強になりました.

 そんな感じで、ひたすら変数のrenameやアドレス計算、コメントをつけたりをたくさんしました(白目). 頑張っていくと、MBRパーティションをPRINCPESで埋めたりしているところを見つけ、シャットダウン処理までたどり着きました.

 あと1時間多く解析していれば、頭がもげるところでした.あぶなかった...

extra pwnタイム

 2日目終了の18時まで時間があまったので、pwnの問題を解く会が急遽開催されました. 3,4問あったのですが、そのうち典型的なbuffer overflowとropを使う問題を(ヒントをちょいちょいもらいつつ)解きました.

 ptr-yudaiがいた時期の身内CTF感があって、楽しかったです(マルウェア解析地獄から抜けたので楽しさ100倍).

さいごに

 元同期やWaniHackaseの方( Hi120ki (@hi120ki) | Twitter )、阪大の教授の方、ありがとうございました.また、講師の2人も楽しい(鬼畜)の講義、ありがとうございます. やっぱり、リアルで集まって集中的にやる分には、鬼畜講義の方が盛り上がりますね.

 次回開催も十分可能性としてあるので、楽しみです(次回はzer0ptsでやりたいな~なんて言ってますが...). 来年は、セキュキャン最後の年なので何としても行きたいですが、院死もあるので何とも言えないですね.

 2日間本当にありがとうございました.お疲れ様です.

InterKosenCTF 2019 で作問した

 チームinsecureとして、InterKosenCTFを8月11~12日に開催しました. 作問は主にptr-yudaiふるつきがしていたのですが、僕も2問作問して出題したので、想定解を簡単に書きたいと思います.

運営メンバーの記事やwirteup集など

ptr-yudai: InterKosenCTF 2019で作問しました - CTFするぞ

ふるつき: InterKosenCTF2019 開催記 - ふるつき

writeup集: InterKosenCTF2019 writeups - HackMD

問題: GitHub - theoldmoon0602/InterKosenCTF2019-challenges-public

[Forensics] Hugtto!

 easyなステガノ問題として出題しました. この問題は、身内CTFで僕が作った超絶簡単ステガノを見たふるつきが助言をくれて作られたものです. 想定解としては、randomのseedをtarやpngの生成時間から予想できるため、どこに埋め込まれているかわかるというものでした. 非想定解もありましたが、解くのがとても簡単になるようなものではなかったのでセーフです. ただ、出題者の意図としては、randomのseedがわかるとrandomを再現できるよーといったところです.

[Crypto] pascal homomorphicity

 hardとして出題しましたが、midiumのFlag Ticketより解かれたし、hardではなくmidiumで出すべきだったと反省しています. まあ、このtag付けをミスっても問題ないのがdynamicスコアのいいところですね!

 当初、ふるつきがpaillier暗号の面白い原理 c=(1+n)^ {m} \bmod{n^ 2}=1 + m\ast n \bmod{n^ 2}を使った問題を出す予定だったのですが、その問題をテストしたときに僕が思いつき改変した問題です. ふるつきの時は c=(1+m)^ {flag} \bmod{m^ 2}(m.bits > flag.bits) mを入力できる問題でした. これだと、原理さえわかれば秒で解けるし、paillier暗号の形ではなかったのでいじりました.

 想定解としては、

  1. 原理に気付く(2項定理や問題文でググるpascal paillierさんが出てくるのでなんとかpaillier暗号にたどり着く)
  2. 暗号文を2つ用意して、原理より gcd(c_1 - 1 , c_2 - 1)=gcd(m_1\ast n, m_2\ast n)=n nを求める
  3. 初めに暗号化されたフラグがあるので、 nがわかっているとやるだけ

でした. 非想定解ではテストのとき、ptr-yudaiが二部探索して解いてました.

 個人的にはフラグ(KosenCTF{Th15_15_t00_we4k_p41ll1er_crypt05y5tem})が絶望的に読みにくいのが残念でした.(無理にリートにしなくてよかったな...) しかし、楽しんでもらえたようでよかったです.

さいごに

 前回のInterKosenCTFよりはお手伝いできたので良かったです. でも、運営中のログ管理、スコアサーバ周りはふるつきとptr-yudaiが2人でしているので、僕も手伝えるぐらいにならないといけないですね(今僕が触ると壊すし、なんもわからん). てか、彼らは一からツールを作ったりしていて、マジですごいのでもっと褒めてあげてください.

 今回がopenなCTFで初作問だったのですが、アンケートで面白いと答えてくださりとてもうれしいのと、ほっとしています. 次回はWinterKosenCTFがあるのですが、こちらは難易度が高めになっているので、作問できるかなといった感じですが、頑張っていきます.

 最後になりましたが、運営メンバー、参加者の皆様、スポンサーの皆様、ありがとうございました.

CyBRICS CTF Quals 2019 Writeup

CyBRICS CTFが7月20~21日に開催されていたので、zer0ptsとして参加しました. 結果は69位で、解いた問題は3つでした.

チームメンバーのWriteup

st98: CyBRICS CTF Quals 2019 の write-up - st98 の日記帳

ptr-yudai: CyBRICS CTF 2019 Writeup - CTFするぞ

[Rev 10pts] Oldman Reverse

以下のアセンブリファイルが渡されます.

.MCALL  .TTYOUT,.EXIT
START:
    mov   #MSG r1 
    mov #0d r2
    mov #32d r3
loop:       
    mov   #MSG r1 
    add r2 r1
    movb    (r1) r0
    .TTYOUT
    sub #1d r3
    cmp #0 r3
    beq     DONE
    add #33d r2
    swab r2
    clrb r2
    swab r2    
    br      loop      
DONE: 
    .EXIT

MSG:
    .ascii "cp33AI9~p78f8h1UcspOtKMQbxSKdq~^0yANxbnN)d}k&6eUNr66UK7Hsk_uFSb5#9b&PjV5_8phe7C#CLc#<QSr0sb6{%NC8G|ra!YJyaG_~RfV3sw_&SW~}((_1>rh0dMzi><i6)wPgxiCzJJVd8CsGkT^p>_KXGxv1cIs1q(QwpnONOU9PtP35JJ5<hlsThB{uCs4knEJxGgzpI&u)1d{4<098KpXrLko{Tn{gY<|EjH_ez{z)j)_3t(|13Y}"
.end START

r3はループ回数に使われてそうで、r1, r2はMSGをごちゃごちゃしてるな~という認識です. 33をr2に足しているので、1文字目、34文字目、67文字目、....とMSGを参照してそうです. あとは、文字列の長さを伸ばしてあげて、pythonでやってあげます.

>>> msg = "cp33AI9~p78f8h1UcspOtKMQbxSKdq~^0yANxbnN)d}k&6eUNr66UK7Hsk_uFSb5#9b&PjV5_8phe7C#CLc#<QSr0sb6{%NC8G|ra!YJyaG_~RfV3sw_&SW~}((_1>rh0dMzi><i6)wPgxiCzJJVd8CsGkT^p>_KXGxv1cIs1q(QwpnONOU9PtP35JJ5<hlsThB{uCs4knEJxGgzpI&u)1d{4<098KpXrLko{Tn{gY<|EjH_ez{z)j)_3t(|13Y}"
>>> (msg*5)[::33]
'cybrics{pdp_gpg_crc_dtd_bkb_php}09|z1Cn'

フラグはcybrics{pdp_gpg_crc_dtd_bkb_php}でした.

[Cyber 10pts] Zakukozh

This image containing flag is encrypted with affine cipher. Scrape it

イメージファイルがアフィン暗号で暗号化されているみたいです. 軽くアフィン暗号について説明すると、


Enc(x) = (ax + b) \bmod{p}

\begin{eqnarray}
Dec(x) &=& a^{-1}(x - b) \bmod{p}
\end{eqnarray}

のような、暗号化、復号が行われます.a, b, pがパラメータとなり、これを見つけると復号できます. アフィン暗号は既知の平文があると、そこからパラメータを推測できるので、イメージファイルのマジックナンバーから推測します. イメージファイルといっても、いくつかあるのですが、暗号化データを見る感じではpngっぽいです.

マジックナンバーに0x00の部分があるので、そこを見るとbが0x59であることがわかります. また、暗号化データの最大値からpも推測でき、pが256であることがわかります. 残るパラメータはaのみです. aはbとqがわかっているので、適当に小さめな値から求めることができます. ここでは、マジックナンバーの0x0aに注目したとすると、暗号化データでは0xefになっていました. そのため、


\begin{eqnarray}
239 &=& (10a + 89) \bmod{256} \\
150 &=& 10a \\
a &=& 15
\end{eqnarray}

となり、aがわかります(modは超えていないだろうという推測で無視しています...). あとは、復号するだけです.

from Crypto.Util.number import inverse

with open("./zakukozh.bin", "rb") as f:
    data = f.read()

a = 15
b = 89
q = 256
inv_a = inverse(a, q)

m = bytearray([])
for c in data:
    m.append(inv_a * (c - b) % q)

with open('./flag.png', 'wb') as f:
    f.write(m)

flag.pngを表示すると、フラグが書いてました. cybrics{W311_C0M3_2_CY13R1C5}

[Forensic 10pts] Tone

youtubeに電話を掛けるときのボタン音が投稿されていました. はじめは、気合で読もうとしたのですが、4,7が低音、2,5,8が中音、3,6,9が高音までしか分からなくて、細かい音の違いが分からなくて泣いていました. そこで、ptr-yudaiがスペクトル解析をしてくれました. スペクトル解析すると、おおよそ正しい数字がわかるので、あとは文字にあてはめます(おおよそなので単語になってなさそうなところをエスパー).

cybrics{secrettonalflag}

録音して波形を見る、という考えになる前に泣いてしまったのが負け

さいごに

はやく夏休みなんねーかな

InnoCTF International 2019 Writeup

 7月13~14日にInnoCTFが開かれていたので、zer0ptsとして参加しました. チームとしては、(多分)9位でした. 終了後スコアサーバーがすぐ落ちたので(は???)、昼頃に見たときの順位です. 僕はwelcom問題含む3問を解きました. 今回Cryptoはguessingばかりだったので、つらかったです.

チームメンバーのWriteup

st98: InnoCTF International 2019 の write-up - st98 の日記帳

[Crypto] One Hundred Time RSA

 nとcが渡されます. 情報はこれだけで、ソースコードはないです.

 nが大きくないので、簡単に素因数分解できます. これでpとqが手に入ったのですが、eがわかりません. 0x10001や3、100(問題名から)を試してもうまくいきません.

 ここで一旦ロシア人になると、eを総当たりしつつ、100回復号を繰り返すという発想に至ります. たしかeが34800とかだった気がします. 結構時間がかかりました.

from Crypto.Util.number import inverse
from binascii import unhexlify

p = 37975227936943673922808872755445627854565536638199
q = 40094690950920881030683735292761468389214899724061
n = p*q
phi = (p-1) * (q-1)

e = 1
while True:
    c = 594147643758126272722748149715320287571901225730250492908477114410071694555274921111773337859009576
    if e % 100 == 0:
        print("[+] now public exponents is :", e)
    d = inverse(e, phi)
    e += 1
    for i in range(100):
        c = pow(c, d, n)
        try:
            m = unhexlify(hex(c)[2:])
            if b"InnoCTF" in m:
                print(m)
        except:
            pass

InnoCTF{cr4ck_rs4_4g41n_7bca}

[Crypto] RF

 暗号文I3_naseincamno_r15Ct_t0T07_}Fnhs{1が渡されます.

 たしか、問題文が「フェンスの上で見つけた」みたいな感じでした. フラグのフォーマットや問題文から推測するに、Rail fence cipherですね. 適当なソルバーに投げてやると、見つかります.

InnoCTF{n0t_ca3sar_7h1s_t1me_in50}

 keyは8でした.

さいごに

 えっっ、guessing過ぎません!? Cryptoはたいていの問題みたんですけど、guessing祭りでした.

 チームメンバー各位お疲れ様でした.

HSCTF 6 Writeup

 6月3~8日にHSCTFが開催されていたので、参加しました. といっても、存在に気付いたのが7日の昼だったので今回はyoshikingdomというチームで参加しました. zer0ptsのメンバーにregister情報投げると、案外みんな参加してくれました. その結果、

f:id:y05h1k1ng:20190608123849p:plain

でした. プロがぽんぽこ解いていって怖かったです. クソみたいな名前じゃなくて、結果zer0ptsでもよかったなと思います.

 登録した張本人はというと、easyなCryptoを2問解いて、寝てました(午後授業フル+バイトだったから許して☆). その2問のWriteupを書いていこうと思います.

チームメンバーのWriteup

theoldmoon0602: HSCTF 6 writeup - ふるつき

ptr-yudai: HSCTF 6 Writeup - CTFするぞ

st98: HSCTF 6 の write-up - st98 の日記帳

[Crypto 130pts] Reverse Search Algorithm

n, e, cが渡されます.

n = 561985565696052620466091856149686893774419565625295691069663316673425409620917583731032457879432617979438142137
e = 65537
c = 328055279212128616898203809983039708787490384650725890748576927208883055381430000756624369636820903704775835777

nが大きくないので、素因数分解してみると、

n = 29 * 19378812610208711050554891591368513578428260883630885898953907471497427917962675301070084754463193723428901453

でした. あとは、やるだけです.

Python 3.5.2 (default, Nov 12 2018, 13:43:14) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from binascii import unhexlify
>>> from Crypto.Util.number import inverse
>>> p = 29
>>> q = 19378812610208711050554891591368513578428260883630885898953907471497427917962675301070084754463193723428901453
>>> e = 0x10001
>>> n = 561985565696052620466091856149686893774419565625295691069663316673425409620917583731032457879432617979438142137
>>> n == p*q
True
>>> c = 328055279212128616898203809983039708787490384650725890748576927208883055381430000756624369636820903704775835777
>>> d = inverse(e, (p-1)*(q-1))
>>> m = pow(c, d, n)
>>> unhexlify(hex(m)[2:])
b'hsctf{y3s_rsa_1s_s0lved_10823704961253}'

hsctf{y3s_rsa_1s_s0lved_10823704961253}

[Crypto 190pts] Super Secure System

 メッセージを投げると、暗号化されたメッセージが返ってくるシステムです.

$ nc crypto.hsctf.com 8111
* * * SUPER SECURE SYSTEM * * *
My encryption system is impossible to crack if used once!
You can use this system to encrypt any of your messages with my super special key!!!
Here is my super secret message: 20235d3e4e162a732e35177c22044e013179111e42530b3b124f31490b753f5c6c7b47347a5f5a112e74772b2c0a776f6c1b680630

Enter the message you want to encrypt: aaa 

Encrypted: 29315f

Enter the message you want to encrypt: bbb

Encrypted: 2a325c

Enter the message you want to encrypt: a

Encrypted: 29

 ちなみに、暗号化は何回でもできます. xorぽいので確認すると、

>>> ord('a')^0x29
72
>>> ord('b')^0x2a
72

 あたりです.また、2文字目、3文字目は別の数字でxorされていることがわかります. 方針としては、フラグの長さ分aを送り、返ってきた値とaでxorを取り復号していきます.

from ptrlib import *

sock = Socket("crypto.hsctf.com", 8111)

sock.recvuntil("Here is my super secret message: ")
c = int(sock.recvline().strip(), 16)

flag_len = len(hex(c)[2:]) // 2
sock.recvuntil("Enter the message you want to encrypt: ")
sock.sendline(b"a"*flag_len)

sock.recvuntil("Encrypted: ")
recv = int(sock.recvline().strip(), 16)
flag = ""
for i in range(0, len(hex(c)[2:]) - 1, 2):
    a = ord('a') ^ int(hex(recv)[2:][i:i+2], 16)
    flag += chr(a ^ int(hex(c)[2:][i:i+2], 16))
print(flag)

hsctf{h0w_d3d_y3u_de3cryP4_th3_s1p3R_s3cuR3_m355a9e?}

 初めxorに気付けなかった...

終わりに

 全然仕事してないじゃん!一応Crypto担当としているので、クビになる前に強くなります. チームメンバー、運営・参加された方々お疲れさまでした.