strcmp.py (2979B)
1 # A CTF exploit by FIGBERT 2 # for UC Davis class ECS189M 3 # twinpeaks.cs.ucdavis.net:30004 4 # Category: Linux and miscellaneous 5 # Challenge: strcmp 6 # 05/01/2020 7 from pwn import * 8 9 def string_to_integer(s: str) -> int: 10 """Returns the passed string's (b26, a-z) base10 value 11 12 Keyword arguments: 13 s -- the string to convert to an int 14 """ 15 # Converts the characters to ascii representations (a=0, z=25) 16 num_values = [(ord(char)-97) for char in s][::-1] 17 lst = [] 18 # Converts the number representation in the list to its base10 value 19 for pos, val in enumerate(num_values): 20 lst.append(val*(26**pos)) 21 # Return the sum of the character values in base10 22 return sum(lst) 23 24 def integer_to_string(num: int, max: int = 19) -> str: 25 """Returns the passed base10 int's string representation 26 27 Keyword arguments: 28 num -- the int to convert to a string 29 max -- the length of the string minus one 30 """ 31 alphabetized_input = "" 32 for a in range(max,0,-1): 33 # Divides the number to get an int (0-25/a-z) 34 digit = int(num/(26**a)) if int(num/(26**a)) <= 25 else 25 35 # Converts the number to the corresponding letter 36 corresponding_character = chr(digit+97) 37 # Adds the new character to the total string 38 alphabetized_input += corresponding_character 39 num -= digit*(26**a) 40 corresponding_character = chr(int(num)+97) 41 alphabetized_input += corresponding_character 42 return alphabetized_input 43 44 def passgen(low: str, high: str, size: int = 19) -> str: 45 """ 46 Returns the string in the middle of `low` and `high` 47 48 Keyword arguments: 49 low -- the least string 50 high -- the highest string 51 size -- the length of the strings 52 """ 53 return integer_to_string((string_to_integer(low)+string_to_integer(high))//2, size) 54 55 cracked = False 56 first_attempt = True 57 LO = "aaaaaaaaaaaaaaaaaaaa" 58 HI = "zzzzzzzzzzzzzzzzzzzz" 59 connection = remote("twinpeaks.cs.ucdavis.edu", 30004) 60 while not cracked: 61 # First run case 62 if first_attempt: 63 # Generates a password 64 password = passgen(LO, HI) 65 # Prints challenge 66 print(str(connection.recv(), "utf-8")) 67 # Sends and prints the password 68 connection.sendline(password) 69 print("Password: %s"%password) 70 first_attempt = False 71 else: 72 response = connection.recvline() 73 previous_pass = password 74 # Checks the response to perform binary search 75 if b" -1 " in response: # Password too small 76 LO = password 77 password = passgen(LO, HI) 78 elif b" 1 " in response: # Password too large 79 HI = password 80 password = passgen(LO, HI) 81 else: # Password cracked 82 cracked = True 83 break 84 connection.sendline(password) 85 print("Password: %s"%password) 86 connection.recvline() 87 print("Flag: %s\n"%str(connection.recvline(), "utf-8").strip()) 88 89 connection.close()