| @@ -0,0 +1,121 @@ | |||
| 1 | + | import pwn | |
| 2 | + | import re | |
| 3 | + | ||
| 4 | + | def get_rand(seed): | |
| 5 | + | state = [0] * 31 | |
| 6 | + | v3 = seed if seed != 0 else 1 | |
| 7 | + | state[0] = v3 | |
| 8 | + | for i in range(1, 31): | |
| 9 | + | v9 = 16807 * (v3 % 127773) - 2836 * (v3 // 127773) | |
| 10 | + | v3 = v9 + (0x7FFFFFFF if v9 < 0 else 0) | |
| 11 | + | state[i] = v3 | |
| 12 | + | ||
| 13 | + | fptr = 3 | |
| 14 | + | rptr = 0 | |
| 15 | + | ||
| 16 | + | def rand(): | |
| 17 | + | nonlocal fptr, rptr, state | |
| 18 | + | val = (state[fptr] + state[rptr]) & 0xFFFFFFFF | |
| 19 | + | state[fptr] = val | |
| 20 | + | res = val >> 1 | |
| 21 | + | fptr += 1 | |
| 22 | + | if fptr >= 31: fptr = 0 | |
| 23 | + | rptr += 1 | |
| 24 | + | if rptr >= 31: rptr = 0 | |
| 25 | + | return res | |
| 26 | + | ||
| 27 | + | for _ in range(310): | |
| 28 | + | rand() | |
| 29 | + | ||
| 30 | + | return rand | |
| 31 | + | ||
| 32 | + | def solve_challenge(dt): | |
| 33 | + | # Connect | |
| 34 | + | conn = pwn.remote('135.235.195.203', 3000, level='error') | |
| 35 | + | ||
| 36 | + | # Wait for shell prompt | |
| 37 | + | conn.recvuntil(b"/ $ ") | |
| 38 | + | conn.sendline(b"/challenge/lock_app") | |
| 39 | + | ||
| 40 | + | # Read until "The current time is:" | |
| 41 | + | conn.recvuntil(b"The current time is: ") | |
| 42 | + | server_time = int(conn.recvline().strip()) | |
| 43 | + | print(f"[+] Server Time: {server_time}, dt: {dt}") | |
| 44 | + | ||
| 45 | + | # Compute SBOX with server_time | |
| 46 | + | rand_init = get_rand(server_time) | |
| 47 | + | rand_init() # Discard | |
| 48 | + | rand_init() # Discard | |
| 49 | + | ||
| 50 | + | SBOX = list(range(256)) | |
| 51 | + | for j in range(255, 0, -1): | |
| 52 | + | v2 = rand_init() | |
| 53 | + | swap_idx = v2 % (j + 1) | |
| 54 | + | SBOX[j], SBOX[swap_idx] = SBOX[swap_idx], SBOX[j] | |
| 55 | + | ||
| 56 | + | def time_math(val): | |
| 57 | + | return (SBOX[(val >> 24) & 0xFF] << 24) | \ | |
| 58 | + | (SBOX[(val >> 16) & 0xFF] << 16) | \ | |
| 59 | + | (SBOX[(val >> 8) & 0xFF] << 8) | \ | |
| 60 | + | SBOX[val & 0xFF] | |
| 61 | + | ||
| 62 | + | # Wait for menu | |
| 63 | + | conn.recvuntil(b"Select option: ") | |
| 64 | + | ||
| 65 | + | # 2. Reset password | |
| 66 | + | conn.sendline(b"2") | |
| 67 | + | ||
| 68 | + | # Read challenge code | |
| 69 | + | # "Your challenge code is: XXXXXXX" | |
| 70 | + | conn.recvuntil(b"Your challenge code is: ") | |
| 71 | + | chal_code = int(conn.recvline().strip()) | |
| 72 | + | print(f"[+] Challenge Code: {chal_code}") | |
| 73 | + | ||
| 74 | + | # Generate response based on guessed time | |
| 75 | + | rand_gen = get_rand(server_time + dt) | |
| 76 | + | v5 = rand_gen() | |
| 77 | + | v6 = rand_gen() | |
| 78 | + | ||
| 79 | + | v7 = time_math(v5) | |
| 80 | + | v8 = time_math(v6) | |
| 81 | + | ||
| 82 | + | v7 = time_math(v5) | |
| 83 | + | v8 = time_math(v6) | |
| 84 | + | ||
| 85 | + | # Both modulos are UNSIGNED 32-bit | |
| 86 | + | val1 = (31337 * v7 + v8) & 0xFFFFFFFF | |
| 87 | + | mod1 = val1 % 1000000 | |
| 88 | + | urandom = chal_code ^ mod1 | |
| 89 | + | ||
| 90 | + | val2 = (v7 ^ v8) & 0xFFFFFFFF | |
| 91 | + | mod2 = val2 % 1000000 | |
| 92 | + | ||
| 93 | + | response = urandom ^ mod2 | |
| 94 | + | ||
| 95 | + | print(f"[+] Predicted Response (dt={dt}): {response}") | |
| 96 | + | ||
| 97 | + | # Send response | |
| 98 | + | conn.recvuntil(b"Response code: ") | |
| 99 | + | conn.sendline(str(response).encode()) | |
| 100 | + | ||
| 101 | + | res = conn.recvall(timeout=3).decode() | |
| 102 | + | conn.close() | |
| 103 | + | ||
| 104 | + | if "Nope" in res: | |
| 105 | + | print("[-] Failed.") | |
| 106 | + | return False | |
| 107 | + | elif "Here's a gift" in res or "SUCCESSFUL" in res: | |
| 108 | + | print("[*] SUCCESS!!!") | |
| 109 | + | print(res) | |
| 110 | + | return True | |
| 111 | + | return False | |
| 112 | + | ||
| 113 | + | if __name__ == "__main__": | |
| 114 | + | for dt in range(0, 5): | |
| 115 | + | for _ in range(3): # try each dt 3 times | |
| 116 | + | try: | |
| 117 | + | if solve_challenge(dt): | |
| 118 | + | import sys | |
| 119 | + | sys.exit(0) | |
| 120 | + | except Exception as e: | |
| 121 | + | pass | |
vee1e / cf0a56f6c8274b74b7d97c7c571b9967
Last active 4 days ago
Osanai Yuki revised this gist 6 months ago · b1fa20a
1 file changed, 121 insertions