---
# System prepended metadata

title: Password Here Please
tags: [MetaCTF]

---

###### tags: `MetaCTF`

# Password Here Please

- I forgot my bank account password! Luckily for me, I wrote a program that checks if my password is correct just in case I forgot which password I used, so this way I don't lock myself out of my account. Unfortunately, I seem to have lost my password list as well...

- Could you take a look and see if you can find my password for me?

- Part 3 requires some math skills. To solve it, think about what is being done by the exponentiation step. Try rewriting the large number in base 257.

```python=
def ValidatePassword(password):
    print("Password Validator v1.0")
    print("Attempting to validate password...")

    if(len(password[::-2]) != 12 or len(password[17:]) != 7):
        print("Woah, you're not even close!!")
        return False

    pwlen = len(password)
    chunk1 = 'key'.join([chr(0x98 - ord(password[c]))
                             for c in range(0, int(pwlen / 3))])
    if "".join([c for c in chunk1[::4]]) != '&e"3&Ew*':
        print("You call that the password? HA!")
        return False

    chunk2 = [ord(c) - 0x1F if ord(c) > 0x60
                  else (ord(c) + 0x1F if ord(c) > 0x40 else ord(c))
                  for c in password[int(pwlen / 3) : int(2 * pwlen / 3)]]
    ring = [54, -45, 9, 25, -42, -25, 31, -79]
    for i in range(0, len(chunk2)):
        if(0 if i == len(chunk2) - 1 else chunk2[i + 1]) != chunk2[i] + ring[i]:
            print("You cracked the passwo-- just kidding, try again! " + str(i))
            return False

    chunk3 = password[int(2 * pwlen / 3):]
    code = 0xaace63feba9e1c71ef460e6dbf1b1fbabfd7e2e35401440ac57e93bd9ba41c4fbd5d437b1dfab11fe7a1c6c2035982a71765fc9a7b32ccef695dffb71babe15733f5bb29f76aae5f80fff
    valid = True
    for i in range(0, len(chunk3)):
        if(ord(chunk3[i]) < 0x28):
            valid = False
        code -= (257 ** (ord(chunk3[i]) - 0x28)) * (1 << i)

    if code == 0 and valid:
        print("Password accepted!")
        return True
    else:
        print("Quite wrong indeed!")
        return False

print("Please enter password")
while not ValidatePassword(input()):
    pass
```

### part1

```python=
if(len(password[::-2]) != 12 or len(password[17:]) != 7):
    print("Woah, you're not even close!!")
    return False
```
- 分析從第17個開始後面總數如果不是7或者總數2格2格跳如果不是12
    - 17+7 = 24
    - 2*12 = 24
    - 也就是說密碼總長度為24

### part2

```python=
pwlen = len(password)
chunk1 = 'key'.join([chr(0x98 - ord(password[c]))
                        for c in range(0, int(pwlen / 3)])
if "".join([c for c in chunk1[::4]]) != '&e"3&Ew*':
    print("You call that the password? HA!")
    return False
```
- for c in range(0, int(pwlen / 3)
    - 將24長度的密碼/3=8個byte長度

- chunk1 = 'key'.join([chr(0x98 - ord(password[c]))的值要等於'&e"3&Ew*'

    - 換而言之0x98分別減ord'&e"3&Ew*'這八個字元會等於密碼

```python=
password = ('&e"3&Ew*')

#print(password)
for c in range(8):
    chunk1 = chr(0x98 - ord(password[c]))
    print(chunk1)
```
- ![](https://i.imgur.com/ajus1XI.png)
    - `r3verS!n`

                        
### part3

```python=
chunk2 = [ord(c) - 0x1F if ord(c) > 0x60
              else (ord(c) + 0x1F if ord(c) > 0x40 else ord(c))
              for c in password[int(pwlen / 3) : int(2 * pwlen / 3)]]
ring = [54, -45, 9, 25, -42, -25, 31, -79]
for i in range(0, len(chunk2)):
    if(0 if i == len(chunk2) - 1 else chunk2[i + 1]) != chunk2[i] + ring[i]:
        print("You cracked the passwo-- just kidding, try again! " + str(i))
        return False
```
- for c in password[int(pwlen / 3) : int(2 * pwlen / 3)]
    - 從第9個字元到第16個

- `ord(c) - 0x1F if ord(c) > 0x60
              else (ord(c) + 0x1F if ord(c) > 0x40 else ord(c))`
```python=
if ord(c) > 0x60:
        return ord(c) - 0x1F
    else:
        if ord(c) > 0x40:
            return ord(c) + 0x1F
        else:
            return ord(c)
```

- `if(0 if i == len(chunk2) - 1 else chunk2[i + 1]) != chunk2[i] + ring[i]:`
    - 最後一個值7==8-1要等於0且chunk後一個值要等於前一個值加對應的ring值
    - 而我們今天最後一個值為0，Chunk[7] = 0 - ring[7]，代表最後chunk值為79，依ring = [54, -45, 9, 25, -42, -25, 31, -79]類推出倒數第二個值為79-31 = 48，chunk為[72, 126, 81, 90, 115, 73, 48, 79]
```python=
chunk = [72, 126, 81, 90, 115, 73, 48, 79]
for i in chunk:
    #print(i)
    if i > 95:
        print (chr(i - 0x1F))
    elif i > 65:
        print (chr(i + 0x1F))
    else:
        print (chr(i))
```
- ![](https://i.imgur.com/8CevG1F.png)
    - `g_pyTh0n`

### part4

```python=
chunk3 = password[int(2 * pwlen / 3):]
code = 0xaace63feba9e1c71ef460e6dbf1b1fbabfd7e2e35401440ac57e93bd9ba41c4fbd5d437b1dfab11fe7a1c6c2035982a71765fc9a7b32ccef695dffb71babe15733f5bb29f76aae5f80fff
valid = True
for i in range(0, len(chunk3)):
    if(ord(chunk3[i]) < 0x28):
        valid = False
    code -= (257 ** (ord(chunk3[i]) - 0x28)) * (1 << i)

if code == 0 and valid:
    print("Password accepted!")
    return True
else:
    print("Quite wrong indeed!")
    return False
```

- `chunk3 = password[int(2 * pwlen / 3):]`
    - 抓16個字元以後的值

- 一提示將code轉成base257的值，用這段程式碼將16進制的code轉成257
    - https://towardsdatascience.com/how-to-write-a-number-systems-calculator-in-python-b172557cb705

- ![](https://i.imgur.com/EY1xIJN.png)

- digits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 8]

- non_zero_digits = [32, 4, 64, 17, 2, 128, 8]
    - 分別代表2 ** 5，2 ** 2，2 ** 6......
    - `code -= (257 ** (ord(chunk3[i]) - 0x28)) * (1 << i)`
        - 中的1<<i等於1*2**i
- indexdigits = [30, 39, 45, 55, 62, 70, 74]

- 因為digits值都為2的次方
    - 17會拆成16跟1

- 根據我們第一個值2 ** 1對應索引值為55，2 ** 2為62，2 ** 3對應74....
    - 最終正列key = [55, 62, 39, 74, 55, 30, 45, 70]

- 題目`yi = ord(chunk3[i]) - 0x28`因此我們逆者推
    - [chr(yi + 0x28) for yi in key]
    - [' _ ', 'f', 'O', 'r', ' _ ', 'F', 'U', 'n']
    - `'_fOr_FUn'‵`

- flag:'r3verS!ng_pyTh0n_fOr_FUn'