├── .gitignore ├── README.md ├── etc ├── ten_minute_emails.lst └── user_agents.txt ├── hookers ├── __init__.py ├── databasestoday_hook.py ├── dehashed_hook.py ├── emailrep_io_hook.py ├── hibp_hook.py ├── hunter_io_hook.py ├── pastebin_hook.py ├── snusbase_hooker.py └── weleakinfo_hook.py ├── lib ├── __init__.py ├── cmd.py ├── formatter.py └── settings.py ├── requirements.txt ├── whatbreach.py └── whatbreach ├── __init__.py └── main.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | *.pyc 3 | venv/* 4 | env 5 | .DS_Store 6 | venv3/* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WhatBreach 2 | 3 | WhatBreach is an OSINT tool that simplifies the task of discovering what breaches an email address has been discovered in. WhatBreach provides a simple and effective way to search either multiple, or a single email address and discover all known breaches that this email has been seen in. From there WhatBreach is capable of downloading the database if it is publicly available, downloading the pastes the email was seen in, or searching the domain of the email for further investigation. To perform this task successfully WhatBreach takes advantage of the following websites and/or API's: 4 | 5 | - WhatBreach takes advantage of [haveibeenpwned.com](https://haveibeenpwned.com/)'s API. HIBP's API is no longer free and costs 3.50 USD per month. To get an API key please see [here](https://haveibeenpwned.com/API/Key) 6 | - WhatBreach takes advantage of [dehashed.com](https://dehashed.com/) in order to discover if the database has been seen in a breach before. WhatBreach provides a link to a dehashed search for effective downloading 7 | - WhatBreach takes advantage of [hunter.io](https://hunter.io/)'s API (requires free API token) this allows simple and effective domain searching and will provide further information on the domain being searched along with store the discovered results in a file for later processing 8 | - WhatBreach takes advantage of pastes from [pastebin.com](https://pastebin.com/) that have been found from HIBP. It will also provide a link to the paste that the breach was seen in and is capable of downloading the raw paste if requested 9 | - WhatBreach takes advantage of [databases.today](https://databases.today/) to download the databases off the website. This allows a simple and effective way of downloading databases without having to search manually 10 | - WhatBreach takes advantage of [weleakinfo.com](https://weleakinfo.com/)'s API (requires free API token) this provides an extra search for the email in order to discover even more public breaches 11 | - WhatBreach takes advantage of [emailrep.io](https://emailrep.io/)'s simple open API to search for possible profiles associated with an email, it also dumps all information discovered into a file for further processing 12 | 13 | Some interesting features of WhatBreach include the following: 14 | 15 | - Ability to detect if the email is a ten minute email or not and prompt to process it or not 16 | - Check the email for deliverable status using hunter.io 17 | - Ability to throttle the requests in order to help prevent HIBP from blocking you 18 | - Download the databases (since they are large) into a directory of your choice 19 | - Search either a single email or a text file containing one email per line 20 | 21 | # Examples 22 | 23 | Help page: 24 | ``` 25 | usage: whatbreach.py [-h] [-e EMAIL] [-l PATH] [-nD] [-nP] [-sH] [-wL] [-dP] 26 | [-vH] [-cT] [-d] [-s DIRECTORY-PATH] [--throttle TIME] 27 | 28 | optional arguments: 29 | -h, --help show this help message and exit 30 | 31 | mandatory opts: 32 | -e EMAIL, --email EMAIL 33 | Pass a single email to scan for 34 | -l PATH, -f PATH, --list PATH, --file PATH 35 | Pass a file containing emails one per line to scan 36 | 37 | search opts: 38 | -nD, --no-dehashed Suppres dehashed output 39 | -nP, --no-pastebin Suppress Pastebin output 40 | -sH, --search-hunter Search hunter.io with a provided email address and 41 | query for all information, this will process all 42 | emails found as normal 43 | -wL, --search-weleakinfo 44 | Search weleakinfo.com as well as HIBP for results 45 | 46 | misc opts: 47 | -dP, --download-pastes 48 | Download pastes associated with the email address 49 | found (if any) 50 | -vH, --verify-hunter Verify the emails found on hunter.io for deliverable 51 | status 52 | -cT, --check-ten-minute 53 | Check if the provided email address is a ten minute 54 | email or not 55 | -d, --download Attempt to download the database if there is one 56 | available 57 | -s DIRECTORY-PATH, --save-dir DIRECTORY-PATH 58 | Pass a directory to save the downloaded databases into 59 | instead of the `HOME` path 60 | --throttle TIME Throttle the HIBP requests to help prevent yourself 61 | from being blocked 62 | ``` 63 | 64 | Simple email search: 65 | ``` 66 | python whatbreach.py -e user1337@gmail.com 67 | 68 | _____ 69 | _ _ _ _ _ _____ _ |___ | 70 | | | | | |_ ___| |_| __ |___ ___ ___ ___| |_ | _| 71 | | | | | | .'| _| __ -| _| -_| .'| _| | |_| 72 | |_____|_|_|__,|_| |_____|_| |___|__,|___|_|_|[][][]|_| 73 | Find emails and their associated leaked databases.. v0.1.5 74 | 75 | 76 | [ i ] starting search on single email address: user1337@gmail.com 77 | [ i ] searching breached accounts on HIBP related to: user1337@gmail.com 78 | [ i ] searching for paste dumps on HIBP related to: user1337@gmail.com 79 | [ i ] found a total of 9 database breach(es) pertaining to: user1337@gmail.com 80 | --------------------------------------------------------------------------- 81 | Breach/Paste: | Database/Paste Link: 82 | Dailymotion | https://www.dehashed.com/search?query=Dailymotion 83 | 500px | https://www.dehashed.com/search?query=500px 84 | LinkedIn | https://www.dehashed.com/search?query=LinkedIn 85 | MyFitnessPal | https://www.dehashed.com/search?query=MyFitnessPal 86 | Bolt | https://www.dehashed.com/search?query=Bolt 87 | Dropbox | https://www.dehashed.com/search?query=Dropbox 88 | Lastfm | https://www.dehashed.com/search?query=Lastfm 89 | Apollo | https://www.dehashed.com/search?query=Apollo 90 | OnlinerSpambot | N/A 91 | --------------------------------------------------------------------------- 92 | ``` 93 | 94 | Searching with weleakinfo and haveibeenpwned: 95 | ``` 96 | python whatbreach.py -e user1337@gmail.com -wL 97 | 98 | _____ 99 | _ _ _ _ _ _____ _ |___ | 100 | | | | | |_ ___| |_| __ |___ ___ ___ ___| |_ | _| 101 | | | | | | .'| _| __ -| _| -_| .'| _| | |_| 102 | |_____|_|_|__,|_| |_____|_| |___|__,|___|_|_|[][][]|_| 103 | Find emails and their associated leaked databases.. v0.1.5 104 | 105 | 106 | [ i ] starting search on single email address: user1337@gmail.com 107 | [ i ] searching breached accounts on HIBP related to: user1337@gmail.com 108 | [ i ] searching for paste dumps on HIBP related to: user1337@gmail.com 109 | [ i ] searching weleakinfo.com for breaches related to: user1337@gmail.com 110 | [ i ] discovered a total of 12 more breaches from weleakinfo.com 111 | [ i ] found a total of 21 database breach(es) pertaining to: user1337@gmail.com 112 | [ w ] large amount of database breaches, obtaining links from dehashed (this may take a minute) 113 | ------------------------------------------------------------------------------- 114 | Breach/Paste: | Database/Paste Link: 115 | Pesfan.com | https://www.dehashed.com/search?query=Pesfan.com 116 | Dailymotion | https://www.dehashed.com/search?query=Dailymotion 117 | Apollo | https://www.dehashed.com/search?query=Apollo 118 | MyFitnessPal | https://www.dehashed.com/search?query=MyFitnessPal 119 | 500px | https://www.dehashed.com/search?query=500px 120 | Collection 4 | https://www.dehashed.com/search?query=Collection 4 121 | OnlinerSpambot | N/A 122 | LinkedIn | https://www.dehashed.com/search?query=LinkedIn 123 | Dropbox.com | https://www.dehashed.com/search?query=Dropbox.com 124 | 500px.com | https://www.dehashed.com/search?query=500px.com 125 | Dailymotion.com | https://www.dehashed.com/search?query=Dailymotion.com 126 | Last.fm March 2012 | https://www.dehashed.com/search?query=Last.fm March 2012 127 | Dropbox | https://www.dehashed.com/search?query=Dropbox 128 | Myfitnesspal.com | https://www.dehashed.com/search?query=Myfitnesspal.com 129 | Collection 1 | https://www.dehashed.com/search?query=Collection 1 130 | Collection 2 | https://www.dehashed.com/search?query=Collection 2 131 | Bolt.cd | https://www.dehashed.com/search?query=Bolt.cd 132 | Lastfm | https://www.dehashed.com/search?query=Lastfm 133 | Bolt | https://www.dehashed.com/search?query=Bolt 134 | Collection 3 | https://www.dehashed.com/search?query=Collection 3 135 | LinkedIn.com | https://www.dehashed.com/search?query=LinkedIn.com 136 | ------------------------------------------------------------------------------- 137 | ``` 138 | 139 | Downloading public databases: 140 | ``` 141 | python whatbreach.py -e user1337@gmail.com -d 142 | 143 | _____ 144 | _ _ _ _ _ _____ _ |___ | 145 | | | | | |_ ___| |_| __ |___ ___ ___ ___| |_ | _| 146 | | | | | | .'| _| __ -| _| -_| .'| _| | |_| 147 | |_____|_|_|__,|_| |_____|_| |___|__,|___|_|_|[][][]|_| 148 | Find emails and their associated leaked databases.. v0.1.5 149 | 150 | 151 | [ i ] starting search on single email address: user1337@gmail.com 152 | [ i ] searching breached accounts on HIBP related to: user1337@gmail.com 153 | [ i ] searching for paste dumps on HIBP related to: user1337@gmail.com 154 | [ i ] found a total of 9 database breach(es) pertaining to: user1337@gmail.com 155 | --------------------------------------------------------------------------- 156 | Breach/Paste: | Database/Paste Link: 157 | Dailymotion | https://www.dehashed.com/search?query=Dailymotion 158 | 500px | https://www.dehashed.com/search?query=500px 159 | LinkedIn | https://www.dehashed.com/search?query=LinkedIn 160 | MyFitnessPal | https://www.dehashed.com/search?query=MyFitnessPal 161 | Bolt | https://www.dehashed.com/search?query=Bolt 162 | Dropbox | https://www.dehashed.com/search?query=Dropbox 163 | Lastfm | https://www.dehashed.com/search?query=Lastfm 164 | Apollo | https://www.dehashed.com/search?query=Apollo 165 | OnlinerSpambot | N/A 166 | --------------------------------------------------------------------------- 167 | [ i ] searching for downloadable databases using query: dailymotion 168 | [ w ] no databases appeared to be present and downloadable related to query: Dailymotion 169 | [ i ] searching for downloadable databases using query: 500px 170 | [ w ] no databases appeared to be present and downloadable related to query: 500px 171 | [ i ] searching for downloadable databases using query: linkedin 172 | [ ? ] discovered publicly available database for query LinkedIn, do you want to download [y/N]: n 173 | [ i ] skipping download as requested 174 | [ w ] no databases appeared to be present and downloadable related to query: LinkedIn 175 | [ i ] searching for downloadable databases using query: myfitnesspal 176 | [ w ] no databases appeared to be present and downloadable related to query: MyFitnessPal 177 | [ i ] searching for downloadable databases using query: bolt 178 | [ w ] no databases appeared to be present and downloadable related to query: Bolt 179 | [ i ] searching for downloadable databases using query: dropbox 180 | [ ? ] discovered publicly available database for query Dropbox, do you want to download [y/N]: n 181 | [ i ] skipping download as requested 182 | [ w ] no databases appeared to be present and downloadable related to query: Dropbox 183 | [ i ] searching for downloadable databases using query: lastfm 184 | [ ? ] discovered publicly available database for query Lastfm, do you want to download [y/N]: n 185 | [ i ] skipping download as requested 186 | [ w ] no databases appeared to be present and downloadable related to query: Lastfm 187 | [ i ] searching for downloadable databases using query: apollo 188 | [ w ] no databases appeared to be present and downloadable related to query: Apollo 189 | [ i ] searching for downloadable databases using query: onlinerspambot 190 | [ w ] no databases appeared to be present and downloadable related to query: OnlinerSpambot 191 | ``` 192 | 193 | Using hunter.io for domain hunting and throttling the requests to attempt prevention of HIBP from blocking you: 194 | ``` 195 | python whatbreach.py -e user1337@fbi.com -sH --throttle 35 196 | 197 | _____ 198 | _ _ _ _ _ _____ _ |___ | 199 | | | | | |_ ___| |_| __ |___ ___ ___ ___| |_ | _| 200 | | | | | | .'| _| __ -| _| -_| .'| _| | |_| 201 | |_____|_|_|__,|_| |_____|_| |___|__,|___|_|_|[][][]|_| 202 | Find emails and their associated leaked databases.. v0.1.5 203 | 204 | 205 | [ i ] starting search on hunter.io using user1337@fbi.com 206 | [ i ] discovered a total of 11 email(s) 207 | [ i ] information discovered associated with fbi.com 208 | [ i ] discovered possible pattern to emails: {first}.{last}@fbi.com 209 | [ w ] did not discover any associated phone number(s) 210 | [ i ] discovered associated email address(es): 211 | -> user1337@fbi.com 212 | -> blackeagle@fbi.com 213 | -> jillian.cartwright@fbi.com 214 | -> management@fbi.com 215 | -> info@fbi.com 216 | -> fmulder@fbi.com 217 | -> markamorgan@fbi.com 218 | -> james.bond@fbi.com 219 | -> robert.mueller@fbi.com 220 | [ w ] hit maximum length, total of 1 not displayed 221 | [ i ] discovered associated external URL(s): 222 | -> http://jobsnotification.blogspot.com/2011/03/ifbi-pgdbo-admission-2011-pg-diploma-in.html 223 | -> http://complaintsboard.com/complaints/fbi-robert-s-muelleriii-huber-heights-ohio-c121118.html 224 | -> http://user.xmission.com/~daina/known_scammers.html 225 | -> http://anonymousxwrites.blogspot.com/2012/02 226 | -> http://boingboing.net/2012/02/14 227 | -> http://joewein.net/dbl-update/2014-06/2014-06-22.htm 228 | -> http://anonymousxwrites.blogspot.fr/2012/02/federal-bureau-of-investigation-fbi-yet.html 229 | -> http://anonymousxwrites.blogspot.sg/2012/02 230 | -> http://meg-golpistasvirtuais.blogspot.fr/2013/04/update-emails-addresses-scammers-dia.html 231 | [ w ] hit maximum length, total of 35 not displayed 232 | [ i ] dumping all information into json file for further processing 233 | [ i ] information written to: /Users/admin/.whatbreach_home/downloads/json_dumps/cbNcFiXZsU_fbi.com.json 234 | [ i ] searching breached accounts on HIBP related to: user1337@fbi.com 235 | [ i ] searching for paste dumps on HIBP related to: user1337@fbi.com 236 | [ ! ] email user1337@fbi.com was not found in any breach 237 | [ i ] searching breached accounts on HIBP related to: blackeagle@fbi.com 238 | [ i ] searching for paste dumps on HIBP related to: blackeagle@fbi.com 239 | [ ! ] email blackeagle@fbi.com was not found in any breach 240 | [ i ] searching breached accounts on HIBP related to: jillian.cartwright@fbi.com 241 | [ i ] searching for paste dumps on HIBP related to: jillian.cartwright@fbi.com 242 | ... 243 | ``` 244 | 245 | Checking for ten minute emails: 246 | ``` 247 | python whatbreach.py -l test.txt -cT 248 | 249 | _____ 250 | _ _ _ _ _ _____ _ |___ | 251 | | | | | |_ ___| |_| __ |___ ___ ___ ___| |_ | _| 252 | | | | | | .'| _| __ -| _| -_| .'| _| | |_| 253 | |_____|_|_|__,|_| |_____|_| |___|__,|___|_|_|[][][]|_| 254 | Find emails and their associated leaked databases.. v0.1.5 255 | 256 | 257 | [ i ] parsing email file: test.txt 258 | [ i ] starting search on a total of 2 email(s) 259 | [ i ] searching breached accounts on HIBP related to: user1337@gmail.com 260 | [ i ] searching for paste dumps on HIBP related to: user1337@gmail.com 261 | [ i ] found a total of 9 database breach(es) pertaining to: user1337@gmail.com 262 | --------------------------------------------------------------------------- 263 | Breach/Paste: | Database/Paste Link: 264 | Dailymotion | https://www.dehashed.com/search?query=Dailymotion 265 | 500px | https://www.dehashed.com/search?query=500px 266 | LinkedIn | https://www.dehashed.com/search?query=LinkedIn 267 | MyFitnessPal | https://www.dehashed.com/search?query=MyFitnessPal 268 | Bolt | https://www.dehashed.com/search?query=Bolt 269 | Dropbox | https://www.dehashed.com/search?query=Dropbox 270 | Lastfm | https://www.dehashed.com/search?query=Lastfm 271 | Apollo | https://www.dehashed.com/search?query=Apollo 272 | OnlinerSpambot | N/A 273 | --------------------------------------------------------------------------- 274 | [ w ] email: userl337@uhren.com appears to be a ten minute email 275 | [ ? ] would you like to process the email[y/N]: n 276 | ``` 277 | 278 | Searching for profiles associated with the email: 279 | ``` 280 | python whatbreach.py -e user@gmail.com -cA 281 | 282 | _____ 283 | _ _ _ _ _ _____ _ |___ | 284 | | | | | |_ ___| |_| __ |___ ___ ___ ___| |_ | _| 285 | | | | | | .'| _| __ -| _| -_| .'| _| | |_| 286 | |_____|_|_|__,|_| |_____|_| |___|__,|___|_|_|[][][]|_| 287 | Find emails and their associated leaked databases.. v0.1.8 288 | 289 | 290 | [ i ] starting search on single email address: user@gmail.com 291 | [ i ] searching for possible profiles related to user@gmail.com 292 | [ i ] all data dumped to file for future processing: /Users/admin/.whatbreach_home/downloads/json_dumps/user_emailrep.json 293 | [ i ] found a total of 5 possible profiles associated with user@gmail.com on the following domains: 294 | -> Twitter 295 | -> Instagram 296 | -> Pastebin 297 | -> Pinterest 298 | -> Spotify 299 | ... 300 | ``` 301 | 302 | # Installation 303 | 304 | Installing is extremely easy, just run `pip install -r requirements.txt` 305 | 306 | # Why? 307 | 308 | During my time in information technology, during researching and doing OSINT, I have noticed a need to find email addresses as well as their password. I have found reliable tools that do this successfully and make the process quick and easy, however I have not found a tool that meets my exact requirements. This tool is basically my own personal take on how I think email searching should work and ties in the database searching and database downloading as well. What better way to break into an email then to have the possible password as well as all _known_ breaches it's been seen in? 309 | 310 | # Shoutouts 311 | 312 | - [NullArray](https://github.com/NullArray) for providing me with the idea for the hash checking and the idea for the databases.today downloads, as well as being an awesome and supportive person at all times. 313 | - [khast3x](https://github.com/khast3x) (or as you know him the creator of [h8mail](https://github.com/khast3x/h8mail)) for being supportive and and overall enjoyable person. The best way to find the data in the databases downloaded from this tool is to use [h8mail](https://github.com/khast3x/h8mail), it's quick, efficient, and easy. Go check it out. 314 | -------------------------------------------------------------------------------- /etc/ten_minute_emails.lst: -------------------------------------------------------------------------------- 1 | 0815.ru 2 | 0815.ru0clickemail.com 3 | 0815.ry 4 | 0815.su 5 | 0845.ru 6 | 0clickemail.com 7 | 0-mail.com 8 | 0wnd.net 9 | 0wnd.org 10 | 10mail.com 11 | 10mail.org 12 | 10minut.com.pl 13 | 10minutemail.cf 14 | 10minutemail.co.za 15 | 10minutemail.com 16 | 10minutemail.de 17 | 10minutemail.ga 18 | 10minutemail.gq 19 | 10minutemail.ml 20 | 10minutemail.net 21 | 10minutesmail.com 22 | 10x9.com 23 | 123-m.com 24 | 126.com 25 | 12houremail.com 26 | 12minutemail.com 27 | 12minutemail.net 28 | 139.com 29 | 163.com 30 | 1ce.us 31 | 1chuan.com 32 | 1fsdfdsfsdf.tk 33 | 1mail.ml 34 | 1pad.de 35 | 1zhuan.com 36 | 20mail.it 37 | 20minutemail.com 38 | 21cn.com 39 | 24hourmail.com 40 | 2fdgdfgdfgdf.tk 41 | 2prong.com 42 | 30minutemail.com 43 | 33mail.com 44 | 3d-painting.com 45 | 3mail.ga 46 | 3trtretgfrfe.tk 47 | 420blaze.it 48 | 4gfdsgfdgfd.tk 49 | 4mail.cf 50 | 4mail.ga 51 | 4warding.com 52 | 4warding.net 53 | 4warding.org 54 | 5ghgfhfghfgh.tk 55 | 5mail.cf 56 | 5mail.ga 57 | 60minutemail.com 58 | 675hosting.com 59 | 675hosting.net 60 | 675hosting.org 61 | 6hjgjhgkilkj.tk 62 | 6ip.us 63 | 6mail.cf 64 | 6mail.ga 65 | 6mail.ml 66 | 6paq.com 67 | 6url.com 68 | 75hosting.com 69 | 75hosting.net 70 | 75hosting.org 71 | 7days-printing.com 72 | 7mail.ga 73 | 7mail.ml 74 | 7tags.com 75 | 8127ep.com 76 | 8chan.co 77 | 8mail.cf 78 | 8mail.ga 79 | 8mail.ml 80 | 99experts.com 81 | 9mail.cf 82 | 9ox.net 83 | a.mailcker.com 84 | a.vztc.com 85 | a45.in 86 | a-bc.net 87 | abyssmail.com 88 | afrobacon.com 89 | ag.us.to 90 | agedmail.com 91 | ajaxapp.net 92 | akapost.com 93 | akerd.com 94 | aktiefmail.nl 95 | alivance.com 96 | amail4.me 97 | ama-trade.de 98 | ama-trans.de 99 | amilegit.com 100 | amiri.net 101 | amiriindustries.com 102 | anappthat.com 103 | ano-mail.net 104 | anonbox.net 105 | anon-mail.de 106 | anonmails.de 107 | anonymail.dk 108 | anonymbox.com 109 | anonymousmail.org 110 | anonymousspeech.com 111 | antichef.com 112 | antichef.net 113 | antireg.com 114 | antireg.ru 115 | antispam.de 116 | antispam24.de 117 | antispammail.de 118 | armyspy.com 119 | artman-conception.com 120 | asdasd.nl 121 | asdasd.ru 122 | atvclub.msk.ru 123 | auti.st 124 | avpa.nl 125 | azmeil.tk 126 | b2cmail.de 127 | baxomale.ht.cx 128 | beddly.com 129 | beefmilk.com 130 | big1.us 131 | bigprofessor.so 132 | bigstring.com 133 | binkmail.com 134 | bio-muesli.info 135 | bio-muesli.net 136 | blackmarket.to 137 | bladesmail.net 138 | bloatbox.com 139 | blogmyway.org 140 | blogos.com 141 | bluebottle.com 142 | bobmail.info 143 | bodhi.lawlita.com 144 | bofthew.com 145 | bootybay.de 146 | boun.cr 147 | bouncr.com 148 | boxformail.in 149 | boximail.com 150 | br.mintemail.com 151 | brainonfire.net 152 | breakthru.com 153 | brefmail.com 154 | brennendesreich.de 155 | broadbandninja.com 156 | bsnow.net 157 | bspamfree.org 158 | bu.mintemail.com 159 | buffemail.com 160 | bugmenever.com 161 | bugmenot.com 162 | bumpymail.com 163 | bund.us 164 | bundes-li.ga 165 | burnthespam.info 166 | burstmail.info 167 | buymoreplays.com 168 | buyusedlibrarybooks.org 169 | byom.de 170 | c2.hu 171 | cachedot.net 172 | cam4you.cc 173 | card.zp.ua 174 | casualdx.com 175 | cc.liamria 176 | cek.pm 177 | cellurl.com 178 | centermail.com 179 | centermail.net 180 | chammy.info 181 | cheatmail.de 182 | childsavetrust.org 183 | chogmail.com 184 | choicemail1.com 185 | chong-mail.com 186 | chong-mail.net 187 | chong-mail.org 188 | clixser.com 189 | clrmail.com 190 | cmail.com 191 | cmail.net 192 | cmail.org 193 | cock.li 194 | coieo.com 195 | coldemail.info 196 | consumerriot.com 197 | cool.fr.nf 198 | correo.blogos.net 199 | cosmorph.com 200 | courriel.fr.nf 201 | courrieltemporaire.com 202 | crapmail.org 203 | crazymailing.com 204 | cubiclink.com 205 | cumallover.me 206 | curryworld.de 207 | cust.in 208 | cuvox.de 209 | d3p.dk 210 | dacoolest.com 211 | dandikmail.com 212 | dayrep.com 213 | dbunker.com 214 | dcemail.com 215 | deadaddress.com 216 | deadchildren.org 217 | deadfake.cf 218 | deadfake.ga 219 | deadfake.ml 220 | deadfake.tk 221 | deadspam.com 222 | deagot.com 223 | dealja.com 224 | delikkt.de 225 | despam.it 226 | despammed.com 227 | devnullmail.com 228 | dfgh.net 229 | dharmatel.net 230 | dicksinhisan.us 231 | dicksinmyan.us 232 | digitalsanctuary.com 233 | dingbone.com 234 | discard.cf 235 | discard.email 236 | discard.ga 237 | discard.gq 238 | discard.ml 239 | discard.tk 240 | discardmail.com 241 | discardmail.de 242 | disposable.cf 243 | disposable.ga 244 | disposable.ml 245 | disposableaddress.com 246 | disposable-email.ml 247 | disposableemailaddresses.com 248 | disposableinbox.com 249 | dispose.it 250 | disposeamail.com 251 | disposemail.com 252 | dispostable.com 253 | divermail.com 254 | dm.w3internet.co.uk 255 | dm.w3internet.co.ukexample.com 256 | docmail.com 257 | dodgeit.com 258 | dodgit.com 259 | dodgit.org 260 | doiea.com 261 | domozmail.com 262 | donemail.ru 263 | dontreg.com 264 | dontsendmespam.de 265 | dotman.de 266 | dotmsg.com 267 | drdrb.com 268 | drdrb.net 269 | dropcake.de 270 | droplister.com 271 | dropmail.me 272 | dudmail.com 273 | dumpandjunk.com 274 | dump-email.info 275 | dumpmail.de 276 | dumpyemail.com 277 | duskmail.com 278 | e4ward.com 279 | easytrashmail.com 280 | edv.to 281 | ee1.pl 282 | ee2.pl 283 | eelmail.com 284 | einmalmail.de 285 | einrot.com 286 | einrot.de 287 | eintagsmail.de 288 | e-mail.com 289 | email.net 290 | e-mail.org 291 | email60.com 292 | emailage.cf 293 | emailage.ga 294 | emailage.gq 295 | emailage.ml 296 | emailage.tk 297 | emaildienst.de 298 | email-fake.cf 299 | email-fake.ga 300 | email-fake.gq 301 | email-fake.ml 302 | email-fake.tk 303 | emailgo.de 304 | emailias.com 305 | emailigo.de 306 | emailinfive.com 307 | emaillime.com 308 | emailmiser.com 309 | emails.ga 310 | emailsensei.com 311 | emailspam.cf 312 | emailspam.ga 313 | emailspam.gq 314 | emailspam.ml 315 | emailspam.tk 316 | emailtemporanea.com 317 | emailtemporanea.net 318 | emailtemporar.ro 319 | emailtemporario.com.br 320 | emailthe.net 321 | emailtmp.com 322 | emailto.de 323 | emailwarden.com 324 | emailx.at.hm 325 | emailxfer.com 326 | emailz.cf 327 | emailz.ga 328 | emailz.gq 329 | emailz.ml 330 | emeil.in 331 | emeil.ir 332 | emkei.cf 333 | emkei.ga 334 | emkei.gq 335 | emkei.ml 336 | emkei.tk 337 | emz.net 338 | enterto.com 339 | ephemail.net 340 | e-postkasten.com 341 | e-postkasten.de 342 | e-postkasten.eu 343 | e-postkasten.info 344 | ero-tube.org 345 | etranquil.com 346 | etranquil.net 347 | etranquil.org 348 | evopo.com 349 | example.com 350 | explodemail.com 351 | express.net.ua 352 | eyepaste.com 353 | facebook-email.cf 354 | facebook-email.ga 355 | facebook-email.ml 356 | facebookmail.gq 357 | facebookmail.ml 358 | faecesmail.me 359 | fakedemail.com 360 | fakeinbox.cf 361 | fakeinbox.com 362 | fakeinbox.ga 363 | fakeinbox.ml 364 | fakeinbox.tk 365 | fakeinformation.com 366 | fake-mail.cf 367 | fakemail.fr 368 | fake-mail.ga 369 | fake-mail.ml 370 | fakemailgenerator.com 371 | fakemailz.com 372 | fammix.com 373 | fansworldwide.de 374 | fantasymail.de 375 | fastacura.com 376 | fastchevy.com 377 | fastchrysler.com 378 | fastermail.com 379 | fastkawasaki.com 380 | fastmail.fm 381 | fastmazda.com 382 | fastmitsubishi.com 383 | fastnissan.com 384 | fastsubaru.com 385 | fastsuzuki.com 386 | fasttoyota.com 387 | fastyamaha.com 388 | fatflap.com 389 | fdfdsfds.com 390 | fightallspam.com 391 | film-blog.biz 392 | filzmail.com 393 | fivemail.de 394 | fixmail.tk 395 | fizmail.com 396 | fleckens.hu 397 | flurred.com 398 | flyspam.com 399 | fly-ts.de 400 | footard.com 401 | forgetmail.com 402 | fornow.eu 403 | fr33mail.info 404 | frapmail.com 405 | freecoolemail.com 406 | free-email.cf 407 | free-email.ga 408 | freeletter.me 409 | freemail.ms 410 | freemails.cf 411 | freemails.ga 412 | freemails.ml 413 | freundin.ru 414 | friendlymail.co.uk 415 | front14.org 416 | fuckingduh.com 417 | fuckmail.me 418 | fudgerub.com 419 | fux0ringduh.com 420 | fyii.de 421 | garbagemail.org 422 | garliclife.com 423 | garrifulio.mailexpire.com 424 | gawab.com 425 | gehensiemirnichtaufdensack.de 426 | gelitik.in 427 | geschent.biz 428 | get1mail.com 429 | get2mail.fr 430 | getairmail.cf 431 | getairmail.com 432 | getairmail.ga 433 | getairmail.gq 434 | getairmail.ml 435 | getairmail.tk 436 | get-mail.cf 437 | get-mail.ga 438 | get-mail.ml 439 | get-mail.tk 440 | getmails.eu 441 | getonemail.com 442 | getonemail.net 443 | ghosttexter.de 444 | giantmail.de 445 | girlsundertheinfluence.com 446 | gishpuppy.com 447 | gmal.com 448 | gmial.com 449 | gmx.com 450 | goat.si 451 | goemailgo.com 452 | gomail.in 453 | gorillaswithdirtyarmpits.com 454 | gotmail.com 455 | gotmail.net 456 | gotmail.org 457 | gotti.otherinbox.com 458 | gowikibooks.com 459 | gowikicampus.com 460 | gowikicars.com 461 | gowikifilms.com 462 | gowikigames.com 463 | gowikimusic.com 464 | gowikinetwork.com 465 | gowikitravel.com 466 | gowikitv.com 467 | grandmamail.com 468 | grandmasmail.com 469 | great-host.in 470 | greensloth.com 471 | grr.la 472 | gsrv.co.uk 473 | guerillamail.biz 474 | guerillamail.com 475 | guerillamail.net 476 | guerillamail.org 477 | guerillamailblock.com 478 | guerrillamail.biz 479 | guerrillamail.com 480 | guerrillamail.de 481 | guerrillamail.info 482 | guerrillamail.net 483 | guerrillamail.org 484 | guerrillamailblock.com 485 | gustr.com 486 | h.mintemail.com 487 | h8s.org 488 | hacccc.com 489 | haltospam.com 490 | harakirimail.com 491 | hartbot.de 492 | hatespam.org 493 | hat-geld.de 494 | herp.in 495 | hidemail.de 496 | hidzz.com 497 | hmamail.com 498 | hochsitze.com 499 | hooohush.ai 500 | hopemail.biz 501 | horsefucker.org 502 | hotmai.com 503 | hot-mail.cf 504 | hot-mail.ga 505 | hot-mail.gq 506 | hot-mail.ml 507 | hot-mail.tk 508 | hotmial.com 509 | hotpop.com 510 | huajiachem.cn 511 | hulapla.de 512 | humaility.com 513 | hush.ai 514 | hush.com 515 | hushmail.com 516 | hushmail.me 517 | i2pmail.org 518 | ieatspam.eu 519 | ieatspam.info 520 | ieh-mail.de 521 | ignoremail.com 522 | ihateyoualot.info 523 | iheartspam.org 524 | ikbenspamvrij.nl 525 | imails.info 526 | imgof.com 527 | imgv.de 528 | imstations.com 529 | inbax.tk 530 | inbox.si 531 | inbox2.info 532 | inboxalias.com 533 | inboxclean.com 534 | inboxclean.org 535 | inboxdesign.me 536 | inboxed.im 537 | inboxed.pw 538 | inboxstore.me 539 | incognitomail.com 540 | incognitomail.net 541 | incognitomail.org 542 | infocom.zp.ua 543 | insorg-mail.info 544 | instantemailaddress.com 545 | instant-mail.de 546 | iozak.com 547 | ip6.li 548 | ipoo.org 549 | irish2me.com 550 | iroid.com 551 | is.af 552 | iwantmyname.com 553 | iwi.net 554 | jetable.com 555 | jetable.fr.nf 556 | jetable.net 557 | jetable.org 558 | jnxjn.com 559 | jourrapide.com 560 | jsrsolutions.com 561 | junk.to 562 | junk1e.com 563 | junkmail.ga 564 | junkmail.gq 565 | k2-herbal-incenses.com 566 | kasmail.com 567 | kaspop.com 568 | keepmymail.com 569 | killmail.com 570 | killmail.net 571 | kir.ch.tc 572 | klassmaster.com 573 | klassmaster.net 574 | klzlk.com 575 | kmhow.com 576 | kostenlosemailadresse.de 577 | koszmail.pl 578 | kulturbetrieb.info 579 | kurzepost.de 580 | l33r.eu 581 | lackmail.net 582 | lags.us 583 | landmail.co 584 | lastmail.co 585 | lavabit.com 586 | lawlita.com 587 | letthemeatspam.com 588 | lhsdv.com 589 | lifebyfood.com 590 | link2mail.net 591 | linuxmail.so 592 | litedrop.com 593 | llogin.ru 594 | loadby.us 595 | login-email.cf 596 | login-email.ga 597 | login-email.ml 598 | login-email.tk 599 | lol.com 600 | lol.ovpn.to 601 | lolfreak.net 602 | lookugly.com 603 | lopl.co.cc 604 | lortemail.dk 605 | losemymail.com 606 | lovebitco.in 607 | lovemeleaveme.com 608 | loves.dicksinhisan.us 609 | loves.dicksinmyan.us 610 | lr7.us 611 | lr78.com 612 | lroid.com 613 | luckymail.org 614 | lukop.dk 615 | luv2.us 616 | m21.cc 617 | m4ilweb.info 618 | ma1l.bij.pl 619 | maboard.com 620 | mac.hush.com 621 | mail.by 622 | mail.me 623 | mail.mezimages.net 624 | mail.ru 625 | mail.zp.ua 626 | mail114.net 627 | mail1a.de 628 | mail21.cc 629 | mail2rss.org 630 | mail2world.com 631 | mail333.com 632 | mail4trash.com 633 | mailbidon.com 634 | mailbiz.biz 635 | mailblocks.com 636 | mailbucket.org 637 | mailcat.biz 638 | mailcatch.com 639 | mailde.de 640 | mailde.info 641 | maildrop.cc 642 | maildrop.cf 643 | maildrop.ga 644 | maildrop.gq 645 | maildrop.ml 646 | maildu.de 647 | maileater.com 648 | mailed.in 649 | maileimer.de 650 | mailexpire.com 651 | mailfa.tk 652 | mail-filter.com 653 | mailforspam.com 654 | mailfree.ga 655 | mailfree.gq 656 | mailfree.ml 657 | mailfreeonline.com 658 | mailguard.me 659 | mailhazard.com 660 | mailhazard.us 661 | mailhz.me 662 | mailimate.com 663 | mailin8r.com 664 | mailinater.com 665 | mailinator.com 666 | mailinator.gq 667 | mailinator.net 668 | mailinator.org 669 | mailinator.us 670 | mailinator2.com 671 | mailincubator.com 672 | mailismagic.com 673 | mailita.tk 674 | mailjunk.cf 675 | mailjunk.ga 676 | mailjunk.gq 677 | mailjunk.ml 678 | mailjunk.tk 679 | mailme.gq 680 | mailme.ir 681 | mailme.lv 682 | mailme24.com 683 | mailmetrash.com 684 | mailmoat.com 685 | mailms.com 686 | mailnator.com 687 | mailnesia.com 688 | mailnull.com 689 | mailorg.org 690 | mailpick.biz 691 | mailquack.com 692 | mailrock.biz 693 | mailsac.com 694 | mailscrap.com 695 | mailseal.de 696 | mailshell.com 697 | mailsiphon.com 698 | mailslapping.com 699 | mailslite.com 700 | mailtemp.info 701 | mail-temporaire.fr 702 | mailtome.de 703 | mailtothis.com 704 | mailtrash.net 705 | mailtv.net 706 | mailtv.tv 707 | mailwithyou.com 708 | mailzilla.com 709 | mailzilla.org 710 | makemetheking.com 711 | malahov.de 712 | manifestgenerator.com 713 | manybrain.com 714 | mbx.cc 715 | mega.zik.dj 716 | meinspamschutz.de 717 | meltmail.com 718 | messagebeamer.de 719 | mezimages.net 720 | mierdamail.com 721 | migmail.pl 722 | migumail.com 723 | ministry-of-silly-walks.de 724 | mintemail.com 725 | misterpinball.de 726 | mjukglass.nu 727 | mmmmail.com 728 | moakt.com 729 | mobi.web.id 730 | mobileninja.co.uk 731 | moburl.com 732 | moncourrier.fr.nf 733 | monemail.fr.nf 734 | monmail.fr.nf 735 | monumentmail.com 736 | ms9.mailslite.com 737 | msa.minsmail.com 738 | msb.minsmail.com 739 | msg.mailslite.com 740 | mt2009.com 741 | mt2014.com 742 | mt2015.com 743 | muchomail.com 744 | mx0.wwwnew.eu 745 | my10minutemail.com 746 | mycard.net.ua 747 | mycleaninbox.net 748 | myemailboxy.com 749 | mymail-in.net 750 | mynetstore.de 751 | mypacks.net 752 | mypartyclip.de 753 | myphantomemail.com 754 | mysamp.de 755 | myspaceinc.com 756 | myspaceinc.net 757 | myspaceinc.org 758 | myspacepimpedup.com 759 | myspamless.com 760 | mytempemail.com 761 | mytempmail.com 762 | mythrashmail.net 763 | mytrashmail.com 764 | nabuma.com 765 | national.shitposting.agency 766 | naver.com 767 | neomailbox.com 768 | nepwk.com 769 | nervmich.net 770 | nervtmich.net 771 | netmails.com 772 | netmails.net 773 | netzidiot.de 774 | neverbox.com 775 | nevermail.de 776 | nice-4u.com 777 | nigge.rs 778 | nincsmail.hu 779 | nmail.cf 780 | nnh.com 781 | noblepioneer.com 782 | nobugmail.com 783 | nobulk.com 784 | nobuma.com 785 | noclickemail.com 786 | nogmailspam.info 787 | nomail.pw 788 | nomail.xl.cx 789 | nomail2me.com 790 | nomorespamemails.com 791 | nonspam.eu 792 | nonspammer.de 793 | noref.in 794 | nospam.wins.com.br 795 | no-spam.ws 796 | nospam.ze.tc 797 | nospam4.us 798 | nospamfor.us 799 | nospammail.net 800 | nospamthanks.info 801 | notmailinator.com 802 | notsharingmy.info 803 | nowhere.org 804 | nowmymail.com 805 | ntlhelp.net 806 | nullbox.info 807 | nurfuerspam.de 808 | nus.edu.sg 809 | nwldx.com 810 | o2.co.uk 811 | o2.pl 812 | objectmail.com 813 | obobbo.com 814 | odaymail.com 815 | odnorazovoe.ru 816 | ohaaa.de 817 | omail.pro 818 | oneoffemail.com 819 | oneoffmail.com 820 | onewaymail.com 821 | onlatedotcom.info 822 | online.ms 823 | oopi.org 824 | opayq.com 825 | ordinaryamerican.net 826 | otherinbox.com 827 | ourklips.com 828 | outlawspam.com 829 | ovpn.to 830 | owlpic.com 831 | pancakemail.com 832 | paplease.com 833 | pcusers.otherinbox.com 834 | pepbot.com 835 | pfui.ru 836 | phentermine-mortgages-texas-holdem.biz 837 | pimpedupmyspace.com 838 | pjjkp.com 839 | plexolan.de 840 | poczta.onet.pl 841 | politikerclub.de 842 | poofy.org 843 | pookmail.com 844 | postonline.me 845 | powered.name 846 | privacy.net 847 | privatdemail.net 848 | privy-mail.com 849 | privymail.de 850 | privy-mail.de 851 | proxymail.eu 852 | prtnx.com 853 | prtz.eu 854 | punkass.com 855 | put2.net 856 | putthisinyourspamdatabase.com 857 | pwrby.com 858 | qasti.com 859 | qisdo.com 860 | qisoa.com 861 | qoika.com 862 | qq.com 863 | quickinbox.com 864 | quickmail.nl 865 | rcpt.at 866 | rcs.gaggle.net 867 | reallymymail.com 868 | realtyalerts.ca 869 | receiveee.com 870 | recode.me 871 | recursor.net 872 | recyclemail.dk 873 | redchan.it 874 | regbypass.com 875 | regbypass.comsafe-mail.net 876 | rejectmail.com 877 | reliable-mail.com 878 | remail.cf 879 | remail.ga 880 | rhyta.com 881 | rklips.com 882 | rmqkr.net 883 | royal.net 884 | rppkn.com 885 | rtrtr.com 886 | s0ny.net 887 | safe-mail.net 888 | safersignup.de 889 | safetymail.info 890 | safetypost.de 891 | sandelf.de 892 | saynotospams.com 893 | scatmail.com 894 | schafmail.de 895 | schmeissweg.tk 896 | schrott-email.de 897 | secmail.pw 898 | secretemail.de 899 | secure-mail.biz 900 | secure-mail.cc 901 | selfdestructingmail.com 902 | selfdestructingmail.org 903 | sendspamhere.com 904 | senseless-entertainment.com 905 | server.ms 906 | services391.com 907 | sharklasers.com 908 | shieldedmail.com 909 | shieldemail.com 910 | shiftmail.com 911 | shitmail.me 912 | shitmail.org 913 | shitware.nl 914 | shmeriously.com 915 | shortmail.net 916 | shut.name 917 | shut.ws 918 | sibmail.com 919 | sify.com 920 | sina.cn 921 | sina.com 922 | sinnlos-mail.de 923 | siteposter.net 924 | skeefmail.com 925 | sky-ts.de 926 | slapsfromlastnight.com 927 | slaskpost.se 928 | slave-auctions.net 929 | slopsbox.com 930 | slushmail.com 931 | smaakt.naar.gravel 932 | smapfree24.com 933 | smapfree24.de 934 | smapfree24.eu 935 | smapfree24.info 936 | smapfree24.org 937 | smashmail.de 938 | smellfear.com 939 | snakemail.com 940 | sneakemail.com 941 | sneakmail.de 942 | snkmail.com 943 | sofimail.com 944 | sofortmail.de 945 | sofort-mail.de 946 | sogetthis.com 947 | sohu.com 948 | solvemail.info 949 | soodomail.com 950 | soodonims.com 951 | spam.la 952 | spam.su 953 | spam4.me 954 | spamail.de 955 | spamarrest.com 956 | spamavert.com 957 | spam-be-gone.com 958 | spambob.com 959 | spambob.net 960 | spambob.org 961 | spambog.com 962 | spambog.de 963 | spambog.net 964 | spambog.ru 965 | spambooger.com 966 | spambox.info 967 | spambox.irishspringrealty.com 968 | spambox.org 969 | spambox.us 970 | spamcannon.com 971 | spamcannon.net 972 | spamcero.com 973 | spamcon.org 974 | spamcorptastic.com 975 | spamcowboy.com 976 | spamcowboy.net 977 | spamcowboy.org 978 | spamday.com 979 | spamdecoy.net 980 | spamex.com 981 | spamfighter.cf 982 | spamfighter.ga 983 | spamfighter.gq 984 | spamfighter.ml 985 | spamfighter.tk 986 | spamfree.eu 987 | spamfree24.com 988 | spamfree24.de 989 | spamfree24.eu 990 | spamfree24.info 991 | spamfree24.net 992 | spamfree24.org 993 | spamgoes.in 994 | spamgourmet.com 995 | spamgourmet.net 996 | spamgourmet.org 997 | spamherelots.com 998 | spamhereplease.com 999 | spamhole.com 1000 | spamify.com 1001 | spaminator.de 1002 | spamkill.info 1003 | spaml.com 1004 | spaml.de 1005 | spammotel.com 1006 | spamobox.com 1007 | spamoff.de 1008 | spamsalad.in 1009 | spamslicer.com 1010 | spamspot.com 1011 | spamstack.net 1012 | spamthis.co.uk 1013 | spamthisplease.com 1014 | spamtrail.com 1015 | spamtroll.net 1016 | speed.1s.fr 1017 | spoofmail.de 1018 | squizzy.de 1019 | sry.li 1020 | ssoia.com 1021 | startkeys.com 1022 | stinkefinger.net 1023 | stop-my-spam.cf 1024 | stop-my-spam.com 1025 | stop-my-spam.ga 1026 | stop-my-spam.ml 1027 | stop-my-spam.tk 1028 | stuffmail.de 1029 | suioe.com 1030 | super-auswahl.de 1031 | supergreatmail.com 1032 | supermailer.jp 1033 | superplatyna.com 1034 | superrito.com 1035 | superstachel.de 1036 | suremail.info 1037 | sweetxxx.de 1038 | tafmail.com 1039 | tagyourself.com 1040 | talkinator.com 1041 | tapchicuoihoi.com 1042 | techemail.com 1043 | techgroup.me 1044 | teewars.org 1045 | teleworm.com 1046 | teleworm.us 1047 | temp.emeraldwebmail.com 1048 | tempail.com 1049 | tempalias.com 1050 | tempemail.biz 1051 | tempemail.co.za 1052 | tempemail.com 1053 | tempe-mail.com 1054 | tempemail.net 1055 | tempimbox.com 1056 | tempinbox.co.uk 1057 | tempinbox.com 1058 | tempmail.eu 1059 | tempmail.it 1060 | temp-mail.org 1061 | temp-mail.ru 1062 | tempmail2.com 1063 | tempmaildemo.com 1064 | tempmailer.com 1065 | tempmailer.de 1066 | tempomail.fr 1067 | temporarily.de 1068 | temporarioemail.com.br 1069 | temporaryemail.net 1070 | temporaryemail.us 1071 | temporaryforwarding.com 1072 | temporaryinbox.com 1073 | temporarymailaddress.com 1074 | tempthe.net 1075 | tempymail.com 1076 | tfwno.gf 1077 | thanksnospam.info 1078 | thankyou2010.com 1079 | thc.st 1080 | thecloudindex.com 1081 | thelimestones.com 1082 | thisisnotmyrealemail.com 1083 | thismail.net 1084 | thrma.com 1085 | throam.com 1086 | throwawayemailaddress.com 1087 | throwawaymail.com 1088 | tijdelijkmailadres.nl 1089 | tilien.com 1090 | tittbit.in 1091 | tizi.com 1092 | tmail.com 1093 | tmailinator.com 1094 | toiea.com 1095 | tokem.co 1096 | toomail.biz 1097 | topcoolemail.com 1098 | topfreeemail.com 1099 | topranklist.de 1100 | tormail.net 1101 | tormail.org 1102 | tradermail.info 1103 | trash2009.com 1104 | trash2010.com 1105 | trash2011.com 1106 | trash-amil.com 1107 | trashcanmail.com 1108 | trashdevil.com 1109 | trashdevil.de 1110 | trashemail.de 1111 | trashinbox.com 1112 | trashmail.at 1113 | trash-mail.at 1114 | trash-mail.cf 1115 | trashmail.com 1116 | trash-mail.com 1117 | trashmail.de 1118 | trash-mail.de 1119 | trash-mail.ga 1120 | trash-mail.gq 1121 | trashmail.me 1122 | trash-mail.ml 1123 | trashmail.net 1124 | trashmail.org 1125 | trash-mail.tk 1126 | trashmail.ws 1127 | trashmailer.com 1128 | trashymail.com 1129 | trashymail.net 1130 | trayna.com 1131 | trbvm.com 1132 | trialmail.de 1133 | trickmail.net 1134 | trillianpro.com 1135 | tryalert.com 1136 | turual.com 1137 | twinmail.de 1138 | tyldd.com 1139 | ubismail.net 1140 | uggsrock.com 1141 | umail.net 1142 | uhren.com 1143 | urhen.com 1144 | upliftnow.com 1145 | uplipht.com 1146 | uroid.com 1147 | us.af 1148 | uyhip.com 1149 | valemail.net 1150 | venompen.com 1151 | verticalscope.com 1152 | veryrealemail.com 1153 | veryrealmail.com 1154 | vidchart.com 1155 | viditag.com 1156 | viewcastmedia.com 1157 | viewcastmedia.net 1158 | viewcastmedia.org 1159 | vipmail.name 1160 | vipmail.pw 1161 | viralplays.com 1162 | vistomail.com 1163 | vomoto.com 1164 | vpn.st 1165 | vsimcard.com 1166 | vubby.com 1167 | vztc.com 1168 | walala.org 1169 | walkmail.net 1170 | wants.dicksinhisan.us 1171 | wants.dicksinmyan.us 1172 | wasteland.rfc822.org 1173 | watchfull.net 1174 | watch-harry-potter.com 1175 | webemail.me 1176 | webm4il.info 1177 | webuser.in 1178 | wegwerfadresse.de 1179 | wegwerfemail.com 1180 | wegwerfemail.de 1181 | wegwerf-email.de 1182 | weg-werf-email.de 1183 | wegwerfemail.net 1184 | wegwerf-email.net 1185 | wegwerfemail.org 1186 | wegwerf-email-addressen.de 1187 | wegwerfemailadresse.com 1188 | wegwerf-email-adressen.de 1189 | wegwerf-emails.de 1190 | wegwerfmail.de 1191 | wegwerfmail.info 1192 | wegwerfmail.net 1193 | wegwerfmail.org 1194 | wegwerpmailadres.nl 1195 | wegwrfmail.de 1196 | wegwrfmail.net 1197 | wegwrfmail.org 1198 | wetrainbayarea.com 1199 | wetrainbayarea.org 1200 | wh4f.org 1201 | whatiaas.com 1202 | whatpaas.com 1203 | whatsaas.com 1204 | whopy.com 1205 | whyspam.me 1206 | wickmail.net 1207 | wilemail.com 1208 | willhackforfood.biz 1209 | willselfdestruct.com 1210 | winemaven.info 1211 | wmail.cf 1212 | wolfsmail.tk 1213 | writeme.us 1214 | wronghead.com 1215 | wuzup.net 1216 | wuzupmail.net 1217 | www.e4ward.com 1218 | www.gishpuppy.com 1219 | www.mailinator.com 1220 | wwwnew.eu 1221 | x.ip6.li 1222 | xagloo.co 1223 | xagloo.com 1224 | xemaps.com 1225 | xents.com 1226 | xmail.com 1227 | xmaily.com 1228 | xoxox.cc 1229 | xoxy.net 1230 | xxtreamcam.com 1231 | xyzfree.net 1232 | yandex.com 1233 | yanet.me 1234 | yapped.net 1235 | yeah.net 1236 | yep.it 1237 | yogamaven.com 1238 | yomail.info 1239 | yopmail.com 1240 | yopmail.fr 1241 | yopmail.gq 1242 | yopmail.net 1243 | youmail.ga 1244 | youmailr.com 1245 | yourdomain.com 1246 | you-spam.com 1247 | ypmail.webarnak.fr.eu.org 1248 | yuurok.com 1249 | yxzx.net 1250 | z1p.biz 1251 | za.com 1252 | zebins.com 1253 | zebins.eu 1254 | zehnminuten.de 1255 | zehnminutenmail.de 1256 | zetmail.com 1257 | zippymail.info 1258 | zoaxe.com 1259 | zoemail.com 1260 | zoemail.net 1261 | zoemail.org 1262 | zomg.info 1263 | nwytg.net 1264 | sellcow.net 1265 | vmani.com 1266 | 10m.email 1267 | uzxia.com 1268 | pokemail.net 1269 | yevme.com 1270 | 10minutemailbox.com -------------------------------------------------------------------------------- /hookers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ekultek/WhatBreach/dad6b9f223b053ec522d57c08a698a6026142cd5/hookers/__init__.py -------------------------------------------------------------------------------- /hookers/databasestoday_hook.py: -------------------------------------------------------------------------------- 1 | import re 2 | import os 3 | 4 | import requests 5 | from bs4 import BeautifulSoup 6 | 7 | from lib.formatter import ( 8 | prompt, 9 | warn, 10 | info 11 | ) 12 | from lib.settings import ( 13 | # DATABASES_URL, 14 | DEFAULT_REQUEST_HEADERS, 15 | DOWNLOADS_PATH 16 | ) 17 | 18 | 19 | class DatabasesTodayHook(object): 20 | 21 | # thank you NullArray for this idea and being an all around badass 22 | # if you dunno him, go checkout his Github https://github.com/NullArray 23 | # he practically invented being awesome! 24 | 25 | def __init__(self, query, proxies=False, headers=False, **kwargs): 26 | if not proxies: 27 | proxies = {} 28 | if not headers: 29 | headers = DEFAULT_REQUEST_HEADERS 30 | self.query = query 31 | self.proxies = proxies 32 | self.headers = headers 33 | self.content = None 34 | self.downloaded_databases = [] 35 | self.database_links = [] 36 | self.downloads_directory = kwargs.get("downloads_directory", DOWNLOADS_PATH) 37 | 38 | def _parse_html(self): 39 | """ 40 | parse the HTML and return it if it has the data in it 41 | """ 42 | searcher = re.compile("{}".format(self.query), re.I) 43 | if searcher.search(str(self.content)) is not None: 44 | return True 45 | return False 46 | 47 | def _find_database_links(self): 48 | """ 49 | find the links to the databases 50 | """ 51 | for table in self.content.find_all(id="myTable"): 52 | for td in table.find_all('td'): 53 | results = td.find_all('a', href=True) 54 | if len(results) != 0: 55 | self.database_links.append(results) 56 | 57 | def _download_database(self, chunk_size=8192): 58 | """ 59 | download the database if it is available 60 | """ 61 | answer = prompt( 62 | "discovered publicly available database for query {}, do you want to download [y/N]".format(self.query) 63 | ) 64 | flatten = lambda l: [str(item) for sublist in l for item in sublist] 65 | database_links = flatten(self.database_links) 66 | to_download = [] 67 | for db in database_links: 68 | try: 69 | to_download.append(db.split('"')[3]) 70 | except Exception: 71 | pass 72 | if answer == "y": 73 | if not os.path.exists(self.downloads_directory): 74 | os.makedirs(self.downloads_directory) 75 | for link in to_download: 76 | local_filename = link.split("/")[-1] 77 | local_file_path = "{}/{}".format(self.downloads_directory, local_filename) 78 | if not os.path.exists(local_file_path): 79 | with requests.get(link, stream=True, proxies=self.proxies, headers=self.headers) as downloader: 80 | downloader.raise_for_status() 81 | with open(local_file_path, "wb") as path: 82 | for chunk in downloader.iter_content(chunk_size=chunk_size): 83 | if chunk: 84 | path.write(chunk) 85 | self.downloaded_databases.append(local_file_path) 86 | else: 87 | info("skipping download as requested") 88 | return self.downloaded_databases 89 | 90 | def hooker(self): 91 | """ 92 | hookers gonna hook 93 | """ 94 | warn( 95 | "databases.today is down, switching to wayback machine (this isn't as reliable but it will still work)" 96 | ) 97 | return WayBackMachine( 98 | self.query, self.proxies, self.headers 99 | ).hooker() 100 | # try: 101 | # req = requests.get(DATABASES_URL.format(self.query.lower()), headers=self.headers, proxies=self.proxies) 102 | # soup = BeautifulSoup(req.content, "html.parser") 103 | # self.content = soup.extract() 104 | # results = self._parse_html() 105 | # if results: 106 | # self._find_database_links() 107 | # if len(self.database_links) != 0: 108 | # return self._download_database() 109 | # else: 110 | # return [] 111 | # except Exception as e: 112 | # return [] 113 | 114 | 115 | class WayBackMachine(object): 116 | 117 | # fix until databases.today comes back online, not as reliable but will still work 118 | 119 | def __init__(self, query, proxies=False, headers=False, **kwargs): 120 | if not proxies: 121 | proxies = {} 122 | if not headers: 123 | headers = DEFAULT_REQUEST_HEADERS 124 | self.query = query 125 | self.proxies = proxies 126 | self.headers = headers 127 | self.content = None 128 | self.downloaded_databases = [] 129 | self.database_links = [] 130 | self.downloads_directory = kwargs.get("downloads_directory", None) 131 | 132 | def _gather_database_urls(self): 133 | retval = [] 134 | search_urls = ( 135 | "https://web.archive.org/web/20190409132908/https://cdn.databases.today/", 136 | "https://web.archive.org/web/20190409132908/https://cdn.databases.today/random", 137 | "https://web.archive.org/web/20190126112059/http://cdn.databases.today/random/dumps/", 138 | "https://web.archive.org/web/20190115081847/http://cdn.databases.today/random/files/", 139 | "https://web.archive.org/web/20190128131503/http://cdn.databases.today/random/github/DevGames/", 140 | "https://web.archive.org/web/20190128131528/http://cdn.databases.today/random/github/Devin148/", 141 | "https://web.archive.org/web/20190128131538/http://cdn.databases.today/random/github/WiseXP/", 142 | "https://web.archive.org/web/20190128131619/http://cdn.databases.today/random/github/chre/", 143 | "https://web.archive.org/web/20190128131637/http://cdn.databases.today/random/github/leonardoipx/", 144 | "https://web.archive.org/web/20190115210749/http://cdn.databases.today/random/minecraft/", 145 | "https://web.archive.org/web/20190124232905/http://cdn.databases.today/random/unverified/", 146 | "https://web.archive.org/web/20190115210130/http://cdn.databases.today/random/vbulletindump/" 147 | ) 148 | for link in search_urls: 149 | try: 150 | req = requests.get(link, headers=self.headers, proxies=self.proxies) 151 | retval.append((req.content, link)) 152 | except: 153 | retval.append((None, None)) 154 | return retval 155 | 156 | def _get_links(self, content): 157 | urls = [] 158 | 159 | for item in content: 160 | if item[0] is not None: 161 | soup = BeautifulSoup(item[0], "html.parser") 162 | for href in soup.findAll('a'): 163 | try: 164 | urls.append("{}".format(href['href'])) 165 | except: 166 | pass 167 | return urls 168 | 169 | def _check_if_matched(self, urls): 170 | matched_urls = [] 171 | for url in urls: 172 | searcher = re.compile(self.query, re.I) 173 | if searcher.search(url) is not None: 174 | matched_urls.append(url) 175 | return matched_urls 176 | 177 | def hooker(self): 178 | """ 179 | temporary hookers gonna hook harder than normal hookers 180 | """ 181 | content = self._gather_database_urls() 182 | links = self._get_links(content) 183 | matched_databases = self._check_if_matched(links) 184 | if len(matched_databases) != 0: 185 | info( 186 | 'found a total of {} databases(s) that matched the query, dumping URL list'.format( 187 | len(matched_databases) 188 | ) 189 | ) 190 | for db in matched_databases: 191 | print("\t~~> {}".format(db)) 192 | return [] 193 | -------------------------------------------------------------------------------- /hookers/dehashed_hook.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from bs4 import BeautifulSoup 3 | 4 | from lib.formatter import warn 5 | 6 | from lib.settings import ( 7 | grab_random_user_agent, 8 | DEHASHED_URL, 9 | VERIFICATION_REGEX, 10 | DEFAULT_REQUEST_HEADERS, 11 | RANDOM_USER_AGENT_PATH 12 | ) 13 | 14 | 15 | class DehashedHook(object): 16 | 17 | def __init__(self, found_breaches, headers=False, proxies=False): 18 | if not proxies: 19 | proxies = {} 20 | if not headers: 21 | headers = DEFAULT_REQUEST_HEADERS 22 | headers["User-Agent"] = grab_random_user_agent(RANDOM_USER_AGENT_PATH) 23 | # we're gonna go ahead and try to trick dehashed into thinking 24 | # we're a real person 25 | try: 26 | del headers["Made-With-Love"] 27 | except: 28 | pass 29 | self.found = found_breaches 30 | self.headers = headers 31 | self.proxies = proxies 32 | self.return_value = None 33 | 34 | def _parse_html(self): 35 | """ 36 | returns a dict of parsed HTML if the term is in the HTML 37 | """ 38 | retval = {} 39 | for i, value in enumerate(self.return_value): 40 | try: 41 | if value[0] is not None: 42 | if VERIFICATION_REGEX.search(value[0]) is not None: 43 | retval[self.found[i]] = (True, value[1]) 44 | else: 45 | retval[self.found[i]] = (False, value[1]) 46 | except Exception: 47 | retval[self.found[i]] = (False, value[1]) 48 | return retval 49 | 50 | def hooker(self): 51 | """ 52 | hookers still gonna hook 53 | """ 54 | self.return_value = [] 55 | for breach in self.found: 56 | search_url = DEHASHED_URL.format(str(breach).strip()) 57 | try: 58 | req = requests.get(search_url, proxies=self.proxies, headers=self.headers, timeout=7) 59 | content = (BeautifulSoup(req.content, "html.parser").extract().decode("utf-8"), search_url) 60 | except Exception as e: 61 | if "HTTPSConnectionPool" in str(e): 62 | warn( 63 | "gateway timeout occurred while searching dehashed (this is caused by the fact that " 64 | "dehashed doesn't like scraping), possible search URL: {}".format( 65 | search_url 66 | ) 67 | ) 68 | content = (None, search_url) 69 | if content[0] != "" or content[0] is not None: 70 | self.return_value.append(content) 71 | if len(self.return_value) != 0: 72 | return self._parse_html() 73 | else: 74 | return None 75 | -------------------------------------------------------------------------------- /hookers/emailrep_io_hook.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import requests 4 | 5 | from lib.formatter import info 6 | 7 | from lib.settings import ( 8 | DEFAULT_REQUEST_HEADERS, 9 | EMAILREP_IO_LINK, 10 | write_processed_to_file, 11 | random_string, 12 | JSON_DATA_DUMPS 13 | ) 14 | 15 | 16 | class EmailRepHook(object): 17 | 18 | def __init__(self, email, proxies=None, headers=None): 19 | if proxies is None: 20 | proxies = {} 21 | if headers is None: 22 | headers = DEFAULT_REQUEST_HEADERS 23 | self.headers = headers 24 | self.proxies = proxies 25 | self.email = email 26 | 27 | def _parse_results(self, content): 28 | results = [] 29 | for item in content["details"]["profiles"]: 30 | results.append(str(item)) 31 | if len(results) != 0: 32 | if not os.path.exists(JSON_DATA_DUMPS): 33 | os.makedirs(JSON_DATA_DUMPS) 34 | file_path = "{}/{}_emailrep.json".format( 35 | JSON_DATA_DUMPS, self.email.split("@")[0] 36 | ) 37 | if not os.path.exists(file_path): 38 | with open(file_path, 'a+') as data: 39 | json.dump(content, data, sort_keys=True, indent=4) 40 | info("all data dumped to file for future processing: {}".format(file_path)) 41 | return results 42 | 43 | def hooker(self): 44 | try: 45 | req = requests.get(EMAILREP_IO_LINK.format(self.email), proxies=self.proxies, headers=self.headers) 46 | return self._parse_results(req.json()) 47 | except Exception: 48 | return None 49 | -------------------------------------------------------------------------------- /hookers/hibp_hook.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | # import arrow 4 | import requests 5 | 6 | from lib.formatter import ( 7 | warn, 8 | info, 9 | error 10 | ) 11 | from lib.settings import ( 12 | HIBP_URL, 13 | HIBP_PASTE_URL, 14 | DEFAULT_REQUEST_HEADERS, 15 | ) 16 | 17 | 18 | class BeenPwnedHook(object): 19 | 20 | def __init__(self, email, api_key, opt, headers=False, proxies=False, blocked=1, retry=False): 21 | if not proxies: 22 | proxies = {} 23 | if not headers: 24 | headers = DEFAULT_REQUEST_HEADERS 25 | self.email = email 26 | self.headers = headers 27 | self.proxies = proxies 28 | self.content = None 29 | self.blocked = blocked 30 | self.max_attempts = 3 31 | self.retry = retry 32 | self.status_codes = { 33 | "blocked": 403, 34 | "throttled": 429 35 | } 36 | self.opt = opt 37 | self.headers["hibp-api-key"] = api_key 38 | 39 | def _get_breach_names(self, is_paste=False): 40 | """ 41 | get the names of the breaches from have i been pwned 42 | """ 43 | report_names = set() 44 | if is_paste: 45 | identifier = ["Id", u"Id"] 46 | else: 47 | identifier = ["Name", u"Name"] 48 | if self.content is not None: 49 | for report in self.content: 50 | try: 51 | for item in identifier: 52 | report_names.add(report[item]) 53 | except Exception: 54 | pass 55 | else: 56 | return None 57 | return list(report_names) 58 | 59 | def account_hooker(self): 60 | """ 61 | hookers accounting gonna hook 62 | """ 63 | try: 64 | req = requests.get( 65 | HIBP_URL.format(self.email), 66 | headers=self.headers, 67 | proxies=self.proxies 68 | ) 69 | if req.status_code == self.status_codes["throttled"]: 70 | wait_time = int(req.headers["Retry-After"]) 71 | # we'll keep this in case we need it later 72 | # human = arrow.now().shift(seconds=wait_time).humanize() 73 | warn( 74 | "you've reached HIBP's request limit, adding {}s to throttle time".format(wait_time) 75 | ) 76 | self.opt.throttleRequests += wait_time 77 | sleep(wait_time) 78 | info("here we go!") 79 | self.account_hooker() 80 | elif req.status_code == self.status_codes["blocked"]: 81 | if self.blocked != self.max_attempts: 82 | if self.retry: 83 | warn( 84 | "you have been blocked from HIBP, WhatBreach will try {} more time(s)".format( 85 | self.max_attempts - self.blocked 86 | ) 87 | ) 88 | sleep(10) 89 | BeenPwnedHook( 90 | self.email, self.headers["hibp-api-key"], self.opt, headers=self.headers, 91 | proxies=self.proxies, blocked=self.blocked + 1 92 | ).account_hooker() 93 | else: 94 | error( 95 | "you have been blocked from HIBP, skipping and continuing, pass the `--do-retry` flag to " 96 | "retry the requests on failure (max of 3 retries will be attempted)" 97 | ) 98 | else: 99 | error( 100 | "you have been blocked, {} attempts have failed, change your IP address and try again".format( 101 | self.max_attempts 102 | ) 103 | ) 104 | else: 105 | self.content = req.json() 106 | if self.content is not None or self.content != "": 107 | return self._get_breach_names() 108 | else: 109 | return None 110 | except ValueError: 111 | # this means something went wrong 112 | return None 113 | 114 | def paste_hooker(self): 115 | """ 116 | paste hookers gonna hook too 117 | """ 118 | try: 119 | req = requests.get( 120 | HIBP_PASTE_URL.format(self.email), 121 | headers=self.headers, 122 | proxies=self.proxies, 123 | ) 124 | self.content = req.json() 125 | return self._get_breach_names(is_paste=True) 126 | except Exception: 127 | return None 128 | -------------------------------------------------------------------------------- /hookers/hunter_io_hook.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | import requests 4 | from lib.formatter import ( 5 | info, 6 | error 7 | ) 8 | from lib.settings import ( 9 | HUNTER_IO_URL, 10 | DEFAULT_REQUEST_HEADERS, 11 | process_discovered, 12 | HUNTER_IO_VERIFY_URL 13 | ) 14 | 15 | 16 | class HunterIoHook(object): 17 | 18 | def __init__(self, email, api_key, proxies=None, headers=None, verify_emails=False): 19 | if proxies is None: 20 | proxies = {} 21 | if headers is None: 22 | headers = DEFAULT_REQUEST_HEADERS 23 | self.api_key = api_key 24 | self.email = email 25 | self.proxies = proxies 26 | self.headers = headers 27 | self.verify = verify_emails 28 | 29 | def __get_domain_from_email(self): 30 | """ 31 | associate the domain name of the email address 32 | """ 33 | data_list = self.email.split("@") 34 | return data_list[-1] 35 | 36 | def __verify_emails_alive(self, email_list): 37 | """ 38 | verify if the email address is deliverable or not 39 | """ 40 | for email in email_list: 41 | info("verifying that {} is alive".format(email)) 42 | try: 43 | req = requests.get( 44 | HUNTER_IO_VERIFY_URL.format(email=email, api_key=self.api_key), 45 | proxies=self.proxies, headers=self.headers 46 | ) 47 | results = json.loads(req.text)["data"]["result"] 48 | if str(results) == "risky": 49 | output_str = "\033[31m{}\033[0m".format(str(results)) 50 | elif str(results) == "deliverable": 51 | output_str = "\033[32m{}\033[0m".format(str(results)) 52 | else: 53 | output_str = "\033[33m{}\033[0m".format(str(results)) 54 | info("result of verification: {}".format(output_str)) 55 | except: 56 | error("error verifying email: {}".format(email)) 57 | 58 | def make_request(self): 59 | """ 60 | make the request to the API 61 | """ 62 | try: 63 | req = requests.get( 64 | HUNTER_IO_URL.format( 65 | domain=self.__get_domain_from_email(), 66 | api_key=self.api_key 67 | ), 68 | headers=self.headers, 69 | proxies=self.proxies 70 | ) 71 | retval = req.text 72 | except Exception: 73 | retval = None 74 | return retval 75 | 76 | def hooker(self): 77 | """ 78 | hookers gonna hook 79 | """ 80 | set_to_list_phone_numebrs = [] 81 | discovered_phone_numbers = set() 82 | other_discovered_emails = set() 83 | discovered_external_links = set() 84 | processed = json.loads(self.make_request()) 85 | domain_name = self.__get_domain_from_email() 86 | try: 87 | processed['errors'][0]['id'] 88 | processed = None 89 | except: 90 | pass 91 | if processed is not None: 92 | try: 93 | email_pattern_identification = "{}@{}".format(processed["data"]["pattern"], domain_name) 94 | except: 95 | email_pattern_identification = None 96 | for i, _ in enumerate(processed["data"]["emails"]): 97 | discovered_phone_numbers.add(processed["data"]["emails"][i]["phone_number"]) 98 | other_discovered_emails.add(str(processed["data"]["emails"][i]["value"])) 99 | for y, _ in enumerate(processed["data"]["emails"][i]["sources"]): 100 | discovered_external_links.add(str(processed["data"]["emails"][i]["sources"][y]["uri"])) 101 | for item in discovered_phone_numbers: 102 | if item is not None: 103 | set_to_list_phone_numebrs.append(item) 104 | other_discovered_emails.add(self.email) 105 | info("discovered a total of {} email(s)".format(len(other_discovered_emails))) 106 | if self.verify: 107 | self.__verify_emails_alive(other_discovered_emails) 108 | file_path = process_discovered( 109 | set_to_list_phone_numebrs, discovered_external_links, 110 | other_discovered_emails, email_pattern_identification, 111 | domain_name, do_write=True 112 | ) 113 | return file_path 114 | else: 115 | error("error while processing domain: {} (have you exceeded your API limit?)".format(domain_name)) 116 | return None 117 | -------------------------------------------------------------------------------- /hookers/pastebin_hook.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import requests 4 | 5 | import lib.settings 6 | import lib.formatter 7 | 8 | 9 | class PastebinRawHook(object): 10 | 11 | def __init__(self, link, headers=None, proxies=None): 12 | self.link = link 13 | if proxies is None: 14 | proxies = {} 15 | if headers is None: 16 | headers = lib.settings.DEFAULT_REQUEST_HEADERS 17 | self.headers = headers 18 | self.proxies = proxies 19 | 20 | def hooker(self, chunk_size=8192): 21 | """ 22 | hookers gonna hook 23 | """ 24 | try: 25 | if not os.path.exists(lib.settings.PASTEBIN_DOWNLOADS): 26 | os.makedirs(lib.settings.PASTEBIN_DOWNLOADS) 27 | with requests.get(self.link, stream=True, proxies=self.proxies, headers=self.headers) as downloader: 28 | local_filename = self.link.split("/")[-1] 29 | local_file_path = "{}/{}_pastebin.txt".format(lib.settings.PASTEBIN_DOWNLOADS, local_filename) 30 | if not os.path.exists(local_file_path): 31 | downloader.raise_for_status() 32 | with open(local_file_path, 'wb') as path: 33 | for chunk in downloader.iter_content(chunk_size=chunk_size): 34 | if chunk: 35 | path.write(chunk) 36 | return local_file_path 37 | except Exception: 38 | return None 39 | -------------------------------------------------------------------------------- /hookers/snusbase_hooker.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | from bs4 import BeautifulSoup 4 | 5 | from lib.formatter import warn 6 | from lib.settings import ( 7 | SNUSBASE_URL_DICT, 8 | DEFAULT_REQUEST_HEADERS 9 | ) 10 | 11 | 12 | class SnusbaseHooker(object): 13 | 14 | def __init__(self, email, username, password, proxy=None, headers=None): 15 | self.email = email 16 | self.username = username 17 | self.password = password 18 | if proxy is None: 19 | proxy = {} 20 | if headers is None: 21 | headers = DEFAULT_REQUEST_HEADERS 22 | self.proxy = proxy 23 | self.headers = headers 24 | self.login_post_data = {"login": self.username, "password": self.password, "action_login": ""} 25 | self.search_post_data = {"csrf_token": "", "term": self.email, "searchtype": "email"} 26 | 27 | def __start_session(self): 28 | session = requests.session() 29 | session.headers = self.headers 30 | session.proxies = self.proxy 31 | return session 32 | 33 | def __get_csrf_token(self, session): 34 | try: 35 | csrf_url = SNUSBASE_URL_DICT["search"] 36 | req = session.get(csrf_url) 37 | soup = BeautifulSoup(req.content, "html.parser") 38 | token = soup.find('input', {'name': 'csrf_token'})['value'] 39 | return token 40 | except TypeError: 41 | return None 42 | 43 | def __do_login(self, session): 44 | login_url = SNUSBASE_URL_DICT["login"] 45 | post_data = self.login_post_data 46 | req = session.post(login_url, data=post_data) 47 | cookie = req.headers['Set-Cookie'] 48 | cf_ray = req.headers['CF-RAY'] 49 | self.headers['CF-RAY'] = cf_ray 50 | self.headers['Set-Cookie'] = cookie 51 | session.headers = self.headers 52 | 53 | def __do_search(self, session): 54 | search_url = SNUSBASE_URL_DICT["search"] 55 | req = session.post(search_url, data=self.search_post_data) 56 | return req.content 57 | 58 | def __parse_results(self, res): 59 | tmp = set() 60 | retval = set() 61 | soup = BeautifulSoup(res, "html.parser") 62 | result_data = soup.findAll('div', {'id': 'topBar'}) 63 | for div in result_data: 64 | tmp.add(str(div)) 65 | for item in list(tmp): 66 | try: 67 | name = item.split("topBar")[-1].split("target=")[0].split("<")[0].strip('"').strip(">").replace("_", " ").split(" ")[0].lower() 68 | retval.add(name) 69 | except: 70 | pass 71 | return list(retval) 72 | 73 | def main(self): 74 | session = self.__start_session() 75 | self.__do_login(session) 76 | csrf_token = self.__get_csrf_token(session) 77 | if csrf_token is None: 78 | warn("login failed, is your password correct?") 79 | return [] 80 | self.search_post_data["csrf_token"] = csrf_token 81 | results = self.__do_search(session) 82 | breaches = self.__parse_results(results) 83 | if len(breaches) == 0: 84 | return None 85 | return breaches 86 | -------------------------------------------------------------------------------- /hookers/weleakinfo_hook.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | from lib.settings import ( 4 | DEFAULT_REQUEST_HEADERS, 5 | WELEAKINFO_URL 6 | ) 7 | 8 | 9 | class WeLeakInfoHook(object): 10 | 11 | def __init__(self, email, token, proxies=None, headers=None): 12 | self.email = email 13 | if proxies is None: 14 | proxies = {} 15 | if headers is None: 16 | headers = DEFAULT_REQUEST_HEADERS 17 | headers['Authorization'] = "Bearer {}".format(token) 18 | self.headers = headers 19 | self.proxies = proxies 20 | 21 | def _make_request(self): 22 | """ 23 | request the shit 24 | """ 25 | try: 26 | req = requests.get(WELEAKINFO_URL.format(self.email), proxies=self.proxies, headers=self.headers) 27 | return req.json() 28 | except Exception: 29 | return {} 30 | 31 | def _parse_results(self, content): 32 | """ 33 | parse the results from the requested shit 34 | """ 35 | parsed_leaks = set() 36 | for item in content: 37 | if "-" in item: 38 | item = item.split(" ")[0] 39 | elif "(" in item: 40 | item = item.split("(")[0] 41 | parsed_leaks.add(str(item)) 42 | return parsed_leaks 43 | 44 | def hooker(self): 45 | """ 46 | work the corner hooker 47 | """ 48 | # pssst, if you're reading this create an issue titled `fat clunky penguins` and you'll be my best friend 49 | # hi btw :D 50 | results = self._make_request() 51 | if results is not None and len(results) != 0: 52 | try: 53 | return self._parse_results(results['Data']) 54 | except Exception: 55 | return None 56 | else: 57 | return None 58 | -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ekultek/WhatBreach/dad6b9f223b053ec522d57c08a698a6026142cd5/lib/__init__.py -------------------------------------------------------------------------------- /lib/cmd.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | import lib.settings 4 | import lib.formatter 5 | 6 | 7 | class Parser(argparse.ArgumentParser): 8 | 9 | def __init__(self): 10 | super(Parser, self).__init__() 11 | 12 | @staticmethod 13 | def optparse(): 14 | parser = argparse.ArgumentParser() 15 | mandatory = parser.add_argument_group("mandatory opts") 16 | mandatory.add_argument( 17 | "-e", "--email", metavar="EMAIL", dest="singleEmail", default=None, 18 | help="Pass a single email to scan for" 19 | ) 20 | mandatory.add_argument( 21 | "-l", "-f", "--list", "--file", metavar="PATH", dest="emailFile", default=None, 22 | help="Pass a file containing emails one per line to scan" 23 | ) 24 | 25 | search_opts = parser.add_argument_group("search opts") 26 | search_opts.add_argument( 27 | "-nD", "--no-dehashed", action="store_false", default=True, dest="searchDehashed", 28 | help="Suppres dehashed output" 29 | ) 30 | search_opts.add_argument( 31 | "-nP", "--no-pastebin", action="store_false", default=True, dest="searchPastebin", 32 | help="Suppress Pastebin output" 33 | ) 34 | search_opts.add_argument( 35 | "-sH", "--search-hunter", action="store_true", default=False, dest="searchHunterIo", 36 | help="Search hunter.io with a provided email address and query for all information, this " 37 | "will process all emails found as normal" 38 | ) 39 | search_opts.add_argument( 40 | "-wL", "--search-weleakinfo", action="store_true", default=False, dest="searchWeLeakInfo", 41 | help="Search weleakinfo.com as well as HIBP for results" 42 | ) 43 | search_opts.add_argument( 44 | "-cA", "--check-accounts", action="store_true", default=False, dest="checkEmailAccounts", 45 | help="Check the profiles associated with an email address" 46 | ) 47 | search_opts.add_argument( 48 | "-sB", "--snusbase", action="store_true", default=False, dest="searchSnusBase", 49 | help="Search snusbase.com for more leaks with a provided email address" 50 | ) 51 | search_opts.add_argument( 52 | "-c", "--cookie", metavar="DEHASHED-COOKIE", dest="dehashedCookie", 53 | help=argparse.SUPPRESS 54 | ) 55 | 56 | misc_opts = parser.add_argument_group("misc opts") 57 | misc_opts.add_argument( 58 | "--do-retry", action="store_true", default=False, dest="retryOnFail", 59 | help="Retry requests to HIBP if they the first one fails" 60 | ) 61 | misc_opts.add_argument( 62 | "-dP", "--download-pastes", action="store_true", default=False, dest="downloadPastes", 63 | help="Download pastes associated with the email address found (if any)" 64 | ) 65 | misc_opts.add_argument( 66 | "-vH", "--verify-hunter", action="store_true", default=False, dest="verifyEmailsThroughHunterIo", 67 | help="Verify the emails found on hunter.io for deliverable status" 68 | ) 69 | misc_opts.add_argument( 70 | "-cT", "--check-ten-minute", action="store_true", default=False, dest="checkTenMinuteEmail", 71 | help="Check if the provided email address is a ten minute email or not" 72 | ) 73 | misc_opts.add_argument( 74 | "-d", "--download", action="store_true", default=False, dest="downloadDatabase", 75 | help="Attempt to download the database if there is one available" 76 | ) 77 | misc_opts.add_argument( 78 | "-s", "--save-dir", metavar="DIRECTORY-PATH", default=lib.settings.DOWNLOADS_PATH, dest="saveDirectory", 79 | help="Pass a directory to save the downloaded databases into instead of the `HOME` path" 80 | ) 81 | misc_opts.add_argument( 82 | "--throttle", metavar="TIME", type=int, dest="throttleRequests", default=0, 83 | help="Throttle the HIBP requests to help prevent yourself from being blocked" 84 | ) 85 | # easter egg, because we gotta keep it salty ya know 86 | misc_opts.add_argument( 87 | "-sS", "--stay-salty", action="store_true", default=False, dest="staySalty", 88 | help=argparse.SUPPRESS 89 | ) 90 | return parser.parse_args() 91 | 92 | @staticmethod 93 | def check_opts(opt): 94 | need_emails = False 95 | if opt.singleEmail is not None and opt.emailFile is not None: 96 | lib.formatter.warn( 97 | "you have provided a list of emails and a singular email at the same time, we're going to put them all " 98 | "together and go with it" 99 | ) 100 | need_emails = True 101 | if not opt.searchDehashed and not opt.searchPastebin: 102 | lib.formatter.warn( 103 | "you have chosen to not output any of the discovered data, literally nothing will be shown, whats the " 104 | "point of WhatBreach if it doesn't find anything? Drop one of the suppressive flags" 105 | ) 106 | exit(1) 107 | if opt.downloadPastes and not opt.searchPastebin: 108 | lib.formatter.warn( 109 | "you have provided that you don't want to see any pastebin output, WhatBreach isn't going to " 110 | "search for pastes if it doesn't need to. So we're not gonna download the pastes, genius.." 111 | ) 112 | opt.downloadPastes = False 113 | if opt.saveDirectory != lib.settings.DOWNLOADS_PATH and not opt.downloadDatabase: 114 | lib.formatter.warn( 115 | "you've chosen a save directory, but nothing is being downloaded? I mean this isn't going to have any " 116 | "problems but it's kinda weird right?" 117 | ) 118 | if opt.staySalty: 119 | lib.formatter.info("#staysalty") 120 | 121 | if need_emails: 122 | return lib.settings.smoosh_multi(opt.singleEmail, opt.emailFile) 123 | -------------------------------------------------------------------------------- /lib/formatter.py: -------------------------------------------------------------------------------- 1 | def info(string): 2 | print( 3 | "[\033[32m i \033[0m] {}".format(string) 4 | ) 5 | 6 | 7 | def warn(string): 8 | print( 9 | "[\033[33m w \033[0m] {}".format(string) 10 | ) 11 | 12 | 13 | def error(string): 14 | print( 15 | "[\033[31m ! \033[0m] {}".format(string) 16 | ) 17 | 18 | 19 | def prompt(string, lowercase=True): 20 | question = raw_input( 21 | "[ ? ] {}: ".format( 22 | string 23 | ) 24 | ) 25 | if lowercase: 26 | return question.lower() 27 | return question 28 | -------------------------------------------------------------------------------- /lib/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import sys 4 | import json 5 | import string 6 | import random 7 | import platform 8 | 9 | import lib.formatter 10 | 11 | from hookers.pastebin_hook import PastebinRawHook 12 | 13 | 14 | # version number 15 | VERSION = "0.2.7" 16 | 17 | # sexy banner 18 | BANNER = """{color_scheme_1} 19 | {tabbed_indent} _____ 20 | {tabbed_indent} _ _ _ _ _ _____ _ |___ | 21 | {tabbed_indent} | | | | |_ ___| |_| __ |___ ___ ___ ___| |_ | _| 22 | {tabbed_indent} | | | | | .'| _| __ -| _| -_| .'| _| | |_| 23 | {tabbed_indent} |_____|_|_|__,|_| |_____|_| |___|__,|___|_|_|[][][]|_|{color_scheme_end} 24 | {tabbed_indent}{color_scheme_2}Find emails and their associated leaked databases.. v{version_number}{color_scheme_end} 25 | 26 | """.format( 27 | color_scheme_end="\033[0m", 28 | color_scheme_1="\033[34m", 29 | color_scheme_2="\033[4;33m", 30 | version_number=VERSION, 31 | tabbed_indent="\t" 32 | 33 | ) 34 | 35 | # home path 36 | HOME = "{}/.whatbreach_home".format(os.path.expanduser("~")) 37 | 38 | # where we gonna download this shit too? 39 | DOWNLOADS_PATH = "{}/downloads".format(HOME) 40 | 41 | # pastebin downloads 42 | PASTEBIN_DOWNLOADS = "{}/pastebin".format(DOWNLOADS_PATH) 43 | 44 | # where we're going to place the JSON data 45 | JSON_DATA_DUMPS = "{}/json_dumps".format(DOWNLOADS_PATH) 46 | 47 | # API token paths 48 | TOKENS_PATH = "{}/tokens".format(HOME) 49 | 50 | # have you been pwned?! 51 | HIBP_URL = "https://haveibeenpwned.com/api/v3/breachedaccount/{}" 52 | 53 | # paste URL 54 | HIBP_PASTE_URL = "https://haveibeenpwned.com/api/v3/pasteaccount/{}" 55 | 56 | # dehashed search query 57 | DEHASHED_URL = "https://www.dehashed.com/search?query={}" 58 | 59 | # databases.tody URL 60 | DATABASES_URL = "https://databases.today/search-nojs.php?for={}" 61 | 62 | # hunter.io API url 63 | HUNTER_IO_URL = "https://api.hunter.io/v2/domain-search?domain={domain}&api_key={api_key}" 64 | 65 | # api link to verify email status 66 | HUNTER_IO_VERIFY_URL = "https://api.hunter.io/v2/email-verifier?email={email}&api_key={api_key}" 67 | 68 | # snusbase 69 | SNUSBASE_URL_DICT = { 70 | "login": "https://snusbase.com/login", 71 | "search": "https://snusbase.com/search" 72 | } 73 | 74 | # link to welinkinfo.com 75 | WELEAKINFO_URL = "https://api.weleakinfo.com/v3/public/email/{}" 76 | 77 | # get the reputation of the email address 78 | EMAILREP_IO_LINK = "https://emailrep.io/{}" 79 | 80 | # our user agent because who doesn't love a good user agent? 81 | USER_AGENT = "Breach-Reporter/{} (Language={}; Platform={})".format( 82 | VERSION, sys.version.split(" ")[0], platform.platform().split("-")[0] 83 | ) 84 | 85 | # default request headers 86 | DEFAULT_REQUEST_HEADERS = { 87 | "User-Agent": USER_AGENT, 88 | "Connection": "close", 89 | "Made-With-Love": "By Eku" 90 | } 91 | 92 | # a giant ass list of ten minute email extensions 93 | TEN_MINUTE_EMAIL_EXTENSION_LIST = "{}/etc/ten_minute_emails.lst".format(os.getcwd()) 94 | 95 | # check if the results actually exist or not 96 | VERIFICATION_REGEX = re.compile("sensitive.data.available.but.hidden", re.I) 97 | 98 | # where the user agents sit 99 | RANDOM_USER_AGENT_PATH = "{}/etc/user_agents.txt".format(os.getcwd()) 100 | 101 | 102 | def random_string(length=10): 103 | """ 104 | random strings so files dont get fucked up 105 | """ 106 | acceptable = string.ascii_letters 107 | _string = [] 108 | for _ in range(length): 109 | _string.append(random.choice(acceptable)) 110 | return "".join(_string) 111 | 112 | 113 | def display_found_databases(data, overflow=23, is_downloaded=False, download_pastes=False): 114 | """ 115 | display the found data in a pretty table 116 | """ 117 | pastebins = [] 118 | if not is_downloaded: 119 | tmp = [] 120 | for item in data.keys(): 121 | if type(data[item]) == tuple: 122 | tmp.append(data[item][-1]) 123 | else: 124 | if len(data[item]) == 8: 125 | pastebins.append("https://pastebin.com/raw/{}".format(data[item])) 126 | data[item] = "https://pastebin.com/{}".format(data[item]) 127 | tmp.append(data[item]) 128 | sep = "-" * len(max(tmp, key=len)) + "-" * overflow 129 | print(sep) 130 | output_template = "{0:25} | {1:35}" 131 | print("\033[99;4mBreach/Paste:\033[0m\t{}|{}\033[99;4mDatabase/Paste Link:\033[0m".format(" " * 10, " ")) 132 | for i, key in enumerate(data.keys(), start=1): 133 | original_key = str(key) 134 | do_show_key = False 135 | key = str(key) 136 | if type(data[key]) == tuple: 137 | result, search_url = data[key][0], data[key][-1] 138 | if len(key) >= 15: 139 | display_key = key[0:15] + "..." 140 | do_show_key = True 141 | if result: 142 | print(output_template.format(key, data[key][-1])) 143 | else: 144 | if do_show_key: 145 | print(output_template.format(display_key, "N/A (breach name: {})".format(original_key))) 146 | else: 147 | print(output_template.format(key, "N/A")) 148 | else: 149 | print(output_template.format(key, str(data[key]))) 150 | print(sep) 151 | else: 152 | sep = "-" * 50 153 | print(sep) 154 | for i, path in enumerate(data, start=1): 155 | print("#{} ~~> {}".format(i, path)) 156 | print(sep) 157 | if download_pastes: 158 | download_raw_pastes(pastebins) 159 | 160 | 161 | def download_raw_pastes(pastebins): 162 | """ 163 | download the pastes 164 | """ 165 | pastebin_hook = PastebinRawHook 166 | if len(pastebins) != 0: 167 | lib.formatter.info("downloading a total of {} paste(s)".format(len(pastebins))) 168 | for paste in pastebins: 169 | path = pastebin_hook(paste).hooker() 170 | if path is not None: 171 | lib.formatter.info("paste downloaded to {}".format(path)) 172 | else: 173 | lib.formatter.error("unable to download provided paste from link: {}".format(paste)) 174 | else: 175 | lib.formatter.warn("no pastes discovered for associated email") 176 | 177 | 178 | def check_ten_minute_email(email, path): 179 | """ 180 | check if the provided email is a ten minute email or not 181 | """ 182 | with open(path) as data: 183 | search_dump = data.read() 184 | current_ext = email.split("@")[-1] 185 | searcher = re.compile(current_ext, re.I) 186 | for item in search_dump.split("\n"): 187 | if searcher.match(item) is not None: 188 | return True 189 | return False 190 | 191 | 192 | def smoosh_multi(single, filename): 193 | """ 194 | add a string and file into a single list 195 | """ 196 | retval = [single] 197 | try: 198 | open(filename).close() 199 | except IOError: 200 | lib.formatter.error( 201 | "the file failed to open, does it exist?" 202 | ) 203 | exit(1) 204 | with open(filename) as data: 205 | for item in data.readlines(): 206 | retval.append(item.strip()) 207 | return retval 208 | 209 | 210 | def grab_random_user_agent(path): 211 | """ 212 | grab a random user agent 213 | """ 214 | with open(path) as agents: 215 | return random.choice(agents.readlines()).strip() 216 | 217 | 218 | def grab_api_tokens(): 219 | """ 220 | grab API tokens from the stored data, this will be useful for when we add more APIs 221 | """ 222 | tokens = {} 223 | filenames = ( 224 | "{}/hunter.io", "{}/weleakinfo.com", "{}/haveibeenpwned.com", "{}/snusbase.com" 225 | ) 226 | if not os.path.exists(TOKENS_PATH): 227 | os.makedirs(TOKENS_PATH) 228 | for f in filenames: 229 | if not os.path.exists(f.format(TOKENS_PATH)): 230 | with open(f.format(TOKENS_PATH), 'a+') as token: 231 | if "snusbase" in f: 232 | username = lib.formatter.prompt( 233 | "enter your username for snusbase", lowercase=False 234 | ) 235 | password = lib.formatter.prompt( 236 | "enter your snusbase password", lowercase=False 237 | ) 238 | results = {"username": username, "password": password} 239 | json.dump(results, token) 240 | else: 241 | item = lib.formatter.prompt( 242 | "you have not provided a token for {}, enter token".format(f.split("/")[-1]), lowercase=False 243 | ) 244 | token.write(item.strip()) 245 | with open(f.format(TOKENS_PATH)) as data: 246 | token_identifier = f.split("/")[-1] 247 | if "snusbase" in f: 248 | tokens[token_identifier] = json.load(data) 249 | else: 250 | tokens[token_identifier] = data.read().strip() 251 | return tokens 252 | 253 | 254 | def write_processed_to_file(data, domain, file_path): 255 | """ 256 | write the processed data to a file 257 | """ 258 | with open(file_path, 'a+') as dump: 259 | json.dump(data[domain], dump, sort_keys=True, indent=4) 260 | return file_path 261 | 262 | 263 | def process_discovered(numbers, urls, emails, pattern, domain, do_write=True): 264 | """ 265 | make a pretty little output of discovered API data 266 | """ 267 | 268 | def output_loop(data, identifier, loop_length=10, numbers=False): 269 | if len(data) != 0: 270 | lib.formatter.info("discovered associated {}:".format(identifier)) 271 | total = len(data) 272 | for i, item in enumerate(data, start=1): 273 | if i != loop_length: 274 | if item is not None: 275 | print("\t-> {}".format(str(item).replace(" ", "-") if numbers else str(item))) 276 | else: 277 | lib.formatter.warn("hit maximum length, total of {} not displayed".format(total - i)) 278 | break 279 | else: 280 | lib.formatter.warn("did not discover any associated {}".format(identifier)) 281 | 282 | lib.formatter.info("information discovered associated with {}".format(domain)) 283 | if "None" not in pattern: 284 | lib.formatter.info("discovered possible pattern to emails: {}".format(pattern)) 285 | else: 286 | lib.formatter.warn("no email recognition pattern found") 287 | output_loop(numbers, "phone number(s)", numbers=True) 288 | output_loop(emails, "email address(es)") 289 | output_loop(urls, "external URL(s)") 290 | if do_write: 291 | filename = "{}_{}.json".format(random_string(), str(domain)) 292 | file_path = "{}/{}".format(JSON_DATA_DUMPS, filename) 293 | if not os.path.exists(JSON_DATA_DUMPS): 294 | os.makedirs(JSON_DATA_DUMPS) 295 | lib.formatter.info("dumping all information into json file for further processing") 296 | write_data = { 297 | domain: { 298 | "recognition_pattern": pattern if pattern is not None else None, 299 | "discovered_emails": list(emails), 300 | "external_urls": list(urls) if len(urls) != 0 else None, 301 | "discovered_numbers": list(numbers) if len(numbers) != 0 else None 302 | } 303 | } 304 | file_path = write_processed_to_file(write_data, domain, file_path) 305 | lib.formatter.info("information written to: {}".format(file_path)) 306 | return file_path 307 | else: 308 | return None 309 | 310 | 311 | def test_file(filename): 312 | """ 313 | check if a file exists or not 314 | """ 315 | try: 316 | open(filename).close() 317 | return True 318 | except IOError: 319 | return False 320 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | arrow==0.13.1 2 | requests==2.21.0 3 | bs4==0.0.1 -------------------------------------------------------------------------------- /whatbreach.py: -------------------------------------------------------------------------------- 1 | from whatbreach.main import main 2 | 3 | 4 | if __name__ == '__main__': 5 | main() 6 | -------------------------------------------------------------------------------- /whatbreach/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ekultek/WhatBreach/dad6b9f223b053ec522d57c08a698a6026142cd5/whatbreach/__init__.py -------------------------------------------------------------------------------- /whatbreach/main.py: -------------------------------------------------------------------------------- 1 | import json 2 | import time 3 | import subprocess 4 | 5 | from lib.cmd import Parser 6 | from hookers.weleakinfo_hook import WeLeakInfoHook 7 | from hookers.hunter_io_hook import HunterIoHook 8 | from hookers.hibp_hook import BeenPwnedHook 9 | from hookers.dehashed_hook import DehashedHook 10 | from hookers.databasestoday_hook import DatabasesTodayHook 11 | from hookers.emailrep_io_hook import EmailRepHook 12 | from hookers.snusbase_hooker import SnusbaseHooker 13 | from lib.settings import ( 14 | test_file, 15 | BANNER, 16 | display_found_databases, 17 | grab_api_tokens, 18 | check_ten_minute_email, 19 | TEN_MINUTE_EMAIL_EXTENSION_LIST 20 | ) 21 | from lib.formatter import ( 22 | info, 23 | error, 24 | warn, 25 | prompt 26 | ) 27 | 28 | 29 | def main(): 30 | try: 31 | opt = Parser().optparse() 32 | print(BANNER) 33 | res = Parser().check_opts(opt) 34 | if res is not None: 35 | to_search = res 36 | else: 37 | to_search = [] 38 | do_not_search = [] 39 | 40 | if len(to_search) == 0: 41 | if opt.singleEmail is None and opt.emailFile is None: 42 | warn("you have not provided an email to scan, redirecting to the help menu") 43 | subprocess.call(["python", "whatbreach.py", "--help"]) 44 | exit(1) 45 | api_tokens = grab_api_tokens() 46 | if opt.searchHunterIo and opt.singleEmail is not None: 47 | info("starting search on hunter.io using {}".format(opt.singleEmail)) 48 | file_results = HunterIoHook( 49 | opt.singleEmail, api_tokens["hunter.io"], verify_emails=opt.verifyEmailsThroughHunterIo 50 | ).hooker() 51 | if file_results is not None: 52 | with open(file_results) as data: 53 | emails = json.loads(data.read())["discovered_emails"] 54 | for email in emails: 55 | to_search.append(email) 56 | else: 57 | to_search.append(opt.singleEmail) 58 | elif opt.searchHunterIo and opt.emailFile is not None: 59 | if not test_file(opt.emailFile): 60 | error("unable to open filename, does it exist?") 61 | exit(1) 62 | api_tokens = grab_api_tokens() 63 | with open(opt.emailFile) as data: 64 | for email in data.readlines(): 65 | email = email.strip() 66 | file_results = HunterIoHook( 67 | email, api_tokens["hunter.io"], verify_emails=opt.verifyEmailsThroughHunterIo 68 | ).hooker() 69 | with open(file_results) as results: 70 | discovered_emails = json.loads(results.read())["discovered_emails"] 71 | for discovered in discovered_emails: 72 | to_search.append(discovered) 73 | elif opt.singleEmail is not None: 74 | info("starting search on single email address: {}".format(opt.singleEmail)) 75 | to_search = [opt.singleEmail] 76 | elif opt.emailFile is not None: 77 | if not test_file(opt.emailFile): 78 | error("unable to open filename, does it exist?") 79 | exit(1) 80 | with open(opt.emailFile) as emails: 81 | info("parsing email file: {}".format(opt.emailFile)) 82 | to_search = emails.readlines() 83 | info("starting search on a total of {} email(s)".format(len(to_search))) 84 | 85 | for email in to_search: 86 | email = email.strip() 87 | 88 | if opt.checkTenMinuteEmail: 89 | if check_ten_minute_email(email, TEN_MINUTE_EMAIL_EXTENSION_LIST): 90 | warn("email: {} appears to be a ten minute email".format(email)) 91 | answer = prompt("would you like to process the email[y/N]") 92 | if answer.startswith("n"): 93 | do_not_search.append(email) 94 | 95 | if opt.checkEmailAccounts: 96 | info("searching for possible profiles related to {}".format(email)) 97 | searcher = EmailRepHook(email) 98 | results = searcher.hooker() 99 | if results is not None and len(results) != 0: 100 | info( 101 | "found a total of {} possible profiles associated with {} on the following domains:".format( 102 | len(results), email 103 | ) 104 | ) 105 | for domain in results: 106 | print("\t-> {}".format(domain.title())) 107 | else: 108 | warn("no possible profiles discovered for email: {}".format(email)) 109 | 110 | if email not in do_not_search: 111 | if opt.throttleRequests != 0: 112 | time.sleep(opt.throttleRequests) 113 | info("searching breached accounts on HIBP related to: {}".format(email)) 114 | account_dumps = BeenPwnedHook( 115 | email, api_tokens["haveibeenpwned.com"], opt, retry=opt.retryOnFail 116 | ).account_hooker() 117 | info("searching for paste dumps on HIBP related to: {}".format(email)) 118 | 119 | if opt.searchPastebin: 120 | paste_dumps = BeenPwnedHook( 121 | email, api_tokens["haveibeenpwned.com"], opt, retry=opt.retryOnFail 122 | ).paste_hooker() 123 | else: 124 | warn("suppressing discovered pastes") 125 | paste_dumps = [] 126 | 127 | if opt.searchWeLeakInfo: 128 | info("searching weleakinfo.com for breaches related to: {}".format(email)) 129 | searcher = WeLeakInfoHook(email, api_tokens["weleakinfo.com"]) 130 | tmp = set() 131 | results = searcher.hooker() 132 | if results is not None: 133 | if account_dumps is not None: 134 | original_length = len(account_dumps) 135 | else: 136 | original_length = 0 137 | if account_dumps is not None: 138 | for item in account_dumps: 139 | tmp.add(item) 140 | if results is not None: 141 | for item in results: 142 | tmp.add(item) 143 | if len(tmp) != 0: 144 | account_dumps = list(tmp) 145 | new_length = len(account_dumps) 146 | amount_discovered = new_length - original_length 147 | if amount_discovered != 0: 148 | info( 149 | "discovered a total of {} more breaches from weleakinfo.com".format( 150 | new_length - original_length 151 | ) 152 | ) 153 | else: 154 | warn("did not discover any breaches") 155 | else: 156 | warn("did not discover any new databases from weleakinfo.com") 157 | else: 158 | warn("no databases discovered on weleakinfo") 159 | 160 | if opt.searchSnusBase: 161 | info("searching snusbase.com for breaches related to '{}'".format(email)) 162 | snusbase_leaks = SnusbaseHooker( 163 | email, api_tokens["snusbase.com"]["username"], 164 | api_tokens["snusbase.com"]["password"] 165 | ).main() 166 | if snusbase_leaks is not None and len(snusbase_leaks) != 0: 167 | info("found a total of {} more leaks using snusbase".format(len(snusbase_leaks))) 168 | for item in snusbase_leaks: 169 | account_dumps.append(item) 170 | set(account_dumps) 171 | account_dumps = list(account_dumps) 172 | else: 173 | warn("did not find anymore leaks using snusbase") 174 | 175 | if account_dumps is not None and paste_dumps is not None and len(account_dumps) != 0: 176 | info( 177 | "found a total of {} database breach(es) and a total of {} paste(s) pertaining to: {}".format( 178 | len(account_dumps), len(paste_dumps), email 179 | ) 180 | ) 181 | if opt.searchDehashed: 182 | if len(account_dumps) > 20: 183 | warn( 184 | "large amount of database breaches, obtaining links from " 185 | "dehashed (this may take a minute)" 186 | ) 187 | found_databases = DehashedHook(account_dumps).hooker() 188 | else: 189 | warn("suppressing discovered databases") 190 | found_databases = {} 191 | for i, dump in enumerate(paste_dumps, start=1): 192 | found_databases["Paste#{}".format(i)] = str(dump) 193 | display_found_databases(found_databases, download_pastes=opt.downloadPastes) 194 | if opt.downloadDatabase: 195 | for item in found_databases.keys(): 196 | if "Paste" not in item: 197 | info("searching for downloadable databases using query: {}".format(item.lower())) 198 | downloaded = DatabasesTodayHook( 199 | str(item), downloads_directory=opt.saveDirectory 200 | ).hooker() 201 | if len(downloaded) != 0: 202 | info( 203 | "downloaded a total of {} database(s) pertaining to query: {}".format( 204 | len(downloaded), item 205 | ) 206 | ) 207 | display_found_databases( 208 | downloaded, is_downloaded=True, download_pastes=opt.downloadPastes 209 | ) 210 | else: 211 | warn( 212 | "no databases appeared to be present and downloadable related to query: {}".format( 213 | str(item) 214 | ) 215 | ) 216 | 217 | elif account_dumps is not None and paste_dumps is None and len(account_dumps) != 0: 218 | info("found a total of {} database breach(es) pertaining to: {}".format(len(account_dumps), email)) 219 | if opt.searchDehashed: 220 | if len(account_dumps) > 20: 221 | warn( 222 | "large amount of database breaches, obtaining links from " 223 | "dehashed (this may take a minute)" 224 | ) 225 | found_databases = DehashedHook(account_dumps).hooker() 226 | else: 227 | warn("suppressing discovered databases") 228 | found_databases = {} 229 | if len(found_databases) != 0: 230 | display_found_databases(found_databases, download_pastes=opt.downloadPastes) 231 | if opt.downloadDatabase: 232 | for item in found_databases.keys(): 233 | if "Paste" not in item: 234 | info("searching for downloadable databases using query: {}".format(item.lower())) 235 | downloaded = DatabasesTodayHook( 236 | str(item), downloads_directory=opt.saveDirectory 237 | ).hooker() 238 | if len(downloaded) != 0: 239 | info( 240 | "downloaded a total of {} database(s) pertaining to query: {}".format( 241 | len(downloaded), item 242 | ) 243 | ) 244 | display_found_databases( 245 | downloaded, is_downloaded=True, download_pastes=opt.downloadPastes 246 | ) 247 | else: 248 | warn( 249 | "no databases appeared to be present and downloadable related to query: {}".format( 250 | str(item) 251 | ) 252 | ) 253 | else: 254 | warn("no output to show, most likely due to output suppression or dehashed") 255 | elif account_dumps is None and paste_dumps is not None: 256 | # this should never happen 257 | error("no database dumps found nor any pastes found for: {}".format(email)) 258 | else: 259 | error("email {} was not found in any breach".format(email)) 260 | 261 | if opt.staySalty: 262 | # i know that you think that you know shit 263 | # all the shade that's coming at me I wonder who throws it 264 | # you can't see the vision boy, you must be outta focus 265 | # that's a real hot program homie, I wonder who wrote it? oh shit 266 | # (lyrics ripped from iSpy by Kyle, all I do is steal bruh) 267 | warn("all this code was stolen with <3 by Eku") 268 | except KeyboardInterrupt: 269 | error("user quit the session") --------------------------------------------------------------------------------