Hints for this task. You should try to solve it without hints first. We give on hint per page, try not to look at all of them at once. First observation: Bob uses CTR-mode, so we can directly modify any part of the message as we want. Second observation: We don't know the password and we likely cannot get it. We should not touch it. Third observation: 'ENCRYPTED' and 'PLAINTEXT' conveniently have the same length. It should be easy to change one into the other. Fourth observation: You can also run bob.py on your local system if you want to add more debugging output. Just create two dummy files for the files that are missing. bob.py will create a fresh shared_key and password which is different from the one used at our servers. Fifth observation: The only remaining problem should be the crc. Have a look at the functions at the beginning of bob.py, in particular the assert statements. Sith observation: We don't know the original crc, but luckily crc is additive. This means, we can fix the crc for the changes we made to the message. CRC stuff foo goo: Let's assume we have a bytestring b'foo' and its crc. crc(b'foo') 1932704819 Now we want to change b'foo' to b'goo' and also fix the crc. We want this crc. crc(b'goo') 1928386052 Can we also get this crc without recomputing, just by fixing the crc of b'foo'? CRC stuff foo goo: First, let's express the change we made to change b'foo' to b'goo' as an xor. delta = bytes((ord('f') ^ ord('g'), 0, 0)) bytewise_xor(b'foo', delta) This gives b'goo'. Can we also apply this to the crc. Look at the additivity again. CRC stuff foo goo: crc(b'foo') ^ crc(delta) This is the desired crc for b'goo': 1928386052 For this whole computation, we just xored values to each other. We can do the same thing on any streamcipher-like encrypted text. Final checks: Let "..." be the delta you computed. Don't forget to compute the crc over binary changes, not hexlified. delta = unhexlify("...") delta_crc = crc(delta) This is how bob computes the crc: crc_correct = crc("{:s},{:s}".format(password, cmd).encode()) Note that he does the crc computation over the decoded plaintext data and a comma. Check: "..." should be 104 characters (hexlified) or 52 bytes when given to crc.