人間になりたい人間になりたいなりたい。2022picoCTFのpicoGYM(過去に出題された問題)をポイントの少ない(基本的には難易度低)ものから解いていくチャレンジCTF超初心者なので、他のwriteupより冗長に丁寧に書くことを心がけます。Linux)を入れたものです。Cat(G,5)ダウンロードできるファイルは拡張子がありませんが、メモ帳で開くことができます。開くと、平文でflagが書かれていることが分かります。26(C,10)ROT13という文字の変換をするとflagを獲得できます。ググると変換できるサイトがあるので、使うと速いと思います。コマンド-dで実行させることで何かしらの処理がされることが分かります。if文の中をみると、encryptとかdecryptとか書いてあるので、それぞれ暗号化と複合化のコマンドなのではないかと予想できます。ende.pyを実行し、flagファイルをコマンド-dを使って復号化することでflagを取得できます。flag(G,10)warmというファイルを実行しろと言われるのでlinux上で実行します。deniedが返ってきます。(考えてみればWindowsにもありますね)permissionの概念に関してはhttps://qiita.com/takuyanin/items/18590600d077df707923が詳しいです。分かりやすく載っています。picoCTFの方のヒントだけ読むと何がなんだかわかりませんが、とにかくchmodコマンドを使ってpermissionの権限を変えると実行できるようになります。picoCTF{b1scu1ts_4nd_gr4vy_755f3544}nyan-picoctf@webshell:~$■Information(F,10)jpgファイルにはExifという情報があります。linux上でjheadというコマンドを使うとみることが出来る.........のですが、それを使ってみてもよく分からず、眠かったので諦めてkusuwadaさんのwriteupを読みました。https://tech.kusuwada.com/entry/2021/04/08/12120510点問題でも、もうそういう事するのか...。はい、、、精進します。netcat...(G,15)与えられたコマンドをlinux上で実行すると、3桁までの数字がたくさん出てきます。ヒントの通り、これらはASCIIコードを表していて、それぞれの数字に対応する文字があります。対応表に基づき、数字を文字に変換していくとflagがゲットできます。下記のようなコードを書けば一発で出てきます。https://wandbox.org/permlink/jTP97qZz8G2asTtN■Transformation(R,20)慣れていないと分かりにくいですが、encはencordの略、ということでエンコードされたflagの文字列を表しています。txtファイルで開くとよく分からない文字列が出てきていますが、問題文を読むと、flag[]から何らかの変換を受けて生成されたことが分かります。これに対応した逆変換をかけることで、flagが生成できます。(と共にvuln.cが添付されている)ということで、完全な死亡フラグっぽい文章があります。その通りで、このプログラムはsecureではありません。聞かれ、何かしらの入力をすると、それに応じて株が買われる仕組みに見えます。NMTGoodbye!~~~~~~~~~~~~~~一度購入するとそのまま終了するので、1を選んで購入した株はそれ以降見ることが出来ません。(1を入力し購入して、その次の実行で2を選んでも何も出てこない)よく分からないですが、1か2を入力、1を入力した場合に何かを入力、の部分しか悪さを出来る部分が無いので、この2つのどちらかがキーとなる可能性がある、程度に思っておきます。ソースコードは149行あり、すこし長い感じがします(競プロ視点)が、main関数から見ていきます。初期化条件はinitialize_portfolio()Portfolio型変数は、structを用いて15行目から18行目で宣言されている。*headを持ち、さらにこのStonkもstructを用いて9行目から13行目で宣言されている。*nextを持つ(自己参照構造体)。型の返り値を持つ関数。中身は、Portfolio型に必要なだけメモリ領域を確保し、moneyに1-2018の適当な値を、headはNULLとした(何も株を持っていない状態)変数pを出力するもの。ここで確保できなかった場合main関数の125行目から128行目でエラー出力をして終わる(基本起こらない)。実際に実行した時にも表示される「1か2を選択して、それに応じた処理をする」の部分。1を押すとbuy_stonks(p)が実行され、2を押すとview_portfolio(p)が実行されるようになっている。(main関数おわり)次に、buy_stonks(p)の中身を見ていきます。62行目から100行目で記述されています。63行目から65行目はpのメモリに何も値が入ってなかった時用のエラー出力。api_buf[FLAG_BUFFER]が宣言されています。フラグ文字列を入れるための変数であることを意味しており、臭います67行目でFILE変数に読み込み専用モード(r)でapiファイルを展開して、72行目でapi_bufにその内容を書き込んでいます。このapi_bufの中身が分かればフラグゲットです。74行目から85行目ではお金が無くなるまで何かしらのアルゴリズムで株を選んで買っていることが分かります。(randって文字が見えるので多分適当です)ただ、それだとすると、この次の入力で何をしているのかが謎です。89行目でuser_buf変数を301バイト分確保し、90行目から93行目では、scanfでuser_bufに文字を入れ、そのままprintfで出しているだけに見えます。ここで気づくのは、printfのフォーマット指定子が全くないことです。Bug"というものが存在することが分かります。Bugと呼ばれる脆弱性なのですが,このようにスタック上のデータを漏洩してしまうだけでなく,スタック以外でもメモリ上のデータを漏洩,改竄することが可能になります.だそうです。GLGoodbye!^C~~~~~~~~~~~~~~~~~~~~のように入力すると、%x指定子のおかげでスタックに入っているものが全部出てきます。o->0x6Fから始まる文字列がないかを探すと、、、6f636970を含む部分があります。エンディアンの関係で順番が逆になっているのでした。ここから始まる部分をASCIIコード変換してあげるとフラグゲットです。aHEAD(W,20)サイトを開くと、謎のBlueボタンとRedボタンが表示されています。ソースを開くと、それぞれGETメソッドとPOSTメソッドが行われていることが分かります。GET/POSTについてはこちらがわかりやすいです。https://qiita.com/7968/items/4bf4d6f28284146c288fとりあえずBurpSuiteを使えと言われているので使い方をhttps://www.as-lab.net/150713/このあたりのサイトで見てみます。このツールはHTTPリクエストの中身を覗いたり改ざんしたり出来るようです。パラメータを見ても怪しいところがありません。はて...というところでヒントを見ると、「選択肢は2つじゃないよ(もっとあるよ)」的なことが書いてあります。upしたのですが、問題のタイトルも加味して考えると、"HEAD"メソッドを試せということのようです。GETやPOSTとなっているところを直接HEADに書き換えてHTTPリクエストを送ってみると、Responseとして"NAME=flag"というパラメータが返ってきていて、その中にflagがあります。Qs問題文の通りRSA暗号を解く問題です。e->Eと読み替えます。N)よりDが求まれば解けます。pow(E,-1,(p-1)(q-1))で、pとqはNを素因数分解した時の2つの素数であるので、問題のキモはNを素因数分解すること。競プロでよくやる素因数分解のアルゴリズムはO(√N)かかってしまうため、80桁以上の素因数分解には向いていないです。入力することで解いてしまうことが多いようです。(どちらも今回のNの素因数分解が出来る事を確認しました)msieveで出た結果はこんな感じ。最後にこの結果を用いて、平文を出しますが、平文が10進数なので16進数に直しASCIIベースで文字に変換すると、答えが得られます。20pts)バイナリファイルの中を見ろと言われます。scriptが役に立つよ」と言われるので、併せて落としてみます。scriptはシェルスクリプトの一種でlinuxで叩くようなコマンド入力を自動化するものと理解しています。(ファイル名).ltdis.x86_64.txtとして出力します。.textはテキストセクションのみを表示するオプションです。(セクションが何なのかよく分かっていない。ここに書いてありそうな予感がします。読んでません)テキストセクションには定数が入っているみたいです。Cでいうmain関数とか。(よく分かっていない)その後、(ファイル名).ltdis.x86_64.txtが存在すれば、同じファイルに対してstringsコマンドを実施してテキストデータとして出力するように書かれています。stringsコマンドは、バイナリファイルの中にあるテキスト情報を抜き出して一覧表示してくれるもので、出力結果を見ていくとpicoCTF{から始まる文字列があるので、これでflagゲットです。staticをバイナリエディタで開き、"picoCTF"で検索するだけでも見つかります。40pts)ワンタイムパスワードに関する問題。keyの長さは50000っぽい?flagは文字列として、keyは"rb"指定なのでバイナリ(16進数)として取得。startup動作flagの長さ分だけkeyを取ってくる。flagの長さが32ならkeyのうち1文字目から32文字目を取ってくる。19行目にて、resultの中にlistとして『「flagを1文字ずつとったものをバイナリに変換したもの」と「keyを1文字ずつとったもの」のXORをとったもの』を入れていくこの結果を表示。shell上で下記のように表示される。文字を数えると32文字。(1byte文字が32文字なので、バイナリにすると64文字出力されている。flag!51466d4e5f575538195551416e4f5300413f1b5008684d5504384157046e4959encrypt動作(1回目)何か任意の文字列を入力する。uiuiとkeyに対してstartup動作と同様のことを行う。keyは再び最初から使うわけではなく、startupで使用したkeyの次の文字から使う。10なら、ここで使われるkeyは33文字目から42文字目まで。(key[32:42])同様にuiとkeyでXORを取ったものを表示encrypt動作(2回目以降)同様だが、keyは直前に使ったところの次から使用する。(正確には1回目でも起こるが)使用したkeyが50000文字に達すると、(34行目から36行目の記述)にあることが起こる。(★)ずっと勘違いしていたのですが、恐らくKEY_FILEの中身は実際には50000文字より長いので、このif文の中身が実行されるとき、実際にはkey[:stop]の部分は出てこないものと思われます。10の文字列を入力すると、ソースコード上はkey[49995:50000]+key[0:5]が出てくるように見えますが、実際にはlen[key]は50000より長いので、key[49995:50005]の文字が出力されていると思われます。以上の動作を考慮すると、50000文字分のkeyを正確に消費すれば、次に使うkeyは最初のflagの時に使ったものと同じになるはず。そのため、encrypt動作にてkeyを50000文字分まで消費した後、既知の文字列をuiとして入力し結果を出力すると、そこから鍵が逆算できます。resultを計算することでkeyを計算できます。https://tsalvia.hatenablog.com/entry/2021/04/08/110000#Easy-Peasy---40-pointsで紹介されているように、直接"0x00"をぶちこむことで、計算しなくても鍵を出す方法があるようです。keyになるという算段です。「"A"を50000文字入力しresultを出して、最後の32文字分を見る」というやり方をすると不正解になります。最後の32文字はkey[0:32]のつもりが、実際にはkey[50000:50032]が出力されているからです。(KEY_FILEが50000文字を超えていることの弊害。問題の不備では...)ともあれ、keyが分かりました。51466d4e5f575538195551416e4f5300413f1b5008684d5504384157046e4959です。これを計算し、最後にASCIIコードから文字列に変換すると32文字の1byte文字が得られます。≫コメント名前タイトルメールアドレスURLパスワード非公開コメント管理者にだけ表示を許可する本文トラックバックこの記事にトラックバックする(FC2ブログユーザー)プロフィールAuthor:にゃん自分のツイッターの発言を受けて話題を広げて自分をプレゼンします。・twitter@nya_______n(main)@nya__________n(音ゲ)その他に存在するのは捨てIDです。