I like my eggs sunny side up, but I ended up scrambling them.
Looking at scrambledeggs.py, there are several operations on the flag as well as the two keys (technically, key2 is derived from key1 so it's just one key) that we need to reverse. The important functions that need to be reversed are enc1 and enc2:
sys.maxsize%28 on my system was 7, so I made the assumption that n would be in the range [0, 7]. enc2 performs a simple substitution operation, which is simple to reverse. To reverse enc1, due to the randomness involved, we would have to brute-force through all 8 possible values of n. As there are 4 enc1s used, we would have to go through 84=4096 combinations to reverse all the enc1s.
There is also a swapping operation taking place, where the swapping within flag, key1 and key2 is all inter-dependent:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
for j in range(2): for i in range(14): temp1 = flag[i] flag[i] = flag[(ord(key1[i])-ord('a'))%28] flag[(ord(key1[i])-ord('a'))%28] = temp1 temp2 = key1[i] key1[i] = key1[(ord(key2[i])-ord('a'))%14] key1[(ord(key2[i])-ord('a'))%14] = temp2 for i in range(14,28): temp1 = flag[i] flag[i] = flag[(ord(key2[i-14])-ord('a'))%28] flag[(ord(key2[i-14])-ord('a'))%28] = temp1 temp2 = key2[i-14] key2[i-14] = key2[(ord(key1[i-14])-ord('a'))%14] key2[(ord(key1[i-14])-ord('a'))%14] = temp2
This is easy to reverse by reversing each swap individually. Care must be taken to run the indices in reverse order.
Next, the keys get swapped with 50% probability, so we have no choice but to try both possibilities. Finally, key2 gets encrypted by adding it with another randomly generated string k modulo 26, to put it simply.
1 2 3 4 5 6 7 8 9 10 11
k = '' for i in range(14): k += random.choice(map) k = list(k) key2 = k+key2 for i in range(14): a = ord(k[i])-ord('a')+ord(key2[i+14]) if a>122: a=a%122 a=a+97 key2[i+14]= chr(a)
Note that if at the end of the ith iteration, chr(a) == k[i], then the original value of key2[i+14] could either have been 'a' or 'z', so we'd have to account for this corner case at each position, possibly leading to an exponential increase in the number of candidates we'd have to check.
Combining all these observations together, we have this following code to reverse the flag: