├── captchasec ├── __init__.py ├── decaptcher.py ├── core.py └── report.py ├── .gitignore ├── LICENSE ├── setup.py └── README.md /captchasec/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding : utf-8 -*- 3 | from .core import CaptchaSec 4 | from argparse import ArgumentParser 5 | 6 | 7 | def main(): 8 | parser = ArgumentParser(description="Command line tool for testing captcha..") 9 | parser.add_argument("-u", "--username", required=True, help="Set username of de-captcher.com") 10 | parser.add_argument("-p", "--password", required=True, help="Set password of de-captcher.com") 11 | parser.add_argument("-d", "--directory", required=True, help="Set directory that includes captcha images") 12 | parser.add_argument("-o", "--output", choices=['html', 'json', 'csv'], default="html", help="Specify report format.") 13 | args = parser.parse_args() 14 | main = CaptchaSec(args.username, args.password, args.directory, args.output) 15 | main.run() 16 | 17 | if __name__ == "__main__": 18 | main() -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .cache 41 | nosetests.xml 42 | coverage.xml 43 | 44 | # Translations 45 | *.mo 46 | *.pot 47 | 48 | # Django stuff: 49 | *.log 50 | 51 | # Sphinx documentation 52 | docs/_build/ 53 | 54 | # PyBuilder 55 | target/ 56 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Mehmet İnce 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding : utf-8 -*- 3 | from setuptools import setup 4 | from codecs import open 5 | from os import path 6 | 7 | here = path.abspath(path.dirname(__file__)) 8 | 9 | with open(path.join(here, 'README.md'), encoding='utf-8') as f: 10 | long_description = f.read() 11 | 12 | setup( 13 | name='Captchasec', 14 | version='0.0.1', 15 | description='Captcha difficulty tester', 16 | long_description=long_description, 17 | url='https://github.com/mmetince/captchasec', 18 | author='Mehmet Ince', 19 | author_email='mehmet@mehmetince.net', 20 | license='MIT', 21 | keywords='captcha security cracker', 22 | packages=['captchasec'], 23 | entry_points={ 24 | 'console_scripts': [ 25 | 'captchasec = captchasec:main' 26 | ], 27 | }, 28 | classifiers=[ 29 | 'Environment :: Console', 30 | 'Intended Audience :: Penetration Testers/Web Developers', 31 | 'Natural Language :: English', 32 | 'Operating System :: OS Independent', 33 | 'Topic :: Security :: Web', 34 | 'License :: OSI Approved :: MIT License', 35 | 'Programming Language :: Python', 36 | 'Programming Language :: Python :: 2.7', 37 | ], 38 | ) -------------------------------------------------------------------------------- /captchasec/decaptcher.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding : utf-8 -*- 3 | import urllib2 4 | from urllib import urlencode 5 | 6 | 7 | class DeCaptcher(object): 8 | """ 9 | Unofficial python client for de-captcher.com API 10 | """ 11 | def __init__(self, username, password): 12 | self.url = "http://poster.de-captcher.com/" 13 | self.username = username 14 | self.password = password 15 | 16 | def check_credentials(self): 17 | """ 18 | Checks out supplied credentials are valid or not? 19 | :return: 20 | """ 21 | data = {"function": "balance", 22 | "username": self.username, 23 | "password": self.password} 24 | response = self.__api(data) 25 | return False if response == "" else True 26 | 27 | def get_balance(self): 28 | """ 29 | Get current balance 30 | :return: 31 | """ 32 | data = {"function": "balance", 33 | "username": self.username, 34 | "password": self.password} 35 | response = self.__api(data) 36 | return response 37 | 38 | def solve_image(self, p): 39 | """ 40 | Send image as binary format and get text. 41 | :param p: 42 | :return: 43 | """ 44 | data = {"function": "picture2", 45 | "username": self.username, 46 | "password": self.password, 47 | "pict_type": "0", 48 | "pict_to": "0", 49 | "pict": open(p, "rb").read()} 50 | response = self.__api(data) 51 | answer = response.split("|")[-1] 52 | return answer 53 | 54 | def __api(self, data): 55 | """ 56 | Simple HTTP Post function with build-in functions 57 | in order to serve this tool without dependencies like `requests` etc. 58 | :param data: 59 | :return: 60 | """ 61 | data = urlencode(data) 62 | req = urllib2.Request(self.url, data) 63 | return urllib2.urlopen(req).read() -------------------------------------------------------------------------------- /captchasec/core.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding : utf-8 -*- 3 | from os import listdir 4 | from os.path import isfile, join 5 | from datetime import datetime 6 | from .decaptcher import DeCaptcher 7 | from .report import Report 8 | import imghdr 9 | 10 | 11 | class CaptchaSec(object): 12 | """ 13 | Main class of this tool. 14 | """ 15 | def __init__(self, username, password, directory, output): 16 | self.solver = DeCaptcher(username, password) 17 | self.cracked_captcha = [] 18 | self.output = output 19 | # Checking our credentials 20 | if not self.solver.check_credentials(): 21 | print "Your credentials are not VALID..!" 22 | exit(0) 23 | 24 | # Print current account balance 25 | print "Your current account balance = {}".format(self.solver.get_balance()) 26 | 27 | # Get images from target directory 28 | print "Determining of jpeg files from given directory..." 29 | self.images = self.get_image_list(directory) 30 | 31 | print "Total number of jpeg = {}".format(len(self.images)) 32 | 33 | def get_image_list(self, d): 34 | """ 35 | Determines of jpeg files from given directory. 36 | :param d: 37 | :return: 38 | """ 39 | f_list = [] 40 | for f in listdir(d): 41 | _t = join(d, f) 42 | if isfile(_t) and imghdr.what(_t) == "jpeg": 43 | f_list.append(_t) 44 | return f_list 45 | 46 | def run(self): 47 | """ 48 | Send images to the cracker one by one and calculate consumed time while API cracking captcha. 49 | :return: 50 | """ 51 | for i in self.images: 52 | print "Sending {}. image to api...".format(i) 53 | start_time = datetime.now() 54 | answer = self.solver.solve_image(i) 55 | end_time = datetime.now() 56 | total_time = (end_time - start_time).total_seconds() 57 | print "Yay! Cracked in {0} second..! Answer is = {1}".format(total_time, answer) 58 | self.cracked_captcha.append({'image': i, 'answer': answer, 'time': total_time}) 59 | 60 | # Time to generate report. 61 | report = Report(self.cracked_captcha, self.output) 62 | report.generate() 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Captchasec 2 | 3 | Chaptchasec is a captcha difficulty tester. It uses de-captcher.com as an OCR server. 4 | 5 | - Gets images from local directory 6 | - Generate report as HTML, CSV, JSON 7 | 8 | ``` 9 | ➜ ~ captchasec -u mmetince -p 687226 -d /tmp/ptt/ 10 | Your current account balance = 9.848000000 11 | Determining of jpeg files from given directory... 12 | Total number of jpeg = 20 13 | Sending /tmp/ptt/1. image to api... 14 | Yay! Cracked in 7.196321 second..! Answer is = 825b3 15 | Sending /tmp/ptt/10. image to api... 16 | Yay! Cracked in 15.235815 second..! Answer is = mrv6n 17 | Sending /tmp/ptt/11. image to api... 18 | Yay! Cracked in 13.220645 second..! Answer is = vh32j 19 | Sending /tmp/ptt/12. image to api... 20 | Yay! Cracked in 5.227966 second..! Answer is = ggz8k 21 | Sending /tmp/ptt/13. image to api... 22 | Yay! Cracked in 3.146601 second..! Answer is = 8xk34 23 | Sending /tmp/ptt/14. image to api... 24 | Yay! Cracked in 10.163727 second..! Answer is = 2nd3w 25 | Sending /tmp/ptt/15. image to api... 26 | Yay! Cracked in 7.188108 second..! Answer is = 46rgd 27 | Sending /tmp/ptt/16. image to api... 28 | Yay! Cracked in 8.175217 second..! Answer is = x76xy 29 | Sending /tmp/ptt/17. image to api... 30 | Yay! Cracked in 2.163303 second..! Answer is = 31 | Sending /tmp/ptt/18. image to api... 32 | Yay! Cracked in 8.165439 second..! Answer is = 5h6mr 33 | Sending /tmp/ptt/19. image to api... 34 | Yay! Cracked in 5.157223 second..! Answer is = t82pc 35 | Sending /tmp/ptt/2. image to api... 36 | Yay! Cracked in 16.233299 second..! Answer is = nvg5y 37 | Sending /tmp/ptt/20. image to api... 38 | Yay! Cracked in 5.194488 second..! Answer is = 8wfd3 39 | Sending /tmp/ptt/3. image to api... 40 | Yay! Cracked in 4.234764 second..! Answer is = sfs9d 41 | Sending /tmp/ptt/4. image to api... 42 | Yay! Cracked in 13.203672 second..! Answer is = cms67 43 | Sending /tmp/ptt/5. image to api... 44 | Yay! Cracked in 12.225136 second..! Answer is = h3g4j 45 | Sending /tmp/ptt/6. image to api... 46 | Yay! Cracked in 6.161707 second..! Answer is = 58vd6 47 | Sending /tmp/ptt/7. image to api... 48 | Yay! Cracked in 16.198338 second..! Answer is = 78c2j 49 | Sending /tmp/ptt/8. image to api... 50 | Yay! Cracked in 7.174163 second..! Answer is = 238z4 51 | Sending /tmp/ptt/9. image to api... 52 | Yay! Cracked in 17.220729 second..! Answer is = k3dgv 53 | Results are saved into result_02-16-15-09:59:42.html 54 | ``` 55 | 56 | HTML report 57 | 58 |  59 | 60 | ### Version 61 | 0.0.1 62 | 63 | ### Tech 64 | 65 | It uses following native Python 2 modules. 66 | 67 | * Datetime 68 | * imghdr 69 | * urllib 70 | * io 71 | 72 | ### Installation 73 | 74 | Following instructions will be complate installation. 75 | 76 | ```sh 77 | $ python setup.py install 78 | ``` 79 | 80 | ### Development 81 | 82 | Want to contribute? Great! 83 | 84 | * Fork it! 85 | * Create your feature branch: git checkout -b my-new-branch 86 | * Commit your changes: git commit -m 'Add some feature' 87 | * Push to the branch: git push origin my-new-branch 88 | * Submit a pull request. 89 | 90 | ### Todo's 91 | 92 | - Error handling 93 | - Custom OCR server 94 | - Fetch captches from remote URL. 95 | 96 | License 97 | ---- 98 | 99 | MIT 100 | 101 | **Free Software, Hell Yeah!** 102 | -------------------------------------------------------------------------------- /captchasec/report.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding : utf-8 -*- 3 | from io import open 4 | from datetime import datetime 5 | 6 | 7 | class Report(): 8 | """ 9 | Class for generate report by user choice 10 | """ 11 | def __init__(self, captcha_list, report_type): 12 | self.captcha_list = captcha_list 13 | self.report_type = report_type 14 | 15 | def generate(self): 16 | """ 17 | Generate report. 18 | :return: 19 | """ 20 | if self.report_type == "csv": 21 | self.csv_report() 22 | elif self.report_type == "json": 23 | self.json_report() 24 | else: 25 | self.html_report() 26 | 27 | def json_report(self): 28 | """ 29 | Import json library in order to write results to the file. 30 | :return: 31 | """ 32 | import json 33 | print "Generating JSON report." 34 | f_name = "result_{0}.json".format(datetime.now().strftime("%m-%d-%y-%H:%M:%S")) 35 | with open(f_name, "w") as f: 36 | output = json.dumps(self.captcha_list, indent=2, sort_keys=True) 37 | f.write(unicode(output)) 38 | f.close() 39 | print "Results are saved into {}".format(f_name) 40 | 41 | def csv_report(self): 42 | """ 43 | Import csv library in order to write results to the csv file. 44 | :return: 45 | """ 46 | import csv 47 | print "Generating CSV report." 48 | f_name = "result_{0}.csv".format(datetime.now().strftime("%m-%d-%y-%H:%M:%S")) 49 | with open(f_name, 'wb') as f: 50 | wr = csv.writer(f, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL, lineterminator='\n') 51 | for i in self.captcha_list: 52 | wr.writerow([i['image'], i['answer'], i['time']]) 53 | print "Results are saved into {}".format(f_name) 54 | 55 | def html_report(self): 56 | table_content = u"" 57 | for id, item in enumerate(self.captcha_list): 58 | table_content += u""" 59 |
| # | 153 |Image | 154 |Answer | 155 |Is correct ? | 156 |
|---|