Rating:

# Rev 102

## Task

Flag format is: JISCTF{data}

File: be_true

## Solution

```bash
$ file be_true
be_true: python 2.7 byte-compiled
```

We use `uncompyle` for this. We need to add the file extension `pyc`.

```python
$ python2 ~/.local/bin/uncompyle6 be_true.pyc
# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# Decompiled from: Python 2.7 (default, [REDACTED])
# Embedded file name: be_true.py
# Compiled at: 2019-12-06 14:36:32
import operator
flag = 0
power = (12 * flag + 44) / 4 - 1234 / 617 * flag - sum([1, 4, 7])
flag *= power
ppc = filter(lambda cc22: not any(cc22 % uu22 == 0 for uu22 in range(2, cc22)), range(2, 10000))
dat = reduce(operator.mul, (ppc[i] ** int(str(flag)[i]) for i in range(len(str(flag)))))
print dat == 3560267726635400465627540581996487760054035685444946475657505105403063442856963534755133504166293811169018648637812735995934052617540980495952470560844800443626277335201401028364068797946796579956457852457279957300619892623751175557650873016730889125068146398488627192356718363004881175012104986391177956396290571688585499385019181192105543180552708742672275440530116680223358366613050183523086165910780504269235376773473500L
# okay decompiling be_true.pyc
```

Let's do this step by step:

```python
power = (12 * flag + 44) / 4 - 1234 / 617 * flag - sum([1, 4, 7])
power = 3 * flag + 11 - 2 * flag - 12
power = flag - 1
```

This is just simplifying the expression.

```python
flag = 0
flag *= power
flag *= flag - 1
flag = flag * (flag - 1)
flag = flag**2 - flag
```

This is just inserting the simplification an moving things around..

So what is `ppc`? It's the `range(2, 10000)` filtered by `not any(c % u == 0 for u in range(2, c))`. This is just creating a list of primes.

So what is `dat`? It's each prime from `ppc` exponented with the corresponding char from `flag` at that index and all of the result multiplied together.

This means we can resote `flag` from the required `dat` with prime factorization.

If `flag` was `201`, dat would be `20 == 2**2 * 3**0 * 5**1`.

Keep in mind there is `print dat` not `print(dat)` so this is python2. We write this script:

```python
def primes(n):
primfac = []
d = 2
while d*d <= n:
while (n % d) == 0:
primfac.append(d)
n //= d
d += 1
if n > 1:
primfac.append(n)
return primfac

flag = 0
cnt = Counter()
# reduced to 269 here since it's zero after that
ppc = filter(lambda cc22: not any(cc22 % uu22 == 0 for uu22 in range(2, cc22//2+1)), range(2, 269))

for prime in ppc:
cnt[prime] = 0

for prime in primes(result):
cnt[prime] += 1

print(cnt)

out = ""

for prime in ppc:
out += str(cnt[prime])

print(out)
```

And get this:

```bash
$ python2 be_true.py
Counter({7: 9, 37: 9, 73: 9, 83: 9, 17: 8, 41: 8, 131: 8, 3: 7, 197: 7, 241: 7, 139: 7, 227: 7, 191: 7, 137: 6, 29: 6, 263: 6, 101: 6, 157: 6, 257: 5, 19: 5, 151: 5, 67: 5, 89: 5, 109: 5, 113: 5, 31: 4, 229: 4, 59: 4, 199: 4, 239: 4, 5: 3, 23: 3, 193: 3, 223: 3, 97: 3, 211: 3, 2: 2, 163: 2, 53: 2, 181: 2, 71: 2, 79: 2, 107: 2, 13: 1, 149: 1, 167: 1, 173: 1, 47: 1, 179: 1, 61: 1, 233: 1, 11: 0, 269: 0, 43: 0, 103: 0, 251: 0, 127: 0})
273901853649801241529295360255086715621112737433741470560
```

`out` is now `flag**2 - flag`. Since it's such a large number the trouble-free way is to calculate the (positive) solution with WolframAlpha.

`flag` is now `5233563352533350594343304433`.

Unhexlify that...

```python
>>> binascii.unhexlify(b'5233563352533350594343304433')
b'R3V3RS3PYCC0D3'
```

Original writeup (https://github.com/klassiker/ctf-writeups/blob/master/2020/jisctf-quals/reverse-engineering/rev-102.md).