crypto
Count me in!
Points: 500
Solves: 1
ファイルを解凍すると、Pythonのプログラムソースcount.pyと暗号化データoutput.txtができます。count.pyは次のようなプログラムになっています。固定の文章の後ろにフラグ文字列を付加したテキストデータを16文字ずつに区切って、worker_functionの中でcounter変数(0から1ずつインクリメントされる)をAES.MODE_ECBで暗号化した値key_streamとXORを取っています。multiprocessingで並列処理をしているので同じkey_streamで暗号化されるものがありそうです。また並列処理のタイミングによってはkey_streamが前後したり実行の都度暗号化された結果が変わります。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...
import multiprocessingfrom Crypto.Cipher import AESfrom secret import key, flagcounter = 0aes = 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 reducefrom operator import xorreturn [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) % 16return data + (chr(pad_byte) * pad_byte)def worker_function(block):global counterkey_stream = aes.encrypt(pad(str(counter)))result = xor_string(block, key_stream)counter += 1return resultdef distribute_work(worker, data_list, processes=8):pool = multiprocessing.Pool(processes=processes)result = pool.map(worker, data_list)pool.close()return resultdef 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 CountYou know that I am called the CountBecause I really love to countI could sit and count all daySometimes I get carried awayI count slowly, slowly, slowly getting fasterOnce I've started counting it's really hard to stopFaster, faster. It is so exciting!I could count forever, count until I drop1! 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 countI 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 fasterOnce I've started counting it's really hard to stopFaster, faster. It is so exciting!I could count forever, count until I drop1! 2! 3! 4!1-2-3-4, 1-2-3-4, 1,2 I love counting whatever theammount! 1-2-3-4 heyayayay heayayay 1-2-3-4That's the song of the Count!""" + flagencrypted = encrypt_parallel(plaintext, 32)print(encrypted.encode("hex"))if __name__ == '__main__':multiprocessing.freeze_support()main()
フラグの部分を復号するにはkey_streamが必要となります。これは暗号化データと固定の文字列部分のXORを取ることで暗号化に使われたkey_streamが分かりますので、それを使ってフラグ部分を復号化しフラグ形式となる文字列に復号できるかどうか確認します。
最初の16文字の暗号処理について、output.txtの先頭32文字
最初の16文字の暗号処理について、output.txtの先頭32文字
と、平文の先頭16文字9d5c66e65fae92af9c8a55d9d3bf640e
’The Song of the '
を16進文字で表した
とでXORを取ります。これが変数counterが0のときのkey_streamとなります。54686520536f6e67206f662074686520
c93403c60cc1fcc8bce533f9a7d7012e
以上を行うPythonプログラムを書きます。
import binasciidef xor(*t):from functools import reducefrom operator import xorreturn [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 CountYou know that I am called the CountBecause I really love to countI could sit and count all daySometimes I get carried awayI count slowly, slowly, slowly getting fasterOnce I've started counting it's really hard to stopFaster, faster. It is so exciting!I could count forever, count until I drop1! 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 countI 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 fasterOnce I've started counting it's really hard to stopFaster, faster. It is so exciting!I could count forever, count until I drop1! 2! 3! 4!1-2-3-4, 1-2-3-4, 1,2 I love counting whatever theammount! 1-2-3-4 heyayayay heayayay 1-2-3-4That'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}