この大会は2016/2/27 9:00(JST)~2016/2/29 9:00(JST)に開催されました。
今回も個人で参戦。結果は110点で259位でした。
参加チームは2921チームいたので、まあまあの順位でした。
解けた問題2問をWriteupとして書いておきます。
Welcome (Misc 10)
ただリンク先が書かれている。リンク先はこんなページ。
よく見てもフラグは見たらない。
終了間近にヒント"look at https://twitter.com/01001000entai"が出ていた。
そのURLにアクセスすると、フラグが載っていた。
SSCTF{WelcOme_TO_S3CTF_2o16}
HeHeDa (Crypto&Exploit 100)
暗号のソースが添付されている。
def LShift(t, k): k %= 8 return ((t << k) | (t >> (8 - k))) & 0xff def encode(p): ret = "" for i in range(8): ret = ('|' if (p >> i) & 1 else 'O') + ret return ret A = [85, 128, 177, 163, 7, 242, 231, 69, 185, 1, 91, 89, 80, 156, 81, 9, 102, 221, 195, 33, 31, 131, 179, 246, 15, 139, 205, 49, 107, 193, 5, 63, 117, 74, 140, 29, 135, 43, 197, 212, 0, 189, 218, 190, 112, 83, 238, 47, 194, 68, 233, 67, 122, 138, 53, 14, 35, 76, 79, 162, 145, 51, 90, 234, 50, 6, 225, 250, 215, 133, 180, 97, 141, 96, 20, 226, 3, 191, 187, 57, 168, 171, 105, 113, 196, 71, 239, 200, 254, 175, 164, 203, 61, 16, 241, 40, 176, 59, 70, 169, 146, 247, 232, 152, 165, 62, 253, 166, 167, 182, 160, 125, 78, 28, 130, 159, 255, 124, 153, 56, 58, 143, 150, 111, 207, 206, 32, 144, 75, 39, 10, 201, 204, 77, 104, 65, 219, 98, 210, 173, 249, 13, 12, 103, 101, 21, 115, 48, 157, 147, 11, 99, 227, 45, 202, 158, 213, 100, 244, 54, 17, 161, 123, 92, 181, 243, 184, 188, 84, 95, 27, 72, 106, 192, 52, 44, 55, 129, 208, 109, 26, 24, 223, 64, 114, 19, 198, 23, 82, 120, 142, 178, 214, 186, 116, 94, 222, 86, 251, 36, 4, 248, 132, 25, 211, 199, 30, 87, 60, 127, 155, 41, 224, 151, 237, 136, 245, 37, 170, 252, 8, 42, 209, 46, 108, 88, 183, 149, 110, 66, 235, 229, 134, 73, 38, 118, 236, 119, 154, 216, 217, 240, 22, 121, 174, 93, 126, 230, 228, 18, 148, 220, 172, 2, 137, 34] B = [0, 2, 3, 7, 1, 5, 6, 4] C = [179, 132, 74, 60, 94, 252, 166, 242, 208, 217, 117, 255, 20, 99, 225, 58, 54, 184, 243, 37, 96, 106, 64, 151, 148, 248, 44, 175, 152, 40, 171, 251, 210, 118, 56, 6, 138, 77, 45, 169, 209, 232, 68, 182, 91, 203, 9, 16, 172, 95, 154, 90, 164, 161, 231, 11, 21, 3, 97, 70, 34, 86, 124, 114, 119, 223, 123, 167, 47, 219, 197, 221, 193, 192, 126, 78, 39, 233, 4, 120, 33, 131, 145, 183, 143, 31, 76, 121, 92, 153, 85, 100, 52, 109, 159, 112, 71, 62, 8, 244, 116, 245, 240, 215, 111, 134, 199, 214, 196, 213, 180, 189, 224, 101, 202, 201, 168, 32, 250, 59, 43, 27, 198, 239, 137, 238, 50, 149, 107, 247, 7, 220, 246, 204, 127, 83, 146, 147, 48, 17, 67, 23, 93, 115, 41, 191, 2, 227, 87, 173, 108, 82, 205, 49, 1, 66, 105, 176, 22, 236, 29, 170, 110, 18, 28, 185, 235, 61, 88, 13, 165, 188, 177, 230, 130, 253, 150, 211, 42, 129, 125, 141, 19, 190, 133, 53, 84, 140, 135, 10, 241, 222, 73, 12, 155, 57, 237, 181, 36, 72, 174, 207, 98, 5, 229, 254, 156, 178, 128, 55, 14, 69, 30, 194, 122, 46, 136, 160, 206, 26, 102, 218, 103, 139, 195, 0, 144, 186, 249, 79, 81, 75, 212, 234, 158, 163, 80, 226, 65, 200, 38, 187, 113, 63, 24, 25, 142, 51, 228, 35, 157, 216, 104, 162, 15, 89] D = [2, 4, 0, 5, 6, 7, 1, 3] plain = bytearray("asdfghjk123456") key = bytearray(/*Missed*/) assert len(key) == 8 t1 = bytearray() for i in plain: t1.append(A[i]) t2 = bytearray() for i in range(len(t1)): t2.append(LShift(t1[i], B[i % 8])) for times in range(16): for i in range(len(t2)): t2[i] = C[t2[i]] for i in range(len(t2)): t2[i] = LShift(t2[i], i ^ D[i % 8]) for i in range(len(t2)): t2[i] ^= key[i % 8] out = "" for i in t2: out += encode(i) print out # out>> # OO|OO||OO|||||OO|OO||O||O|O||O|||O|OOOOOOO|O|O|O|||||OO|||O|||OO||O|OOOOOO|O|OO|OO||||OO|||OOOO|||||O||||O|OO|O|O|O||OO|O||O|OO|O||O|||O||O|OO|OOOOOO||OOO|O|O|O|||O|OO|O|O||O||O||OOOOO|||OO|O| # flag >> # OO||O||O|O|||OOOO||||||O|O|||OOO||O|OOOO||O|O|OO|||||OOOO||||O||OO|OO||O||O|O|O|||||OOOOOO|O|O||OOOOOOO||O|||OOOO||OO|OO|||O|OO|O|||O|O|OO|OOOO|OOO|OOO|OOOO||O|OO||||OO||||OOO|O|O||OO||||O||OOO|||O|OO|OO||OO||OOOO|O|
これからflagを復号する問題。
この暗号のkeyは8バイトで、1バイト単位で計算している。
outでもflagでも8バイトごとに同じ文字で計算しているものを探すスクリプトを作る。
import string def LShift(t, k): k %= 8 return ((t << k) | (t >> (8 - k))) & 0xff def encode(p): ret = "" for i in range(8): ret = ('|' if (p >> i) & 1 else 'O') + ret return ret A = [85, 128, 177, 163, 7, 242, 231, 69, 185, 1, 91, 89, 80, 156, 81, 9, 102, 221, 195, 33, 31, 131, 179, 246, 15, 139, 205, 49, 107, 193, 5, 63, 117, 74, 140, 29, 135, 43, 197, 212, 0, 189, 218, 190, 112, 83, 238, 47, 194, 68, 233, 67, 122, 138, 53, 14, 35, 76, 79, 162, 145, 51, 90, 234, 50, 6, 225, 250, 215, 133, 180, 97, 141, 96, 20, 226, 3, 191, 187, 57, 168, 171, 105, 113, 196, 71, 239, 200, 254, 175, 164, 203, 61, 16, 241, 40, 176, 59, 70, 169, 146, 247, 232, 152, 165, 62, 253, 166, 167, 182, 160, 125, 78, 28, 130, 159, 255, 124, 153, 56, 58, 143, 150, 111, 207, 206, 32, 144, 75, 39, 10, 201, 204, 77, 104, 65, 219, 98, 210, 173, 249, 13, 12, 103, 101, 21, 115, 48, 157, 147, 11, 99, 227, 45, 202, 158, 213, 100, 244, 54, 17, 161, 123, 92, 181, 243, 184, 188, 84, 95, 27, 72, 106, 192, 52, 44, 55, 129, 208, 109, 26, 24, 223, 64, 114, 19, 198, 23, 82, 120, 142, 178, 214, 186, 116, 94, 222, 86, 251, 36, 4, 248, 132, 25, 211, 199, 30, 87, 60, 127, 155, 41, 224, 151, 237, 136, 245, 37, 170, 252, 8, 42, 209, 46, 108, 88, 183, 149, 110, 66, 235, 229, 134, 73, 38, 118, 236, 119, 154, 216, 217, 240, 22, 121, 174, 93, 126, 230, 228, 18, 148, 220, 172, 2, 137, 34] B = [0, 2, 3, 7, 1, 5, 6, 4] C = [179, 132, 74, 60, 94, 252, 166, 242, 208, 217, 117, 255, 20, 99, 225, 58, 54, 184, 243, 37, 96, 106, 64, 151, 148, 248, 44, 175, 152, 40, 171, 251, 210, 118, 56, 6, 138, 77, 45, 169, 209, 232, 68, 182, 91, 203, 9, 16, 172, 95, 154, 90, 164, 161, 231, 11, 21, 3, 97, 70, 34, 86, 124, 114, 119, 223, 123, 167, 47, 219, 197, 221, 193, 192, 126, 78, 39, 233, 4, 120, 33, 131, 145, 183, 143, 31, 76, 121, 92, 153, 85, 100, 52, 109, 159, 112, 71, 62, 8, 244, 116, 245, 240, 215, 111, 134, 199, 214, 196, 213, 180, 189, 224, 101, 202, 201, 168, 32, 250, 59, 43, 27, 198, 239, 137, 238, 50, 149, 107, 247, 7, 220, 246, 204, 127, 83, 146, 147, 48, 17, 67, 23, 93, 115, 41, 191, 2, 227, 87, 173, 108, 82, 205, 49, 1, 66, 105, 176, 22, 236, 29, 170, 110, 18, 28, 185, 235, 61, 88, 13, 165, 188, 177, 230, 130, 253, 150, 211, 42, 129, 125, 141, 19, 190, 133, 53, 84, 140, 135, 10, 241, 222, 73, 12, 155, 57, 237, 181, 36, 72, 174, 207, 98, 5, 229, 254, 156, 178, 128, 55, 14, 69, 30, 194, 122, 46, 136, 160, 206, 26, 102, 218, 103, 139, 195, 0, 144, 186, 249, 79, 81, 75, 212, 234, 158, 163, 80, 226, 65, 200, 38, 187, 113, 63, 24, 25, 142, 51, 228, 35, 157, 216, 104, 162, 15, 89] D = [2, 4, 0, 5, 6, 7, 1, 3] out = 'OO|OO||OO|||||OO|OO||O||O|O||O|||O|OOOOOOO|O|O|O|||||OO|||O|||OO||O|OOOOOO|O|OO|OO||||OO|||OOOO|||||O||||O|OO|O|O|O||OO|O||O|OO|O||O|||O||O|OO|OOOOOO||OOO|O|O|O|||O|OO|O|O||O||O||OOOOO|||OO|O|' flag = 'OO||O||O|O|||OOOO||||||O|O|||OOO||O|OOOO||O|O|OO|||||OOOO||||O||OO|OO||O||O|O|O|||||OOOOOO|O|O||OOOOOOO||O|||OOOO||OO|OO|||O|OO|O|||O|O|OO|OOOO|OOO|OOO|OOOO||O|OO||||OO||||OOO|O|O||OO||||O||OOO|||O|OO|OO||OO||OOOO|O|' d1 = {} d2 = {} d3 = {} for i in range(len(out) / 8): for try_key in string.printable: for try_plain in string.printable: t1 = A[ord(try_plain)] t2 = LShift(t1, B[i % 8]) for times in range(16): t2 = C[t2] t2 = LShift(t2, i ^ D[i % 8]) t2 ^= ord(try_key) if encode(t2) == out[i*8:i*8+8]: index1 = str(i % 8).zfill(2) + ':' + try_key if i / 8 == 0: d1[index1] = try_plain elif i / 8 == 1: index2 = str(i).zfill(2) + ':' + try_key if index1 in d1: d2[index1] = d1[index1] d2[index2] = try_plain else: index2 = str(i - 8).zfill(2) + ':' + try_key index3 = str(i).zfill(2) + ':' + try_key if index1 in d2: d3[index1] = d2[index1] d3[index2] = d2[index2] d3[index3] = try_plain #for key, value in sorted(d3.items()): # print key, value d4 = {} d5 = {} d6 = {} d7 = {} for i in range(len(flag) / 8): for try_key in string.printable: for try_plain in string.printable: t1 = A[ord(try_plain)] t2 = LShift(t1, B[i % 8]) for times in range(16): t2 = C[t2] t2 = LShift(t2, i ^ D[i % 8]) t2 ^= ord(try_key) if encode(t2) == flag[i*8:i*8+8]: index1 = str(i % 8).zfill(2) + ':' + try_key if i / 8 == 0: index2 = str(i + 8).zfill(2) + ':' + try_key index3 = str(i + 16).zfill(2) + ':' + try_key index4 = str(i + 24).zfill(2) + ':' + try_key if index1 in d3: d4[index1] = d3[index1] d4[index2] = d3[index2] d4[index3] = d3[index3] d4[index4] = try_plain elif i / 8 == 1: index2 = str(i).zfill(2) + ':' + try_key index3 = str(i + 8).zfill(2) + ':' + try_key index4 = str(i + 16).zfill(2) + ':' + try_key index5 = str(i + 24).zfill(2) + ':' + try_key if index1 in d4: d5[index1] = d4[index1] d5[index2] = d4[index2] d5[index3] = d4[index3] d5[index4] = d4[index4] d5[index5] = try_plain elif i / 8 == 2: index2 = str(i - 8).zfill(2) + ':' + try_key index3 = str(i).zfill(2) + ':' + try_key index4 = str(i + 8).zfill(2) + ':' + try_key index5 = str(i + 16).zfill(2) + ':' + try_key index6 = str(i + 24).zfill(2) + ':' + try_key if index1 in d5: d6[index1] = d5[index1] d6[index2] = d5[index2] d6[index3] = d5[index3] d6[index4] = d5[index4] d6[index5] = d5[index5] d6[index6] = try_plain else: index7 = str(i + 24).zfill(2) + ':' + try_key if index1 in d6: d6.update({index7:try_plain}) for key, value in sorted(d6.items()): print key, value
これを実行すると、次のような結果となる。
00:^ a 01:& s 02:# d 03:q f 04:D g 05:9 h 06:3 j 07:_ k 08:^ 1 09:& 2 10:# 3 11:q 4 12:D 5 13:9 6 14:3 7 15:_ 8 16:^ ! 17:& @ 18:# # 19:q $ 20:D % 21:9 ^ 22:3 & 23:_ * 24:^ S 25:& S 26:# C 27:q T 28:D F 29:9 { 30:3 1 31:_ q 32:^ a 33:& z 34:# 9 35:q o 36:D l 37:9 . 38:3 n 39:_ h 40:^ y 41:& 6 42:# 4 43:q r 44:D f 45:9 v 46:3 7 47:_ u 48:^ j 49:& m 50:# }
SSCTF{1qaz9ol.nhy64rfv7ujm}