前两天有别的比赛,没怎么打这场,第二天晚上才 开始重点做。第三天晚上九点疯狂上分,攒了三天的flag倾泻而出,得分趋势变成了竖线。队友们TQL~
reverse 签到 ida直接找到flag
zzzz3333333 38*38的矩阵,正则提取系数,然后matlab解。
提取系数:
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 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 code = '''int __cdecl sub_401500(char *a1) { int result; // eax if ( 48 * a1[7] + 64 * a1[5] + 4 * a1[4] + 59 * a1[1] + 85 * *a1 + 76 * a1[2] + 65 * a1[3] + 50 * a1[6] + 11 * a1[8] + 66 * a1[9] != 44858 ) return 0; if ( 96 * a1[7] + 6 * a1[6] + 97 * a1[4] + 71 * a1[1] + 87 * *a1 + 26 * a1[2] + 80 * a1[3] + 100 * a1[5] + 20 * a1[8] + 46 * a1[9] != 54177 ) return 0; if ( 82 * a1[8] + 29 * a1[7] + 54 * a1[4] + 22 * a1[1] + 27 * *a1 + 92 * a1[2] + 9 * a1[3] + 35 * a1[5] + 36 * a1[6] + 90 * a1[9] != 40412 ) return 0; if ( 60 * a1[7] + 31 * a1[5] + 47 * *a1 + 32 * a1[1] + 55 * a1[2] + 17 * a1[3] + 70 * a1[4] + 10 * a1[6] + 34 * a1[8] + 25 * a1[9] != 32362 ) return 0; if ( 53 * a1[7] + 89 * a1[6] + 13 * a1[4] + 72 * a1[3] + 49 * a1[1] + 18 * *a1 + 61 * a1[2] + 3 * a1[5] + 67 * a1[8] + 15 * a1[9] != 37176 ) return 0; if ( 78 * a1[8] + 38 * a1[5] + 69 * a1[2] + 77 * *a1 + 16 * a1[1] + 99 * a1[3] + 33 * a1[4] + 8 * a1[6] + 5 * a1[7] + 91 * a1[9] != 42742 ) return 0; if ( 62 * a1[8] + 52 * a1[7] + 58 * a1[2] + 45 * a1[1] + 40 * *a1 + 51 * a1[3] + 24 * a1[4] + 95 * a1[5] + 19 * a1[6] + 94 * a1[9] != 47553 ) return 0; if ( 28 * a1[8] + 63 * a1[7] + 12 * a1[6] + 57 * a1[4] + 30 * a1[3] + 42 * a1[2] + a1[1] + 88 * *a1 + 83 * a1[5] + 73 * a1[9] != 41059 ) return 0; if ( 41 * a1[8] + 93 * a1[6] + 68 * a1[5] + 98 * a1[2] + 75 * a1[1] + 39 * *a1 + 86 * a1[3] + 14 * a1[4] + 23 * a1[7] + 7 * a1[9] != 43919 ) return 0; if ( 56 * a1[8] + 74 * a1[5] + 43 * a1[4] + 84 * a1[3] + 44 * a1[2] + 37 * *a1 + 81 * a1[1] + 2 * a1[6] + 21 * a1[9] != 35933 ) return 0; if ( 36 * a1[16] + 98 * a1[14] + 79 * a1[10] + 97 * a1[11] + 33 * a1[12] + 60 * a1[15] + 24 * a1[17] + 78 * a1[18] + 72 * a1[19] != 47783 ) return 0; if ( 74 * a1[17] + 39 * a1[16] + 51 * a1[15] + 8 * a1[14] + 77 * a1[13] + 69 * a1[12] + 16 * a1[11] + 73 * a1[10] + 64 * a1[18] + 28 * a1[19] != 44266 ) return 0; if ( 47 * a1[18] + 52 * a1[17] + 53 * a1[16] + 99 * a1[15] + a1[14] + 38 * a1[13] + 67 * a1[12] + 45 * a1[11] + 61 * a1[10] + 66 * a1[19] != 44988 ) return 0; if ( 5 * a1[17] + 4 * a1[13] + 89 * a1[12] + 31 * a1[10] + 11 * a1[11] + 93 * a1[14] + 3 * a1[15] + 84 * a1[16] + 65 * a1[18] + 100 * a1[19] != 46698 ) return 0; if ( 82 * a1[16] + 62 * a1[13] + 58 * a1[12] + 42 * a1[11] + 86 * a1[10] + 85 * a1[14] + 27 * a1[15] + 43 * a1[17] + 15 * a1[18] + 26 * a1[19] != 45689 ) return 0; if ( 22 * a1[16] + 34 * a1[13] + 2 * a1[12] + 23 * a1[11] + 46 * a1[10] + 29 * a1[14] + 48 * a1[15] + 35 * a1[17] + 19 * a1[18] + 70 * a1[19] != 27224 ) return 0; if ( 96 * a1[18] + 81 * a1[17] + 92 * a1[15] + 54 * a1[14] + 94 * a1[11] + 57 * a1[10] + 55 * a1[12] + 80 * a1[13] + 71 * a1[16] + 25 * a1[19] != 58395 ) return 0; if ( 13 * a1[17] + 75 * a1[13] + 21 * a1[11] + 59 * a1[10] + 56 * a1[12] + 50 * a1[14] + 41 * a1[15] + 44 * a1[16] + 40 * a1[18] + 49 * a1[19] != 40625 ) return 0; if ( 12 * a1[16] + 91 * a1[14] + 88 * a1[13] + 87 * a1[12] + 68 * a1[10] + 7 * a1[11] + 83 * a1[15] + 20 * a1[17] + 32 * a1[18] + 37 * a1[19] != 45008 ) return 0; if ( 10 * a1[17] + 18 * a1[16] + 9 * a1[15] + 6 * a1[14] + 76 * a1[10] + 14 * a1[11] + 17 * a1[12] + 90 * a1[13] + 63 * a1[18] + 30 * a1[19] != 32400 ) return 0; if ( 83 * a1[26] + 45 * a1[25] + 4 * a1[24] + 48 * a1[22] + 38 * a1[20] + 22 * a1[21] + 7 * a1[23] + 62 * a1[27] + 25 * a1[28] + 85 * a1[29] != 37450 ) return 0; if ( 14 * a1[28] + 86 * a1[26] + 93 * a1[25] + 42 * a1[24] + 94 * a1[21] + 70 * a1[20] + 58 * a1[22] + 40 * a1[23] + 76 * a1[27] + 11 * a1[29] != 48740 ) return 0; if ( 72 * a1[28] + 46 * a1[26] + 92 * a1[25] + 98 * a1[24] + 55 * a1[23] + 80 * a1[20] + 32 * a1[21] + 12 * a1[22] + 84 * a1[27] + 27 * a1[29] != 53599 ) return 0; if ( 53 * a1[27] + 49 * a1[23] + 99 * a1[22] + 41 * a1[20] + 20 * a1[21] + 87 * a1[25] + 81 * a1[26] + 71 * a1[28] + 73 * a1[29] != 52140 ) return 0; if ( 68 * a1[28] + 61 * a1[21] + 28 * a1[20] + 91 * a1[22] + 31 * a1[23] + 67 * a1[24] + 15 * a1[25] + 44 * a1[26] + 6 * a1[27] + 64 * a1[29] != 44449 ) return 0; if ( 9 * a1[27] + 60 * a1[25] + 96 * a1[23] + 17 * a1[20] + 10 * a1[21] + 29 * a1[22] + 5 * a1[24] + 100 * a1[26] + 21 * a1[28] + 69 * a1[29] != 35276 ) return 0; if ( 59 * a1[26] + 66 * a1[25] + 23 * a1[22] + 8 * a1[20] + 24 * a1[21] + 16 * a1[23] + 56 * a1[24] + 90 * a1[27] + 36 * a1[28] + 39 * a1[29] != 35577 ) return 0; if ( 35 * a1[25] + 65 * a1[23] + 63 * a1[22] + 75 * a1[20] + 88 * a1[21] + 33 * a1[24] + 82 * a1[26] + 18 * a1[27] + a1[28] + 37 * a1[29] != 42004 ) return 0; if ( 54 * a1[28] + 57 * a1[27] + 43 * a1[24] + 74 * a1[21] + 19 * a1[20] + 51 * a1[22] + 13 * a1[23] + 79 * a1[25] + 3 * a1[26] + 26 * a1[29] != 35802 ) return 0; if ( 34 * a1[28] + 50 * a1[27] + 78 * a1[26] + 52 * a1[25] + 77 * a1[24] + 95 * a1[23] + 30 * a1[22] + 89 * a1[20] + 2 * a1[21] + 97 * a1[29] != 54527 ) return 0; if ( 46 * a1[36] + 73 * a1[34] + 15 * a1[30] + 16 * a1[31] + 41 * a1[32] + 94 * a1[33] + 28 * a1[35] + 45 * a1[37] != 34469 ) return 0; if ( 82 * a1[36] + 10 * a1[32] + 48 * a1[31] + 65 * a1[30] + 6 * a1[33] + 30 * a1[34] + 27 * a1[35] + 32 * a1[37] != 31558 ) return 0; if ( 62 * a1[36] + 39 * a1[35] + 36 * a1[33] + 97 * a1[31] + 52 * a1[30] + 70 * a1[32] + 13 * a1[34] + 66 * a1[37] != 41820 ) return 0; if ( 44 * a1[34] + 42 * a1[33] + 78 * a1[32] + 83 * a1[31] + 96 * a1[30] + 4 * a1[35] + 9 * a1[36] + 51 * a1[37] != 38668 ) return 0; if ( 79 * a1[36] + 37 * a1[33] + 92 * a1[30] + 18 * a1[31] + 86 * a1[32] + 7 * a1[34] + 95 * a1[37] != 45530 ) return 0; if ( 71 * a1[36] + 43 * a1[35] + 57 * a1[34] + 49 * a1[33] + 88 * a1[32] + 61 * a1[30] + 24 * a1[31] + 91 * a1[37] != 51396 ) return 0; if ( 34 * a1[36] + 75 * a1[35] + 35 * a1[32] + 23 * a1[30] + 3 * a1[31] + 53 * a1[33] + 14 * a1[34] + 47 * a1[37] != 28874 ) return 0; if ( 22 * a1[36] + 84 * a1[35] + 26 * a1[34] + 90 * a1[33] + 99 * a1[30] + 98 * a1[31] + 25 * a1[32] + a1[37] != 38231 ) return 0; }''' code = code.replace('*a1' , 'a1[0]' ) import rel = [] right = [] r = re.finditer(r'if.+?;' , code, re.S) for line in r: tmp = [0 ] * 38 rr = re.finditer(r'(\d+?) \* a1\[(\d+?)\]' , line.group()) for i in rr: a, b = int(i.group(1 )), int(i.group(2 )) tmp[b] = a _rr = re.search(r'\+ a1\[(\d+?)\]' , line.group()) if _rr: a, b = 1 , int(_rr.group(1 )) tmp[b] = a l.append(tmp) rrr = re.search(r'!\= (\d+)' , line.group()) right.append(int(rrr.group(1 ))) for i in l: print(str(i)[1 :-1 ] + ';' ) print() print(str(right).replace(',' , ';' ))
matlab部分截图:
能用matlab解的最好不要用z3。z3基本靠爆破,matlab解线性方程是直接调用数学公式,不是一个时间复杂度哦。
奇怪的exe pyinstaller打包的python程序,用pyinstxtractor.py解包,uncomlyle6提取python代码。
源码:
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 import base64from binascii import *c = [35 , 101 , 131 , 114 , 38 ] enc = [122 , 17 , 205 , 28 , 104 , 106 , 80 , 219 , 39 , 81 , 98 , 87 , 214 , 75 , 112 , 100 , 63 , 244 , 32 , 99 , 110 , 3 , 187 , 8 , 114 , 17 , 9 , 176 , 22 , 22 , 87 , 84 , 206 , 20 , 104 , 19 , 49 , 244 , 39 , 23 ] print('please input your flag:' ) key = input() a = base64.b64encode(key.swapcase().encode('utf-8' )) print(a) print(hexlify(a)) f = 1 s = [] for x in range(3 ): for i in range(len(a)): if (i + x) % 3 == 0 : s.append(a[i]) print(s) for i in range(len(s)): print(enc[i] ^ c[(i % 5 )], s[i] ) if enc[i] != s[i] ^ c[(i % 5 )]: f = 0 break if f == 1 : print('RIGHT' ) else : print('WRONG' )
难度不大,我就不解释了,直接放解题脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 c = [ 35 , 101 , 131 , 114 , 38 ] enc = [122 , 17 , 205 , 28 , 104 , 106 , 80 , 219 , 39 , 81 , 98 , 87 , 214 , 75 , 112 , 100 , 63 , 244 , 32 , 99 , 110 , 3 , 187 , 8 , 114 , 17 , 9 , 176 , 22 , 22 , 87 , 84 , 206 , 20 , 104 , 19 , 49 , 244 , 39 , 23 ] for i in range(len(enc)): enc[i] ^= c[i%5 ] print(enc) new = [0 ] * len(enc) o = 0 for x in range(3 ): for i in range(len(enc)): if (i + x) % 3 == 0 : new[i] = enc[o] print(enc[o],end=' ' ) o+=1 print() print(new) b = b'' import structfor i in range(len(new)): b += struct.pack('B' , new[i]) print(b) import base64r = base64.b64decode(b) print(r.swapcase())
swapcase()大小写互换有点意思哦。我和炜昊都倒在这里。
ez_code python字节码。
分析大概是这样的,只是分析的草稿,注释可能有小疏漏哦。
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 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 3 0 LOAD_GLOBAL 0 (print) 2 LOAD_CONST 1 ('please input your flag:') 4 CALL_FUNCTION 1 6 POP_TOP 4 8 LOAD_GLOBAL 1 (input) 10 CALL_FUNCTION 0 12 STORE_FAST 0 (flag) 5 14 LOAD_GLOBAL 2 (len) 16 LOAD_FAST 0 (flag) 18 CALL_FUNCTION 1 20 LOAD_CONST 2 (36) 22 COMPARE_OP 3 (!=) # len = 36 24 POP_JUMP_IF_FALSE 30 6 26 LOAD_CONST 3 (0) 28 RETURN_VALUE 7 >> 30 BUILD_LIST 0 32 STORE_FAST 1 (a) 8 34 LOAD_CONST 3 (0) 36 STORE_FAST 2 (t) # t = 0 12 38 LOAD_FAST 0 (flag) 40 GET_ITER >> 42 FOR_ITER 58 (to 102) 44 STORE_FAST 3 (i) 13 46 LOAD_FAST 2 (t) 48 LOAD_CONST 4 (1) 50 BINARY_AND 52 LOAD_CONST 4 (1) 54 COMPARE_OP 2 (==) # t & 1 == 1 奇数则跳 56 POP_JUMP_IF_FALSE 78 14 58 LOAD_FAST 1 (a) 60 LOAD_METHOD 3 (append) 62 LOAD_GLOBAL 4 (ord) 64 LOAD_FAST 3 (i) 66 CALL_FUNCTION 1 68 LOAD_CONST 5 (128) # 偶数则a.append(ord(i)+128) 70 BINARY_ADD 72 CALL_METHOD 1 74 POP_TOP 76 JUMP_FORWARD 14 (to 92) 16 >> 78 LOAD_FAST 1 (a) 80 LOAD_METHOD 3 (append) 82 LOAD_GLOBAL 4 (ord) 84 LOAD_FAST 3 (i) 86 CALL_FUNCTION 1 88 CALL_METHOD 1 # 奇数则a.append(ord(i)) 90 POP_TOP 17 >> 92 LOAD_FAST 2 (t) 94 LOAD_CONST 4 (1) 96 INPLACE_ADD 98 STORE_FAST 2 (t) # t+1 100 JUMP_ABSOLUTE 42 # 跳回循环开始 21 >> 102 LOAD_FAST 1 (a) 104 LOAD_CONST 3 (0) 106 BINARY_SUBSCR 108 LOAD_CONST 6 (5) 110 BINARY_RSHIFT 112 STORE_FAST 4 (b) # a[0] >> 5 22 114 LOAD_GLOBAL 5 (range) 116 LOAD_GLOBAL 2 (len) 118 LOAD_FAST 1 (a) 120 CALL_FUNCTION 1 122 CALL_FUNCTION 1 124 GET_ITER >> 126 FOR_ITER 82 (to 210) 128 STORE_FAST 3 (i) 23 130 LOAD_FAST 3 (i) 132 LOAD_GLOBAL 2 (len) 134 LOAD_FAST 1 (a) 136 CALL_FUNCTION 1 138 LOAD_CONST 4 (1) 140 BINARY_SUBTRACT # len(a) - 1 142 COMPARE_OP 2 (==) 144 POP_JUMP_IF_FALSE 172 # 循环体在172,而146是循环后运行的 24 146 LOAD_FAST 1 (a) 148 LOAD_FAST 3 (i) 150 BINARY_SUBSCR 152 LOAD_CONST 7 (8) 154 BINARY_MULTIPLY # a[i] * 8 156 LOAD_CONST 8 (255) 158 BINARY_AND # (a[i] * 8) & 0xff 160 LOAD_FAST 4 (b) 162 BINARY_OR 164 LOAD_FAST 1 (a) 166 LOAD_FAST 3 (i) 168 STORE_SUBSCR # a[i] = (a[0] >> 5) | ((a[i] << 3) & 0xff) 170 JUMP_ABSOLUTE 126 26 >> 172 LOAD_FAST 1 (a) 174 LOAD_FAST 3 (i) 176 BINARY_SUBSCR 178 LOAD_CONST 7 (8) 180 BINARY_MULTIPLY 182 LOAD_CONST 8 (255) 184 BINARY_AND # (a[i] * 8) & 0xff 186 LOAD_FAST 1 (a) 188 LOAD_FAST 3 (i) 190 LOAD_CONST 4 (1) 192 BINARY_ADD 194 BINARY_SUBSCR 196 LOAD_CONST 6 (5) 198 BINARY_RSHIFT # a[i+1] >> 5 200 BINARY_OR 202 LOAD_FAST 1 (a) 204 LOAD_FAST 3 (i) 206 STORE_SUBSCR # a[i] = (a[i+1] >> 5) | ((a[i] << 3) & 0xff) 208 JUMP_ABSOLUTE 126 28 >> 210 BUILD_LIST 0 212 STORE_FAST 5 (num) 32 214 LOAD_GLOBAL 5 (range) 216 LOAD_CONST 9 (2) 218 LOAD_CONST 10 (129) 220 CALL_FUNCTION 2 222 GET_ITER >> 224 FOR_ITER 60 (to 286) 226 STORE_FAST 3 (i) # for i in range(2, 129) 33 228 LOAD_CONST 11 (False) 230 STORE_FAST 2 (t) 34 232 LOAD_GLOBAL 5 (range) 234 LOAD_CONST 9 (2) 236 LOAD_FAST 3 (i) 238 CALL_FUNCTION 2 240 GET_ITER >> 242 FOR_ITER 26 (to 270) 244 STORE_FAST 6 (j) 35 246 LOAD_FAST 3 (i) 248 LOAD_FAST 6 (j) 250 BINARY_MODULO 252 LOAD_CONST 3 (0) 254 COMPARE_OP 2 (==) # i % j == 0 256 POP_JUMP_IF_FALSE 242 36 258 LOAD_CONST 12 (True) 260 STORE_FAST 2 (t) # t = True 37 262 POP_TOP 264 EXTENDED_ARG 1 266 JUMP_ABSOLUTE 270 268 JUMP_ABSOLUTE 242 38 >> 270 LOAD_FAST 2 (t) 272 POP_JUMP_IF_TRUE 224 # not t 39 274 LOAD_FAST 5 (num) 276 LOAD_METHOD 3 (append) 278 LOAD_FAST 3 (i) # num.append(i) 280 CALL_METHOD 1 282 POP_TOP 284 JUMP_ABSOLUTE 224 40 >> 286 LOAD_CONST 3 (0) 288 BUILD_LIST 1 290 LOAD_GLOBAL 2 (len) 292 LOAD_FAST 1 (a) 294 CALL_FUNCTION 1 296 BINARY_MULTIPLY 298 STORE_FAST 7 (c) 41 300 LOAD_GLOBAL 5 (range) 302 LOAD_GLOBAL 2 (len) 304 LOAD_FAST 1 (a) 306 CALL_FUNCTION 1 308 CALL_FUNCTION 1 310 GET_ITER >> 312 FOR_ITER 78 (to 392) 314 STORE_FAST 3 (i) # for i in range(len(a)) 42 316 LOAD_FAST 1 (a) 318 LOAD_FAST 3 (i) 320 BINARY_SUBSCR 322 LOAD_CONST 13 (4) 324 BINARY_RSHIFT # a[i] >> 4 326 LOAD_FAST 5 (num) 328 LOAD_FAST 3 (i) 330 LOAD_CONST 14 (31) 332 BINARY_MODULO 334 BINARY_SUBSCR # num[i % 31] 336 LOAD_CONST 15 (15) 338 BINARY_AND # num[i % 31] & 0xf 340 BINARY_XOR 342 STORE_FAST 8 (x1) # x1 = (a[i] >> 4) ^ (num[i % 31] & 0xf) 43 344 LOAD_FAST 1 (a) 346 LOAD_FAST 3 (i) 348 BINARY_SUBSCR 350 LOAD_CONST 15 (15) 352 BINARY_AND # a[i] & 0xf 354 LOAD_FAST 5 (num) 356 LOAD_FAST 3 (i) 358 LOAD_CONST 14 (31) 360 BINARY_MODULO 362 BINARY_SUBSCR # num[i % 31] 364 LOAD_CONST 13 (4) 366 BINARY_RSHIFT # num[i % 31] >> 4 368 BINARY_XOR 370 STORE_FAST 9 (x2) # x2 = (a[i] & 0xf) ^ (num[i % 31] >> 4) 44 372 LOAD_FAST 9 (x2) 374 LOAD_CONST 16 (16) 376 BINARY_MULTIPLY # 16 * x2 378 LOAD_FAST 8 (x1) 380 BINARY_ADD # 16 * x2 + x1 382 LOAD_FAST 7 (c) 384 LOAD_FAST 3 (i) 386 STORE_SUBSCR # c[i] = 16 * x2 + x1 388 EXTENDED_ARG 1 390 JUMP_ABSOLUTE 312 47 >> 392 LOAD_CONST 17 (227) # 密文 394 LOAD_CONST 18 (169) 396 LOAD_CONST 17 (227) 398 LOAD_CONST 19 (45) 400 LOAD_CONST 20 (234) 402 LOAD_CONST 21 (39) 404 LOAD_CONST 22 (98) 406 LOAD_CONST 23 (190) 408 LOAD_CONST 24 (197) 410 LOAD_CONST 25 (7) 412 LOAD_CONST 26 (229) 414 LOAD_CONST 27 (137) 416 LOAD_CONST 24 (197) 418 LOAD_CONST 28 (132) 420 LOAD_CONST 29 (119) 422 LOAD_CONST 30 (142) 424 LOAD_CONST 31 (97) 426 LOAD_CONST 32 (167) 428 LOAD_CONST 33 (59) 430 LOAD_CONST 34 (96) 432 LOAD_CONST 35 (166) 434 LOAD_CONST 36 (94) 436 LOAD_CONST 37 (136) 438 LOAD_CONST 17 (227) 440 LOAD_CONST 38 (131) 442 LOAD_CONST 39 (202) 444 LOAD_CONST 37 (136) 446 LOAD_CONST 40 (250) 448 LOAD_CONST 41 (21) 450 LOAD_CONST 42 (99) 452 LOAD_CONST 43 (20) 454 LOAD_CONST 44 (173) 456 LOAD_CONST 45 (121) 458 LOAD_CONST 46 (41) 460 LOAD_CONST 47 (125) 462 LOAD_CONST 48 (165) 464 BUILD_LIST 36 466 STORE_FAST 10 (d) 48 468 LOAD_CONST 4 (1) 470 STORE_FAST 11 (e) 49 472 LOAD_GLOBAL 5 (range) 474 LOAD_GLOBAL 2 (len) 476 LOAD_FAST 10 (d) 478 CALL_FUNCTION 1 480 CALL_FUNCTION 1 482 GET_ITER >> 484 FOR_ITER 34 (to 520) 486 STORE_FAST 3 (i) 50 488 LOAD_FAST 10 (d) 490 LOAD_FAST 3 (i) 492 BINARY_SUBSCR 494 LOAD_FAST 7 (c) 496 LOAD_FAST 3 (i) 498 BINARY_SUBSCR 500 COMPARE_OP 3 (!=) 502 EXTENDED_ARG 1 504 POP_JUMP_IF_FALSE 484 51 506 LOAD_CONST 3 (0) 508 STORE_FAST 11 (e) 52 510 POP_TOP 512 EXTENDED_ARG 2 514 JUMP_ABSOLUTE 520 516 EXTENDED_ARG 1 518 JUMP_ABSOLUTE 484 53 >> 520 LOAD_FAST 11 (e) 522 LOAD_CONST 4 (1) 524 COMPARE_OP 2 (==) 526 EXTENDED_ARG 2 528 POP_JUMP_IF_FALSE 540 54 530 LOAD_GLOBAL 0 (print) 532 LOAD_CONST 49 ('YOU ARE RIGHT') 534 CALL_FUNCTION 1 536 POP_TOP 538 JUMP_FORWARD 8 (to 548) 56 >> 540 LOAD_GLOBAL 0 (print) 542 LOAD_CONST 50 ('WRONG') 544 CALL_FUNCTION 1 546 POP_TOP >> 548 LOAD_CONST 0 (None) 550 RETURN_VALUE
手写其逻辑:
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 flag = input() if len(flag) != 36 : exit() t = 0 a = [] for i in flag: if t & 1 == 1 : a.append(ord(i)+128 ) else : a.append(ord(i)) t += 1 a[len(a)-1 ] = ((a[len(a)-1 ] << 3 ) & 0xff ) | (a[0 ] >> 5 ) for i in range(len(a)-1 ): a[i] = ((a[i] << 3 ) & 0xff ) | (a[i+1 ] >> 5 ) num = [] for i in range(2 , 129 ): t = False for j in range(2 , i): if i % j == 0 : t = True if not t: num.append(i) c = [0 ] * len(flag) for i in range(len(a)): x1 = (a[i] >> 4 ) ^ (num[i % 31 ] & 0xf ) x2 = (a[i] & 0xf ) ^ (num[i % 31 ] >> 4 ) c[i] = (x2 << 4 ) + x1 d=[227 , 169 , 227 , 45 , 234 , 39 , 98 , 190 , 197 , 7 , 229 , 137 , 197 , 132 , 119 , 142 , 97 , 167 , 59 , 96 , 166 , 94 , 136 , 227 , 131 , 202 , 136 , 250 , 21 , 99 , 20 , 173 , 121 , 41 , 125 , 165 ] for i in range(len(d)): if d[i] != c[i]: print('WRONG' ) exit() print('YOU ARE RIGHT' )
逆向主要是两段,第一段就是简单的左移3右移5。
第二段简单分析下见下图,就是a[i]交换高低4bit后与num[i%31]异或。
逆向脚本:
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 num=[] for i in range(2 ,129 ): t=False for j in range(2 ,i): if i%j==0 : t=True if not t: num.append(i) print(len(num)) c=d=[227 , 169 , 227 , 45 , 234 , 39 , 98 , 190 , 197 , 7 , 229 , 137 , 197 , 132 , 119 , 142 , 97 , 167 , 59 , 96 , 166 , 94 , 136 , 227 , 131 , 202 , 136 , 250 , 21 , 99 , 20 , 173 , 121 , 41 , 125 , 165 ] print(c) a = [] for i in range(len(c)): tmp = d[i] ^ num[i % 31 ] tmp = (tmp >> 4 ) + ((tmp & 0xf ) << 4 ) a.append(tmp) s = '' for i in range(len(a)): s += bin(a[i])[2 :].zfill(8 ) print(s) s = s[-3 :] + s[:-3 ] print(s) flag = [] for i in range(len(a)): tmp = int(s[i*8 : i*8 +8 ], 2 ) if i % 2 == 0 : flag.append(tmp) else : flag.append(tmp-128 ) print(flag) print('' .join(list(map(chr, flag))))
time 这题很有意思哦。
输入flag前会验证时间,必须在特定的年月日时分秒才能继续。但是还不能简单地patch掉这些验证。因为会把这些参数计算出一个int后传入验证flag的函数,并参与flag验证的逻辑。所以需要计算出这个int,然后patch掉时间验证之后,进入flag验证函数前,手动修改传入的这个参数 55*7*903274960*9*2018*32 = 0xec48d400
。
这题应该是用了一些C语言没有的函数,伪代码有点奇怪,但没有特别的c++的特征(其实是有点的。不知道怎么编译的。识别不出来这些奇怪的库函数,只能动调慢慢推测。
输入flag后,创建一个flag备份,记作buffer,并通过下面逻辑,将传入的与时间有关的int进行转换,生成0~4的字节,并拼接到buffer的首部。
从int中分出4个byte, &0x7f后如果满足上述逻辑,就添加到buffer的头部。可能添加0~3个字节,这取决于时间参数。对于通过验证的唯一参数0xec48d400,会添加3个字节。
创建一个table,长62,值为0-9a-zA-Z
从buffer(3个时间参数导出的字节+flag)中找到每个字符在table0-9a-zA-Z中首次出现的索引:
然后主要的逻辑在sub_401541。
这次是从flag中找到每个字符在table0-9a-zA-Z中首次出现的索引,然后与上一步的table_from_find_first_index_by_buffer[i]模62相加。
什么意思呢?
一个数组是3个时间参数相关字节+flag,一个”数组“是flag,这两个数组对于元素模62相加,然后作为索引取table0-9a-zA-Z的字符。
所以其实就是个错位相加。
动调到这个函数,拿到这3个时间参数相关字节0x0d, 0x0c, 0x38。然后错位计算。
解密脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import stringfrom z3 import *time = 55 *7 *903274960 *9 *2018 *32 print(hex(time&0xffffffff )) cipher = 'P6GvwFypZN1BbFn5tVgoWeK81LkeQ6uvuiovDgO' print(len(cipher)) table = string.digits + string.ascii_lowercase + string.ascii_uppercase print(table) a = (table.find(cipher[0 ]) - 0x0d + 62 ) % 62 b = (table.find(cipher[1 ]) - 0x0c + 62 ) % 62 c = (table.find(cipher[2 ]) - 0x38 + 62 ) % 62 index = [a, b, c] print(index) for i in range(3 , len(cipher)): tmp = (table.find(cipher[i]) - index[i-3 ] + 62 ) % 62 index.append(tmp) for i in index[:-3 ]: print(table[i],end='' ) print()
baby_encrypt 把flag主体按-分割拆成3部分,分别进入函数验证
三个main都是md5,逐渐魔改递进。
main是原版md5,然后把md5走一些古典算法,然后比较密文。
从密文可以逆回md5。然后可以查彩虹表。
main1算法:
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 int __cdecl main1 (char *part1) { int v1; int v2; unsigned int k; int v5[16 ]; char Src[8 ]; int md5_ctx[2 ]; int ctx_state; char md5_digest[16 ]; const char *v10; int tmp; int low; int high; int v14; unsigned int v15; int j; int i; md5_init(md5_ctx); v1 = strlen (part1); MD5Update((int )md5_ctx, part1, v1); v14 = 0 ; v15 = ((unsigned int )md5_ctx[0 ] >> 3 ) & 0x3F ; if ( v15 > 0x37 ) v2 = 120 - v15; else v2 = 56 - v15; v14 = v2; MD5Encode((int )Src, (int )md5_ctx, 8u ); MD5Update((int )md5_ctx, &padding, v14); MD5Update((int )md5_ctx, Src, 8 ); MD5Encode((int )md5_digest, (int )&ctx_state, 0x10 u); for ( i = 0 ; i <= 15 ; ++i ) { high = (unsigned __int8)md5_digest[i] >> 4 ; low = md5_digest[i] & 0xF ; md5_digest[i] = 16 * low + (high ^ low); *((_BYTE *)&v5[8 ] + 2 * i) = (unsigned __int8)md5_digest[i] >> 4 ; *((_BYTE *)&v5[8 ] + 2 * i + 1 ) = md5_digest[i] & 0xF ; } for ( i = 0 ; i <= 31 ; i += 8 ) { for ( j = 0 ; j <= 3 ; ++j ) { tmp = *((char *)&v5[8 ] + i + j); *((_BYTE *)&v5[8 ] + j + i) = *((_BYTE *)&v5[8 ] + i + 7 - j); *((_BYTE *)&v5[8 ] + i + 7 - j) = tmp; } } for ( k = 0 ; k < 8 ; ++k ) v5[k] = 0 ; for ( i = 0 ; i <= 31 ; ++i ) { if ( *((char *)&v5[8 ] + i) > 9 || *((char *)&v5[8 ] + i) < 0 ) { if ( *((char *)&v5[8 ] + i) > 9 && *((char *)&v5[8 ] + i) <= 15 ) *((_BYTE *)v5 + i) = *((_BYTE *)&v5[8 ] + i) + 87 ; } else { *((_BYTE *)v5 + i) = *((_BYTE *)&v5[8 ] + i) + 48 ; } } v10 = "e0c1942932d5845b5128552378fb20bf" ; for ( i = 0 ; i <= 31 ; ++i ) { if ( *((_BYTE *)v5 + i) != v10[i] ) return 0 ; } return 1 ; }
逆向脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 a = 'e0c1942932d5845b5128552378fb20bf' a = [ord(i) for i in a] for i in range(0 , 32 , 8 ): for j in range(4 ): a[i+j], a[i+7 -j] = a[i+7 -j], a[i+j] a = [int(str(chr(i)), 16 ) for i in a] for i in range(16 ): t1 = a[i*2 ] t2 = a[i*2 +1 ] t1, t2 = t1 ^ t2, t1 a[i*2 ], a[i*2 +1 ] = t1, t2 hash1 = '' for i in a: hash1 += str(hex(i)[2 :]) print(hash1)
main2算法(只比main1多了一步)
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 int __cdecl main2 (char *Str) { int v1; int v2; unsigned int k; unsigned int m; int v6[16 ]; char Src[8 ]; int md5_ctx[2 ]; int v9; char digest[16 ]; const char *v11; int v12; int v13; int v14; unsigned int v15; int *ctx_state; int len; unsigned int v18; int l; int j; int i; md5_init(md5_ctx); v1 = strlen (Str); MD5Update((int )md5_ctx, Str, v1); len = 0 ; v18 = ((unsigned int )md5_ctx[0 ] >> 3 ) & 0x3F ; if ( v18 > 0x37 ) v2 = 0x78 - v18; else v2 = 0x38 - v18; len = v2; MD5Encode((int )Src, (int )md5_ctx, 8u ); MD5Update((int )md5_ctx, &padding, len); MD5Update((int )md5_ctx, Src, 8 ); ctx_state = &v9; for ( i = 0 ; i <= 3 ; ++i ) { for ( j = 0 ; j <= 2 ; ++j ) { v15 = (unsigned int )ctx_state[i] >> 28 ; ctx_state[i] = 16 * ctx_state[i] + v15; } ctx_state[i] ^= 0xA3DFA1DB ; } MD5Encode((int )digest, (int )ctx_state, 0x10 u); for ( k = 0 ; k < 8 ; ++k ) v6[k + 8 ] = 0 ; for ( i = 0 ; i <= 15 ; ++i ) { v14 = (unsigned __int8)digest[i] >> 4 ; v13 = digest[i] & 0xF ; *((_BYTE *)&v6[8 ] + 2 * i) = v13; *((_BYTE *)&v6[8 ] + 2 * i + 1 ) = v14 ^ v13; } for ( i = 0 ; i <= 31 ; i += 8 ) { for ( l = 0 ; l <= 3 ; ++l ) { v12 = *((char *)&v6[8 ] + i + l); *((_BYTE *)&v6[8 ] + l + i) = *((_BYTE *)&v6[8 ] + i + 7 - l); *((_BYTE *)&v6[8 ] + i + 7 - l) = v12; } } for ( m = 0 ; m < 8 ; ++m ) v6[m] = 0 ; for ( i = 0 ; i <= 31 ; ++i ) { if ( *((char *)&v6[8 ] + i) > 9 || *((char *)&v6[8 ] + i) < 0 ) { if ( *((char *)&v6[8 ] + i) > 9 && *((char *)&v6[8 ] + i) <= 15 ) *((_BYTE *)v6 + i) = *((_BYTE *)&v6[8 ] + i) + 87 ; } else { *((_BYTE *)v6 + i) = *((_BYTE *)&v6[8 ] + i) + 48 ; } } v11 = "d039a1b9c6daa1b450b044aeb2696a44" ; for ( i = 0 ; i <= 31 ; ++i ) { if ( *((_BYTE *)v6 + i) != v11[i] ) return 0 ; } return 1 ; }
逆向脚本(注意MD5Encode的大小端转换哦)
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 b = 'd039a1b9c6daa1b450b044aeb2696a44' b = [ord(i) for i in b] print(b) for i in range(0 , 32 , 8 ): for j in range(4 ): b[i+j], b[i+7 -j] = b[i+7 -j], b[i+j] print(b) b = [int(str(chr(i)), 16 ) for i in b] print(b) for i in range(16 ): t1 = b[i*2 ] t2 = b[i*2 +1 ] t1, t2 = t1 ^ t2, t1 b[i*2 ], b[i*2 +1 ] = t1, t2 b_data = [] for i in range(16 ): tmp = (b[i*2 ]<<4 ) + b[i*2 +1 ] b_data.append(tmp) print(b_data) for i in range(4 ): tmp = b_data[i*4 ] + (b_data[i*4 +1 ]<<8 ) + (b_data[i*4 +2 ]<<16 ) + (b_data[i*4 +3 ]<<24 ) tmp ^= 0xA3DFA1DB tmp = ((tmp<<20 )&0xffffffff ) + (tmp>>12 ) b_data[i*4 ] = tmp&0xff b_data[i*4 +1 ] = (tmp>>8 )&0xff b_data[i*4 +2 ] = (tmp>>16 )&0xff b_data[i*4 +3 ] = (tmp>>24 )&0xff print(b_data) b_md5 = '' for i in b_data: b_md5 += hex(i)[2 :].zfill(2 ) print(b_md5)
main3算法:
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 int __cdecl main3 (char *part3) { int v1; int v2; unsigned int l; int result; int Buffer; int f_part3[20 ]; char Src[8 ]; int ctx[2 ]; _BYTE v9[80 ]; char digest[16 ]; char _part3[16 ]; const char *cipher; int v13; size_t v14; FILE *fFLAG; FILE *fdata; int v17; int v18; int v19; int v20; _BYTE *v21; int padlen; unsigned int v23; int k; char part3_b3; char part3_b1; int j; int i; strcpy (_part3, part3); md5_init(ctx); v1 = strlen (part3); MD5Update((int )ctx, part3, v1); padlen = 0 ; v23 = ((unsigned int )ctx[0 ] >> 3 ) & 0x3F ; if ( v23 > 0x37 ) v2 = 120 - v23; else v2 = 56 - v23; padlen = v2; MD5Encode((int )Src, (int )ctx, 8u ); MD5Update((int )ctx, &padding, padlen); MD5Update((int )ctx, Src, 8 ); v21 = v9; for ( i = 0 ; i <= 3 ; ++i ) { for ( j = 0 ; j <= 2 ; ++j ) { v20 = *(_DWORD *)&v21[4 * i] >> 28 ; *(_DWORD *)&v21[4 * i] = 16 * *(_DWORD *)&v21[4 * i] + v20; } *(_DWORD *)&v21[4 * i] ^= 0xA3DFA1DB ; } MD5Encode((int )digest, (int )v9, 0x10 u); for ( i = 0 ; i <= 15 ; ++i ) { v19 = (unsigned __int8)digest[i] >> 4 ; v18 = digest[i] & 0xF ; *((_BYTE *)&f_part3[12 ] + 2 * i) = v18; *((_BYTE *)&f_part3[12 ] + 2 * i + 1 ) = v19 ^ v18; } part3_b1 = _part3[1 ] & 0x7F ; part3_b3 = _part3[3 ] & 0x7F ; for ( i = 0 ; i <= 31 ; ++i ) { if ( i != 1 ) part3_b1 ^= *((_BYTE *)&f_part3[12 ] + i); if ( i ) part3_b3 ^= *((_BYTE *)&f_part3[12 ] + i); } for ( i = 0 ; i <= 31 ; i += 8 ) { for ( k = 0 ; k <= 3 ; ++k ) { v17 = *((char *)&f_part3[12 ] + i + k); *((_BYTE *)&f_part3[12 ] + k + i) = *((_BYTE *)&f_part3[12 ] + i + 7 - k); *((_BYTE *)&f_part3[12 ] + i + 7 - k) = v17; } } for ( l = 0 ; l < 8 ; ++l ) f_part3[l + 4 ] = 0 ; for ( i = 0 ; i <= 31 ; ++i ) { if ( *((char *)&f_part3[12 ] + i) > 9 || *((char *)&f_part3[12 ] + i) < 0 ) { if ( *((char *)&f_part3[12 ] + i) > 9 && *((char *)&f_part3[12 ] + i) <= 15 ) *((_BYTE *)&f_part3[4 ] + i) = *((_BYTE *)&f_part3[12 ] + i) + 87 ; } else { *((_BYTE *)&f_part3[4 ] + i) = *((_BYTE *)&f_part3[12 ] + i) + 48 ; } } fdata = fopen("data" , "rb" ); fFLAG = fopen("FLAG" , "w+b" ); if ( fdata && fFLAG ) { f_part3[2 ] = 0 ; f_part3[3 ] = 0 ; v14 = 0 ; v13 = 0 ; i = 0 ; while ( 1 ) { v14 = fread(f_part3, 1u , 1u , fdata); if ( !v14 ) break ; if ( (i & 1 ) == 0 ) Buffer = f_part3[0 ] ^ part3_b1; if ( i % 2 == 1 ) Buffer = f_part3[0 ] ^ part3_b3; ++i; fwrite(&Buffer, 1u , 1u , fFLAG); } fclose(fdata); fclose(fFLAG); cipher = "46f627c53e41fc2a2182ba286295bc35" ; for ( i = 0 ; i <= 31 ; ++i ) { if ( *((_BYTE *)&f_part3[4 ] + i) != cipher[i] ) return 0 ; } result = 1 ; } else { puts ("error!" ); result = 0 ; } return result; }
main3是在main2基础上改的。
hint中有提示jpg。答案就是,第三段的md5查表查不出来,长度是13,爆破也不太容易。但是第三段flag就在jpg里面写着(data是jpg的密文)
那data的密钥是啥呢?来看下逻辑。
首先flag的第三部分&0x7f后,分奇偶分别与md5计算后但是验证前的中间值循环异或。
好的,中间值我们可以逆向得到,但是这个输入值拿不到啊。这里不是突破点。
那再来看下,从data读入密文,异或后,buffer是解密的明文。
buffer是输出,f_part3[0]是从data文件中读入的一个字节,part3_b1是密钥。
如果是jpg,那么文件头是固定(ffd8ffe0)的,所以buffer已知一定的字节。然后是f_part3[0],这是异或和的密文,就在data里,也已知。所以我们可求密钥。
解密脚本:
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 b = '46f627c53e41fc2a2182ba286295bc35' b = [ord(i) for i in b] print(b) for i in range(0 , 32 , 8 ): for j in range(4 ): b[i+j], b[i+7 -j] = b[i+7 -j], b[i+j] print(b) b = [int(str(chr(i)), 16 ) for i in b] print(b) part3_b1 = 0xbd ^ 0xff part3_b3 = 0x8b ^ 0xd8 print(part3_b1, part3_b3) with open('data' , 'rb' )as f: b = f.read() b = list(b) for i in range(len(b)): if i % 2 == 0 : b[i] ^= part3_b1 else : b[i] ^= part3_b3 bb = b'' import structfor i in b: bb += struct.pack('B' , i) with open(r'data.jpg' , 'wb' )as f: f.write(bb)
crypto RSA签到 1 2 3 4 5 6 7 8 9 10 11 12 13 14 n = 807862607863494903203347547751222668477246136996519972166847 c = 6525071913169990474785757170304035615411828876052879070297 e = 65537 from Crypto.Util.number import *from gmpy2 import *P31 = 1034526559407993507734818408829 P30 = 780900790334269659443297956843 phi = (P31-1 ) * (P30-1 ) d = inverse(e, phi) m = pow(c, d, n) print(m) print(long_to_bytes(m))
简单的密码学 task.py
1 2 3 4 5 6 7 8 9 10 11 12 import libnumimport randome=libnum.s2n(flag) n = 2 ** 514 m = random.randint(2 , n-1 ) | 1 c = pow(m, e, n) print('m = ' + str(m)) print('c = ' + str(c))
flag是e,所以是离散对数的求解。
贴个资料:
直接上sympy的轮子:
1 2 3 4 5 6 7 from sympy.ntheory import *from Crypto.Util.number import *n = 2 ** 514 m = 45930439493588458217814199095166325056793804285450102007731089001050571514856332627851425138364361016243889773238664380678029627984235001868004334568770697 c = 5057805883715955343508948629802682033540608675113624374337084633322875196538392521768197949724904990019045804655058020268973563802830621371118940310488041 flag = discrete_log(n,c,m) print(long_to_bytes(flag))
名字不重要 给出一个pyc,一个流量包。
pyc改成python3.8.5的魔数,然后转成python代码。
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 import hmac, hashlib, random, structKIDING_SIZE = 32 SIG_SIZE = 16 TOTAL_SIZE = set((c for c in range(256 ))) KEY = b'af5f76f605a700ae8c0895c3e6175909' def func1 (v ): return bytes([v]) def sign_sign_sign (val, key ): return hmac.new(key, val, digestmod=(hashlib.sha256)).digest()[:SIG_SIZE] def chaff_chaff_chaff_b (val, key ): messgs = {} messgs[val[0 ]] = sign_sign_sign(val, key) while len(messgs) < KIDING_SIZE: arg1 = list(TOTAL_SIZE - set(messgs.keys())) c = random.choice(arg1) if c == val: raise ValueError('C~h~o~s~e d~u~p~l~i~c~a~t~e~!' ) bad_sig = bytes(random.choices((list(TOTAL_SIZE)), k=SIG_SIZE)) messgs[c] = bad_sig block = [] for k, v in messgs.items(): block.append(b'%s%s' % (func1(k), v)) else : random.shuffle(block) return '' .join(block) def chaff_chaff_chaff_m (val, key ): if not isinstance(val, bytes): val = val.encode('utf-8' ) the_out = [] for b in val: the_out.append(chaff_chaff_chaff_b(func1(b), key)) else : out1 = '' .join(the_out) return struct.pack('>I' , len(val)) + out1 def winnow_winnow_winnow_m (val, key ): if not isinstance(val, bytes): val = val.encode('utf-8' ) msglen = struct.unpack('>I' , val[:4 ])[0 ] val = val[4 :] block_len = (SIG_SIZE + 1 ) * KIDING_SIZE expected_len = block_len * msglen if len(val) != expected_len: raise ValueError('E~x~p~e~c~t~e~d l~e~n~g~t~h %d, saw %d.' % (expected_len, len(val))) pieces = [] for c in range(msglen): chunk = val[block_len * c:block_len * (c + 1 )] res = winnow_winnow_winnow_b(chunk, key) pieces.append(res) else : return '' .join(pieces) def winnow_winnow_winnow_b (val, key ): while val: c = func1(val[0 ]) sig = val[1 :SIG_SIZE + 1 ] if sign_sign_sign(c, key) == sig: return c val = val[SIG_SIZE + 1 :] raise ValueError('~N~o v~a~l~i~d s~i~g f~o~u~n~d!' ) def main (): inp = b'~T~h~i~s i~s a t~e~s~t m~e~s~s~a~g~e!' msg = chaff_chaff_chaff_m(inp, KEY) ret = winnow_winnow_winnow_m(msg, KEY) if inp != ret: print('W~r~o~n~g r~e~t: %s' % ret) if __name__ == '__main__' : main()
传输模型为首先4个字节是消息长度。然后是消息,每32*17字节为一组,每组的有效信息只有1字节。对该字节求hash,取前16byte添加在有效信息这一字节后面,这是共17字节。然后随机选31字节,这是非有效的垃圾信息,重复上述步骤,共得到32*17字节,最后随机打乱32小组的相对顺序。有效信息其实只有一字节。然后后面的有效信息同理。
另一端取出一组后,共3217字节,循环32次。利用提前约定好的key,计算32个字节的hash,共32\ 16字节,对比计算结果和每个小组中的第2~17个字节的签名是否相符,相符则是有效信息,其余31字节则是垃圾信息。
但我们没有key怎么办呢?统计。
由于一个字节的签名永远是相同的。所以如果一组中的签名也在其余组中出现,那么这大概率就是有效信息及其签名。
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 from Crypto.Util.number import *from scapy.all import rdpcappackets = rdpcap("message.pcap" ) sport=3199 src="127.0.0.1" f = b'' for packet in packets: if "TCP" in packet and packet['TCP' ].payload: if packet["IP" ].src==src and packet["TCP" ].sport==sport: f += packet['TCP' ].payload.load f = f[4 :] packets = [] for i in range(0 , len(f), 32 *17 ): packets.append(f[i:i+32 *17 ]) data = [] all_value = [] for packet in packets: tmp = [] for i in range(0 , 32 *17 , 17 ): group = packet[i:i+17 ] ch, sig = group[0 ], group[1 :] all_value.append((ch, sig)) tmp.append((ch, sig)) data.append(tmp) result = [] for item in data: for m in item: if all_value.count(m) > 1 : result.append(m) break print(b'' .join([long_to_bytes(item[0 ]) for item in result]))
名字没想好 task.py
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 from gmpy2 import *import gmpy2from Crypto.Util.number import *from sympy import *import sympyflag1 = b'CUMTCTF{**********' m1 = bytes_to_long(flag1) p1 = getPrime(1024 ) q1 = getPrime(1024 ) e1 = 103738 n1 = p1 * q1 gift = lcm(p1 - 1 , q1 - 1 ) c1 = pow(m1, e1, n1) print('n1 = ' , n1) print('c1 = ' , c1) print('gift = ' , gift) flag2 = b'**********************' e2 = 65537 m2 = bytes_to_long(flag2) p2 = getPrime(1024 ) q2 = sympy.nextprime(p2) n2 = p2 * q2 phi2 = (p2 - 1 ) * (q2 - 1 ) d2 = gmpy2.invert(e2, phi2) c2 = pow(m2, e2, n2) print('d = ' , d2) print('c2 = ' , c2)
data:
1 2 3 4 5 n1 = 24511956296934419790810802924028121267308277322350201914243748724443965915830044792139346496470216715543376102606906727287935669186132061565360428924230740995935556111187855700300365517739695893842582114724005232045077425187550801509268664723237890122110051088839310003135672964413501812829310021228720112275276180469100308793523051405119335989674132224715582989624204590983857159312466387546505666052162775188773736419909262619409755848412558718676873188073997893894862353873441073313610102773845304906678909624700529896455885309546409645526387707907518497436045821973310653257012148438207441605902771515486273283273 c1 = 7357116532209949285136310518084676100522798730487701269950303460540634127932201594120600757671807456790592531487713433579926404640474277692592102315472760853853767347752080563508622523821339163225554653816787201616233932746815764392729597579461985789538131853246938443458331139199802764554726447278501492140335824365867574318693890007499638038064582031311613039571335453968072426153706431456149868515230310567240569544961967582304893471240728585336273245259533905230737876248875784828430507371662455796543123714325161987112223947057481814610592300979207673818538093532100233028106442070524965861451563388404227738574 gift = 12255978148467209895405401462014060633654138661175100957121874362221982957915022396069673248235108357771688051303453363643967834593066030782680214462115370497967778055593927850150182758869847946921291057362002616022538712593775400754634332361618945061055025544419655001567836482206750906414655010614360056137481173664901476116870144816992211793902146834987166288769615612767704010592138813256140678199511291489394523989294805910740127557682458229594376211232977501267410539674224065875285801753027816046254818608535462445306054117075379711073762930279723764342988824053970592468109679774789092077979655857748513636834 d = 14519297697723031496224953772301033569165883208616356699837703756220717249229195213146695656923357394378868735444167631602696573904678412172248043414276910206086892084385988564720914312238316434518024995169814463252129242492227202678878240875905293369168263909256455159691392124769949072754243536472227070447391890140409479709945084894060833468804156778720190688101601664725009609222256314873780002770605127043596912060811904733471592387441742111474341938658516761896926403628885365926903655309306738689809023277824030268579979837642613499180913999651379232105756338399243024739524553588216117189742912479604441636257 c2 = 23574157314515030841894399693996910252287747536395985840285410194536546768646580704111053676040921830550019965767796038280932469005359270920519250763405535872475345625907947986452218739530197421244240070129909526493952916306821311836861766221812155261751444946282559677005557815746813525162411907545113665605490915464367483833005576787591204417525937745572210195816236947103271664048065491627347939268785403334419989160034526164012966888952162714736497312282011026789187871221751240709801544484784941178786820290118585681595783245449236394480319395321877182096839866054466492123200354772280398476167002177544154960579
一共两关。
首先观察到e明显不是素数,但是e/2是。所以rsa的公司转换成m的平方的e/2方。套公式的时候,要把e/2当成e代入,求出的是m的平方。然后开方可得m。
然后得想办法求phi。很明显题目给出了p-1和q-1的最小公倍数。由于lcm(p-1, q-1) * gcd(p-1, q-1) = (p-1)*(q-1)
。
简记为lcm * gcd = phi
phi和n的长度差不太多,n的长度是2048,而lcm的长度是2047,所以gcd只需要爆个位数就行。爆出phi就可以求第一段flag.
那第二关呢?
已知e, d, c。求n。
很明显p和q是相邻素数,在这前提下p约等于根号下n约等于根号下phi。
phi可以表示成(e*d-1)/k,e和d已知。所以可以爆破k。ed乘积是2063,phi必然比d要大,而d的长度是2047,所以爆破上限是2的16次方。
稍微约束下就开始爆破。对phi开根号,可以得到p的近似值tmp。然后next_prime(tmp)必然是p或者q。为啥呢?因为p<q,如果p和q都在tmp的左侧,那么p*q<tmp的平方即phi。矛盾哦。
脚本:
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 from gmpy2 import *from Crypto.Util.number import *from sympy import *n1 = 24511956296934419790810802924028121267308277322350201914243748724443965915830044792139346496470216715543376102606906727287935669186132061565360428924230740995935556111187855700300365517739695893842582114724005232045077425187550801509268664723237890122110051088839310003135672964413501812829310021228720112275276180469100308793523051405119335989674132224715582989624204590983857159312466387546505666052162775188773736419909262619409755848412558718676873188073997893894862353873441073313610102773845304906678909624700529896455885309546409645526387707907518497436045821973310653257012148438207441605902771515486273283273 c1 = 7357116532209949285136310518084676100522798730487701269950303460540634127932201594120600757671807456790592531487713433579926404640474277692592102315472760853853767347752080563508622523821339163225554653816787201616233932746815764392729597579461985789538131853246938443458331139199802764554726447278501492140335824365867574318693890007499638038064582031311613039571335453968072426153706431456149868515230310567240569544961967582304893471240728585336273245259533905230737876248875784828430507371662455796543123714325161987112223947057481814610592300979207673818538093532100233028106442070524965861451563388404227738574 _lcm = gift = 12255978148467209895405401462014060633654138661175100957121874362221982957915022396069673248235108357771688051303453363643967834593066030782680214462115370497967778055593927850150182758869847946921291057362002616022538712593775400754634332361618945061055025544419655001567836482206750906414655010614360056137481173664901476116870144816992211793902146834987166288769615612767704010592138813256140678199511291489394523989294805910740127557682458229594376211232977501267410539674224065875285801753027816046254818608535462445306054117075379711073762930279723764342988824053970592468109679774789092077979655857748513636834 e1 = 103738 // 2 for _gcd in range(1 , 10 ): try : phi = _lcm * _gcd d1 = inverse(e1, phi) m1 = pow(c1, d1, n1) m1 = iroot(m1, 2 )[0 ] msg = long_to_bytes(m1) if b'CUMTCTF{' in msg: print(msg) break except : pass d2 = 14519297697723031496224953772301033569165883208616356699837703756220717249229195213146695656923357394378868735444167631602696573904678412172248043414276910206086892084385988564720914312238316434518024995169814463252129242492227202678878240875905293369168263909256455159691392124769949072754243536472227070447391890140409479709945084894060833468804156778720190688101601664725009609222256314873780002770605127043596912060811904733471592387441742111474341938658516761896926403628885365926903655309306738689809023277824030268579979837642613499180913999651379232105756338399243024739524553588216117189742912479604441636257 c2 = 23574157314515030841894399693996910252287747536395985840285410194536546768646580704111053676040921830550019965767796038280932469005359270920519250763405535872475345625907947986452218739530197421244240070129909526493952916306821311836861766221812155261751444946282559677005557815746813525162411907545113665605490915464367483833005576787591204417525937745572210195816236947103271664048065491627347939268785403334419989160034526164012966888952162714736497312282011026789187871221751240709801544484784941178786820290118585681595783245449236394480319395321877182096839866054466492123200354772280398476167002177544154960579 e2 = 65537 ed = e2 * d2 print(len(bin(ed)[2 :])) for k in range(2 **14 , 2 **15 ): if (ed - 1 ) % k == 0 : phi2 = (ed - 1 ) // k tmp = iroot(phi2, 2 )[0 ] p2 = next_prime(tmp) if phi2 % (p2-1 ) == 0 : q2 = phi2 // (p2-1 ) + 1 n2 = p2 * q2 m2 = pow(c2, d2, n2) msg = long_to_bytes(m2) print(msg) break
Merry_Christmas task.py
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 from Crypto.Util.number import *from gmpy2 import *bit_length = 1024 p = getPrime(bit_length) q = getPrime(bit_length) n = p*q m = bytes_to_long(flag) n= p * q e = 65537 c = pow(m,e,n) p1 = getPrime(bit_length) q1 = getPrime(bit_length) n1 = p1*q1 e1 = 979691 c1 = pow(p,e1,n1) gift1 = pow(907 *p1+q1,587 ,n1) gift2 = pow(p1+q1,691 ,n1) print('n={}' .format(n)) print('c={}' .format(c)) print('n1={}' .format(n1)) print('c1={}' .format(c1)) print('gift1={}' .format(gift1)) print('gift2={}' .format(gift2))
data:
1 2 3 4 5 6 n=17539423546879883396629573776616418986256902147283732214295946312835113344061142956076117932720247053739715326040027048199629442201144987405090572982720131052885163184811793669071684926986445262835990861167700118224153436202178098707759605979066475651999711718728200184335695206586643579499656822346329750835696158561669170301767928780361376643304324731146650458384564533895090608529488304659924485356518526226061081943815971670656857778229528022465452008890430046982169571771039198877713729197033434033303723925335811353531172899520232033290866272195248554656110282928669639257994965701208856346298076998993772423097 c=5560694632613114538708358450844738346732427106497566176686415566542021811907746171660858360055720615188679328728275250111979427060322426593068123630729075838980217642604281020733578019517061369665467249555496690538379316251258553434263030485822069081031041121329559075841297923650799241347196473466430248261213536319894271629049899379974582453405472218720572088937075254938460083046946717784821298765199164644879680847984441166684509290675197526982405556980540919856072198191306527746754844792294221564010770506298266272017613487725494001276623402987809305696759434595799863487759478902384039066714073292949058853003 n1=21465819616864492551767155722996412718832402997933699784091937387760830726039866762857450959675228856561597024318920734312362144261628290737563681759442171285581931041622345778933572673367607809994811354957971820829401430301563611970709279094237597394734599103937206689348004861322161582747568764567491894069565665829828570957338594421227530701263883322496237907509301547209937444268813162260988374157151529111924866290775985684107622034449136081744171954609262107449388993051611516007232903948144186151363436032658716266030263647775582015141329829060294352706551807295555026827381280240539020513044515406829846588787 c1=19585478304129650368934167685581947379018238627360258251578178648406399091655911309790559870365866290321783969820131014958701556570645863667895395615377725655139970869868226237575462206775170966585306390686724869174973947234608655786245191308423334769172394586099003865664934720651493266130413617892286830586179842568659758155132923079476873190047514962385696606866440573294836559927597496331643346032100075257329902065785369011323134807157288931237650262052445952481912276967263237183320639027956890814569212814115581834172475173790422964999583755677956698930811772293980516268488171908878145019531149798750799613142 gift1=21073862899796816496314528055339279280335681203948249072101881208021752125789533267427994742277358208178070970462447090818216561770563907183494712376741842209323406667050344266668347773728401520981152006053958337605219297650281680615939792818684114311810254344598007357629176456353064311734075462353266893546853648829947081541158912147691654438830914577857503519080776224006347318623082457516638594584206488534978134212723395494600005197454325625290580653432901204502054226866606652982669196910942405139803194404497913820850500332680877820694279428529873469583387698995104411071804749202120283361058269192420218572231 gift2=7634352822409241151514235360777296908269419654786551951076299092182838191720014827302929726661609788893676185300000003824161794580145215813570705896440007085639728197111313542046542236060921056046727832889041640187683808320443684484085665265794806366182119574554965179974119587542057100849953753232435527244682735108194058759240757296546820383552711669453408694460188770050594702462736564767783116432265746800810795602828775783509056534518928775187835786128676790426643882842096826044057116388930041087679950264956074503205229333151001519229166174531496272703271636344792947552939606533888390978361247276796123693665
之前上海市ctf的题,原地tp我之前的wp
解题脚本:
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 from Crypto.Util.number import *from gmpy2 import *n=17539423546879883396629573776616418986256902147283732214295946312835113344061142956076117932720247053739715326040027048199629442201144987405090572982720131052885163184811793669071684926986445262835990861167700118224153436202178098707759605979066475651999711718728200184335695206586643579499656822346329750835696158561669170301767928780361376643304324731146650458384564533895090608529488304659924485356518526226061081943815971670656857778229528022465452008890430046982169571771039198877713729197033434033303723925335811353531172899520232033290866272195248554656110282928669639257994965701208856346298076998993772423097 c=5560694632613114538708358450844738346732427106497566176686415566542021811907746171660858360055720615188679328728275250111979427060322426593068123630729075838980217642604281020733578019517061369665467249555496690538379316251258553434263030485822069081031041121329559075841297923650799241347196473466430248261213536319894271629049899379974582453405472218720572088937075254938460083046946717784821298765199164644879680847984441166684509290675197526982405556980540919856072198191306527746754844792294221564010770506298266272017613487725494001276623402987809305696759434595799863487759478902384039066714073292949058853003 n1=21465819616864492551767155722996412718832402997933699784091937387760830726039866762857450959675228856561597024318920734312362144261628290737563681759442171285581931041622345778933572673367607809994811354957971820829401430301563611970709279094237597394734599103937206689348004861322161582747568764567491894069565665829828570957338594421227530701263883322496237907509301547209937444268813162260988374157151529111924866290775985684107622034449136081744171954609262107449388993051611516007232903948144186151363436032658716266030263647775582015141329829060294352706551807295555026827381280240539020513044515406829846588787 c1=19585478304129650368934167685581947379018238627360258251578178648406399091655911309790559870365866290321783969820131014958701556570645863667895395615377725655139970869868226237575462206775170966585306390686724869174973947234608655786245191308423334769172394586099003865664934720651493266130413617892286830586179842568659758155132923079476873190047514962385696606866440573294836559927597496331643346032100075257329902065785369011323134807157288931237650262052445952481912276967263237183320639027956890814569212814115581834172475173790422964999583755677956698930811772293980516268488171908878145019531149798750799613142 gift1=21073862899796816496314528055339279280335681203948249072101881208021752125789533267427994742277358208178070970462447090818216561770563907183494712376741842209323406667050344266668347773728401520981152006053958337605219297650281680615939792818684114311810254344598007357629176456353064311734075462353266893546853648829947081541158912147691654438830914577857503519080776224006347318623082457516638594584206488534978134212723395494600005197454325625290580653432901204502054226866606652982669196910942405139803194404497913820850500332680877820694279428529873469583387698995104411071804749202120283361058269192420218572231 gift2=7634352822409241151514235360777296908269419654786551951076299092182838191720014827302929726661609788893676185300000003824161794580145215813570705896440007085639728197111313542046542236060921056046727832889041640187683808320443684484085665265794806366182119574554965179974119587542057100849953753232435527244682735108194058759240757296546820383552711669453408694460188770050594702462736564767783116432265746800810795602828775783509056534518928775187835786128676790426643882842096826044057116388930041087679950264956074503205229333151001519229166174531496272703271636344792947552939606533888390978361247276796123693665 e1 = 979691 e = 65537 tmp = pow(gift2, 587 , n1) - pow(gift1, 691 , n1) p1 = gcd(tmp, n1) q1 = n1 // p1 phi1 = (p1 - 1 ) * (q1 - 1 ) d1 = inverse(e1, phi1) p = pow(c1, d1, n1) q = n // p phi = (p - 1 ) * (q - 1 ) d = inverse(e, phi) m = pow(c, d, n) msg = long_to_bytes(m) print(msg)