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