Decode patterns like: ''.join(chr(x ^ y) for x, y in zip([0xde, 0xf9, ...], [0x8d] * 11)) ''.join(chr(x ^ y) for x, y in zip([N, ...], [K] * M)) ''.join(chr(x ^ K) for x in [N, N, N])
(self, source: str)
| 365 | return pattern.sub(d, source) |
| 366 | |
| 367 | def _decode_xor_zip(self, source: str) -> str: |
| 368 | """ |
| 369 | Decode patterns like: |
| 370 | ''.join(chr(x ^ y) for x, y in zip([0xde, 0xf9, ...], [0x8d] * 11)) |
| 371 | ''.join(chr(x ^ y) for x, y in zip([N, ...], [K] * M)) |
| 372 | ''.join(chr(x ^ K) for x in [N, N, N]) |
| 373 | """ |
| 374 | # Pattern 1: zip([...], [K] * M) or zip([...], [K, K, K, ...]) |
| 375 | p1 = re.compile( |
| 376 | r"[\"'][\"']\.join\s*\(\s*(?:chr\s*\(\s*\w+\s*\^\s*\w+\s*\)\s*for\s+\w+\s*,\s*\w+\s+in|" |
| 377 | r"\(chr\s*\(\s*\w+\s*\^\s*\w+\s*\)\s*for\s+\w+\s*,\s*\w+\s+in)\s+zip\s*\(" |
| 378 | r"\s*\[([0-9,\s0xXa-fA-F]+)\]\s*,\s*" |
| 379 | r"\[([0-9,\s0xXa-fA-F]+)\]\s*(?:\*\s*\d+)?\s*\)\s*\)\s*\)" |
| 380 | ) |
| 381 | |
| 382 | def d1(m): |
| 383 | try: |
| 384 | def parse_list(s): |
| 385 | # Handle hex literals like 0xde |
| 386 | return [int(x.strip(), 0) for x in s.split(',') if x.strip()] |
| 387 | arr1 = parse_list(m.group(1)) |
| 388 | arr2_raw = m.group(2) |
| 389 | arr2 = parse_list(arr2_raw) |
| 390 | # If arr2 has one element, it's a repeated key |
| 391 | if len(arr2) == 1: |
| 392 | key = arr2[0] |
| 393 | result = ''.join(chr(x ^ key) for x in arr1) |
| 394 | else: |
| 395 | result = ''.join(chr(x ^ y) for x, y in zip(arr1, arr2)) |
| 396 | return repr(result) if result.isprintable() else m.group(0) |
| 397 | except Exception: |
| 398 | return m.group(0) |
| 399 | |
| 400 | source = p1.sub(d1, source) |
| 401 | |
| 402 | # Pattern 2: Use safe eval for remaining zip patterns |
| 403 | p2 = re.compile( |
| 404 | r"[\"'][\"']\.join\s*\([^)]{0,500}\bzip\b[^)]{0,300}\)\s*\)" |
| 405 | ) |
| 406 | |
| 407 | def d2(m): |
| 408 | expr = m.group(0) |
| 409 | try: |
| 410 | result = eval(expr, {'__builtins__': {'chr': chr, 'zip': zip, 'range': range}}) |
| 411 | if isinstance(result, str) and result.isprintable() and len(result) > 0: |
| 412 | return repr(result) |
| 413 | except Exception: |
| 414 | pass |
| 415 | return m.group(0) |
| 416 | |
| 417 | source = p2.sub(d2, source) |
| 418 | return source |
| 419 | |
| 420 | def _decode_xor_chr_list(self, source: str) -> str: |
| 421 | pattern = re.compile( |