SECCON 2017 Online writeup

SECCON 2017 Online writeup

yharima チームで参加.1900 pts で 84th でした.

Run me!

フィボナッチ数列11011 項目を求める問題.
与えられる実装は,非常に効率が悪い実装になっているので高速化してあげれば良い.
が,そんなことしなくても http://php.bubble.ro/fibonacci/ にぶち込んで,先頭 32 文字とれば良いだけ.
SECCON{65076140832331717667772761541872}

putchar music

C プログラムが与えられて,何の映画かを答える.
プログラムをみると何らかの音楽を再生していて,それを再生したら映画のタイトルがわかる,的な問題.
問題に,映画タイトルにスペースがあったら "_" に変えろ,というのがあったのと,
その昔 SECCON WARS という STAR WARS ネタがあったのと,そろそろ最後のジェダイが公開される,というあたりから, 何も考えず STAR WARS だろうと思って,入力したら正解だった.このあたりが自分が絶好調だった.
SECCON{STAR_WARS}

Powerful_Shell

power shell が与えられる.
ubuntu でも動くらしいので適当にインストールして実行してみるとエラーになる.
どうも ` が含まれているのが原因なので,置き換えてみると,ピアノの鍵盤が出て来る.
コード自体の末尾に Write-Host $ECOON 的なものを挿すとデコードされたコードがみれる.
デコードされたコードをみて,適当にデバッグログを差し込みながら解析すると,
hhjhhjhjkjhjhf を入力すると次のステージに進める.
さらに Enter password と出てくる.これは,内部にある base64 エンコードされたコードをデコードしたものと,
上記の hhjhhjhjkjhjhf によって生成される鍵から復号された結果のコードが実行されている.
中身はこんな感じ.

{;}=+$();${=}=${;};${+}=++${;};${@}=++${;};${.}=++${;};${[}=++${;};
${]}=++${;};${(}=++${;};${)}=++${;};${&}=++${;};${|}=++${;};
${"}="["+"$(@{})"[${)}]+"$(@{})"["${+}${|}"]+"$(@{})"["${@}${=}"]+"$?"[${+}]+"]";
${;}="".("$(@{})"["${+}${[}"]+"$(@{})"["${+}${(}"]+"$(@{})"[${=}]+"$(@{})"[${[}]+"$?"[${+}]+"$(@{})"[${.}]);
${;}="$(@{})"["${+}${[}"]+"$(@{})"[${[}]+"${;}"["${@}${)}"];"${"}${.}${(}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&}+${"}${(}${+}+${"}${&}${@}+${"}${+}${=}${+}+${"}${|}${)}+${"}${+}${=}${=}+${"}${[}${]}+${"}${)}${@}+${"}${+}${+}${+}+${"}${+}${+}${]}+${"}${+}${+}${(}+${"}${.}${@}+${"}${[}${]}+${"}${&}${=}+${"}${+}${+}${[}+${"}${+}${+}${+}+${"}${+}${=}${|}+${"}${+}${+}${@}+${"}${+}${+}${(}+${"}${.}${@}+${"}${.}${|}+${"}${(}${|}+${"}${+}${+}${=}+${"}${+}${+}${(}+${"}${+}${=}${+}+${"}${+}${+}${[}+${"}${.}${@}+${"}${+}${+}${(}+${"}${+}${=}${[}+${"}${+}${=}${+}+${"}${.}${@}+${"}${+}${+}${@}+${"}${|}${)}+${"}${+}${+}${]}+${"}${+}${+}${]}+${"}${+}${+}${|}+${"}${+}${+}${+}+${"}${+}${+}${[}+${"}${+}${=}${=}+${"}${.}${|}+${"}${+}${.}+${"}${+}${=}+${"}${)}${.}+${"}${+}${=}${@}+${"}${[}${=}+${"}${.}${(}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&}+${"}${.}${@}+${"}${[}${]}+${"}${+}${=}${+}+${"}${+}${+}${.}+${"}${.}${@}+${"}${.}${|}+${"}${&}${=}+${"}${[}${&}+${"}${+}${+}${|}+${"}${(}${|}+${"}${+}${+}${[}+${"}${.}${(}+${"}${)}${@}+${"}${]}${+}+${"}${[}${|}+${"}${[}${|}+${"}${.}${|}+${"}${[}${+}+${"}${+}${@}${.}+${"}${+}${.}+${"}${+}${=}+${"}${|}+${"}${&}${)}+${"}${+}${+}${[}+${"}${+}${=}${]}+${"}${+}${+}${(}+${"}${+}${=}${+}+${"}${[}${]}+${"}${)}${@}+${"}${+}${+}${+}+${"}${+}${+}${]}+${"}${+}${+}${(}+${"}${.}${@}+${"}${.}${|}+${"}${)}${+}+${"}${+}${+}${+}+${"}${+}${+}${+}+${"}${+}${=}${=}+${"}${.}${@}+${"}${)}${[}+${"}${+}${+}${+}+${"}${|}${&}+${"}${.}${.}+${"}${.}${|}+${"}${]}${|}+${"}${+}${.}+${"}${+}${=}+${"}${|}+${"}${&}${)}+${"}${+}${+}${[}+${"}${+}${=}${]}+${"}${+}${+}${(}+${"}${+}${=}${+}+${"}${[}${]}+${"}${)}${@}+${"}${+}${+}${+}+${"}${+}${+}${]}+${"}${+}${+}${(}+${"}${.}${@}+${"}${.}${[}+${"}${&}${.}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&}+${"}${+}${@}${.}+${"}${.}${(}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&}+${"}${+}${@}${]}+${"}${.}${[}+${"}${+}${.}+${"}${+}${=}+${"}${+}${@}${]}|${;}"|&${;}

これは,最後の部分が評価されて実行されている.これは,評価される前を Write-Host を実行するとさらにコードがみえる.
中身をみると最後, power shell になっていて,入力された文字が P0wEr$H311 と入力するとフラグがでる(というかそれそのものがフラグ).

SECCON{P0wEr$H311}

Simon and Speck Block Ciphers

Simon とかいう暗号化方式で暗号化された結果と plain text と鍵の一部などが与えられる.
実装自体は論文の通りにやればできるが,めんどい,適当にぐぐると以下の実装がでてくる.

GitHub - inmcm/Simon_Speck_Ciphers: Implementations of the Simon and Speck Block Ciphers

あとは以下のようなコードを書いて,鍵の不明な部分を総当りするだけ(実行ときに適当に grep する).

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include "Simon.h"

int main() {
  Simon_Cipher my_simon_cipher = *(Simon_Cipher *)malloc(sizeof(Simon_Cipher));
  //uint8_t simon96_64_plain[] = {0x6d, 0x56, 0x4d, 0x37, 0x42, 0x6e, 0x6e, 0x71};
  uint8_t simon96_64_plain[] = {0x71, 0x6e, 0x6e, 0x42, 0x37, 0x4d, 0x56, 0x6d};
  //uint8_t simon96_64_cipher[] = {0xbb, 0x5d, 0x12, 0xba, 0x42, 0x28, 0x34, 0xb5};
  uint8_t simon96_64_cipher[] = {0xb5, 0x34, 0x28, 0x42, 0xba, 0x12, 0x5d, 0xbb};

  for (int c1 = 0x20; c1 <= 0x7e; ++c1) {
    for (int c2 = 0x20; c2 <= 0x7e; ++c2) {
      for (int c3 = 0x20; c3 <= 0x7e; ++c3) {
        for (int c4 = 0x20; c4 <= 0x7e; ++c4) {
          // uint8_t simon96_64_key[] = {0x53, 0x45, 0x43, 0x43, 0x4f, 0x4e, 0x7b, c1, c2, c3, c4, 0x7d};
          uint8_t simon96_64_key[] = {0x7d, c4, c3, c2, c1, 0x7b, 0x4e, 0x4f, 0x43, 0x43, 0x45, 0x53};
          Simon_Init(&my_simon_cipher, Simon_96_64, ECB, simon96_64_key, NULL, NULL);

          uint8_t ciphertext_buffer[16];
          Simon_Encrypt(my_simon_cipher, &simon96_64_plain, &ciphertext_buffer);
          printf("%c%c%c%c: %02x %02x %02x %02x %02x %02x %02x %02x\n", c1, c2, c3, c4,
           ciphertext_buffer[0], ciphertext_buffer[1], ciphertext_buffer[2], ciphertext_buffer[3],
           ciphertext_buffer[4], ciphertext_buffer[5], ciphertext_buffer[6], ciphertext_buffer[7]);
        }
      }
    }
  }
  return 0;
}

最初,与えられているデータの入力をコメントアウトされている状態で定義していたが,答えが出ずしばらくハマっていた.
よくよく考えるとリトルエンディアンで書かないとだめ?と思って逆にしてみたら答えが出た.

SECCON{6Pz0}

Thank you for playing!

SECCON{We have done all the challenges. Enjoy last 12 hours. Thank you!} 

その他

Baby Stack で無限に時間を溶かした.
EIP までは割りとあっさり奪えたのだけど,その後どう ROP するかでハマった.
最初は mmap で executable な領域を確保したあとに read で shellcode 積んで, EIP 飛ばせばいいや,と思ったのだけど,
mmpa まではできたけど pop gadget がなくてその後の ROP chain に繋げられず死亡.
その後 syscall 叩くことなども考えたけど,どれもうまくいかず終了.非常に辛い….

まとめ

国内決勝まであとちょっとだったらしい?
非常に辛いけど力不足を実感したので,また来年まで修行します.