-
-
[原创] KCTF 2023 第八题 wp - 98k
-
2023-9-17 15:44 2086
-
代码量非常少,不过编译器优化得到逻辑很乱。整理下逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | int check( char * input, int length) { char _flag[10][4]; char key[5][4]; for ( int i = 0; i < length; i++) { int j = trans(input, i); // 0~9 if (i & 1) assert (j == 0); else assert (j != 0); if (!check(key, j)) j = 9; for ( int a = 0; a < 5; a++) { for ( int b = 0; b < 4; b++) { key[a][b] ^= _flag[j][b]; } } if (j == 9) { _flag[9][1] = ~_flag[9][1] & 0x7f; } } int a = 0; int b = 0; for ( int i = 0; i < 5; i++) { a ^= key[i][0] ^ key[i][2]; b ^= key[i][1] ^ key[i][3]; } return (a & 0x1f) == 0 && (b & 0x1f) == 0; } |
所以问题大致是这样的,给定了 10 个初始比特值,还给了 10 组(实际上是 11 组)比特值,每次从这 10 组中有限制的选择一组出来,异或到初始比特值中,要求最后使 10 个比特值都变成 0 。
将初始比特值和可选择异或的比特值计算出来得到:
1 2 3 4 5 6 7 8 9 10 11 12 | 01000 10101 00000 00001 00000 00010 00000 00100 00000 01000 00000 10000 00001 00000 00010 00000 00100 00000 01000 00000 10000 00000 |
也就是每次可以改变 1 比特。限制条件为每隔一轮需要将最低比特改掉;除最低比特外,能修改某个比特位的条件就是它后续的比特位最高位为 1 ,后面的全是 0 (上面代码中 check 的检查)
根据这些限制条件就可以手动构造,再转成输入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | #!/usr/bin/env python3 def check( input ): _flag = list (b 'flag{BzcZDnfNIqmQCtkTGlwLyDYeiHIjxSXwkRKzpFPv}\x00\x00' ) key = list (b 'Can you crack me?^olo^\x00\x00' ) v7 = _flag[ 42 ] for i in range ( len ( input )): c = input [i] v9 = (c + ( 0xFFFEC610 >> (i % 31 ))) % 10 assert (i & 1 ) = = int (v9 < 1 ) v26 = 0 for j in range ( 4 ): v26 | = (key[ 16 + j] ^ key[ 12 + j] ^ key[ 8 + j] ^ key[ 4 + j] ^ key[j]) << ( 8 * j) # print(hex(v26)) # print(((v26 >> 16) ^ v26) & 0x1f, ((v26 >> 24) ^ (v26 >> 8)) & 0x1f) while v9 > = 1 : if v9 > = 6 : if (v26 ^ (v26 >> 16 )) & 0x1f ! = 0 : v9 = 9 break else : v12 = (v26 >> 24 ) & 0xff v13 = 13 - v9 v14 = (v26 >> 8 ) & 0xff else : v12 = (v26 >> 16 ) & 0xff v13 = 8 - v9 v14 = v26 & 0xff # print(bin(v12)[2:].rjust(8, '0'), bin(v14)[2:].rjust(8, '0'), v13) if (((v14 << v13) + 0x80 ) & 0xff ) ! = ((v12 << v13) & 0xff ): v9 = 9 break if v9: print (v9, end = ' ' ) for i in range ( 5 ): for j in range ( 4 ): key[ 4 * i + j] ^ = _flag[ 4 * v9 + 5 + j] if v9 > 8 : v7 = ~v7 & 0x7f _flag[ 42 ] = v7 # 42 - 5 = 37, (9, 1) print () v26 = 0 for j in range ( 4 ): v26 | = (key[ 16 + j] ^ key[ 12 + j] ^ key[ 8 + j] ^ key[ 4 + j] ^ key[j]) << ( 8 * j) print ( hex (v26), bin (((v26 >> 16 ) ^ v26) & 0x1f )[ 2 : ].rjust( 5 , '0' ), bin (((v26 >> 24 ) ^ (v26 >> 8 )) & 0x1f )[ 2 : ].rjust( 5 , '0' )) if ((v26 >> 16 ) ^ v26) & 0x1f ! = 0 or ((v26 >> 24 ) ^ (v26 >> 8 )) & 0x1f ! = 0 : return False else : return True ''' flag = [0x3f] * 62 for i in range(len(flag)): if i & 1: flag[i] = (10 - (0xFFFEC610 >> (i % 31))) % 10 else: flag[i] = (9 - (0xFFFEC610 >> (i % 31))) % 10 while flag[i] < 0x30: flag[i] += 10 print(bytes(flag)) # 38968638916054237581658165816584705954700796332849074907490749 print(check(bytes(flag))) ''' key = b 'Can you crack me?^ol' s = [ 0 ] * 2 for i in range ( 2 ): for j in range ( 0 , len (key), 4 ): s[i] ^ = (key[j + i] ^ key[j + i + 2 ]) & 0x1f _flag = b 'BzcZDnfNIqmQCtkTGlwLyDYeiHIjxSXwkRKzpFPvp9Pv' # _flag = b'BzcZDnfNIqmQCtkTGlwLyDYeiHIjxSXwkRKzp9Pv' t = [] for i in range ( 11 ): t.append([]) for j in range ( 2 ): t[ - 1 ].append((_flag[ 4 * i + j] ^ _flag[ 4 * i + j + 2 ]) & 0x1f ) print ( ' ' .join( bin (i)[ 2 :].rjust( 5 , '0' ) for i in s[:: - 1 ])) print () for _t in t: print ( ' ' .join( bin (i)[ 2 :].rjust( 5 , '0' ) for i in _t[:: - 1 ])) flag = [] values = [ # 01000 10101 1 , # 01000 10110 2 , # 01000 10011 1 , # 01000 10000 5 , # 01001 10001 1 , # 01001 10010 2 , # 01001 10111 1 , # 01001 10100 3 , # 01001 11101 1 , # 01001 11110 2 , # 01001 11011 1 , # 01001 11000 4 , # 01001 01001 1 , # 01001 01010 2 , # 01001 01111 1 , # 01001 01100 3 , # 01001 00101 1 , # 01001 00110 2 , # 01001 00011 1 , # 01001 00000 6 , # 01011 00001 1 , # 01011 00010 2 , # 01011 00111 1 , # 01011 00100 3 , # 01011 01101 1 , # 01011 01110 2 , # 01011 01011 1 , # 01011 01000 4 , # 01011 11001 1 , # 01011 11010 2 , # 01011 11111 1 , # 01011 11100 3 , # 01011 10101 1 , # 01011 10110 2 , # 01011 10011 1 , # 01011 10000 5 , # 01010 10001 1 , 2 , 1 , 3 , 1 , 2 , 1 , 4 , 1 , 2 , 1 , 3 , 1 , 2 , 1 , 7 , # 01110 00001 1 , 2 , 1 , 3 , 1 , 2 , 1 , 4 , 1 , 2 , 1 , 3 , 1 , 2 , 1 , 5 , # 01111 10001 1 , 2 , 1 , 3 , 1 , 2 , 1 , 4 , 1 , 2 , 1 , 3 , 1 , 2 , 1 , 6 , # 01101 00001 1 , 2 , 1 , 3 , 1 , 2 , 1 , 4 , 1 , 2 , 1 , 3 , 1 , 2 , 1 , 5 , # 01100 10001 1 , # 01100 10010 2 , # 01100 10111 1 , # 01100 10100 3 , # 01100 11101 1 , # 01100 11110 2 , # 01100 11011 1 , # 01100 11000 4 , # 01100 01001 1 , 2 , 1 , 3 , 1 , 2 , 1 , # 01100 00000 8 , # 00100 00001 1 , 2 , 1 , 3 , 1 , 2 , 1 , 4 , 1 , 2 , 1 , 3 , 1 , 2 , 1 , 5 , # 00101 10001 1 , 2 , 1 , 3 , 1 , 2 , 1 , 4 , 1 , 2 , 1 , 3 , 1 , 2 , 1 , 6 , # 00111 00001 1 , 2 , 1 , 3 , 1 , 2 , 1 , 4 , 1 , 2 , 1 , 3 , 1 , 2 , 1 , 5 , # 00110 10001 1 , 2 , 1 , 3 , 1 , 2 , 1 , 4 , 1 , 2 , 1 , 3 , 1 , 2 , 1 , 7 , # 00010 00001 1 , 2 , 1 , 3 , 1 , 2 , 1 , 4 , 1 , 2 , 1 , 3 , 1 , 2 , 1 , 5 , # 00011 10001 1 , 2 , 1 , 3 , 1 , 2 , 1 , 4 , 1 , 2 , 1 , 3 , 1 , 2 , 1 , 6 , # 00001 00001 1 , 2 , 1 , 3 , 1 , 2 , 1 , 4 , 1 , 2 , 1 , 3 , 1 , 2 , 1 , 5 , # 00000 10001 1 , 2 , 1 , 3 , 1 , 2 , 1 , 4 , 1 , 2 , 1 , 3 , 1 , 2 , 1 , ] values + = [ 9 , 9 , 9 , 9 ] * 0 for i in range ( 2 * len (values)): if i & 1 : flag.append(( 0 - ( 0xFFFEC610 >> (i % 31 ))) % 10 ) else : flag.append((values[i / / 2 ] - ( 0xFFFEC610 >> (i % 31 ))) % 10 ) while flag[ - 1 ] < 0x30 : flag[ - 1 ] + = 10 print (bytes(flag)) print (check(bytes(flag))) # 582606981190746395118531851185249089744027265368693769576937697816165851808443150195011501950410798490871663488927792799277958360668112074539521851185318514909974002766535869476937695769681626582180144305010501950115040079949037162348792789277927995826067811907483951185218511853490897410272653986937694769376988161658318084433501950105019504207984904716634829277927892779584606681100745395418511852185149009740027365358697769376947696816365821809443050125019501050400790490371673487927 # 58260698119074639511853185118524908974402726536869376957693769781616585180844315019501150195041079849087166348892779279927795836066811207453952185118531851490997400276653586947693769576968162658218014430501050195011504007994903716234879278927792799582606781190748395118521851185349089741027265398693769476937698816165831808443350195010501950420798490471663482927792789277958460668110074539541851185218514900974002736535869776937694769681636582180944305012501950105040079049037167348792749074907 # 5826069811907463951185318511852490897440272653686937695769376978161658518084431501950115019504107984908716634889277927992779583606681120745395218511853185149099740027665358694769376957696816265821801443050105019501150400799490371623487927892779279958260678119074839511852185118534908974102726539869376947693769881616583180844335019501050195042079849047166348292779278927795846066811007453954185118521851490097400273653586977693769476968163658218094430501250195010504007904903716734879274907490749389686 # 582606981190746395118531851185249089744027265368693769576937697816165851808443150195011501950410798490871663488927792799277958360668112074539521851185318514909974002766535869476937695769681626582180144305010501950115040079949037162348792789277927995826067811907483951185218511853490897410272653986937694769376988161658318084433501950105019504207984904716634829277927892779584606681100745395418511852185149009740027365358697769376947696816365821809443050125019501050400790490371673487927490749074938968638916054 # 58260698119074639511853185118524908974402726536869376957693769781616585180844315019501150195041079849087166348892779279927795836066811207453952185118531851490997400276653586947693769576968162658218014430501050195011504007994903716234879278927792799582606781190748395118521851185349089741027265398693769476937698816165831808443350195010501950420798490471663482927792789277958460668110074539541851185218514900974002736535869776937694769681636582180944305012501950105040079049037167348792749074907493896863891605423758165 # 5826069811907463951185318511852490897440272653686937695769376978161658518084431501950115019504107984908716634889277927992779583606681120745395218511853185149099740027665358694769376957696816265821801443050105019501150400799490371623487927892779279958260678119074839511852185118534908974102726539869376947693769881616583180844335019501050195042079849047166348292779278927795846066811007453954185118521851490097400273653586977693769476968163658218094430501250195010504007904903716734879274907490749389686389160542375816581658165 |
正常来说输入转换得到的数字应该不能为 9 ,但是程序中并没有对 9 做错误的返回,所以可以在输入的任意 4 个连续的偶数位置插 9 (奇数位补0),得到的结果不变,就能构造出多解。上面代码中给出了在末尾补 9 时得到的几组多解。
赞赏
他的文章