CSAW CTF Qualification Round 2019 Writeup

この大会は2019/9/14 5:00(JST)~2019/9/16 5:00(JST)に開催されました。
今回もチームで参戦。結果は2301点で1301チーム中52位でした。
自分で解けた問題をWriteupとして書いておきます。

mcgriddlev2 (Misc 1)

問題にフラグが書いてあった。

flag{W3lcome_7o_CSAW_QUALS_2019!}

beleaf (Rev 50)

Ghidraでデコンパイルする。

undefined8 FUN_001008a1(void)

{
  size_t sVar1;
  long lVar2;
  long in_FS_OFFSET;
  ulong local_b0;
  char local_98 [136];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  printf("Enter the flag\n>>> ");
  __isoc99_scanf(&DAT_00100a78,local_98);
  sVar1 = strlen(local_98);
  if (sVar1 < 0x21) {
    puts("Incorrect!");
                    /* WARNING: Subroutine does not return */
    exit(1);
  }
  local_b0 = 0;
  while (local_b0 < sVar1) {
    lVar2 = FUN_001007fa((ulong)(uint)(int)local_98[local_b0]);
    if (lVar2 != *(long *)(&DAT_003014e0 + local_b0 * 8)) {
      puts("Incorrect!");
                    /* WARNING: Subroutine does not return */
      exit(1);
    }
    local_b0 = local_b0 + 1;
  }
  puts("Correct!");
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}

入力文字の先頭から1バイトずつに対して、FUN_001007faの結果、DAT_003014e0の先頭から8バイトごとに比較し、同じであればよい。

long FUN_001007fa(char cParm1)

{
  long local_10;
  
  local_10 = 0;
  while ((local_10 != -1 && ((int)cParm1 != *(int *)(&DAT_00301020 + local_10 * 4)))) {
    if ((int)cParm1 < *(int *)(&DAT_00301020 + local_10 * 4)) {
      local_10 = local_10 * 2 + 1;
    }
    else {
      if (*(int *)(&DAT_00301020 + local_10 * 4) < (int)cParm1) {
        local_10 = (local_10 + 1) * 2;
      }
    }
  }
  return local_10;
}

FUN_001007faは複雑なので、1文字ずつブルートフォースして、フラグを割り出す。

def fun_001007fa(c, d):
    l10 = 0
    while (l10 != -1) and (ord(c) != ord(d[l10])):
        if ord(c) < ord(d[l10]):
            l10 = l10 * 2 + 1
        else:
            if ord(d[l10]) < ord(c):
                l10 = (l10 + 1) * 2
        if l10 >= len(d):
            return -1
    return l10

data1 = 'wf{_ny}\xffblr\xff\xff\xff\xff\xff\xffaei\xffot' + '\xff' * 16 + 'g' \
    + '\xff' * 6 + 'u' + '\xff' * 253 + '\x00' * 4
data2 = [0x01, 0x09, 0x11, 0x27, 0x02, 0x00, 0x12, 0x03, 0x08, 0x12, 0x09, \
    0x12, 0x11, 0x01, 0x03, 0x13, 0x04, 0x03, 0x05, 0x15, 0x2e, 0x0a, 0x03, \
    0x0a, 0x12, 0x03, 0x01, 0x2e, 0x16, 0x2e, 0x0a, 0x12, 0x06]

flag = ''
for i in range(len(data2)):
    for code in range(32, 127):
        if fun_001007fa(chr(code), data1) == data2[i]:
            flag += chr(code)
            break

print flag
flag{we_beleaf_in_your_re_future}

byte_me (Crypto 50)

$ nc crypto.chal.csaw.io 1003
8e3a4d70926b32ebb4b80e01189400f5086f25345940d66251babd2416e8eead8ffd5269278d9698812b891f577ff29c
Tell me something: 1
1
9dda04f64d140ce28198d71a17c9a16a264e34905a8e2b98de75bfbb62511843f9695b9b19b68e18a855fd4165a0759d8ea390f066b50eb675fffeff8495c3ea
Tell me something: 11
11
62dce69af355d465f4a088272724eff92f1c4ea0d91991823fccedaf1d94571bdfd97444cbfb5c6ed1b34a55899e2c3ebaaf99f38e84a6fd0a6642df7b712128
Tell me something: 111
111
abc5b8172151e716c60c523e39216edf9251a2a5cdb06e5750347aea2dc55c770f429cd2f7dd7fe3745678f9a5883ae2c03462ccf07acd173cdb0f5e301aded0
Tell me something: 1111
1111
53f47a70d13d8e20d1cc42c0a2325d0040212da4ec2809de85334b33cc6b042000e44eac9de2d4936504f9d473256119d1c243a49e01912ddcc6d23ef2a48a23
Tell me something: 11111
11111
857b2920911fb76c7e85cd19827ed6720049a29b122473108f213308d65e51440c533b2662c66c23cfc090435366f5ec5e8087e099425589c07996f8296d674e
Tell me something: 111111
111111
6d066dc3da495754785925f977d4608fbf82745fb42de4a14cf7611290ca1b25ed6ec3190c45cb32d73597863acff829ad25096ca29779d444c0577dacffa349
Tell me something: 1111111
1111111
2287829082fa2e8505e659b4334112e165950407b7ab634c61cad1948b1d86209f2192349315b3c582dee17c2921778172ce67fb239624c51e6923269fd224e8
Tell me something: 11111111
11111111
6158350a39f891f48c7aadd6016929e97f86432532d9efeb845bfc0db2042e4892423d64fd379ac0dea7528d983d6a039d18dee79e57138fff3851561de63909
Tell me something: 111111111
111111111
cdc2c9e31679b591e6aab11bfde5844badbd372bd6aecde3fc525b8216abb3d9a208e24b91039bd0959c0203fe587844b1ffbc6a86dfb84a5c404c4886028243
Tell me something: 1111111111
1111111111
0ea89afaacfba70ad2e826db9f07ee8d8a4d7d46228f6d80574b08bc7f17c3345f9d429b73e80185b613dd695fd8cc0c0265317e33ee102b19bc1526b84b9696
Tell me something: 11111111111
11111111111
8cb20a624038412d7aea7d0b09a3e5a1c8683a01bd349eee78d2cfacb308c8a267fa6f630031312508447603446ef1a5a63a57ba14017694cce47b8e08b81d44
Tell me something: 111111111111
111111111111
22d566a71035fec1b7c7e58ca65f64e23f2479b333df5d120194ea7f36360bdc218db8645397986cb5a53e4f31ea8900c63916fb939a745b5efb806323c0c416
Tell me something: 1111111111111
1111111111111
43fb5cdacd8325351d9288a49cd7a490756f30735e7ae58c85384630d75165abe7dcd9b4db0739d553e79e90e7a5438ce0593a91ded5f8ddd2d7db8ae76726b7
Tell me something: 11111111111111
11111111111111
6b117dc1904ba5a12a03e46ec2aebc058293d384389a2abcb752fac6b6e5c4f3432cb3e234c61b987401528b974a717e7157d9d202b615dbb015f73e7baaf38b
Tell me something: 111111111111111
111111111111111
6b117dc1904ba5a12a03e46ec2aebc057f61f330259ba1ccc54ac820b909598e8a2f7bc303ba9bfa81c0d66799e8bda3391c47ff2e503469dd03aa35d905adca
Tell me something: 1111111111111111
1111111111111111
6b117dc1904ba5a12a03e46ec2aebc0561b740da7797aaab1349a9bb74d1e37b086f25345940d66251babd2416e8eead8ffd5269278d9698812b891f577ff29c
Tell me something: 11111111111111111
11111111111111111
6b117dc1904ba5a12a03e46ec2aebc058bee55c773bc41bee18bd3a30a8e69b2264e34905a8e2b98de75bfbb62511843f9695b9b19b68e18a855fd4165a0759d8ea390f066b50eb675fffeff8495c3ea

AES暗号と推測できる。14バイト入力以降、暗号の最初の16バイトが同じ。

$ nc crypto.chal.csaw.io 1003
61835cf30e584280675ba53d13cc1ee9e6eacfc06b1a067d455e3f5ca9ec2ba1e38c5804b51b070717cf7116d9d6ad9a
Tell me something: 11111111111111111
11111111111111111
0071526a819c004eddfc086ca46cc5afaa1d3d0aafb3875c4f1b486779ee314123954b52b47f09098f87b3466f5679df3a4237df6e0bb82ade1e43acdc0c448b140c08213d26ff80ed32e0ee8e3d5c0c
Tell me something: 111111111111111111111111111111111 
111111111111111111111111111111111
0071526a819c004eddfc086ca46cc5af82f1811eb70021838da3a52c5c5934c0aa1d3d0aafb3875c4f1b486779ee314123954b52b47f09098f87b3466f5679df3a4237df6e0bb82ade1e43acdc0c448b140c08213d26ff80ed32e0ee8e3d5c0c

16バイト同じデータを追加してみる。暗号も最後16バイトは同じデータになった。ECBモードのようだ。
17バイト入力で、80バイトになったので、以下のような構成になっているはず。

0123456789abcdef
SSFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFP

0123456789abcdef
SSxxxxxxxxxxxxxx
xxxFFFFFFFFFFFFF
FFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFF
PPPPPPPPPPPPPPPP

1文字ずつはみ出させ、暗号結果を比較し、フラグを求める。そう思ってスクリプトを作成したがうまくいかない。アクセスするたびに先頭のsaltの長さが変わっていると思われる。

flag: 45バイト
x: 5バイトで80バイトの暗号化データになった場合

0123456789abcdef
SSSSSSSSSSSSSSxx
xxxFFFFFFFFFFFFF
FFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFF
PPPPPPPPPPPPPPPP

0123456789abcdef
SSSSSSSSSSSSSSxx
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxF
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxF
FFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFF
FFFFFFFFFFFFPPPP

0123456789abcdef
SSSSSSSSSSSSSSxx
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxF
FFFFFFFFFFFFFFFF
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxF
FFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFF
FFFFFFFFFFFFPPPP

このことを考慮してスクリプトを作成する。

import socket

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('crypto.chal.csaw.io', 1003))

data = recvuntil(s, '\n').rstrip()
print data
enc_len = len(data) / 2
print enc_len

#### research salt length ####
LEN_FLAG = 45

for i in range(16):
    data = recvuntil(s, ': ')
    try_text = '1' * (i + 1)
    print data + try_text
    s.sendall(try_text + '\n')
    data = recvuntil(s, '\n').rstrip()
    print data
    enc = recvuntil(s, '\n').rstrip()
    print enc
    if len(enc) / 2 != enc_len:
        salt_len = 63 - LEN_FLAG - i
        break

#### get flag byte by byte ####
flag = ''
for i in range(LEN_FLAG):
    for code in range(32, 127):
        head_blocks = 'x' * (16 * 4 - salt_len - i - 1) + flag + chr(code)
        try_text = head_blocks + 'x' * (16 * 4 - i - 1)

        data = recvuntil(s, ': ')
        print data + try_text
        s.sendall(try_text + '\n')
        data = recvuntil(s, '\n').rstrip()
        print data
        enc = recvuntil(s, '\n').rstrip()
        print enc
        enc4 = enc[32*3:32*4]
        enc8 = enc[32*7:32*8]
        if enc4 == enc8:
            flag += chr(code)
            break

print flag
flag{y0u_kn0w_h0w_B10cks_Are_n0T_r31iab13...}

count_on_me (Crypto 100)

$ nc crypto.chal.csaw.io 1002
Send me a random seed
1111222233334444
Encrypted flag:
FF�����q����+b뾅n�u��RĬ�a�Rر:][&G\�H�
����k�]��4+a��&ZXQy$T�&������E�pr��_���͜o
gL��Z*���^N�`�Pot ?�`��O��s���*lT���T��Di��w��
�J�j�Lֹ��J:������.�/�����.�س��^Ǩ�d�e	�l?�
�5@�ʰ�n#��9Na�
                ��vZ����3�x�	d��U��V�'bI��
Ww�	UE�C���I�</��d�=�n�u	]˝{p0��j����O��$�w
}~��9-��+:��yɴ����JmkR-�K����D���X��Ҩ)
�82���cn3�_(������Ҿ�G���4/=���syFp��f9Z'��$�
`[1��YB�� �H��2N�F�����X �S�b�#2�8�{	�s��:
��oRG�P��ߨ�GG�Y4��aq��xbx�3���A�&�~n
�f���|"��$�t3E�ƶ�Ay�ȯ�iA50���6Z���%����G^
�#7lgH�η�4��s�x��a���NxtӡK�]e��Q6��QUw���
��/=BTZ\mk�w�#۵����@
                     o��	3t���L�!����G�W
U��5ח,�S��������:�ǩ��_�&�L�n������^ɯ��h0
�����A.P���gF�j}���7dε�^SU�i�?V��0i�;mA�� �;
4F�\�M�*��P"�az����0��x2�^x��0�
                                     ]͓D�Q�
SR���l�q�F���B2'�^��{-���b�N��^��5�ٕ���Lɥ
�`�'�rq.%�g�`8�U��mP�w|:��S�t���h	���	E��
"UDO��Ɗ�=�
           ²��Zi�D����-���ž���v7��I����

��kZ�~�z�Q��|F���&��Ԡ�9���iT��L�#:��
                                         aG�
�k!ᬡB�:a�e�8Lل��'����ԧ�%i!e�
"\=>_%�3�!����0Ś3�5�z�#)�Bh��-�`)�a����i��
3�|\������
X��_��9���;��
               g���v8^z�����!}�
)2��qʦzo��΀��wN#��{�o�@(8��b�@����8M�,ƒ|
�B@����x��;\�
>m��GWYBg,�xc���ڎ�,��A3�
�t�N��ʝ�ιI��������ӳ����!�� ��i�}y��)
��'
   ��9���F"�ӂz�HLL �I�`���yՉĔqj�~(�fi8x�t
�u��V��T
���]#~��W:zf�_��qJխ���X�@5u
�|)e����|2�r���
                M�&�5KK�94����Dc�m�yr"�gϚYў
-�g��&'����w>
0�E��C3�O�jR7Όޅ���_��$m"�j
"'hy�v%%�Tw*�����0
                      6��[[�p��}���\����<���
�,����͌�?���&}֞�jMd��7B���L(]�
                               �\H-�'�t�Jo
k��=��lQm>T���Ƽk�{_��
#���e,������6/=�-?�
2�uCG���Mتp�i$�d�5 ��j�-����"�f�Y엕�o�<Z�P�R
}DG*ۧ�ɲ�%n�';1��~����B���_5��Y�m�~$���%aŹ
m�
  O>^7��:^��+_s���v\�s��(f,����r���i��v
�nYM�5њ�gc
�G#h����˘���ŒB/�}���&R���i
1
 R
,�ǖ�b~��:S�=�8
               J�
                 ��rKOӨx���ydw���.�?����
U,��t��éܗf�X
             �	�����Zm2��+�4g��'��{z'�"�T
J�:��<[.��W/ͩ[a>g�U�[���ié<�_����|d��
�3F�'�&�Ç�ޏ��W���5�)y�0��[�x�������.��
�ͮ���7��9q���"^v�-@�:C�SD6�~�s0�ȖVva�(lf2w,
1s��$0�Kp��8`�	�8vą*�MͿ6��5evg<;ϕ�U՜vEuMu��
)���ʘ��hM?KE/��&x����dTI��}��q��O�M�BkUӊO�u
�j��-�=e������r��L�
                    Ƀ��v��dOEm8U�b��/q�}�
'}��<7ٹJ�/�)t����D|�Ԛ�2����@Y2xG��^%F[�W��
��d�
    Ȁ��@"�I	��ȑd���:��#�-ߙ
�cA��\�$D
!Q���1�1z�=Q����G��MfU�7�5!�Ypsd�z
5�eFi@�����6b�H�p]x:��ZMQ5�B��iu��;����
;.�a/L�����:&6���+����ۃ�`�����'93�)S�琋���
�2
���x&��[�\X�UA�(Nu���6��|����^\�0V�����Y%�
��d�\�MNjq�;�p�7�܄�j�|����R�·��(�2��������
���K�����`��G�
��\xv��u,�U|��k1�L�
p���߈�)
#��5�D�)��{5�K�M��d�qQ�.Wa�NS1/^���
                                     cWg����
>W%˭E
     ���V)Z��)Ư@��8�雩Ȯ���m.α
�F.
   ����ʦ
�,#������6��5��eBA�$��'Y~��\��s�on����#}�|�$�
ڜP�����t�y�lP$,����&ß�/;�%١u�n�=S�C"�̣
`���y�
       )i��N
            ,�]���FC]�J��K�{Z��y��3����$b��
Ew��ƧE��r�ڢ��Ut㶛�rA
                        H�&�g�gN�Krc�v��
��9P�g�
       �f���NE�b.�T��G|hS���C��('eQ����r���
��B!w�4(�b䢎��m :���(׽0����c�&#534574;��mt�60�K����
x}I�bX=���=|��W��klnr1�
mq��G%��]{-]~���
                 ܟ���c�D���6����V$�T`����M"�L
�rnE��NO�I' �?�CVx�
��z���*�ɯ���s��֒�F&�Y4����4�?�wI��v2���
�H���2�U�J���1��o,
                    ��k�{s��xQ����1����+�c�
���E��D;���C�>�o-
h{&�I���
�;��2��r�YLyD��<
�_�Y^ai儹���y//j��X��
Q��/��
���L]���9&t�
               ��cJV�s1�Mv����ph���Ԣ��
S���N�9'=���W^�~�X˨����!�9AM>ˉ�䃽S���&�(
�Xѹ�T��B�(,�R��P擜Z��`#��I�ߞ���'�c�~��gP�
ޠՏC�?
�(&��#Ǔפ�ڧ�:w�/��ubpe]

���{K��C���p��%���}�������������YC���AbJ�,
1t]����׈��/U�ɦ��w�I�5(��T+.,�pU�K�����b
pr��o�'
���4ԧ����Q����~�3,9ϯ��0�����z� yOL�
�￲L/B��䩕��[���z��B�BhMw~Sy���`QȐq+��X�
�5=�h�2e�01g��>�6���w��[�Ym�e”�@n+�
à}'=�	��|��$b�rs��J�V�s\�����ju+���#�
3p��
2�.�q�
         �>�
ɷm�����7]�l��Ap  �>"�� �/�?��
`���G�Y��e��
j�6         U�"\x����NK

�i�5B���4u�
];}�L�/�Ķ�z���v�C�Va��y%���iDv���n\B)T�.��!�
�N�bS�Z\��;u]�G\�.�	�1i^L�
.���	��6�?S����	�
�?�����Ѣ�������<�Sz�~V��
                           ��7���}��7������
���2hƃ��>��r<A���Aպm
ܜ|R��n������B 
�&�ݽ�gG��"$���VRڃ_�Ė�J�d\�W
O��ؽ.���j����
�����6A����i��Z�;��-���+aaK�5�u	Te�y���p��7
hr����d7 
           � ^���w�Ҍ�-u{S���]ވ��Z%��80�f�
B�NJ��ڢNP&5G) &Qm�d4ר�`�S��0
                             �M h��p�ړ ��
]G7@��X���X3P�l�c�v��vϸk�HY#��9�@��x!Ak�Ox���a
�9w�R����Xf����fdi����%	$l$9�����p��@-��
���ƥ8�x�.��L&�l v<'d�P�fu��Ay:��"w!ɨ@�V
k�Z*m=o��Z[����r� ��06�K���#ZV~@j^6%=.�
�=b��<E ��7SRN��9�%#�����t٨��k��g��Y�ɖq�!�n
��-�fk�^%ĺ�S�x�E�eBx}�͜y���F�s�vYѻ)��
��z>lߒC��
S�x�e�B��P�r0���\.<e��)
)�BA
���=B5M�O���b��Lhs,:�l!�./_��[+�
�!'�HK9qD��J�nT#/M�����=K��r�m����������
�%�E�����W�xLF$��e��*��C����])�ҫ������WK���
����l ��:����Ɠ�*��;~~�W�
                          ��b�}�x��Q�
                                     ���	���
�_h‚N�i��!��6�8�3#��g�D��W�oGS�o�IՄ��,��
Okay bye

サーバ処理の概要は以下の通り。

・randomのseedを数値(16桁)で指定する。
・100回、以下を実行する。
 ・'Encrypted Flag: <flag>'の暗号化を表示

※暗号化
 ・blocks: 16バイトごとの配列(\x00パディング)
 ・4バイトランダム整数→16バイトリトルエンディアン
  aes.encrypt(16バイトリトルエンディアン) ^ block

暗号化データの長さから暗号化対象は3ブロック分であることがわかる。つまりランダム値を取得する処理を300回行うことになる。最初のブロックの平文が"Encrypted Flag: "と分かっているため、最初のブロックと別のブロックで、同じランダム値になれば、XORで平文を求めることができる。まずは300回の中で同じランダム値になるものを探す。

import random

init = 1000000000000000

for seed in range(init, init + 1000000):
    random.seed(seed)
    rv = []
    for i in range(300):
        rv.append(random.getrandbits(32))

    if len(set(rv)) != 300:
        print 'seed =', seed
        print list(set([x for x in rv if rv.count(x) > 1]))[0]

この結果は以下の通り。

seed = 1000000000026100
3908936488
seed = 1000000000027013
1797854874
seed = 1000000000242922
888417342
seed = 1000000000303303
2077519103
seed = 1000000000394343
1302182496
seed = 1000000000533328
2485904517
seed = 1000000000673051
3982022670
seed = 1000000000721327
3930063372
seed = 1000000000732217
3280084977
seed = 1000000000764544
2876139729
seed = 1000000000802182
3602748008
seed = 1000000000862650
982727507
seed = 1000000000890137
2088408045
seed = 1000000000958167
1824344903

さらに異なるブロック間で同じものを探す。

import random

seeds = [1000000000026100, 1000000000027013, 1000000000242922]
doubles = [3908936488, 1797854874, 888417342]

for i in range(len(seeds)):
    random.seed(seeds[i])
    print 'seed =', seeds[i]
    for j in range(300):
        rv = random.getrandbits(32)
        if rv == doubles[i]:
            print j, j % 3

この結果は以下の通り。

seed = 1000000000026100
113 2
253 1
seed = 1000000000027013
60 0
260 2
seed = 1000000000242922
12 0
121 1

この情報を元に復号する。

import socket
import random
from Crypto.Cipher import AES

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

def str_xor(s1, s2):
    return ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(s1, s2))

PT1 = 'Encrypted Flag: '

#### SEED = 1000000000242922 ####
SEED = 1000000000242922

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('crypto.chal.csaw.io', 1002))

data = recvuntil(s, '\n').rstrip()
print data
print SEED
s.sendall(str(SEED) + '\n')

data = recvuntil(s, '\n').rstrip()
print data

encs = []
for _ in range(100):
    data = s.recv(48)
    print data
    encs.append(data)
    data = recvuntil(s, '\n').rstrip()
    print data

data = recvuntil(s, '\n').rstrip()
print data

index1 = 12
enc1 = encs[index1 // 3][16*(index1%3):16*(index1%3)+16]
key = str_xor(PT1, enc1)

index2 = 121
enc2 = encs[index2 // 3][16*(index2%3):16*(index2%3)+16]
pt2 = str_xor(key, enc2)

#### SEED = 1000000000027013 ####
SEED = 1000000000027013

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('crypto.chal.csaw.io', 1002))

data = recvuntil(s, '\n').rstrip()
print data
print SEED
s.sendall(str(SEED) + '\n')

data = recvuntil(s, '\n').rstrip()
print data

encs = []
for _ in range(100):
    data = s.recv(48)
    print data
    encs.append(data)
    data = recvuntil(s, '\n').rstrip()
    print data

data = recvuntil(s, '\n').rstrip()
print data

index1 = 60
enc1 = encs[index1 // 3][16*(index1%3):16*(index1%3)+16]
key = str_xor(PT1, enc1)

index2 = 260
enc2 = encs[index2 // 3][16*(index2%3):16*(index2%3)+16]
pt3 = str_xor(key, enc2)

print
flag = pt2 + pt3
print flag

実行結果は以下の通り。

Send me a random seed
1000000000242922
Encrypted flag:
b謇D・
サ・-ムF]テ/゚ヒC゙woセセ遊返怕}ux|。ナヨ・ア]yヲ

ЖN「q)・ソ・
トp6d夷Aュ{ヘQ_        ク萼
傳ケヲ禅頓

l・暝ヨヲータD・e郗ッ・ゥ{cw・ゥ誣オ縉!ァサュョ牒ア頚・

M・*ー戓dンッソj・kW斈bVィ~ケ砕v4給・・・,t

pdQ0齦・Tqn憚・Y犲Rスfウez「0キ俸q・督皛;ネ鉈・

ス・ナnワY<瀅キ-ヒ"ヒe7テ9i・f}諫V+9チナ鯑6キワ3

0ヘrEKセ密リ~ &コ「フXFgN
乳・J4ンユEa&レD酢脾ン>」ハ

・P&]・yg~イトイU      ・6稹・・ta$・・
Aウo$IエNYr
        :
        :
フ*・hカSィz輩・B。1SVgIw*Jノマホ〔ソX?・・Bln

矍ヲ郝・ウチ$ウュ・jvワ・・須m ・イMA殄kヒ」V晄

スyスア}[2・Rン・暴Z^ャK・敵1ヒリ,ヘト・屑$Y・・,ョシ

・・#J這ー=嘴уモW・伴軽シ

ッAハムャソpヒ4サゥ&乗Syォ1苓サeエEュツレキvヲチr熬Q毆

ノwW3293禪;・・d+GW?ッA薜・z・€嶝コ燈hm遮滾

鳰媾チ{・ネロエ5フ・・1Wヨ8{ラモ簔?ム垳s・ユi・lリAヵM

0!ィ=□WM輦悔ニA・      ゥ・\ホPエョI衣テG#

Okay bye

flag{U_c@n_coUn7_0n_m3_l1kE_123}
flag{U_c@n_coUn7_0n_m3_l1kE_123}

DES 2 Bites (Crypto 200)

暗号化のイメージはこのような感じ。

plainText --(key1, DES暗号)--> byte --(key2, DES暗号) --> cipherText

DES2Bytes.txt、DES2Bytes.encが与えられているので、その組み合わせから鍵を求める必要がありそう。key1, key2ともDESのWeak keyが使われているとヒントが出たため、下記のURLの内容を参考に総当たりする。

https://en.wikipedia.org/wiki/Weak_key
https://crypto.stackexchange.com/questions/12214/can-you-explain-weak-keys-for-des
from Crypto.Cipher import DES
import binascii
import itertools

IV = '13371337'

def getNibbleLength(offset):    
    if str(offset)[0] == '9':
        return len(str(offset)) + 1
    return len(str(offset))

def decodeText(cipherText, offset):
    nibbleLen = getNibbleLength(offset)
    output = ''
    for i in range(0, len(cipherText), nibbleLen):
        val = int(cipherText[i:i+nibbleLen]) - offset
        if val > 10:
            val -= 1
        output += hex(val)[2]
    output = output.decode('hex')
    return output

def padInput(input):
    bS = len(input) / 8
    if len(input) % 8 != 0:
        return input.ljust((bS+1) * 8, '_')
    return input

def unpadInput(input):
    return input.rstrip('_')

def desEncrypt(input, key):
    cipher = DES.new(key, DES.MODE_OFB, IV)
    msg = cipher.encrypt(padInput(input))
    return msg

def desDecrypt(input, key):
    cipher = DES.new(key, DES.MODE_OFB, IV)
    msg = unpadInput(cipher.decrypt(input))
    return msg

#### get keys ####
with open('DES2Bytes.enc', 'r') as f:
    ct = f.read()

ct = decodeText(ct, 9133337)
ct = binascii.unhexlify(ct)

with open('DES2Bytes.txt', 'r') as f:
    pt = f.read()

vuln_keys = [
'0101010101010101',
'FEFEFEFEFEFEFEFE',
'E0E0E0E0F1F1F1F1',
'1F1F1F1F0E0E0E0E',
'0000000000000000',
'FFFFFFFFFFFFFFFF',
'E1E1E1E1F0F0F0F0',
'1E1E1E1E0F0F0F0F',
'011F011F010E010E',
'1F011F010E010E01',
'01E001E001F101F1',
'E001E001F101F101',
'01FE01FE01FE01FE',
'FE01FE01FE01FE01',
'1FE01FE00EF10EF1',
'E01FE01FF10EF10E',
'1FFE1FFE0EFE0EFE',
'FE1FFE1FFE0EFE0E',
'E0FEE0FEF1FEF1FE',
'FEE0FEE0FEF1FEF1',
'1F1F01010E0E0101',
'E00101E0F10101F1',
'011F1F01010E0E01',
'FE1F01E0FE0E01F1',
'1F01011F0E01010E',
'FE011FE0FE010EF1',
'01011F1F01010E0E',
'E01F1FE0F10E0EF1',
'E0E00101F1F10101',
'FE0101FEFE0101FE',
'FEFE0101FEFE0101',
'E01F01FEF10E01FE',
'FEE01F01FEF10E01',
'E0011FFEF1010EFE',
'E0FE1F01F1FE0E01',
'FE1F1FFEFE0E0EFE',
'FEE0011FFEF1010E',
'1FFE01E00EFE01F1',
'E0FE011FF1FE010E',
'01FE1FE001FE0EF1',
'E0E01F1FF1F10E0E',
'1FE001FE0EF101FE',
'FEFE1F1FFEFE0E0E',
'01E01FFE01F10EFE',
'FE1FE001FE0EF101',
'0101E0E00101F1F1',
'E01FFE01F10EFE01',
'1F1FE0E00E0EF1F1',
'FE01E01FFE01F10E',
'1F01FEE00E01FEF1',
'E001FE1FF101FE0E',
'011FFEE0010EFEF1',
'01E0E00101F1F101',
'1F01E0FE0E01F1FE',
'1FFEE0010EFEF001',
'011FE0FE010EF1FE',
'1FE0FE010EF1FE01',
'0101FEFE0101FEFE',
'01FEFE0101FEFE01',
'1F1FFEFE0E0EFEFE',
'1FE0E01F0EF1F10E',
'FEFEE0E0FEFEF1F1',
'01FEE01F01FEF10E',
'E0FEFEE0F1FEFEF1',
'01E0FE1F01F1FE0E',
'FEE0E0FEFEF1F1FE',
'1FFEFE1F0EFEFE0E',
'E0E0FEFEF1F1FEFE'
]

for keys in itertools.product(vuln_keys, repeat=2):
    key1 = binascii.unhexlify(keys[0])
    key2 = binascii.unhexlify(keys[1])
    byte = desEncrypt(pt, key1)
    cipherText = desEncrypt(byte, key2)
    if cipherText == ct:
        break

print 'key1 =', key1.encode('hex')
print 'key2 =', key2.encode('hex')

#### decrypt ####
with open('FLAG.enc', 'r') as f:
    ct = f.read()

ct = decodeText(ct, 9133337)
ct = binascii.unhexlify(ct)

enc_flag = desDecrypt(ct, key2)
flag = desDecrypt(enc_flag, key1)
print flag

実行結果は以下の通り。

key1 = fe1ffe1ffe0efe0e
key2 = fe01e01ffe01f10e
Er ehrbaren nochmals bummelte mi la abziehen. Sah hing mirs gewi gro sie was fast hand. Oder zum ruh man ists teil kind zaun. Wahres ist verlor das jungen der wurden dem spahte. Oha ganz gang und bart hast neu zur sind. Leer wer und bett ehe tur herr. Gegenuber wer vermodert ihm belustigt argerlich. Zarte ri nacht zehen licht es. Wo du schleiche sudwesten getrunken fu. Wohnzimmer so regungslos nettigkeit aufzulosen wu. Ubelnehmen bis kartoffeln stockwerke das des dazwischen gro aufgespart. Gegen haute ihr kommt vor euern. Ich hinter schwer bundel sog dir linken. Doch ja eile so warf du haar kein wenn zu. Du ja schlanken te weiterhin zerfasert besserung la ausblasen geheimnis. Vergrast funkelte trostlos ab menschen da kollegen. Steh sich bart zu bett stie mehr ja. Ewige sie die oha kalte steht. Ein schonheit anzeichen man wie gru spazieren bewirtung ausdenken. Heiland heruber pa je so trocken. Tal nachdem schritt alt traurig. Mitwisser vom gegenteil bin ten uberhaupt. Gar aus stunde messer schlie. Behutsam zog ehrbaren geholfen ihm eigentum mir. Schleiche je se schwachen angerufen. Gro schoner bin anrufen langsam offenen nachdem fingern. Birkendose lattenzaun so geschlafen vorsichtig vielleicht am bodenlosen. Ture ja se floh ganz. Geborene schmalen tadellos ort hob sag geholfen vom schlafen hinunter. Zeigte nieder bin weg die mutter wie kummer fellen lassig. Also nun igen sog wei brot. Hufschmied mut man wohlgefuhl mir grasgarten. Eine arme ihm also tat zum dank hut furs. Madchens brannten nur auf gerberei man heiraten hindurch. Langsam ihr schlank wandern gar mag melodie. Bis ist nur vom herein heftig bilder. Herkommen anzeichen bis vor ernsthaft ein argerlich meisterin. Wurden spater uns liegen bin ein des spital. Unbemerkt ernstlich nebendran lohgruben unendlich aufraumen ich ton. Verlohnt he zwischen ab in einander pa. Bodenlosen he zu vorpfeifen dachkammer. Schwachem mannsbild ri schreibet um. Eia dessen lustig weg sachen neckte suchte. Wendete zuhorer dritten ein nachdem antwort gesicht tur den ton. Leuchtete neugierig dahinging vergnugen man ehe. Kam nachtessen was vertreiben brotkugeln see. Unendlich die auf hellroten kreiselnd kellnerin schonsten. Um du mischen schurze melodie ei geschah. Was froh ihn als wach wie sehr tief. Abwarts brachte mu stillen lacheln nachdem la te. Des schuttelte drechslers stockwerke ehe hausdacher. Sich auch zu ei dies chen sa he gern. <<flag{~tak3_0n3_N!bbI3_@t_@_t!m3~}>> Am knopf viere sa es essen te. Bis lag mehrmals launisch nirgends eck oha. Ab im er brotlose he herunter prachtig liebsten. Mancherlei so lattenzaun scherzwort em zu aufgespart ob dammerigen. Zusammen abraumen brauchte tut bezahlen behalten ton ige. Wach gang ein auf ihn ding froh ganz leid. Mi geblendet ab polemisch kammertur um pa verstehen. Wochen wahres du fu katzen mi gelang suchte zu. Vorwarts zu bummelte sa brauchen bi an. Sagen begru tat fromm man lie dabei uns. Kennt reden zahne da im recht leuen mager. Handen an zu sachte werdet ku durren gefegt. Sie zaunpfahle abendsuppe verbergend gesprachig ein aufzulosen auskleiden. Braunen auffiel stunden tag ers. Hab blatt durch lernt ferne die nur. Beinahe bestand alt saubere ton wahrend sondern. Wachsamen holzspane in kellnerin filzhutes um he. Du verdrossen in launischen da es lattenzaun. Bodenlosen ri pa zu bescheiden fu feierabend. Pa bummelte im so em eigentum gebogene. Anzeichen in schreiben so kraftiger bekummert aufstehen. Geschlafen nachtessen ach neu wer aufzulosen den bescheiden nettigkeit. Sitzt darum ruhig neu aus zog flo. Geschah lag ins saubere des lustige raschen dritten lichten hin. Man aller trost herrn roten war armen ihr lag.

復号結果の中にフラグが紛れ込んでいる。

flag{~tak3_0n3_N!bbI3_@t_@_t!m3~}

SuperCurve (Crypto 300)

$ nc crypto.chal.csaw.io 1000
a = 1
b = -1
p = 14753
n = 7919
Public key: (5169, 6687)
What is the secret?

楕円曲線上のDLPの問題。orderが小さいので、総当たりする。

import socket
from supercurve import SuperCurve, curve

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('crypto.chal.csaw.io', 1000))

curve = SuperCurve(
    field = 14753, order = 7919,
    a = 1, b = -1, g = (1, 1),
)

base = curve.g

data = recvuntil(s, '?').rstrip()
print data
pub = eval(data.split('\n')[4].split(': ')[1])

for sec in range(1, curve.order):
    mul = curve.mult(sec, base)
    if mul == pub:
        print sec
        break

s.sendall(str(sec) + '\n')
data = recvuntil(s, '\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data

実行結果は以下の通り。

a = 1
b = -1
p = 14753
n = 7919
Public key: (2242, 12492)
What is the secret?
3397

flag{use_good_params}
flag{use_good_params}

Fault Box (Crypto 400)

$ nc crypto.chal.csaw.io 1001
====================================
            fault box
====================================
1. print encrypted flag
2. print encrypted fake flag
3. print encrypted fake flag (TEST)
4. encrypt
====================================
1
762D2A4856553D24DE9110BBA2DDBE1AAB44890BAAADB6CA30529BC2A7FF5CF408EEBBFBA5E5A909041F104FB67D9E61D96660BAE342A830A87409FD73386831FB1894C9F13B91F6762E0689E8558B22A88A8EECDD69ED9DC0845C918930FC3962D49E8E3DBA065B5AAB6EC3F4ED77F6C04AF0EDD72AE5704D944DAAD93B9C4DB48F5969BD96A88FF54AC3E46DBD64133345958501A467E28DFFB3F42533C4D58520B4394FA4A45AB39888D5403D9B300FE9EA7AD2E2A36ACFED57ECD0AAA354D0521D7BD49760A2AA66DE84BBEEEE55C86340D0251F956DC89DE5C2D7695C1868A0BA2EDB1F759BB423DEDB4AB8D7224B44186B6D5B3428D8C44D8E494F7D7D
====================================
            fault box
====================================
1. print encrypted flag
2. print encrypted fake flag
3. print encrypted fake flag (TEST)
4. encrypt
====================================
2
807BEFEDF208BB8F7D950D266C8D7291C9408BB3FF7A9C6670A1D51B9FEE1DD9C2DD2A337860EC5FB1A92293CF8A4A5439867E04BFC6D60FC180DECBD206A6D5451C1AC8DFD396E0ABF20386A092B96668F6DD7EB875FC81173E7B420A95FA9CA70269F51045CA189E9BCA87CACBBF23179F2B1B1B5D5E3F6B2F82DE0904A39E06AE6FFE8D699B38815C2D7C28D9BD5D26FBF57B3898A8E41E828DE881EABAF6B2BC5519561ED3724FDFD38D8613E51C01E8F8432E15DB44DBCC94D0C536BC7E7AF01FD65F7BEB3098A220146A86E131B06173DF2F189C0E649ACED38527EE36B78899BFF172F25BB690981865DA127FD0261671F7442035485D46C951A91EED
====================================
            fault box
====================================
1. print encrypted flag
2. print encrypted fake flag
3. print encrypted fake flag (TEST)
4. encrypt
====================================
3
3FE0F12C0A5742D6C62740CD448309DE810EE3C2F10A675F02090F1142075DF6903309509BD8EF5844329D0E12B9AEB9DCA565A2F000684FFA8A5813B32031D6814A302CAB5C9BB2D2475C6ED625D527E43D279DDBC76FF9DBAFF1D97F2C9C7C939AF9096AB0BC4AFC1CC6AE150EDF18CB567D0F2B8DBDBAAF1CB4A68476E5245960FF058E4BD3E7A26FE8F0E0FEB8C6237C4088F9D9A8990B28FC0BB4C5415A76C6074F72AE79302D9B90B0874C2DA17317E2A5CDB303BB24076C63BC4F55C178CE622BC2634794D5EDF85AF2D19F84F724D1CFE2F9F7AB8E47CF55A69546B639D9119F14A1C9270599B0ABC371F481D6B1557E8B26B2A03B6368415D784FC5
====================================
            fault box
====================================
1. print encrypted flag
2. print encrypted fake flag
3. print encrypted fake flag (TEST)
4. encrypt
====================================
4
input the data:0
EDE7070934B122B7B106E715E536EAA5874E7E571D83E3EE4ADFC46BF413898819F86630C906621F4203A99FFA19DDBE485A4B4303395E171C189301C73960A87B1D73FB7D5D4C9FAA2B212742D1D148F953752CE05F90EFAAB06565F35ECDF6AA98A450C3009C860EA9582DA5CBD9954419D46935F3934A528D0D98A1F09D060C725AD04382BBCB06498E9AF6CD925D5553933459BBB3C7ABBBFDD758C749E4C6468119342399FB701BC18B24D7DE753227EF51FA7BF2A735E35DA8E07BBAFC9182299A7A3B0287B3E4D2A93072B6A594CD55F35271D6EDA99BB9E8D1181A4C3252F73054CC6619B95550B04B1A98D4A42CDE8C155759B428637317610E657
====================================
            fault box
====================================
1. print encrypted flag
2. print encrypted fake flag
3. print encrypted fake flag (TEST)
4. encrypt
====================================
4
input the data:0
EDE7070934B122B7B106E715E536EAA5874E7E571D83E3EE4ADFC46BF413898819F86630C906621F4203A99FFA19DDBE485A4B4303395E171C189301C73960A87B1D73FB7D5D4C9FAA2B212742D1D148F953752CE05F90EFAAB06565F35ECDF6AA98A450C3009C860EA9582DA5CBD9954419D46935F3934A528D0D98A1F09D060C725AD04382BBCB06498E9AF6CD925D5553933459BBB3C7ABBBFDD758C749E4C6468119342399FB701BC18B24D7DE753227EF51FA7BF2A735E35DA8E07BBAFC9182299A7A3B0287B3E4D2A93072B6A594CD55F35271D6EDA99BB9E8D1181A4C3252F73054CC6619B95550B04B1A98D4A42CDE8C155759B428637317610E657
====================================
            fault box
====================================
1. print encrypted flag
2. print encrypted fake flag
3. print encrypted fake flag (TEST)
4. encrypt
====================================

サーバの処理の概要は以下の通り。

p, x = gen_prime()
- base: 1024bitランダム整数
- off: base + offが素数となる最小値のoff
- p: base + off
- x: off

q, y = gen_prime()
- base: 1024bitランダム整数
- off: base + offが素数となる最小値のoff
- q: base + off
- y: off

n = p * q
e = 0x10001
phi = (p-1) * (q-1)
d = inverse(e, phi)

fake_flag = 'fake_flag{(yの32バイト16進数大文字)}'
→yはあまり大きい数字にならない。

■enc_flag
pow(FLAG, e, n)
-> 16進数大文字表記

■enc_fake_flag
pow(fake_flag, e, n)
-> 16進数大文字表記

■enc_fake_flag_TEST
ep = inverse(d, p-1)
eq = inverse(d, q-1)
qinv = inverse(q, p)
c1 = pow(fake_flag, ep, p)
c2 = pow(fake_flag, eq, q) ^ x
h = (qinv * (c1 - c2)) % p
c = c2 + h*q
-> 16進数大文字表記

■enc_msg
pow(input, e, n)

enc_msg以外を2回実行すると、パラメータがリセットされるので、1~3のうち得られないデータがある。また、タイトルからRSA-CRT Fault Attackを利用するような気がする。いろいろ試したり、検討したりした結果、以下の方針とする。

1.enc_msgで2,4,16の暗号化数値を取得し、Nを算出する。
2.enc_flagでフラグの暗号化数値を取得する。(これは外せない)
3.enc_fake_flag_TESTでfake_flagの暗号化データ(c2が誤っている)を取得する。
4.すでに2回enc_msg以外を使用しているので、enc_fake_flagで得られるはずの数値はブルートフォースで適切なものを探す。
5.3,4の結果からRSA-CRT Fault Attackを使って、Nを素因数分解する。
6.5の結果から2で取得した暗号化数値を復号する。
import socket
from Crypto.Util.number import *

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

def egcd(a, b):
    x,y, u,v = 0,1, 1,0
    while a != 0:
        q, r = b//a, b%a
        m, n = x-u*q, y-v*q
        b,a, x,y, u,v = a,r, u,v, m,n
    gcd = b
    return gcd, x, y

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('crypto.chal.csaw.io', 1001))

data = recvuntil(s, 'encrypt\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data

#### calculate N ####
try_rsa_enc = []
for m in [2, 4, 16]:
    print '4'
    s.sendall('4\n')
    data = recvuntil(s, 'data:')
    print data + chr(m)
    s.sendall(chr(m) + '\n')
    data = recvuntil(s, '\n').rstrip()
    print data
    enc = int(data, 16)
    try_rsa_enc.append(enc)

    data = recvuntil(s, 'encrypt\n').rstrip()
    print data
    data = recvuntil(s, '\n').rstrip()
    print data

diff1 = (try_rsa_enc[0]) ** 2 - try_rsa_enc[1]
diff2 = (try_rsa_enc[1]) ** 2 - try_rsa_enc[2]

N, _, _ = egcd(diff1, diff2)
e = 0x10001

for i in range(100, 1, -1):
    if N % i == 0:
        N = N / i

#### get encrypted flag ####
print '1'
s.sendall('1\n')
data = recvuntil(s, '\n').rstrip()
print data
c = int(data, 16)
data = recvuntil(s, 'encrypt\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data

#### get fake flag (FAULT) ####
print '3'
s.sendall('3\n')
data = recvuntil(s, '\n').rstrip()
print data
c2 = int(data, 16)

#### calclate p, q (Brute Force) ####
for y in range(4096):
    fake_flag = 'fake_flag{%s}' % (('%X' % y).rjust(32, '0'))
    c1 = pow(bytes_to_long(fake_flag), e, N)
    p, _, _ = egcd(pow(c2 - c1, e, N), N)
    if p > 1 and p < N:
        q = N / p
        break

assert p * q == N

#### decrypt flag ####
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, N)
flag = long_to_bytes(m)
print flag

実行結果は以下の通り。

====================================
            fault box
====================================
1. print encrypted flag
2. print encrypted fake flag
3. print encrypted fake flag (TEST)
4. encrypt
====================================
4
input the data:
851D6D9C07943581FF5252E8A885C64600668D05D26DB97687B5AB68531E667786CE792E57916ECCAC637C0D895F57ED31A1CD4A8B4CA78AD54F13C66005DE2E2765804FF61A2258544F79E611E78634FE909558C2F419867E945B9FD7CF516C627401DD1C0BBD8BD265F9E6110105609270A84D8A9BEEDE3E9BD94D38C888AEE4B6EC29605DD532B193315BE4A2C78943DD6B662058D93BBE3EE7B0B7D6A54C3309F7375986F4371E521DA68700033F407E2405BFA82D7D5BCE8D0F5D2FF2AC3DBBFCE4A1F782C60E225DDB4973C4E1D6B10CE8E23D242362E7CB838A2A36733F585FB0DBD92755F8569FB595DD81B9AE0999A330C6E9A33361E67F1D5EF8C
====================================
            fault box
====================================
1. print encrypted flag
2. print encrypted fake flag
3. print encrypted fake flag (TEST)
4. encrypt
====================================
4
input the data:
17831212B2DB05436E7E3021D12089C78223853577606D6B2421E1AA06E65AA0934D214F64ECA61C12C508544560FCB98BC177286D00BB65A2FB49242E11B4EA5E05AAB2A89DBBF20B6FD78AD7436AFE0F415BF4AE64B0D8CEFC587D60C614E5922829EADD754EE377C9E15E03D7C1E8E545452BAED350D5DECA6E0CE65E72DD9954D15321C6B9A557A2FF52631B0C05917E341925D7CFD7E6DEDDBBB468E4F99EFEA89EBE3F213A9CCBD73980C681B217B326FCFC2355545596B76B4119137F73C40062DEF6DC0F1F57A68F4C0A61F95979854A63DCDC4110C0D47376D7F03FADC9CBC82A4B6BA2EF3D70274422228A943C178D8DF64D47C5DBA42F92F2A602
====================================
            fault box
====================================
1. print encrypted flag
2. print encrypted fake flag
3. print encrypted fake flag (TEST)
4. encrypt
====================================
4
input the data:
131293C26592B866F22504428549D0457964E9617D321BEBE7F6A48778BB93D681396BF4D773D4C1F992CD6EF670C8A38067F0A55BC594582277B7651905D40A88CC6F405CB5F31A88836FF6CF8B50F647B5D412DB5689EACFAB59C3DF61D184666CC2B67B31FEEEA58F18485E3851D7EE8BF8D24E873F91780AEDF570AFA966546B0659E4ED16E6A83A2570EFDC59D6BAF9DDB1FB1E39D6D9FD275A281E7B376634D68C559B3365179E597A504AFF430DCC73CBFB99D2210A5A1533A149ABCE64163E362AB06A066AF4AF0D8BFC69A5437050D9266AA2588673E3111D8745BB02DCF59B55B7F3F09A35C10F67D1CAC55A6C4B11B58776B4C974266CBF4E95F9
====================================
            fault box
====================================
1. print encrypted flag
2. print encrypted fake flag
3. print encrypted fake flag (TEST)
4. encrypt
====================================
1
CC11224FBCD599ADF47C4B06965B61E2A98C031DFE3A0CBFAD4C01FF7A99D4715EA6C3882305E30369779371A6E4F16C9D0484995ED74D971E21B59D4FD28E95A569A4F54E87694714FCBAF368B5DD6A723292AA26F51BA444585A9FFC9DDB5BA8B4168E64E3310FE6696E6E1E04BC19A872A3E28558CC2DD35D4F3D73BA3BA7AC2303F2A279C20D04D339E3CF6EF10B9B3B97C9238E5A93FCD2722DD00C51AD7324AB0DC5C86310B12FF95D4C183C3AF3214C1D08BE88181F7C08FC397871A212A6997C6603792AF769BFB616BA17BC4351804D9ACB1FCE8A078EFD95240A4AC7E50F4A1E6D982ECD8A5B9C29AFEF44C85E30C28C19142868C0B11086DE901
====================================
            fault box
====================================
1. print encrypted flag
2. print encrypted fake flag
3. print encrypted fake flag (TEST)
4. encrypt
====================================
3
20B1A2D3D32FD90013A160B644E3B438DEDE2D49D03C22E3236A4B0CE7B7E50F3EF31CF52D32FB7E65C38EE09E9A035E523FA3A3260079B756B089D9DB7B106AC6EBD0A69F49DC0EAB76239818B385D43B562C76823A726B8051F283E513823EA9C6E81E2F80D3661B5974667244FFEDA882DAB1D693D664CD6B0510C6F38D6C43C79EA09CDE55435DD33A720DD810ABC74915FC6FEA58EC83CE4A6DE257B1B47B1765EFB1E4A578A3FD657A691DCBD4A4C450B90BE5E3AFB6015E79620B3C188C0C7852008C258F6DD662D13214F05FE17660C1AA545D9FC5F1243E573D484AF832E53C9CDA555672DB6AB333B0AEEFE8D0BA529C6874162E8EB4B60753ED49
flag{ooo000_f4ul7y_4nd_pr3d1c74bl3_000ooo}
flag{ooo000_f4ul7y_4nd_pr3d1c74bl3_000ooo}