バランスを取りたい

よくCTFの記事を書きます

RuCTF 2014 Writeup (Stegano 100)

100. Cat's eye

Find the key.
Format is "RUCTF_.*"
f:id:xrekkusu:20140312113028g:plain

Steganographyで画像といえばStegSolveなのでとりあえず読ませて様子を見ることにしました。
するとこの画像はGIFアニメで8枚の画像からできていることがわかります。


ほぼ同じ画像が8枚出てきたのでそれらを分離してそれぞれの差分を取ってみました。
具体的には、StegSolveのImage Combinatorで差を取っていって8枚の画像の中で色が異なっているピクセルを1枚に集約した画像を作りました。(めっちゃCombinatorしまくった)

f:id:xrekkusu:20140312113529p:plain


すると上のような画像が出来上がるので、拡大してみると、
どうやら上部に横方向に2行と4/5くらいのあたりに点が集中していることがわかります。

ここで、横方向にデータが並んでいるのではないかと検討をつけました。
フラグの頭がRなので、二進値の01010010を探すとぴったり当てはまります。

このことを既に画像差分を取得するスクリプトを書いていた@akiymさんに報告したところ、
ものの数分でフラグを奪取してくれました。

RuCTF 2014 Writeup (Crypto 200)

200. Mary Queen

Mary Queen of Scots goes chinese. We capture secret message from prison where Mary Queen stands. Help us figure out what message means.

ファイルを開くとE4 xx yyな文字とスペースが並んでいることがわかります。
何が何だかさっぱりわからなかったのですが、xx yyが結構被っていること、スペースが英語っぽい位置にあることから、とりあえず頻度分析を回してみました。


その結果、53種類の文字とスペースがあることがわかり、アルファベットの大文字小文字なんじゃないかと検討をつけました。
適当なサイトから英字の頻度表を持ってきて、とりあえず頻度が高い26文字を置換。
残りは適当に大文字のアルファベットで埋めたりしてそれっぽく処理してます。


置換した結果、英文っぽいけどなんか違う文章が生成されたのでそれを換字式暗号のソルバーに突っ込んだところ、文章の最初の部分が"lewis carroll alices adventures"だということがわかりました。


フラグは"Alice's Adventures in Wonderland"でこの時既に解けているはずだったのですが、
まさか物語のタイトルが答えだと思わず、全文を復元しようと原文と照らしあわせてました。


結局答えが分からず放置してたのですが、
@akiymさんがhttps://www.youtube.com/watch?v=_htopuN4pCkを見つけてきてくれたおかげで、実は既に暗号は解けていてそれ以上の謎はないことが判明。

さらに、IRCでcrypto200の答えについて、「case-insensitiveだけどpunctuationは重要」っていう運営の発言があったのをふと思い出し、"Alice's Adventures in Wonderland"をsubmitしたところ200ptを獲得できました。

import struct

dic = {
  "b890": "e",
  "b994": "t",
  "b9a7": "a",
  "b8b7": "o",
  "b891": "i",
  "b99e": "s",
  "baab": "n",
  "b898": "r",
  "b9ab": "h",
  "b9a5": "l",
  "b9a4": "d",
  "b89d": "u",
  "b9a0": "?",
  "bbaa": "g",
  "bba1": "c",
  "bb90": "w",
  "b8a8": "y",
  "b8bc": "m",
  "babc": "the",
  "b8a1": "p",
  "ba9f": "b",
  "bb83": "f",
  "b8ad": "k",
  "b8ac": "v",
  "b8ae": "and",
  "b893": "of",
  "ba86": "in",
  "b9a9": "q",
  "bbb2": "that",
  "bbb8": "x",
  "baba": "E",
  "b885": "as",
  "baa3": "G",
  "b981": "j",
  "b996": "I",
  "b9be": "J",
  "bb84": "z",
  "b998": "with",
  "bb9e": "but",
  "bbbb": "for",
  "bb94": "so",
  "b983": "not",
  "b991": "what",
  "baac": "this",
  "bab6": "is",
  "bab9": "if",
  "b8b2": "when",
  "ba83": "there",
  "b89e": "me",
  "b8a4": "my",
  "ba94": "on",
  "bb8b": "from",
  "bb88": "where"
}

f = open('d8cb57bf1b34bf8c58836724ee2b0b71', 'rb')

sample = ""

while True:
  op = f.read(1)
  if op == ' ':
    sample += " "
    continue
  elif op == "":
    break
  
  code = struct.unpack(">H", f.read(2))
  s = "%x" % code

  sample += dic[s]

print sample

RuCTF 2014 Writeup (Crypto 100)

100. MD5

Server (python27.quals.ructf.org:12337) accepts only authorized messages.
It works like this:

	buf = c.recv(4096)
	digest, msg = buf.split(" ", 1)
	if (digest == md5(password+msg).hexdigest()):
		#here I send a secret
	else:
		c.send("Wrong signature\n")

You have intercepted one authorized message: "b34c39b9e83f0e965cf392831b3d71b8 do test connection". Construct your own authorized message! Answer starts with 'RUCTF_'

Length extension attackを知ってるかどうかが勝負の分かれ目らしい。
IRCで変な質問してる人がいたりして面白かったです(真顔


この手の攻撃で知ってるツールはHashPumpだけだったのでそれでなんとかしました。
結果下見たいなコードになったんですが、Pythonほとんど書いたことが無くて文字列の処理周りでめっちゃ大変なことになってます。
あと、文字列周りでエラー吐く可能性があったんですが何事も無く動いたのでそのままです。

import socket
import time
import commands

host = "python27.quals.ructf.org"
port = 12337

known_sig = "b34c39b9e83f0e965cf392831b3d71b8"
known_text = "do test connection"

def test(sign, text):
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM);
  sock.connect((host, port))
  
  data = sign + " " + text
  sock.send(data)
  time.sleep(0.1)
  return sock.recv(4096)

for i in range(1,32):
  cmd = "/Users/rex/CTF/tools/HashPump/HashPump"
  cmd += " -s " + known_sig
  cmd += " -d \"" + known_text + "\""
  cmd += " -k " + str(i)
  cmd += " -a " + "AAAA"
  sign, text = commands.getoutput(cmd).split('\n')
  a, b = text.split('\\x80')
  b = b[:-4].replace('\\x','').decode('hex')

  data = a + '\x80' + b + 'AAAA'
  res = test(sign, data)
  print str(i) + ': ' + res
  if not 'Wrong' in res:
    break

RuCTF 2014 Writeup (Recon)

100. Favourite Book

Have you ever met Olimpiada Balalaykina?
She is a young girl who likes to chat and dreams to meet Pavel Durov.
We'd like to know her favorite book.

これ、だいぶ困りました。
ぐぐってもFacebookでも全く出てこないので放置ゲーしてました。


@lmt_swallowが「やっぱりvk.comかなあ」と言うので二人で見に行ったところ、アカウントを発見。

なんかの文章付きのバッグの写真をアップロードしているのでGoogle画像検索に投げつけました。

すると、"Pride and Prejudice Cotton Book Bag"って名前らしいことがわかるので、
"Pride and Prejudice"をsubmitして100pt。


200. Stolen Camera

Have you ever met Olimpiada Balalaykina?
She is a young girl who likes to chat and dreams to meet Pavel Durov.
Сould name the city where her camera was stolen.

vk.comのpostにある、
"My friend always tells me not to use my relatives' birthdays as a password but he have just tweeted that his own mail had been hacked! Hahaha! :DDD"
がどう考えても怪しい。でもなんだろう。

っていう状態で、Grannyって誰だろうと@akiymさんに聞いたところ、
普通に「おばあちゃん」って意味だとわかったのでそこでひらめきました。

  • 親族の誕生日がパスワード
  • 誕生日は先週の日曜日(写真のアップロード日は2014年3月6日)
  • おそらく80歳を祝っているバースデーケーキ
  • メールアドレスが公開されている

という条件から、メールボックスが見られると推測し、メールアドレスのドメインからMXレコードを引いたところ、GoogleAppsでした。


パスワード19340302とかやってたんですが@akiymさんが地域によって日付の書き方違う、とナイスな指摘をしてくれたので02031934でメールボックスに侵入。


するとGoogleMap付きのメールがあるので、
そのMap上のポイントと、VKのamerican tripのアルバムのコメントの内容から
Day7に行った場所、すなわちGreat Junctionをsubmitして200pt。

200点問題はちゃんと推理可能なように適度にヒントが散りばめられていてすごくいい問題でした

あけましておめでとうございます!

早速ですが今年もCTFやります!

happy new year!!

超眠い状態で作ったのでデザインには突っ込まないで下さい
そして手抜き感があるのも(ry


急いで作ったからぽっかり穴空いてるかもしれないけどあんまり触らないでね!

CSAW CTF 2013 Reversing 150 Write-up

f:id:xrekkusu:20130923123414p:plain

見た感じ.NETのアセンブリだからとりあえずILSpyで開いてみます。


f:id:xrekkusu:20130923123205p:plain



あっ…(察し)



なんて騒いでないで.NETの知識を使ってガンガン進んでいきましょう。


Submitボタンを押すとClickイベントが走るのでそこに何かがあるはずです。

Clickイベントといえば (object sender, EventArgs e)ですね。

private void eval_ᜀ(object obj, EventArgs eventArgs)
{
	string strB = null;
	Assembly executingAssembly = Assembly.GetExecutingAssembly();
	ResourceManager resourceManager = new ResourceManager(executingAssembly.GetName().Name + ".Resources", executingAssembly);
	DateTime now = DateTime.Now;
	string arg_65_0 = this.eval_ᜀ.Text;
	string value = string.Format("{0}", now.Hour + 1);
	string text = "NeEd_MoRe_Bawlz";
	this.eval_ᜀ(text, Convert.ToInt32(value), ref strB);
	if (string.Compare(arg_65_0.ToUpper(), strB) == 0)
	{
		this.eval_ᜂ.Text = "";
		this.eval_ᜀ(this.eval_ᜀ(107));
		this.eval_ᜁ();
		this.eval_ᜂ.Text = string.Format(this.eval_ᜂ.Text, this.eval_ᜀ(resourceManager));
		this.eval_ᜃ.Image = (Bitmap)resourceManager.GetObject("Sorry You Suck");
	}
	else
	{
		this.eval_ᜃ.Image = (Bitmap)resourceManager.GetObject("Almost There");
		this.eval_ᜀ();
	}
}


if(string.Compare(...))なんてのが見えます。
この条件をtrueにすればフラグが表示されそうです。


ifの1行前を見ると、ref付きで何かの関数に処理を投げています。

private void eval_ᜀ(string text, int num, ref string ptr) {
  int num2 = 0;
  if (0 < text.Length) {
    do {
      char c = text[num2];
      int num3 = 1;
      if (1 < num) {
        do {
          c = Convert.ToChar(this.eval_ᜀ(Convert.ToInt32(c), num3));
          num3++;
        }
        while (num3 < num);
      }
      ptr += c;
      num2++;
    }
    while (num2 < text.Length);
  }
  ptr = this.eval_ᜀ(ptr);
}

中盤、終盤のevalはそれぞれこんな感じになってます。

private int eval_ᜀ(int num, int num2) {
  return (new int[] {
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113
  })[num2] ^ num;
}
private string eval_ᜀ(string s) {
  byte[] bytes = Encoding.ASCII.GetBytes(s);
  return BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(bytes)).Replace("-", "");
}


NeEd_MoRe_Bawlzを暗号化した文字列と、ユーザーから入力された文字列が一致してればいいみたいな空気です。
しかもそれは1時間ごとに変わるらしい。


ということなので手っ取り早く上のコードをうまく繋ぎあわせて入力すべき文字列が表示されるようなプログラムを作ります。



そしてフラグをゲットします。

f:id:xrekkusu:20130923131456p:plain



でもこのフラグは通りませんでした…


というのも、途中に出てくるNeEd_MoRe_BawlzをGoogleで検索すると大量のideoneがヒットして、そこを見るだけで解けてしまうっぽいです。


[追記]

実際は元の文字列が文字化けして????????...なってたのをコンバートした結果?????...のハッシュ値になってしまっていたという情報。

通らないからここからもう一捻りかと思って調べたら?????...のハッシュであることは理解してたんだけどねえ…。

======


なので"If your key isn't working PM ColdHeat on IRC"に従ってPMを送ってみると、


"how did you get the key?"


あっ…あっ…(英語ができない)


"i used ILSpy"

"describe more. go in depth"


あっ…あっ…



ってな感じで時間かけてやりとりした結果30分後にフラグを入手、150ポイントが手にはいりました。



というわけで "how did you get the key?" に対する答えでした。