【write-up】SECCON BeginnersCTF【[Rev]ghost】

前書き

SECCON BeginnersCTFから既に一週間近くが経過してしまいましたが、未だに後追いをしています。やらなきゃいけないこと、やりたいこと等山積ですが、のんびりやっていきたいと思います。あと、個人的な感想ですが、この問題はReversingというよりかはMisk感の方があったかなぁと言う気がします。

write-up

よく分からないソースコードと出力ファイルが渡される。written by a ghost 👻とのことで、調べてみるとGhostscriptのようである。gsコマンドで実行できるので、実行し、ctf4b{と入力してみる。 f:id:yamanobori_programing:20200601181940p:plain
output.txtの先頭部分と一致する。以下、一致する文字をブルートフォースで探索するスクリプトを作成し実行する。

import subprocess

cmd='gs chall.gs'
flag='ctf4b{'
echo='echo'
strBase='_!$%&0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz}'
decLaw=[]

FILE=open('output.txt','rt')
dec=FILE.read()
FILE.close()

decLaw=dec.split(' ')

for i in range(len(decLaw)-7):
    for j in range(len(strBase)):
        flagTmp=flag+strBase[j]

        run1=subprocess.Popen(cmd,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
        run2=subprocess.Popen([echo,flagTmp],stdin=subprocess.PIPE,stdout=run1.stdin)
        output=run1.stdout.read().decode('utf-8')
        
        output=output.split('\n')
        tmp=output[4].split(' ')
        if( decLaw[:len(tmp)-1]==tmp[:-1] ):
            flag+=strBase[j]
            print(flag)
            break
        run1.kill()
        run2.kill()

subprocessを用いることで新にプロセスを生成したり、入力やその出力結果を取得することが出来る。詳しくはドキュメントを参照。このスクリプトを動かすとflagを得る。
ctf4b{st4ck_m4ch1n3_1s_4_l0t_0f_fun!}

【write-up】SECCON BeginnersCTF【[Misc]emoemocode】

前書き

Revが2問続いていたので、箸休めのMiscです。

write-up

渡されたファイルを開くと🍣🍴🍦🌴🍢🍻🍳🍴🍥🍧🍡🍮🌰🍧🍲🍡🍰🍨🍹🍟🍢🍹🍟🍥🍭🌰🌰🌰🌰🌰🌰🍪🍩🍽って感じで絵文字。それぞれの絵文字がascii文字と対応しているんだろうと踏んで、適当にctf4b{deadbeef}と書かれたテキストファイルを作成してバイナリエディタで比較してみる。 f:id:yamanobori_programing:20200531170031p:plain
絵文字の下1バイトとctf4b{を眺めてみるとなんとなく対応しているように見える。Pythonord()unicodeを取得し、ctf4b{のそれぞれのasciiコードとの差分を取得し、デコードする。

emoji='🍣🍴🍦🌴🍢🍻🍳🍴🍥🍧🍡🍮🌰🍧🍲🍡🍰🍨🍹🍟🍢🍹🍟🍥🍭🌰🌰🌰🌰🌰🌰🍪🍩🍽'
flag=''

for i in range(len(emoji)):
    flag+=chr(ord(emoji[i])-0x1f300)

print(flag)

ctf4b{stegan0graphy_by_em000000ji}

【write-up】SECCON BeginnersCTF【[Rev]yakisoba】

前書き

日曜日にCTFを放り出して何をしていたかというと、洋服と靴を買いに行っていました…。来月のカード支払いが恐ろしい…。 土曜日に何をしていたかは秘密です。

write-up

問題文と、ヒントのYou'd better automate your analysisからangrの使用を連想します。angrについて軽く説明しておくと、angrとは、Pythonで記述されたバイナリ解析用フレームワークで、以下のようなことができるとされています。
- 逆アセンブル - シンボリック実行
- コントロールフロー分析etc...
angrの記事はまた別の機会に書こうと思うので、今回はこの問題に特有の部分のみ抜粋して書いていこうと思います。例のごとくfileコマンドで色々と…。 f:id:yamanobori_programing:20200529134027p:plain
ELF-64bitでstriped、stripedではあるものの、IDAでmain関数を確認することが出来る、たまにできたりできなかったりする違いは何なのだろう?逆アセンブル結果を見てみると、mov eax 0xor eax eaxに書き換えられていたり、呼び出し先の関数がスパゲティーコード化されているなど、明らかに難読化されているっぽい…。 f:id:yamanobori_programing:20200529161731p:plain
過去のwrite-upを参考に本問題のwrite-upを作成していきます。参考にしたwrite-upは以下の二つになります。(と言っても少し書き換えただけですが…)
ox0xo.github.io qiita.com
少し書き換えただけのものを一応二つアップしておきます。

import angr

project = angr.Project('./yakisoba')
entry = project.factory.entry_state()
simgr = project.factory.simgr(entry)
simgr.explore()

states = simgr.deadended
for state in states:
    flag = b"".join(state.posix.stdin.concretize())
    print(flag)
import angr

p=angr.Project('./yakisoba')
state=p.factory.entry_state()
sim=p.factory.simulation_manager(state)
sim.explore(find=0x4006d2,avoid=0x4006f7)
if(len(sim.found)>0):
    print(sim.found[0].posix.dumps(0))

これを走らせるとflagを得る。
ctf4b{sp4gh3tt1_r1pp3r1n0}

スクリプトについて

この問題をやってみての率直な感想は、「今までやってたRevの問題って(まぁ自覚はしてたものの)あんまり大したことない問題だったんだなぁ」ってこと。キャンプの立ち話でangrとかmiasmとCTFの話については少ししたのですが、それからCTFのRev問題でangrとか使うような事もあまりなかったことと、キャンプ以降少しセキュリティから離れた世界線を生きていたので、今回の問題はRevの範囲でも今まで触れたことが無い問題で新鮮味がありました。なるべく多くの事を吸収してから次の問題に進みたいと思います。今回参考にしたwrite-upについては、ほぼほぼ使いまわしな感じがするので、とりあえず、この節では、このスクリプト内でどんな動作が行われているかを確認して、次の問題に移りたいと思います。
先のスクリプトについて、以下のコメントの様にまとめ、解説していきたいと思います。

import angr

project = angr.Project('./yakisoba')                   #load
entry = project.factory.entry_state()                   #entry
simgr = project.factory.simgr(entry)                    #simgr
simgr.explore()                                         #exp

states = simgr.deadended                                #deadended
for state in states:
    flag = b"".join(state.posix.stdin.concretize())
    print(flag)
import angr

p=angr.Project('./yakisoba')                   #load
state=p.factory.entry_state()                   #entry
sim=p.factory.simulation_manager(state)         #simgr
sim.explore(find=0x4006d2,avoid=0x4006f7)     #exp
if(len(sim.found)>0):
    print(sim.found[0].posix.dumps(0))

load

angrにおけるバイナリのロードは

project=angr.Project('filepath')

によって行われています。それだけ。

entry

state=p.factory.entry_state()

によって、エントリーポイントにおける実行ファイルの状態を表すobjectを返します。ドキュメントとか見てると、state.regs.ripレジスタの値を取得したりしているので、色々値を取得できるっぽい?

simgr

APIドキュメントによれば、simgrsimulation_managerは全く同じものの様です。(じゃあ何で二つ存在するんだ...)これによって新たなsimulation_managerを構成できます。simulation_managerの概念的な理解は、この図で出きると思います。

f:id:yamanobori_programing:20200531140846p:plain
引用:https://hackmd.io/@K-atc/HJmVUH4Rb?type=view#Simulation-Manager
何となくは理解できるけど、やはりもう少し理解を深めるためにはシンボリック実行自体の理解が必要なように思われる…。

exp

explorメソッドで任意のアドレスに到達して、かつまた任意のアドレスに到達しないような状態を取得することが出来ます。findやavoid以外にも引数をとることが出来ますが、今の僕では説明し切れないのでまた次の機会に…。

deadended

stashはいくつかの状態をとることが出来ますが、deadendedはその中のうちの一つで、何らかの理由でラウンドが継続できなくなったときにこの状態になるようです。(参考にしたスクリプトは探索終了時にそ明示的に探索の終了を表すためにdeadendedを与えているのでしょうか?)
angrやシンボリック実行については、まだよく分からない部分の方が多いので、少しづつ理解を進めていこうと思います。

【write-up】SECCON BeginnersCTF【[Rev]mask】

前書き

5/23~24にかけて開催されていたSECCON BeginnersCTFに参加するべく全裸待機していたのですが、何やかんやあって結局参加できず…。後で解き直せそうな問題は何問か回収してきたので、これをシコシコとやっていくことにします。やっていく問題は以下。
- [Misc]emoemoencode
- [Crypto]R&B
- [Rev]mask
- [Rev]yakisoba
- [Rev]ghost
- [Rev]siblangs
- [Rev]sneaky
- [Pwn]Beginner's Stack
- [Pwn]Elementary Stack
- [Pwn]ChildHeap
- [Pwn]flip
あと、write-upはどこまで詳細に書くべきか非常に迷うのですが、今回は自分がとった行動をなるべく詳細に書いていこうと思います。

write-up

バイナリが渡されるのでfileコマンドで基本的な情報を確認する。 f:id:yamanobori_programing:20200528223947p:plain
ELF-64bitでnot striped、IDAでコントロールフローを確認する。バイナリを動かしてみると、入力された文字列対して何らかの操作が行われているので、この操作の部分を特定することにする。main関数以外にユーザー定義の関数が見当たらないので、main関数内を見てみると、以下のベーシックブロックを得る。 f:id:yamanobori_programing:20200528224952p:plain
入力文字列に対して、0x75と0xebでand演算を行い、その結果がそれぞれ別のアドレスに保存されている。すべての入力文字にmaskをかけた後のベーシックブロックを見てみると、先にmaskをかけた2つの文字列がそれぞれatd4`qdedtUpetepqeUdaaeUeaqauc`b bk`kj`KbababcaKbacaKiackiに等しいかをstrcmp関数で確認している。 f:id:yamanobori_programing:20200528225815p:plain
f:id:yamanobori_programing:20200528225840p:plain
よって、以下のスクリプトで元の文字列を求める。

#convert binary and conbine them

#0x75 = 0111 0101
#0xeb = 1110 1011

string1="atd4`qdedtUpetepqeUdaaeUeaqau"
string2="c`b bk`kj`KbababcaKbacaKiacki"
flag=""

for i in range(len(string1)):
    char1=string1[i]
    char2=string2[i]

    flag += chr(ord(char1)+((0x8a)&ord(char2)))

print(flag)

ctf4b{dont_reverse_face_mask}

【Rev・バイナリ解析関係】strippedなバイナリからメイン関数を探す【Rev】

前書き

この記事の誤り・誤解を招く表記を発見した場合にはTwitterまでお願いします。

CTFでは主にRevをちょこちょことやっているのですが、よくstrippedなバイナリに出会うことがあります。今まで何となくmain関数を見つけてやっていたのですが(解けたとは言ってない)、なんかもっとまともなmain関数の見つけ方はないものだろうか...と考えていました。今回main関数のアドレスの見つけ方がようやくわかった気がしたので備忘録として残しておきます。多分プロCTFerの方からしたら常識みたいなところがあると思うのですが...

radare2を使う(一つ目の方法)

radare君は優秀なようで、strippedなバイナリを投げてもmain関数を見つけてきてくれます。やったね!

evtrypoint以降で呼び出されている_libc_start_mainの第1引数を参照する(二つ目の方法)

entrypointはreadelfで参照するなりIDAで解析した時のstart(_start)が対応します。このstartでは最終的に_lib_start_mainを呼び出しています。この時の第一引数にはmain関数のアドレスが格納されているので、main関数の解析時にはこのアドレスにbreakpointなりを置くとよいでしょう。

【雑記(分類不可)】やっておきたい事【やりたいことリスト】

前書き

就活もひと段落したわけですが、その間に色々やりたい事、やり残してきたこと等々あるので、とりとめもなく書いていこうと思います(やりたいことが増えたらここに追加していこうと思います)

やりたい事リスト

大変お恥ずかしながら、セキュリティキャンプの技術的なまとめが出来ておりません...。半年以上前のことなのに...、ぴえん🥺終了直後はTeXで論文形式にしてまとめると意気込んでいたのに、時間を作り出すのに失敗してしまいました...。キャンプのSlackやもらった資料を基に記憶をたどっていきたいと思います。

そんなこんなであわただしくキャンプは終わったのですが、講師の方から昨年の資料を頂いていたのでしばらくそれで遊んでいた時期がありました。プログラム自体は2/3程完成していたのですが、若干時間が空いてしまったので、随所随所を思い出しながら完成させていこうと思います。

上のプログラムを作成していく中で「フルスクラッチでパッカーを作りたいなぁ」と思うようになり、ELFのパッカーをフルスクラッチで作ろうと考えています。(最終的には GitHubで公開したいけど、公開していいものかというところは大きい。)(お気づきかもしれませんが、講師の方からもらったものというのは、つまりはそういうことです。)パッカーは最終的にはVM型のものとかも作ってみたいんですけどねぇ...。これ書きながら自作エミュレータ本をやりたいと思っていたことを思い出したのでリストに加えておきます。あと自作OS本も。(あんまり自作OSやりたいと生半可な気持ちで言うと奈落の底に突き落とされるというのをどこかで聞いたことがあるが...)そういえばこれを書いてる時点で友人が「バイナリアンは変態が多い」といってるのを思い出した。理由は必死にエロゲの解析妨害を突破しようとするからだそう。

コンウェイ先生がCOVID-19でお亡くなりになられました。元々数学科を志望していたこともあって、コンウェイ先生がこの世を去られたことは、やはり重みをもって感じられます。CTFでも何度か題材として登場していたライフゲームC++で実装していきたいと思います。なぜC++なのかというと、大学の講義でやったC++を思い出していくということと、その中の演習問題にC++の実装の演習問題があったからです。(ちなみに、このC++の教科書は、この講義を担当されていた教授自ら執筆なさったものです。)

技術書を買い込んではさらに買い込むをしていたので、だいぶ技術書がたまっています。就職するまでに技術書を消費しておいて、いざ働きだしたときにある程度の技術を備えておきたい...

就職先はまぁまぁ大きい組織なのですが、そこでIPAの資格(情報処理安全確保支援士があれば最高)を持ってると配属の決定時にまぁまぁ効力を発揮しそうなのでこれ取得していきたいと思います。情報処理安全確保支援士があれば最高ですが、時間も限られているので、時間と試験内容と相談しながら決めていきたいと思います。

昨年2019年に二輪免許を取得したい機運が高まったので取得していきます。もっとも、昨今の状況下でいつになる事やらというところはありますが...

二輪免許を取得したらやはりどっか行きたくなるもので、だいぶ前に誘われていた北海道ツーリングと最近誘われた佐渡島ツーリングに行きたいと思います。大変お恥ずかしながら、新潟に居住しだして3年がたつものの、いまだに佐渡島に行ったことがないので、これを機に制覇していきたいと思います。最も、昨今の状況下で以下略。

まぁそんなこんなでいろいろやりたいことはあるのですが、如何せんやりたいことが多い。おまけに卒論もあるので、この1年は大分無理をしていくことになりそうです。卒論でパッカーのフルスクラッチ実装をOKしてくれれば一石二鳥なのですが...。やりたいことが増えたらまた追加していこうと思います。

※2020/5/4追加_Vulnhub

だいぶ前にKipotix level1をやって以来放置していたVulnhib、これに限らず触ってないCTFの分野も大分あるので裾を広げていきたい。

※2020/5/25追加_NISTのDFトレーニング教材

イエラエって会社はいい会社らしいのでデジタルフォレンジック勉強会で触れなかった問題をしこしことやっていく。

【お品書き】5月のお品書き【5月】

前書き

お久しぶりです。就活も無事終了し研究室も無事に決まったのでちょこちょことブログの方も再開していきたいと思います。今まではあったこととかをなんとなくブログに書いていくスタイルでやってたのですが、月の初めに目標とかやりたいことを設定して、それについての備忘録的な運用をしていくのもいいのかなぁと思ったのでしばらくこのスタイルで行こうと思います。需要あるか分からないけど、個人記とか山行記録についても少しづつ更新していこうと思います。

今月のお品書き

  • 卒業研究の具体的なテーマ決め
  • SECCON Beginners CTF 2020に出る(それまでにCpawCTF全完)
  • 就活エントリを書く(5/5)
    卒論はなんとなく難読化とかの解析妨害系の分野についてやろうと考えています。あんまり興味ない分野の研究もしたくないですし...。学位論文にどこまでのレベルのものが求められているのかもまだよく分かってない感があるので、そこら辺も教授とすり合わせていきたいと思います。
    毎年5月のSECCON Beginners CTFが今年もあるので出ます。(去年はちょうど弊部活の新歓登山とブッキングしてたのと、セキュリティキャンプの課題にリソースを全振りしてたので参加できなかった...)それまでにCpawCTFの方を全完しておきたいと思います。早く終わったら終わったでまたなんか考えます。(きっと積んである技術書の消費に回されると思うのですが...)
    冒頭でもお話したのですが、無事プー太郎を回避、だいぶ前から考慮に入れていた某に就職が確定したので、需要があるかも微妙ですが、就活エントリを書いていきたいと思います。(まぁ某にお伺いを立てて「ダメです」といわれたら書けないんですけど…)
    まぁそんな感じでブログの方も再開していきますので、「仕方ないから読んでやるかぁ」な聖人君子のような方でもいれば、今後ともよろしくお願いします。