I was sniffing some web traffic for a while, I think i finally got something interesting. Help me find flag through all these packets.
net_756d631588cb0a400cc16d1848a5f0fb.pcap

This was a 100 point challenge. Overall it was pretty fun. First thing to do with the pcap is strings it and look for an easy win. While we didn't get an easy win here, we did get a nice reference point:

\$ strings net_756d631588cb0a400cc16d1848a5f0fb.pcap | grep -i flag
FLAG = 'flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}'
print encode(FLAG, cnt=?)

So we now know that there's a python script in there somewhere that will compute the flag and print it (or similar). I used wireshark to extract it. While I don't feel the need to go into the mechanics of extracting it here, it's worth noting that the syntax "frame contains 'flag{'" is super helpful in finding the correct packet the first time around.

Here's what the extracted python file looks like:

import string
import random
from base64 import b64encode, b64decode

FLAG = 'flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}'

enc_ciphers = ['rot13', 'b64e', 'caesar']
# dec_ciphers = ['rot13', 'b64d', 'caesard']

def rot13(s):
_rot13 = string.maketrans(
"ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz",
"NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm")
return string.translate(s, _rot13)

def b64e(s):
return b64encode(s)

def caesar(plaintext, shift=3):
alphabet = string.ascii_lowercase
shifted_alphabet = alphabet[shift:] + alphabet[:shift]
table = string.maketrans(alphabet, shifted_alphabet)
return plaintext.translate(table)

def encode(pt, cnt=50):
# Note that it's "2" because 2 == "b64e" in this scheme, which is what it's doing
tmp = '2{}'.format(b64encode(pt))
# cnt incrementing from 0 to 49
for cnt in xrange(cnt):
# randomly choose a way to encode it
c = random.choice(enc_ciphers)
# i is the index (starting from 1) of the list above for the given encoding (i.e.: (c = 'rot13',i = 1))
i = enc_ciphers.index(c) + 1
# The following executes the given random selection and stores the output in _tmp
_tmp = globals()[c](tmp)
# Update tmp to be "i<output>". This allows us to know what to do to reverse the encoding
tmp = '{}{}'.format(i, _tmp)

return tmp

if __name__ == '__main__':
# cnt = ?
print encode(FLAG, cnt=50)

I have added notes in-line to describe what's happening (it didn't come with them). The script just takes in a string (the flag in this case) and performs cnt number of encodings on the string, then saving the output for the next input. It uses a random generator to determine what encoding to use, thus the flag output would be different if the author ran the script again. It doesn't matter to us what encodings are used, nor what the cnt variable is. For the encryption side, All of the encodings are easily reversible.

They key insight in this is to notice that script tacks on the index (+1) of the encoding to the front of the string. This means, at every step of the decoding, all we need to do is check the first integer and use the appropriate decoding function. As for the decoding functions themselves, while they're not provided, they're trivial to write.

With all that said, all that was left was to create the decoding script. Here's what I created:

import string
import random
from base64 import b64encode, b64decode

FLAG = 'flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}'

#enc_ciphers = ['rot13', 'b64e', 'caesar']
dec_ciphers = ['rot13', 'b64d', 'caesard']

def rot13(s):
_rot13 = string.maketrans(
"ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz",
"NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm")
return string.translate(s, _rot13)

def b64d(s):
return b64decode(s)

# Decryption is the same as shifting it 26-3
def caesard(plaintext, shift=23):
alphabet = string.ascii_lowercase
shifted_alphabet = alphabet[shift:] + alphabet[:shift]
table = string.maketrans(alphabet, shifted_alphabet)
return plaintext.translate(table)

def decode(ct):
while True:
try:
# i = integer for encryption
i = int(ct) - 1
except:
# Assume we won if this is true
print(ct)
exit(0)

# ct = actual "ciphertext"
ct = ct[1:]

# Get the name of the encryption
c = dec_ciphers[i]

_ct = globals()[c](ct)
ct = _ct

if __name__ == '__main__':