payload_arr = create_payload_array(server_mac, LOCAL_MAC, index)
if not verify_do_check_client(payload_arr, LOCAL_MAC, index, server_mac):
print("we are sad :(")
def evaluate_alphabet(alphabet: str, exponent: int, modulus: int, value_map = lambda x: x):
"""
Determine if a proposed alphabet of payload bytes is still able to encode all values that
a payload with no restrictions could represent.
value_map can be used to to make the search faster by limiting the search space.
Returns a mapping of desired inputs and the inputs that produce them (we're just
going to brute force this because of the alphabet constraints)
"""
unrestricted_possible_values = set()
for i in range(modulus):
unrestricted_possible_values.add(value_map(pow(i, exponent, modulus)))
possible_values = dict()
for num in int_alphabet_generator(alphabet, 4):
result = value_map(pow(num, exponent, modulus))
if result not in possible_values:
possible_values[result] = num
if len(possible_values) == len(unrestricted_possible_values):
return possible_values
assert False, f"Not all possible values found within modulus {len(possible_values)} / {len(unrestricted_possible_values)}"
# some subset of chars it should be safe to use in the urlparam
alphabet = "lmaoztebcdfghijknpqrsuvwxy"
# used for the first 4 entries in client_data, before a new exponent and
# modulus are derived. figure out all representable values so we can use
# this when we craft the first 4 integers of payload which let us control
# the derived values used for the rest of the decoding
header_encoding_map = evaluate_alphabet(alphabet, 0x1687, 0x7561)
# since it turns out we have absolute control over the exponent and modulus,
# can just precalculate. we also only care about the lower byte of the encoded
# values, as do_check_client truncates the modular exponentation result when
# calculating mac address bytes. so once we have all possible lower bytes, we're
# done.
mac_encoding_map = evaluate_alphabet(alphabet, 0x1, 0x1687, lambda x: x & 0xff)
# new exponent/modulus will be derived based on our input and this
# index which is selected randomly and given to us. we have to work
# with a exponent of the form:
#
# new_exponent = (pow(input1, 0x1687, 0x7561) * calculated_idx) + pow(input2, 0x1687, 0x7561)
# new_modulus = (pow(input3, 0x1687, 0x7561) * calculated_idx) + pow(input4, 0x1687, 0x7561)
#
# we're going to take advantage of the multiply, and pick input1 and input3 such that
# calculated_idx is multiplied by 0, making it irrelevant to payload generation.
# since we've now gotten control of the exponent and modulus, we just staple the
# local and remote mac addresses to the payload.
payload.extend(map(mac_encoding_map.__getitem__, LOCAL_MAC + server_mac + server_mac))