crack.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #!/usr/bin/python3
  2. # -*- coding: iso-8859-15 -*-
  3. """
  4. This file is part of the cintruder project, https://cintruder.03c8.net
  5. Copyright (c) 2012/2020 psy <epsylon@riseup.net>
  6. cintruder is free software; you can redistribute it and/or modify it under
  7. the terms of the GNU General Public License as published by the Free
  8. Software Foundation version 3 of the License.
  9. cintruder is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  12. details.
  13. You should have received a copy of the GNU General Public License along
  14. with cintruder; if not, write to the Free Software Foundation, Inc., 51
  15. Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. """
  17. from PIL import Image
  18. import hashlib, os, math, time
  19. import shutil
  20. class VectorCompare:
  21. def magnitude(self, concordance):
  22. total = 0
  23. for word, count in concordance.items():
  24. # print concordance
  25. total += count ** 2
  26. return math.sqrt(total)
  27. def relation(self, concordance1, concordance2):
  28. topvalue = 0
  29. for word, count in concordance1.items():
  30. if word in concordance2:
  31. topvalue += count * concordance2[word]
  32. return topvalue / (self.magnitude(concordance1) * self.magnitude(concordance2))
  33. class CIntruderCrack(object):
  34. """
  35. Class to bruteforce captchas
  36. """
  37. def __init__(self, captcha=""):
  38. """
  39. Initialize main CIntruder
  40. """
  41. self.captcha = self.set_captcha(captcha)
  42. start = time.time()
  43. if not os.path.exists("core/images/previews/"):
  44. os.mkdir("core/images/previews/")
  45. else:
  46. shutil.rmtree("core/images/previews/")
  47. os.mkdir("core/images/previews/")
  48. def buildvector(self, im):
  49. d1 = {}
  50. count = 0
  51. for i in im.getdata():
  52. d1[count] = i
  53. count += 1
  54. return d1
  55. def set_captcha(self, captcha):
  56. """
  57. Set the captcha.
  58. """
  59. self.captcha = captcha
  60. return captcha
  61. def crack(self, options):
  62. v = VectorCompare()
  63. path, dirs, files = next(os.walk("dictionary/"))
  64. dictionary = dirs
  65. imageset = []
  66. last_letter = None
  67. print("[Info] Loading dictionary...\n")
  68. for letter in dictionary:
  69. for img in os.listdir('dictionary/'+letter):
  70. temp = []
  71. temp.append(self.buildvector(Image.open("dictionary/%s/%s"%(letter, img))))
  72. imageset.append({letter:temp})
  73. try:
  74. im = Image.open(self.captcha)
  75. im.save("core/images/previews/last-preview.gif")
  76. im2 = Image.new("P", im.size, 255)
  77. im = im.convert("P")
  78. except:
  79. print("[Error] Fail during cracking!. Is that captcha supported?\n")
  80. if os.path.exists('core/images/previews'):
  81. shutil.rmtree('core/images/previews') # remove last OCR
  82. return
  83. temp = {}
  84. try:
  85. setids = int(options.setids)
  86. except:
  87. setids = 3 # default pixel colour id
  88. for x in range(im.size[1]):
  89. for y in range(im.size[0]):
  90. pix = im.getpixel((y, x))
  91. temp[pix] = pix
  92. if pix == setids: # pixel colour id
  93. im2.putpixel((y, x), 0)
  94. inletter = False
  95. foundletter = False
  96. start = 0
  97. end = 0
  98. letters = []
  99. for y in range(im2.size[0]): # slice across
  100. for x in range(im2.size[1]): # slice down
  101. pix = im2.getpixel((y, x))
  102. if pix == 0: # != 255
  103. inletter = True
  104. if foundletter == False and inletter == True:
  105. foundletter = True
  106. start = y
  107. if foundletter == True and inletter == False:
  108. foundletter = False
  109. end = y
  110. letters.append((start, end))
  111. inletter = False
  112. count = 0
  113. countid = 1
  114. word_sug = None
  115. end = time.time()
  116. elapsed = end - start
  117. words = {}
  118. for letter in letters:
  119. m = hashlib.md5()
  120. m.update(str(letter))
  121. im3 = im2.crop((letter[0], 0, letter[1], im2.size[1]))
  122. guess = []
  123. for image in imageset:
  124. for x, y in image.items():
  125. if len(y) != 0:
  126. guess.append(( v.relation(y[0], self.buildvector(im3)), x))
  127. guess.sort(reverse=True)
  128. word_per = guess[0][0] * 100
  129. if str(word_per) == "100.0":
  130. print("Image position : "+ str(countid))
  131. print("Broken Percent : "+ str(int(round(float(word_per))))+ "%"+ " [ FULL CRACKED!!! ]")
  132. words[countid] = guess[0][1]
  133. else:
  134. print("Image position : "+ str(countid))
  135. print("Broken Percent : %.4f" % word_per+ "%")
  136. words[countid] = "_"
  137. print("Word suggested : "+str(guess[0][1]))
  138. print("-------------------")
  139. if word_sug == None:
  140. word_sug = str(guess[0][1])
  141. else:
  142. word_sug = word_sug + str(guess[0][1])
  143. count += 1
  144. countid = countid + 1
  145. print("\n========================================")
  146. if options.verbose:
  147. print("[Info] Elapsed OCR time : "+ str(elapsed))
  148. print("========================================")
  149. if word_sug is None:
  150. print("Suggested Solution: [ No idea!. Try to add more images to your dictionary/ ]")
  151. else:
  152. print("Cracked Words: "+ str(list(words.values())))
  153. print("Suggested Solution: [ "+ str(word_sug)+ " ]")
  154. print("========================================\n")
  155. return word_sug