###### 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)
```
- 
- `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))
```
- 
- `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
- 
- 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'