Advertisement
cookthebook

Crib Drag writeup

Mar 4th, 2015
293
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.53 KB | None | 0 0
  1. Crib Drag:
  2. solved by AuPhishYellow member cookthebook for sCTF 2015
  3.  
  4. Crib drag is based upon a core principle in cryptography. Whenever you're given two cipher texts of the same length, you can be almost sure they were encrypted with the "one" time pad. The one time pad is where you take a key of the same length as the plaintext and bitwise xor it with the key. This would be completely secure if you use the key once, but if you use it twice, like they did in this challenge, it can be easily broken. Here is some algebra to show you exactly how my script solves the challenge, keep in mind if a xor b = c, then a xor c = b. And a xor a = 0.
  5.  
  6. c - cipher text
  7. k - key
  8. p - plaintext
  9.  
  10. c1 = p1 xor k
  11. c2 = p2 xor k
  12. c1 xor c2 = p1 xor k xor p2 xor k
  13. = p1 xor p2 xor k xor k
  14. = p1 xor p2 xor 0
  15. = p1 xor p2
  16.  
  17. Thus, by simply xoring the ciphertexts together, we get the xor of the plaintexts. Now, let's say p1 includes the string "cookthebook". If we do every single possible position of "cookthebook" in a string of spaces and "cookthebook" and xor it with the xor'd plaintexts, we will get some part of p2. Here is an example:
  18.  
  19. p1 = "Iam cookthebook"
  20. p2 = "Hello world!!!!"
  21.  
  22. p1 xor p2 xor " "*4 + "cookthebook" = 4 bytes + "o world!!!!"
  23.  
  24. From here, it can be easily seen that p2 should be "Hello world!!!!". This is exactly what this script does with c1 and c2:
  25.  
  26. ------------------------------------------------------------------------
  27. c1 = "2d0710181b01111f0817171401071c11091a0a"
  28. c2 = "3c091311111a1a0e180003120d1a0811091a0a"
  29.  
  30. C1 = list()
  31. C2 = list()
  32.  
  33. for i in range(len(c1)/2):
  34. C1.append(c1[i*2:i*2+2])
  35. C2.append(c2[i*2:i*2+2])
  36.  
  37. P = list()
  38.  
  39. C = zip(C1,C2)
  40.  
  41. for (i,j) in C:
  42. xor = hex(int(i,16)^int(j,16)).replace('L','').replace('0x','')
  43. if len(xor) == 1:
  44. xor = '0' + xor
  45. P.append(xor)
  46.  
  47. #Insert plaintext prediction here
  48. test = 'guess'
  49.  
  50. printme = ''
  51. for (i,j) in zip(list(test),C2):
  52. printme += chr(ord(i)^int(j,16))
  53.  
  54. print printme
  55. ------------------------------------------------------------------------
  56.  
  57. This script simply tests every single possible position of the "test" variable and prints all of the results. Note that the last four bytes are the same in each ciphertext, so no matter what you set "test" to be, the last position will always look like "test". Try running the script with test = "guess" and you will notice that it fits nicely with one of the outputs. From there, simply start reconstructing each phrase until "test" is as long as the cipher text. The flag will be the common key between the ciphertexts.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement