しゃろの日記

CTFのwriteup置き場になる予定(`・ω・´)

School CTF Spring 2015 writeup

School CTF Spring 2015に参加しました。

14問解いて3050ptの6位(Non-School Teamsでの順位)でした(`・ω・´)

学生向けということもあり、さくさく解ける難易度でした(*´ω`*)


Affine Cipher(crypto:200pt)

出題当初は説明がよくわからない感じだったが、途中でアフィン暗号らしい問題に変更された。

対応表を作って終了。

alphabet = "abcdefghijklmnopqrstuvwxyz_"

dictionary = {}
alphabet.each_char{|c|
    dictionary[alphabet[(alphabet.index(c) * 4 + 15) % alphabet.length]] = c
}

puts "ifpmluglesecdlqp_rclfrseljpkq".chars.map{|c| dictionary[c]}.join
# => "flag_is_every_haxor_love_math"

FLAG:every_haxor_love_math

Super Digest 4(crypto:400pt)

class Hasher
    @@sd4_iv = 0
    @@sd4_block_size = 4
    @@sd4_alphabet = "abcdefghijklmnopqrstuvwxyz"
    def sd4(line)
        special_value = @@sd4_iv
        if line.size % @@sd4_block_size != 0
            line+="x"*(@@sd4_block_size - line.size % @@sd4_block_size)
        end
        (0...line.size).step(@@sd4_block_size) do |i|
            current_block = line[i..i+@@sd4_block_size-1].bytes
            special_value = sd4_round(special_value, current_block)
        end
        return special_value
    end
    def sd4_round(special_value, current_block)
        sum = current_block.inject(0){ |res, elem| res+=elem }
        sum += special_value
        return sum
    end
end

文字数が4の倍数になるように末尾に"x"をパディングした後、各文字のASCIIコードを合計したものをハッシュ値としている。

1ステージのみで時間制限もなく、solver書くのもめんどくさかったので手計算で解いた。

FLAG:sometimes_i_think_that_super_digest_is_not_so_super

Hidden file(forensics:200pt)

zipファイルの中には"F", "L", "A", "G", "I", "S"と1文字ずつ描かれた画像ファイルとThumbs.dbが入っている。

I deleted my pass, so dont try to hack me, dudes :d

とあり、ファイルシステム上は削除されていてもThumbs.dbの中に残っているような気がしたので、Thumbs.dbを覗けるツールを探してきて覗いたところ、
zipに入っていなかった画像ファイルのサムネイルがいっぱいでてきた。

FLAG:XP_WAS_SO_SWEET_FOR_HACKERS

Agreement by default(joy:100pt)

joyって何……?

"Where does a wise man hide a leaf? In the forest."

というヒントと共に謎のインストーラが渡される。

文字化けが激しいという以外は普通のインストーラと変わらないが、使用許諾の同意の後にインストールキーの入力を求められた。

インストールキーをクラックする案件? と思ったが、ヒントでピンときて使用許諾をよく見たところ、文中にフラグが紛れ込んでいるのを発見。

f:id:Charo_IT:20150503212350j:plain

FLAG:NoB0dy_Re@Ds_Agr33m3nt

Weird selfie(joy:100pt)

おっさんの写真が渡され、写真を撮った人物を答える問題。

こいつ誰やねん……とGoogle画像検索にかけたところ、Kevin Mitnick氏の情報が出てきた。

すごい人らしい(小並感)

FLAG:kevin_mitnick

Old school hacking(joy:200pt)

.NETで作られたマインスイーパ

ILSpyで見たところ、フラグ生成処理(文字列定数をくっつけるだけだが……)があった。

FLAG:Game_Maker_Not_For_Serious_Programmers

Tricky authorization(networks:200pt)

pcapファイル内にあったやりとりを再現したらフラグが返ってきた。

$ nc sibears.ru 11811
>>> R U redi keeds?
> Aye Eye pactain
CORRECT!
>>> I cant here U!
> cleen ur eARs 0ld f4rt!
CORRECT!
>>> Oooo00oO0h! Wh0 livs in a pain-appl undr the see?
> 5PuNGE bUb pnts^2!
FLAG: p1ain_tex7_is_sti11_p1ain_ev3n_if_its_tricky

FLAG:p1ain_tex7_is_sti11_p1ain_ev3n_if_its_tricky

School incident(reverse:150pt)

LOL, look at these stupid admins, bros! They set easy-breasy root password and store md5 of the password in /etc/shadow:

root@school:#cat /etc/shadow root:f505f1e49e98cea82c9c4265262444f6:14425:0:99999:7::: teacher:*:14425:0:99999:7:::
adm:*:14425:0:99999:7:::
...

MD5をクラックしてくれるサービスに投げる。

FLAG:i_am_admin

Strange program(reverse:300pt)

今回解いた問題の中で一番の問題児。

We have found the strange file named mascal.pas in one of directories on our server. Probably it is a source code of some program, but we can't understand its algorithm. Can you tell us its output?

Сценарii Добре_декодер_прапор;
Змiннi:
  прапор1, прапор2, прапор3, прапор4 : рядок;
  результат_прапор : рядок;
  позицiя : цiле число;
 
  Функцiя перевертати_рядок(гарний_рядок : рядок) : рядок;
  Змiннi:
     часовий_рядок : рядок;
     i, рядок_довжина : цiле число;
     ц : ієрогліф;
  Почати
    часовий_рядок := гарний_рядок;
    рядок_довжина := Довжина(часовий_рядок) + 1;
    Заради i := 1 до рядок_довжина дiлити 2 зробити
    Почати
      ц := часовий_рядок[i];
      часовий_рядок[i] := часовий_рядок[рядок_довжина - i];
      часовий_рядок[рядок_довжина - i] := ц;
    Кiнец;
    перевертати_рядок := часовий_рядок;
  Кiнец;
 
Почати
  прапор1 := 'АРОКАРП';
  прапор2 := 'ФАРГОНИЛЕЦ';
  прапор3 := 'ЗА-ХОП-ХЛОПЯ';
  прапор4 := 'ЖРУЖЕОБЛОМОВ';
 
  позицiя := Положення('-',прапор3);
  В той час як позицiя <> 0 зробити
  Почати
    Видаляти(прапор3, позицiя, 1);
    позицiя := Положення('-',прапор3);
  Кiнец;
 
  прапор1[4] := 'П';    
  позицiя := Положення('ОБЛОМ',прапор4);
  Видаляти(прапор4, позицiя - 1, Довжина('ОВ') + 1 + Довжина('ОБЛОМ'));
  Вписувати('БА',прапор4,Довжина(прапор4)+1);
  прапор4[1] := 'Д';
 
  позицiя := Положення('ХОПХЛОП',прапор3);
  Видаляти(прапор3, позицiя + 3, 4);
  Вписувати('ЛЕНН',прапор3,Довжина(прапор3));
 
  прапор2 := перевертати_рядок(прапор2);
  Видаляти(прапор2, 3, Довжина(прапор2)-2);
 
  результат_прапор := прапор3 + '_' + перевертати_рядок(прапор1) + '_' + прапор2 + '_' + прапор4;
  Написати_лiнiя(результат_прапор);
Kiнец;

適当な単語を選んでGoogle翻訳にかけてみたところ、どうもPascalのソースの変数名・関数名・予約語ウクライナ語にしたものっぽい。なんだそりゃ……。

とりあえずPascalに直してみた。

Program good_flag_decoder;
var
  flag1, flag2, flag3, flag4 : string;
  result_flag : string;
  policies : integer;
 
  function reverse_string(good_string : string) : string;
  var
     temp_string : string;
     i, string_length : integer;
     ts : char;
  begin
    temp_string := good_string;
    string_length := length(temp_string) + 1;
    for i := 1 to string_length div 2 do
    begin
      ts := temp_string[i];
      temp_string[i] := temp_string[string_length - i];
      temp_string[string_length - i] := ts;
    end;
    reverse_string := temp_string;
  end;
 
begin
  flag1 := 'АРОКАРП';
  flag2 := 'ФАРГОНИЛЕЦ';
  flag3 := 'ЗА-ХОП-ХЛОПЯ';
  flag4 := 'ЖРУЖЕОБЛОМОВ';
 
  policies := pos('-',flag3);
  while policies <> 0 do
  begin
    delete(flag3, policies, 1);
    policies := pos('-',flag3);
  end;
 
  flag1[4] := 'П';    
  policies := pos('ОБЛОМ',flag4);
  delete(flag4, policies - 1, length('ОВ') + 1 + length('ОБЛОМ'));
  insert('BA',flag4,length(flag4)+1);
  flag4[1] := 'Д';
 
  policies := pos('ХОПХЛОП',flag3);
  delete(flag3, policies + 3, 4);
  insert('ЛЕНН',flag3,length(flag3));
 
  flag2 := reverse_string(flag2);
  delete(flag2, 3, length(flag2)-2);
 
  result_flag := flag3 + '_' + reverse_string(flag1) + '_' + flag2 + '_' + flag4;
  writeln(result_flag);
end.

ideoneで実行してみたが、文字列変数にマルチバイト文字が入っているのがお気に召さないらしく、実行時エラーになってしまった。

仕方がないのでRubyで書き直し、フラグを出した。

class String
    def delete(start, count)
        self[0...start] + self[start + count...self.length]
    end
end

flag1="АРОКАРП"
flag2="ФАРГОНИЛЕЦ"
flag3="ЗА-ХОП-ХЛОПЯ"
flag4="ЖРУЖЕОБЛОМОВ"

flag3 = flag3.gsub(/-/, "")

flag1[3] = "П"
policies = flag4.index('ОБЛОМ')
flag4 = flag4.delete(policies - 1, 8)
flag4 += "БА"
flag4[0]="Д"

policies = flag3.index("ХОПХЛОП")
flag3 = flag3.delete(policies + 3, 4)
flag3 = flag3.insert(flag3.length - 1, "ЛЕНН")

flag2 = flag2.reverse
flag2 = flag2.delete(2, flag2.length - 2)

result_flag = flag3 + "_" + flag1.reverse + "_" + flag2 + "_" + flag4
puts result_flag
# => "ЗАХОПЛЕННЯ_ПРАПОРА_ЦЕ_ДРУЖБА"

ウクライナ語で"Capture the Flag is friendship"という意味らしい。

てか断りなくフラグに非ASCII文字が入ってるのはどうなの……w

FLAG:ЗАХОПЛЕННЯ_ПРАПОРА_ЦЕ_ДРУЖБА

Run the image?(stego:400pt)

JPEGファイルの後ろにexeファイルがくっついていた。

分離して実行したらフラグが表示される。

FLAG:aw3s0me_flag

Shop of goodness(web:100pt)

「フラグが買えるネットショップ」の模様。

f:id:Charo_IT:20150503223105p:plain 画面が1つ進むと、URLパラメータのstの値も1つ増える。 f:id:Charo_IT:20150503223321p:plain

「銀河カードの番号」なるものの入力を求められるが…… f:id:Charo_IT:20150503223436p:plain

SQLインジェクション脆弱性はなく、何を入れてもエラー画面に。 f:id:Charo_IT:20150503223453p:plain

しかし、stを5にすると購入完了画面が出せる。 f:id:Charo_IT:20150503223508p:plain

FLAG:GoOgle_iS_yOur_FrieNd

Stored pass(web:100pt)

パスワードフィールドに最初からフラグが入っているので、Webコンソールで

document.getElementsByName("password")[0].value
// => saving_passwords_is_bad_idea

で終了。

FLAG:saving_passwords_is_bad_idea

Junior pentesting(web:300pt)

user : admin'-- 
pass : hoge

でsubmitするとフラグが出る。

FLAG:dont_drop_my_tables

Unusual redirection(web:300pt)

flagページにアクセスしようとすると302でoopsページに飛ばされるが、302のレスポンス内にフラグが入っている。

FLAG:old_link_is_cool_link