Compare commits

...

104 Commits

Author SHA1 Message Date
Raphael dab7d35e02
Create pull_request_template.md 2019-03-03 12:14:49 +01:00
Raphael cb823066b4
Merge pull request #38 from sundowndev/develop
[Fix] Google search results & add source
2019-02-21 15:05:18 +01:00
Raphael 1c2ec491b5
Version 1.0.2 2019-02-21 14:57:44 +01:00
Raphael aaaf9304bd
Increase web pages results limit to 10 2019-02-21 14:49:58 +01:00
Raphael 937b3abe4f
Merge pull request #37 from sundowndev/source/findwhocallsme
Reputation source & Google search hotfix
2019-02-21 14:47:21 +01:00
sundowndev 3a63bd036d [Fix] Google search results 2019-02-21 14:42:18 +01:00
sundowndev 2e17453143 Use local format in OSINT scan 2019-02-21 14:41:37 +01:00
Raphael be44f64d58
Add findwhocallsme.com source 2019-02-21 13:12:28 +01:00
Raphael 719135c4c3
Merge pull request #35 from sundowndev/develop
[Fix] Country name for OVH scan
2019-02-19 15:12:01 +01:00
Raphael e02b4edaeb
Remove useless .replace() 2019-02-19 15:04:28 +01:00
Raphael f020a1ec85
Version 2019-02-19 14:59:02 +01:00
Raphael dc6c226252
Merge pull request #34 from sundowndev/hotfix/numCountry
Number country
2019-02-19 14:57:44 +01:00
sundowndev 303c583201 Fix: country name for OVH scan 2019-02-19 14:21:11 +01:00
Raphael 8bac8eb377
Merge pull request #32 from sundowndev/develop
Scanning improvements, readme & refactor
2019-02-18 16:58:42 +01:00
Raphael c553ca1e85
Merge pull request #33 from sundowndev/feature/refactor
Refactor
2019-02-18 16:48:47 +01:00
sundowndev 22c8bcfccb Refactor python file
Now using main() to launch tool, put everything else in some functions and put every lib import at the top of the file. Looking forward to a better file structure with multiple python files :-). It\'s already better to handle exceptions
2019-02-18 16:43:10 +01:00
sundowndev 384370eaa1 Test script 2019-02-18 16:07:50 +01:00
Raphael 1ca83be4da
Merge pull request #31 from sundowndev/awesome-readme
Awesome readme
2019-02-18 15:25:27 +01:00
sundowndev 1d69e2708d Autoindent code 2019-02-18 15:18:30 +01:00
sundowndev 006fd8bd91 Show help msg when any number is passed 2019-02-18 15:17:46 +01:00
Raphael ec85cdbd23
Update README.md 2019-02-18 15:10:39 +01:00
Raphael ec2ff93a87
Update README.md 2019-02-18 14:17:38 +01:00
Raphael e1b10a5d50
Beautify readme 2019-02-18 14:08:54 +01:00
sundowndev e1559004fb Add exception on numverify scan 2019-02-18 11:59:48 +01:00
sundowndev a5bf2d4918 Delete country codes file 2019-02-18 11:52:01 +01:00
sundowndev e3b4778cd4 Merge branch 'feature/countryName' into develop 2019-02-18 11:50:40 +01:00
Raphael 6309f6f960
Delete CountryCodes.json 2019-02-18 11:48:53 +01:00
sundowndev 85ba7478d9 Generated examples 2019-02-18 11:47:11 +01:00
sundowndev ea78993e47 Remove (useless) area result in local scan 2019-02-18 11:46:44 +01:00
sundowndev c1efb3650d Use local scan to find code instead of using third party API 2019-02-18 11:41:25 +01:00
Raphael 9116d5654b
Merge pull request #26 from sundowndev/hotfix/data-patch
Hotfix : Remove Canada country code
2019-02-14 18:39:34 +01:00
Raphael 942d7f8edc
Issue templates (#29) 2019-02-14 18:33:08 +01:00
Raphael 807c2a1a6d
Merge pull request #27 from sundowndev/develop
Decode responses to utf8
2019-02-04 19:29:12 +01:00
sundowndev 6fe97094eb Decode responses to utf8 2019-02-04 12:30:19 +01:00
Raphael 2b119cc913
Issue templates 2019-01-31 15:11:20 +01:00
Raphael 5ced4f7aec
Remove Canada and spaces
Issue #24
2019-01-31 14:33:09 +01:00
Raphael e108c1e36c
Merge pull request #20 from sundowndev/develop
v1.0.0-rc4 merge
2019-01-31 13:58:36 +01:00
Raphael 9872168db6
Merge branch 'master' into develop 2019-01-28 22:31:31 +01:00
Raphael 4e2869cba7
locatefamily.com footprinting 2019-01-28 15:05:42 +01:00
Raphael 2a6ecf15dd
Merge pull request #25 from sundowndev/hotfix/countryScan
[Fix #24] Country code scan
2019-01-28 11:38:47 +01:00
sundowndev 00cc280c40 Add exception on OVH API request 2019-01-28 11:36:24 +01:00
sundowndev ff06854856 Local database update 2019-01-28 11:30:05 +01:00
sundowndev c505ef1be8 [Fix #24] Country code scan
Use local json database to find country code instead of using third party API
2019-01-28 11:11:16 +01:00
Raphael 4fdab3bf34
Merge pull request #23 from sundowndev/master
Rebase develop
2019-01-25 22:36:26 +01:00
Raphael 3cfb11355f
Merge pull request #22 from sundowndev/hotfix/numverify
[Fix] Numverify scan & error exception
2019-01-23 18:43:36 +01:00
sundowndev 0eec71535b [Fix] Numverify scan & error exception 2019-01-23 18:40:31 +01:00
Raphael f09c96f826
Version
Set version to 1.0.0 and update number formatting examples.
2019-01-23 18:10:33 +01:00
Raphael 8e1cae6b9c
Delete RESOURCES.md
Moved to wiki
2019-01-20 15:46:50 +01:00
Raphael 27b39208b0
Merge pull request #21 from sundowndev/patch-msg
Patch need help message
2019-01-17 09:19:57 +00:00
Raphael bdc0bf8b23
fallback version to v1.0.0-rc2 2019-01-17 10:12:23 +01:00
Raphael 922186ca79
Need help message link 2019-01-17 10:11:40 +01:00
Raphael 170a94b702
Python badge 2019-01-14 14:25:28 +01:00
Raphael f0b54fbef4
Wiki link 2019-01-14 12:00:15 +01:00
Raphael 17c11ec794
Merge pull request #19 from sundowndev/travis-cfg
travis config
2019-01-14 10:38:12 +00:00
Raphael 58f35cb634
using python 3.7-dev 2019-01-14 11:35:37 +01:00
Raphael c9a8441f36
Build status 2019-01-14 11:34:43 +01:00
Raphael 74904549a9
Update .travis.yml 2019-01-14 11:32:55 +01:00
Raphael ac3eff13de
Create .travis.yml 2019-01-14 11:28:09 +01:00
Raphael 11b47c0562
Merge pull request #18 from sundowndev/develop
1.1.2-rc1 Improve footprinting
2019-01-14 10:22:55 +00:00
Raphael a8a3015f12
version 2019-01-14 11:22:44 +01:00
sundowndev f2dd168491 [Fix] Document footprinting 2019-01-14 11:19:55 +01:00
sundowndev 96406c4e23 Ask to rerun OSINT scan at finish state 2019-01-14 11:19:29 +01:00
sundowndev 7eadfa502b Generated examples 2019-01-14 10:30:07 +01:00
sundowndev 31eb7425c6 no-ansi option & minor refactor 2019-01-14 10:29:09 +01:00
Raphael 51f76150e4
Merge pull request #17 from sundowndev/develop
1.1.0-rc1 release
2019-01-14 08:58:55 +00:00
Raphael 347d0e87bf
Version 2019-01-14 09:58:27 +01:00
sundowndev ea3e0a0024 Script to generate example outputs 2019-01-07 15:02:02 +01:00
Raphael 45875a1d62
Document footprints request 2019-01-07 12:33:54 +01:00
Raphael e9b42d078c
Document footprints : adding .xls extension 2019-01-07 12:12:05 +01:00
Raphael 89baab6f87
[Docs] OSINT Tutorial link 2019-01-04 14:13:44 +01:00
Raphael bcf11a938b
[Fix #15] Add exception on tempophone API call 2018-12-29 18:58:40 +01:00
Raphael 6cce114a7a
Typo 2018-12-26 15:55:32 +01:00
Raphael 59ac083ccd
Add smslive.co 2018-12-26 15:52:30 +01:00
Raphael fd999a1d05
[Docs] OSINT resources 2018-12-21 18:29:39 +01:00
Raphael eb7ba13ee9
[Docs] OSINT resources 2018-12-21 18:24:26 +01:00
Raphael dee05839ec
[Docs] Captcha Troubleshooting
>The cookie should be created after you complete the captcha. If there's no captcha and *GOOGLE_ABUSE_EXEMPTION* cookie, try pressing F5 to refresh the page. The cookie should've been created. If refreshing the page does not help, change the query to something different (change the number or add text). Google will not necessarily ask you to complete a captcha if your request is the exact same as the previous one, because it'll usually be cached.
2018-12-21 11:37:04 +01:00
Raphael ed79a4f23f
tag badge 2018-12-20 15:05:21 +01:00
Raphael 01f60ef4bf
lib import priority
Import sys before other libs to avoid errors on sys.exit() when requirements are missing
2018-12-16 14:04:23 +00:00
Raphael 120e190c29
Rename tests/list.txt to examples/input.txt 2018-12-14 17:26:37 +01:00
Raphael 7a14c7c5bd
[Docs] Typo 2018-12-14 17:23:52 +01:00
Raphael ec227c0782
Merge pull request #13 from sundowndev/hotfix/openssl
[v1.0.0-rc2] Hotfix: openssl & text color bugs
2018-12-14 15:07:56 +01:00
sundowndev 4e5994347c Remove exception text colors to avoid bugs 2018-12-14 15:07:14 +01:00
sundowndev b51d475695 Delete useless debug file 2018-12-14 14:59:08 +01:00
sundowndev 76eb594566 Fix: bug using output option 2018-12-14 14:56:23 +01:00
sundowndev 89e1b2b7f1 Reset colors at exit 2018-12-14 14:44:58 +01:00
sundowndev c7029aca68 README 2018-12-14 12:58:34 +01:00
sundowndev 79c89e2dd7 Requirements 2018-12-14 12:58:20 +01:00
sundowndev 268787dce8 [Fix #11] Fix OpenSSL bug & colorama 2018-12-14 12:57:55 +01:00
Raphael 30226cc436
Merge pull request #10 from sundowndev/develop
Develop
2018-12-11 15:09:15 +01:00
sundowndev 92d1683a86 Python script update feature 2018-12-11 15:07:22 +01:00
sundowndev c53d514cfc [Fix #4] Update OSINT files 2018-12-11 15:07:22 +01:00
Raphael feddcbed9b
version 2018-12-11 15:05:42 +01:00
Raphael 692480457f
Merge pull request #9 from sundowndev/develop
Update feature & migration to Python 3
2018-12-11 15:03:56 +01:00
Raphael 47ceb86dd5
License scan status 2018-12-11 13:42:44 +01:00
sundowndev 21ebdf881f Merge branch 'develop' of github.com:sundowndev/PhoneInfoga into develop 2018-12-11 12:02:44 +01:00
sundowndev 1f8cdb6cf4 OSINT sources 2018-12-11 12:02:16 +01:00
sundowndev d911cd9b7e Replace variables in dork requests 2018-12-11 12:01:52 +01:00
sundowndev 20495f1024 [Fix #7] Migrating to Python 3
Code refactor to migrate to Python 3. Using format() instead of %s, cleanup strings and dictionaries. Release v0.10-dev
2018-12-11 11:33:21 +01:00
Raphael d50ed5d576
Note about dealing with Google CAPTCHA 2018-12-11 09:54:38 +01:00
sundowndev 68fa969b39 Merge branch 'feature/python3' into develop 2018-12-10 16:24:27 +01:00
sundowndev aa0485ba9d Badges 2018-12-10 16:24:09 +01:00
sundowndev f03061dd00 Add argparse to requirements 2018-12-10 16:23:36 +01:00
sundowndev 3964c4a504 Refactor to use Python3 using 2to3 2018-12-10 16:22:38 +01:00
Raphael aa155692cc
Installation 2018-12-09 20:27:03 +01:00
13 changed files with 622 additions and 325 deletions

5
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,5 @@
1. Please DO NOT open pull request on the **master** branch. Use the **develop** branch instead!
2. Explain your changes as much as possible
3. If possible, use a well understanding title and use labels ! (e.g: "[Bug] Google Captcha", "[Feature] Footprinting on Bing")
Thank you for contributing ! :tada:

7
.travis.yml Normal file
View File

@ -0,0 +1,7 @@
language: python
python:
- "3.6"
- "3.7-dev"
install:
- pip install -r requirements.txt
script: bash ./examples/generate.sh

126
README.md
View File

@ -1,10 +1,35 @@
# PhoneInfoga
<h1 align="center">PhoneInfoga</h1>
Information gathering & OSINT reconnaissance tool for phone numbers.
<div align="center">
<a href="https://travis-ci.org/sundowndev/PhoneInfoga">
<img src="https://img.shields.io/travis/sundowndev/PhoneInfoga/master.svg?style=flat-square" alt="Build Status" />
</a>
<a href="#">
<img src="https://img.shields.io/badge/python-3.6-blue.svg?style=flat-square" alt="Python version" />
</a>
<a href="https://github.com/sundowndev/PhoneInfoga/releases">
<img src="https://img.shields.io/github/tag/SundownDEV/PhoneInfoga.svg?style=flat-square" alt="Latest version" />
</a>
<a href="https://github.com/sundowndev/PhoneInfoga/blob/master/LICENSE">
<img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square" alt="License" />
</a>
</div>
One of the most advanced tools to scan phone numbers using only free resources. The goal is to first gather basic information such as country, area, carrier and line type on any international phone numbers with a very good accuracy. Then try to determine the VoIP provider or search for footprints on search engines to try identify the owner.
<h4 align="center">Information gathering & OSINT reconnaissance tool for phone numbers</h4>
**This tool requires python 2.x**
<div align="center">
<sub>For the love of open source investigations. Built with ❤︎ by
<a href="https://twitter.com/sundowndev">@sundowndev</a>
</div>
<h3 align="center">
<a href="https://github.com/sundowndev/PhoneInfoga/wiki">Documentation</a> |
<a href="https://medium.com/@SundownDEV/phone-number-scanning-osint-recon-tool-6ad8f0cac27b">OSINT Tutorial</a>
</h3>
## About
PhoneInfoga is one of the most advanced tools to scan phone numbers using only free resources. The goal is to first gather basic information such as country, area, carrier and line type on any international phone numbers with a very good accuracy. Then try to determine the VoIP provider or search for footprints on search engines to try identify the owner.
## Features
@ -20,30 +45,18 @@ One of the most advanced tools to scan phone numbers using only free resources.
The tool only accepts E164 and International formats as input.
- E164: +3396360XXXX
- International: +33 9 63 60 XX XX
- National: 09 63 60 XX XX
- RFC3966: tel:+33-9-63-60-XX-XX
- Out-of-country format from US: 011 33 9 63 60 XX XX
## Available scanners
Use `any` to disable this feature. Default value: `all`
- numverify
- ovh
## Installation
```bash
git clone https://github.com/sundowndev/PhoneInfoga
cd ./PhoneInfoga
pip install -r requirements.txt
python ./phoneinfoga.py -h
cd PhoneInfoga/
python3 -m pip install -r requirements.txt
```
## Usage
### [The full usage documentation has been moved to the wiki](https://github.com/sundowndev/PhoneInfoga/wiki)
```
usage: phoneinfoga.py -n <number> [options]
@ -65,77 +78,8 @@ optional arguments:
-u, --update Update the tool & databases
```
Example (quotes are optional, use it when typing special formats) :
```
python phoneinfoga.py -n "(+42)837544833"
```
Check for a number range on OVH :
```
python phoneinfoga.py -n +42837544833 -s ovh
```
Check several numbers at once :
```
python ./phoneinfoga.py -i numbers.txt -o results.txt
```
**Note: `--osint` is not compatible with `--output` option.**
Use all scanners and run OSINT reconnaissance :
```
python phoneinfoga.py -n +42837544833 -s all --osint
```
## Formatting
E.164 formatting for phone numbers entails the following:
- A + (plus) sign
- International Country Calling code
- Local Area code
- Local Phone number
For example, heres a US-based number in standard local formatting: (415) 555-2671
![](https://i.imgur.com/0e2SMdL.png)
Heres the same phone number in E.164 formatting: +14155552671
![](https://i.imgur.com/KfrvacR.png)
In the UK, and many other countries internationally, local dialing may require the addition of a '0' in front of the subscriber number. With E.164 formatting, this '0' must usually be removed.
For example, heres a UK-based number in standard local formatting: 020 7183 8750
Heres the same phone number in E.164 formatting: +442071838750
## Dealing with Google captcha
PhoneInfo use a workaround to handle Google bot detection. When running OSINT scan, you will usually be blacklisted very easily by Google, which will ask the tool to complete a captcha.
>When you search on Google using custom requests (Google Dorks), you get very easily blacklisted. So Google shows up a page where you have to complete a captcha to continue. As soon as the captcha is completed, Google create a cookie named "GOOGLE_ABUSE_EXEMPTION" which is used to whitelist your browser and IP address for some minutes. This temporary whitelist is enough to let you gather a lot of information from many sources. So I decided to add a simple user manipulation to bypass this bot detection. [...] So I'll just try make requests and wait until I get a 503 error, which means I got blacklisted. Then I ask the user to follow an URL to manually complete the captcha and copy the whitelist token to paste it in the CLI. The tool is now able to continue to scan!
![](https://i.imgur.com/qbFZa1m.png)
### Steps
- Follow the URL
- Complete the captcha if needed
- Open the dev tool (F12 on most browsers)
- Go to **Storage**, then **Cookies**
- Copy the value of the *GOOGLE_ABUSE_EXEMPTION* cookie and paste it in the CLI
![](https://i.imgur.com/KkE1EM5.png)
## Custom formatting
Sometimes the phone number has footprints but is used with a different formatting. This is a problem because for example if we search for "+15417543010", we'll not find web pages that write it that way : "(541) 7543010". So the tool use a (optional) custom formatting given by the user to find further and more accurate results.
## License
This tool is licensed under the GNU General Public License v3.0.
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fsundowndev%2FPhoneInfoga.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fsundowndev%2FPhoneInfoga?ref=badge_large)

13
examples/generate.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/bash
scriptDir=$(dirname -- "$(readlink -f -- "$BASH_SOURCE")")
python3 $scriptDir/../phoneinfoga.py -n "+86 591 2284 8571" -h
python3 $scriptDir/../phoneinfoga.py -n "+86 591 2284 8571" -s any --no-ansi
python3 $scriptDir/../phoneinfoga.py -i $scriptDir/input.txt -o $scriptDir/output_from_input.txt -s any
python3 $scriptDir/../phoneinfoga.py -n "+86 591 2284 8571" -s all -o $scriptDir/output_single.txt
echo "Test script executed."

View File

@ -0,0 +1,87 @@
___ _ _____ __
/ _ \ |__ ___ _ __ ___ \_ \_ __ / _| ___ __ _ __ _
/ /_)/ '_ \ / _ \| '_ \ / _ \ / /\/ '_ \| |_ / _ \ / _` |/ _` |
/ ___/| | | | (_) | | | | __/\/ /_ | | | | _| (_) | (_| | (_| |
\/ |_| |_|\___/|_| |_|\___\____/ |_| |_|_| \___/ \__, |\__,_|
|___/
PhoneInfoga Ver. v1.0.0
Coded by Sundowndev
[!] ---- Fetching informations for 8562099453217 ---- [!]
[-] Running local scan...
[+] International format: +856 20 99 453 217
[+] Local format: 02099453217
[+] Country found: Laos (+856)
[+] City/Area: Laos
[+] Carrier: Unitel
[+] Timezone: Asia/Vientiane
[-] The number is valid and possible.
[-] Scan finished.
[!] ---- Fetching informations for 59172768361 ---- [!]
[-] Running local scan...
[+] International format: +591 72768361
[+] Local format: 072768361
[+] Country found: Bolivia (+591)
[+] City/Area: Bolivia
[+] Carrier: Entel
[+] Timezone: America/La_Paz
[-] The number is valid and possible.
[-] Scan finished.
[!] ---- Fetching informations for 32474123456 ---- [!]
[-] Running local scan...
[+] International format: +32 474 12 34 56
[+] Local format: 0474123456
[+] Country found: Belgium (+32)
[+] City/Area: Belgium
[+] Carrier: Proximus
[+] Timezone: Europe/Brussels
[-] The number is valid and possible.
[-] Scan finished.
[!] ---- Fetching informations for 15417543010 ---- [!]
[-] Running local scan...
[+] International format: +1 541-754-3010
[+] Local format: 05417543010
[+] Country found: United States (+1)
[+] City/Area: Corvallis, OR
[+] Carrier:
[+] Timezone: America/Los_Angeles
[-] The number is valid and possible.
[-] Scan finished.
[!] ---- Fetching informations for 8659122848571 ---- [!]
[-] Running local scan...
[+] International format: +86 591 2284 8571
[+] Local format: 059122848571
[+] Country found: China (+86)
[+] City/Area: Fuzhou, Fujian
[+] Carrier:
[+] Timezone: Asia/Shanghai
[-] The number is valid and possible.
[-] Scan finished.
[!] ---- Fetching informations for 74964819375 ---- [!]
[-] Running local scan...
[+] International format: +7 496 481-93-75
[+] Local format: 04964819375
[+] Country found: Russia (+7)
[+] City/Area: Moscow
[+] Carrier:
[+] Timezone: Europe/Moscow
[-] The number is valid and possible.
[-] Scan finished.
[!] ---- Fetching informations for 39172768361 ---- [!]
[-] Running local scan...
[-] Scan finished.

View File

@ -0,0 +1,30 @@
___ _ _____ __
/ _ \ |__ ___ _ __ ___ \_ \_ __ / _| ___ __ _ __ _
/ /_)/ '_ \ / _ \| '_ \ / _ \ / /\/ '_ \| |_ / _ \ / _` |/ _` |
/ ___/| | | | (_) | | | | __/\/ /_ | | | | _| (_) | (_| | (_| |
\/ |_| |_|\___/|_| |_|\___\____/ |_| |_|_| \___/ \__, |\__,_|
|___/
PhoneInfoga Ver. v1.0.0
Coded by Sundowndev
[!] ---- Fetching informations for 8659122848571 ---- [!]
[-] Running local scan...
[+] International format: +86 591 2284 8571
[+] Local format: 059122848571
[+] Country found: China (+86)
[+] City/Area: Fuzhou, Fujian
[+] Carrier:
[+] Timezone: Asia/Shanghai
[-] The number is valid and possible.
[-] Running Numverify.com scan...
[+] Number: (+86) 059122848571
[+] Country: China (People's Republic of) (CN)
[+] Location: Fuzhou
[+] Carrier:
[+] Line type: landline
(!) This is most likely a landline, but it can still be a fixed VoIP number.
[-] Running OVH scan...
[-] Scan finished.

View File

@ -98,5 +98,10 @@
"site": "receive-sms-online.com",
"request": "site:\"receive-sms-online.com\" intext:\"$n\"",
"stop": 1
},
{
"site": "smslive.co",
"request": "site:\"smslive.co\" intext:\"$n\"",
"stop": 1
}
]

View File

@ -1,13 +1,13 @@
[
{
"site": "numinfo.net",
"request": "site:\"numinfo.net\" intext:\"$n\" | $i",
"request": "site:\"numinfo.net\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
"dialCode": null,
"stop": 2
},
{
"site": "sync.me",
"request": "site:\"sync.me\" intext:\"$n\" | $i",
"request": "site:\"sync.me\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
"dialCode": null,
"stop": 1
},
@ -16,5 +16,23 @@
"request": "site:\"whocallsyou.de\" intext:\"0$n\"",
"dialCode": null,
"stop": 1
},
{
"site": "pastebin.com",
"request": "site:\"pastebin.com\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
"dialCode": null,
"stop": 5
},
{
"site": "whycall.me",
"request": "site:\"whycall.me\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
"dialCode": null,
"stop": 1
},
{
"site": "locatefamily.com",
"request": "site:locatefamily.com intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
"dialCode": null,
"stop": 1
}
]

View File

@ -1,12 +1,17 @@
[
{
"title": "reputation report on whosenumber.info",
"request": "site:\"whosenumber.info\" intext:\"$n\" intitle:\"who called\"",
"request": "site:whosenumber.info intext:\"$n\" intitle:\"who called\"",
"stop": 1
},
{
"title": "phone fraud footprints",
"request": "intitle:\"Phone Fraud\" intext:\"$n\" | \"$n\"",
"request": "intitle:\"Phone Fraud\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
"stop": 5
},
{
"title": "reputation report on findwhocallsme.com",
"request": "site:findwhocallsme.com intext:\"$n\" | intext:\"$i\"",
"stop": 1
}
]

View File

@ -1,22 +1,22 @@
[
{
"site": "facebook.com",
"request": "site:\"facebook.com\" intext:\"$i\" | intext:\"$n\"",
"request": "site:\"facebook.com\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
"stop": 5
},
{
"site": "twitter.com",
"request": "site:\"twitter.com\" intext:\"$i\" | intext:\"$n\"",
"request": "site:\"twitter.com\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
"stop": 5
},
{
"site": "linkedin.com",
"request": "site:\"linkedin.com\" intext:\"$i\" | intext:\"$n\"",
"request": "site:\"linkedin.com\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
"stop": 5
},
{
"site": "instagram.com",
"request": "site:\"instagram.com\" intext:\"$i\" | intext:\"$n\"",
"request": "site:\"instagram.com\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
"stop": 5
}
]

View File

@ -1,27 +1,32 @@
#!/usr/bin/env python
#!/usr/bin/env python3
__version__ = '0.9-dev'
__version__ = 'v1.0.2'
def banner():
print " ___ _ _____ __ "
print " / _ \ |__ ___ _ __ ___ \_ \_ __ / _| ___ __ _ __ _ "
print " / /_)/ '_ \ / _ \| '_ \ / _ \ / /\/ '_ \| |_ / _ \ / _` |/ _` |"
print " / ___/| | | | (_) | | | | __/\/ /_ | | | | _| (_) | (_| | (_| |"
print " \/ |_| |_|\___/|_| |_|\___\____/ |_| |_|_| \___/ \__, |\__,_|"
print " |___/ "
print " PhoneInfoga Ver. %s " % __version__
print " Coded by Sundowndev "
print "\n"
try:
import sys
import signal
from colorama import Fore, Style
import atexit
import argparse
import random
import time
import hashlib
import json
import re
import requests
import urllib3
from bs4 import BeautifulSoup
import html5lib
import phonenumbers
from phonenumbers import carrier
from phonenumbers import geocoder
from phonenumbers import timezone
from urllib.parse import urlencode
except Exception as e:
print('[!] Missing requirements. Try running python3 -m pip install -r requirements.txt')
sys.exit()
print "\n \033[92m"
banner()
import sys
import argparse
import random
parser = argparse.ArgumentParser(description=
"Advanced information gathering tool for phone numbers (https://github.com/sundowndev/PhoneInfoga) version %s" % __version__,
parser = argparse.ArgumentParser(description="Advanced information gathering tool for phone numbers (https://github.com/sundowndev/PhoneInfoga) version {}".format(__version__),
usage='%(prog)s -n <number> [options]')
parser.add_argument('-n', '--number', metavar='number', type=str,
@ -40,66 +45,81 @@ parser.add_argument('--osint', action='store_true',
help='Use OSINT reconnaissance')
parser.add_argument('-u', '--update', action='store_true',
help='Update the tool & databases')
help='Update the project')
parser.add_argument('--no-ansi', action='store_true',
help='Disable colored output')
parser.add_argument('-v', '--version', action='store_true',
help='Show tool version')
args = parser.parse_args()
# If any param is passed, execute help command
if not len(sys.argv) > 1:
parser.print_help()
sys.exit();
uagent = []
uagent.append(
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0) Opera 12.14")
uagent.append(
"Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:26.0) Gecko/20100101 Firefox/26.0")
uagent.append(
"Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20090913 Firefox/3.5.3")
uagent.append(
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)")
uagent.append(
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.7 (KHTML, like Gecko) Comodo_Dragon/16.1.1.0 Chrome/16.0.912.63 Safari/535.7")
uagent.append(
"Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)")
uagent.append(
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.1) Gecko/20090718 Firefox/3.5.1")
uagent.append(
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:63.0) Gecko/20100101 Firefox/63.0")
if args.update:
print 'update'
sys.exit()
try:
import time
import hashlib
import json
import re
import requests
from bs4 import BeautifulSoup
import html5lib
import phonenumbers
from phonenumbers import carrier
from phonenumbers import geocoder
from phonenumbers import timezone
except KeyboardInterrupt:
print '\033[91m[!] Exiting.'
sys.exit()
except:
print '\033[91m[!] Missing requirements. Try running pip install -r requirements.txt'
sys.exit()
scanners = ['any', 'all', 'numverify', 'ovh']
uagent=[]
uagent.append("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0) Opera 12.14")
uagent.append("Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:26.0) Gecko/20100101 Firefox/26.0")
uagent.append("Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20090913 Firefox/3.5.3")
uagent.append("Mozilla/5.0 (Windows; U; Windows NT 6.1; en; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)")
uagent.append("Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.7 (KHTML, like Gecko) Comodo_Dragon/16.1.1.0 Chrome/16.0.912.63 Safari/535.7")
uagent.append("Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)")
uagent.append("Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.1) Gecko/20090718 Firefox/3.5.1")
uagent.append("Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:63.0) Gecko/20100101 Firefox/63.0")
number = '' # Full number format
localNumber = '' # Local number format
internationalNumber = '' # International numberformat
numberCountryCode = '' # Dial code; e.g:"+33"
numberCountry = '' # Country; e.g:France
number = '' # Full number format; e.g: 3312345678
localNumber = '' # Local number format; e.g: 06 12 34 56 78
internationalNumber = '' # International number format; e.g: +33 6 12 34 56 78
numberCountryCode = '' # Dial code; e.g: 33
numberCountry = '' # Country; e.g: fr
googleAbuseToken = ''
customFormatting = ''
if args.no_ansi or args.output:
code_info = '[-] '
code_warning = '(!) '
code_result = '[+] '
code_error = '[!] '
code_title = ''
else:
code_info = Fore.RESET + Style.BRIGHT + '[-] '
code_warning = Fore.YELLOW + Style.BRIGHT + '(!) '
code_result = Fore.GREEN + Style.BRIGHT + '[+] '
code_error = Fore.RED + Style.BRIGHT + '[!] '
code_title = Fore.YELLOW + Style.BRIGHT
def banner():
print(" ___ _ _____ __ ")
print(" / _ \ |__ ___ _ __ ___ \_ \_ __ / _| ___ __ _ __ _ ")
print(" / /_)/ '_ \ / _ \| '_ \ / _ \ / /\/ '_ \| |_ / _ \ / _` |/ _` |")
print(" / ___/| | | | (_) | | | | __/\/ /_ | | | | _| (_) | (_| | (_| |")
print(" \/ |_| |_|\___/|_| |_|\___\____/ |_| |_|_| \___/ \__, |\__,_|")
print(" |___/ ")
print(" PhoneInfoga Ver. {}".format(__version__))
print(" Coded by Sundowndev")
print("\n")
def resetColors():
if not args.output:
print(Style.RESET_ALL)
def search(req, stop):
global googleAbuseToken
global uagent
chosenUserAgent = random.choice(uagent)
s = requests.Session()
reqSession = requests.Session()
headers = {
'User-Agent': chosenUserAgent,
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
@ -108,25 +128,30 @@ def search(req, stop):
'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'Keep-Alive': '115',
'Connection': 'keep-alive',
'Cache-Control': 'no-cache',
'Cookie': 'Cookie: CGIC=Ij90ZXh0L2h0bWwsYXBwbGljYXRpb24veGh0bWwreG1sLGFwcGxpY2F0aW9uL3htbDtxPTAuOSwqLyo7cT0wLjg; CONSENT=YES+RE.fr+20150809-08-0; 1P_JAR=2018-11-28-14; NID=148=aSdSHJz71rufCokaUC93nH3H7lOb8E7BNezDWV-PyyiHTXqWK5Y5hsvj7IAzhZAK04-QNTXjYoLXVu_eiAJkiE46DlNn6JjjgCtY-7Fr0I4JaH-PZRb7WFgSTjiFqh0fw2cCWyN69DeP92dzMd572tQW2Z1gPwno3xuPrYC1T64wOud1DjZDhVAZkpk6UkBrU0PBcnLWL7YdL6IbEaCQlAI9BwaxoH_eywPVyS9V; SID=uAYeu3gT23GCz-ktdGInQuOSf-5SSzl3Plw11-CwsEYY0mqJLSiv7tFKeRpB_5iz8SH5lg.; HSID=AZmH_ctAfs0XbWOCJ; SSID=A0PcRJSylWIxJYTq_; APISID=HHB2bKfJ-2ZUL5-R/Ac0GK3qtM8EHkloNw; SAPISID=wQoxetHBpyo4pJKE/A2P6DUM9zGnStpIVt; SIDCC=ABtHo-EhFAa2AJrJIUgRGtRooWyVK0bAwiQ4UgDmKamfe88xOYBXM47FoL5oZaTxR3H-eOp7-rE; OTZ=4671861_52_52_123900_48_436380; OGPC=873035776-8:; OGP=-873035776:;'
}
try:
URL = 'https://www.google.com/search?tbs=li:1&q=%s&amp;gws_rd=ssl' % (req)
r = s.get(URL + googleAbuseToken, headers=headers)
REQ = urlencode({'q': req})
URL = 'https://www.google.com/search?tbs=li:1&{}&amp;gws_rd=ssl&amp;gl=us '.format(
REQ)
r = reqSession.get(URL + googleAbuseToken, headers=headers)
while r.status_code == 503:
print code_warning + 'You are temporary blacklisted from Google search. Complete the captcha at the following URL and copy/paste the content of GOOGLE_ABUSE_EXEMPTION cookie : %s' % URL
print '\n' + code_info + 'Need help ? Read https://github.com/sundowndev/PhoneInfoga#dealing-with-google-captcha'
token = raw_input('\nGOOGLE_ABUSE_EXEMPTION=')
while r.status_code != 200:
print(code_warning + 'You are temporary blacklisted from Google search. Complete the captcha at the following URL and copy/paste the content of GOOGLE_ABUSE_EXEMPTION cookie : {}'.format(URL))
print('\n' + code_info +
'Need help ? Read https://github.com/sundowndev/PhoneInfoga/wiki')
token = input('\nGOOGLE_ABUSE_EXEMPTION=')
googleAbuseToken = '&google_abuse=' + token
r = s.get(URL + googleAbuseToken, headers=headers)
r = reqSession.get(URL + googleAbuseToken, headers=headers)
soup = BeautifulSoup(r.text, 'html5lib')
soup = BeautifulSoup(r.content, 'html.parser')
results = soup.find("div", id="search").find_all("div", class_="g")
links=[]
counter=0
links = []
counter = 0
for result in results:
counter += 1
@ -140,18 +165,23 @@ def search(req, stop):
url = re.sub(r'(?:\&sa\=)(?:.*)', '', url)
url = re.sub(r'(?:\&rct\=)(?:.*)', '', url)
if re.match(r"^(/search\?q=)", url) is not None:
if re.match(r"^(?:\/search\?q\=)", url) is not None:
url = 'https://google.com' + url
links.append(url)
if url is not None:
links.append(url)
return links
except:
print code_error + 'Request failed. Please retry or open an issue on GitHub.'
except Exception as e:
print(code_error + 'Request failed. Please retry or open an issue on https://github.com/sundowndev/PhoneInfoga.')
print(e)
return []
def formatNumber(InputNumber):
return re.sub("(?:\+)?(?:[^[0-9]*)", "", InputNumber)
def localScan(InputNumber):
global number
global localNumber
@ -159,40 +189,47 @@ def localScan(InputNumber):
global numberCountryCode
global numberCountry
print code_info + 'Running local scan...'
print(code_info + 'Running local scan...')
FormattedPhoneNumber = "+" + formatNumber(InputNumber)
try:
PhoneNumberObject = phonenumbers.parse(FormattedPhoneNumber, None)
except:
except Exception as e:
return False
else:
if not phonenumbers.is_valid_number(PhoneNumberObject):
return False
number = phonenumbers.format_number(PhoneNumberObject, phonenumbers.PhoneNumberFormat.E164).replace('+', '')
numberCountryCode = phonenumbers.format_number(PhoneNumberObject, phonenumbers.PhoneNumberFormat.INTERNATIONAL).split(' ')[0]
number = phonenumbers.format_number(
PhoneNumberObject, phonenumbers.PhoneNumberFormat.E164).replace('+', '')
numberCountryCode = phonenumbers.format_number(
PhoneNumberObject, phonenumbers.PhoneNumberFormat.INTERNATIONAL).split(' ')[0]
numberCountry = phonenumbers.region_code_for_country_code(
int(numberCountryCode))
countryRequest = json.loads(requests.request('GET', 'https://restcountries.eu/rest/v2/callingcode/%s' % numberCountryCode.replace('+', '')).content)
numberCountry = countryRequest[0]['alpha2Code']
localNumber = phonenumbers.format_number(
PhoneNumberObject, phonenumbers.PhoneNumberFormat.E164).replace(numberCountryCode, '0')
internationalNumber = phonenumbers.format_number(
PhoneNumberObject, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
localNumber = phonenumbers.format_number(PhoneNumberObject, phonenumbers.PhoneNumberFormat.E164).replace(numberCountryCode, '')
internationalNumber = phonenumbers.format_number(PhoneNumberObject, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
country = geocoder.country_name_for_number(PhoneNumberObject, "en")
location = geocoder.description_for_number(PhoneNumberObject, "en")
carrierName = carrier.name_for_number(PhoneNumberObject, 'en')
print code_result + 'International format: %s' % internationalNumber
print code_result + 'Local format: 0%s' % localNumber
print code_result + 'Country code: %s' % numberCountryCode
print code_result + 'Location: %s' % geocoder.description_for_number(PhoneNumberObject, "en")
print code_result + 'Carrier: %s' % carrier.name_for_number(PhoneNumberObject, 'en')
print code_result + 'Area: %s' % geocoder.description_for_number(PhoneNumberObject, 'en')
print(code_result + 'International format: {}'.format(internationalNumber))
print(code_result + 'Local format: 0{}'.format(localNumber))
print(code_result + 'Country found: {} ({})'.format(country, numberCountryCode))
print(code_result + 'City/Area: {}'.format(location))
print(code_result + 'Carrier: {}'.format(carrierName))
for timezoneResult in timezone.time_zones_for_number(PhoneNumberObject):
print code_result + 'Timezone: %s' % (timezoneResult)
print(code_result + 'Timezone: {}'.format(timezoneResult))
if phonenumbers.is_possible_number(PhoneNumberObject):
print code_info + 'The number is valid and possible.'
print(code_info + 'The number is valid and possible.')
else:
print code_warning + 'The number is valid but might not be possible.'
print(code_warning + 'The number is valid but might not be possible.')
def numverifyScan():
global number
@ -200,59 +237,70 @@ def numverifyScan():
if not args.scanner == 'numverify' and not args.scanner == 'all':
return -1
print code_info + 'Running Numverify.com scan...'
print(code_info + 'Running Numverify.com scan...')
try:
requestSecret = ''
resp = requests.get('https://numverify.com/')
soup = BeautifulSoup(resp.text, "html5lib")
except Exception as e:
print(code_error + 'Numverify.com is not available')
return -1
requestSecret = ''
resp = requests.get('https://numverify.com/')
soup = BeautifulSoup(resp.text, "html5lib")
for tag in soup.find_all("input", type="hidden"):
if tag['name'] == "scl_request_secret":
requestSecret = tag['value']
break;
break
apiKey = hashlib.md5()
apiKey.update(number + requestSecret)
apiKey = apiKey.hexdigest()
apiKey = hashlib.md5((number + requestSecret).encode('utf-8')).hexdigest()
headers = {
'host': "numverify.com",
'connection': "keep-alive",
'content-length': "49",
'accept': "application/json",
'origin': "https://numverify.com",
'x-requested-with': "XMLHttpRequest",
'user-agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
'referer': "https://numverify.com/",
'accept-encoding': "gzip, deflate, br",
'accept-language': "en-US,en;q=0.9,fr;q=0.8,la;q=0.7,es;q=0.6,zh-CN;q=0.5,zh;q=0.4",
'cache-control': "no-cache"
'Host': 'numverify.com',
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:64.0) Gecko/20100101 Firefox/64.0',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3',
'Accept-Encoding': 'gzip, deflate, br',
'Referer': 'https://numverify.com/',
'X-Requested-With': 'XMLHttpRequest',
'DNT': '1',
'Connection': 'keep-alive',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache'
}
response = requests.request("GET", "https://numverify.com/php_helper_scripts/phone_api.php?secret_key=" + apiKey + "&number=" + number, data="", headers=headers)
try:
response = requests.request(
"GET", "https://numverify.com/php_helper_scripts/phone_api.php?secret_key={}&number={}".format(apiKey, number), data="", headers=headers)
if response.content == "Unauthorized" or response.status_code != 200:
print(code_error + "An error occured while calling the API (bad request or wrong api key).")
data = json.loads(response.content.decode('utf-8'))
except Exception as e:
print(code_error + 'Numverify.com is not available')
return -1
data = json.loads(response.content)
if response.content == "Unauthorized" or response.status_code != 200:
print((code_error + "An error occured while calling the API (bad request or wrong api key)."))
return -1
if data["valid"] == False:
print(code_error + "Error: Please specify a valid phone number. Example: +6464806649")
print((code_error + "Error: Please specify a valid phone number. Example: +6464806649"))
sys.exit()
InternationalNumber = '('+data["country_prefix"]+')' + data["local_format"]
InternationalNumber = '({}){}'.format(
data["country_prefix"], data["local_format"])
print(code_result + "Number: (%s) %s") % (data["country_prefix"],data["local_format"])
print(code_result + "Country: %s (%s)") % (data["country_name"],data["country_code"])
print(code_result + "Location: %s") % data["location"]
print(code_result + "Carrier: %s") % data["carrier"]
print(code_result + "Line type: %s") % data["line_type"]
print((code_result +
"Number: ({}) {}").format(data["country_prefix"], data["local_format"]))
print((code_result +
"Country: {} ({})").format(data["country_name"], data["country_code"]))
print((code_result + "Location: {}").format(data["location"]))
print((code_result + "Carrier: {}").format(data["carrier"]))
print((code_result + "Line type: {}").format(data["line_type"]))
if data["line_type"] == 'landline':
print(code_warning + "This is most likely a land line, but it can still be a fixed VoIP.")
print((code_warning + "This is most likely a landline, but it can still be a fixed VoIP number."))
elif data["line_type"] == 'mobile':
print(code_warning + "This is most likely a mobile, but it can still be a VoIP.")
print((code_warning + "This is most likely a mobile number, but it can still be a VoIP number."))
def ovhScan():
global localNumber
@ -261,30 +309,49 @@ def ovhScan():
if not args.scanner == 'ovh' and not args.scanner == 'all':
return -1
print code_info + 'Running OVH scan...'
print(code_info + 'Running OVH scan...')
querystring = { "country": numberCountry.lower() }
querystring = {"country": numberCountry.lower()}
headers = {
'accept': "application/json",
'cache-control': "no-cache"
}
response = requests.request("GET", "https://api.ovh.com/1.0/telephony/number/detailedZones", data="", headers=headers, params=querystring)
data = json.loads(response.content)
try:
response = requests.request(
"GET", "https://api.ovh.com/1.0/telephony/number/detailedZones", data="", headers=headers, params=querystring)
data = json.loads(response.content.decode('utf-8'))
except Exception as e:
print(code_error + 'OVH API is unreachable. Maybe retry later.')
return -1
if isinstance(data, list):
askedNumber = "0" + localNumber.replace(localNumber[-4:], 'xxxx')
for voip_number in data:
if voip_number['number'] == askedNumber:
print(code_info + "1 result found in OVH database")
print(code_result + "Number range: " + voip_number['number'])
print(code_result + "City: " + voip_number['city'])
print(code_result + "Zip code: " + voip_number['zipCode'] if voip_number['zipCode'] is not None else '')
print((code_info + "1 result found in OVH database"))
print(
(code_result + "Number range: {}".format(voip_number['number'])))
print((code_result + "City: {}".format(voip_number['city'])))
print((code_result + "Zip code: {}".format(
voip_number['zipCode'] if voip_number['zipCode'] is not None else '')))
askForExit()
def replaceVariables(string):
global number
global internationalNumber
global localNumber
string = string.replace('$n', number)
string = string.replace('$i', internationalNumber)
string = string.replace('$l', localNumber)
return string
def osintIndividualScan():
global number
global internationalNumber
@ -296,17 +363,20 @@ def osintIndividualScan():
for dork in dorks:
if dork['dialCode'] is None or dork['dialCode'] == numberCountryCode:
if customFormatting:
dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + ' | intext:"%s"' % (customFormatting)
dorkRequest = replaceVariables(
dork['request']) + ' | intext:"{}"'.format(customFormatting)
else:
dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber)
dorkRequest = replaceVariables(dork['request'])
print(
(code_info + "Searching for footprints on {}...".format(dork['site'])))
print(code_info + "Searching for footprints on %s..." % dork['site'])
for result in search(dorkRequest, stop=dork['stop']):
if result:
print(code_result + "URL: " + result)
print((code_result + "URL: " + result))
else:
return -1
def osintReputationScan():
global number
global internationalNumber
@ -316,14 +386,15 @@ def osintReputationScan():
for dork in dorks:
if customFormatting:
dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + ' | intext:"%s"' % (customFormatting)
dorkRequest = replaceVariables(
dork['request']) + ' | intext:"{}"'.format(customFormatting)
else:
dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber)
dorkRequest = replaceVariables(dork['request'])
print(code_info + "Searching for %s..." % dork['title'])
print((code_info + "Searching for {}...".format(dork['title'])))
for result in search(dorkRequest, stop=dork['stop']):
if result:
print(code_result + "URL: " + result)
print((code_result + "URL: " + result))
def osintSocialMediaScan():
global number
@ -334,14 +405,17 @@ def osintSocialMediaScan():
for dork in dorks:
if customFormatting:
dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber) + ' | intext:"%s"' % (customFormatting)
dorkRequest = replaceVariables(
dork['request']) + ' | intext:"{}"'.format(customFormatting)
else:
dorkRequest = dork['request'].replace('$n', number).replace('$i', internationalNumber)
dorkRequest = replaceVariables(dork['request'])
print(
(code_info + "Searching for footprints on {}...".format(dork['site'])))
print(code_info + "Searching for footprints on %s..." % dork['site'])
for result in search(dorkRequest, stop=dork['stop']):
if result:
print(code_result + "URL: " + result)
print((code_result + "URL: " + result))
def osintDisposableNumScan():
global number
@ -349,149 +423,245 @@ def osintDisposableNumScan():
dorks = json.load(open('osint/disposable_num_providers.json'))
for dork in dorks:
dorkRequest = dork['request'].replace('$n', number)
dorkRequest = replaceVariables(dork['request'])
print(
(code_info + "Searching for footprints on {}...".format(dork['site'])))
print(code_info + "Searching for footprints on %s..." % dork['site'])
for result in search(dorkRequest, stop=dork['stop']):
if result:
print(code_result + "Result found: %s" % dork['site'])
print(code_result + "URL: " + result)
askForExit()
print((code_result + "Result found: {}".format(dork['site'])))
print((code_result + "URL: " + result))
askForExit()
def osintScan():
def osintScan(rerun=False):
global number
global localNumber
global internationalNumber
global numberCountryCode
global numberCountry
global customFormatting
if not args.osint:
return -1
print code_info + 'Running OSINT footprint reconnaissance...'
print(code_info + 'Running OSINT footprint reconnaissance...')
# Whitepages
print(code_info + "Generating scan URL on 411.com...")
print code_result + "Scan URL: https://www.411.com/phone/%s" % internationalNumber.replace('+', '').replace(' ', '-')
if not rerun:
# Whitepages
print((code_info + "Generating scan URL on 411.com..."))
print(code_result + "Scan URL: https://www.411.com/phone/{}".format(
internationalNumber.replace('+', '').replace(' ', '-')))
askingCustomPayload = raw_input(code_info + 'Would you like to use an additional format for this number ? (y/N) ')
askingCustomPayload = input(
code_info + 'Would you like to use an additional format for this number ? (y/N) ')
if askingCustomPayload == 'y' or askingCustomPayload == 'yes':
customFormatting = raw_input(code_info + 'Custom format: ')
if rerun or askingCustomPayload == 'y' or askingCustomPayload == 'yes':
customFormatting = input(code_info + 'Custom format: ')
print(code_info + '---- Web pages footprints ----')
print((code_info + '---- Web pages footprints ----'))
print(code_info + "Searching for footprints on web pages... (limit=5)")
print((code_info + "Searching for footprints on web pages... (limit=10)"))
if customFormatting:
req = '%s | intext:"%s" | intext:"%s" | intext:"%s"' % (number,number,internationalNumber,customFormatting)
req = '{} | intext:"{}" | intext:"{}" | intext:"{}"'.format(
number, number, internationalNumber, customFormatting)
else:
req = '%s | intext:"%s" | intext:"%s"' % (number,number,internationalNumber)
for result in search(req, stop=5):
if result:
print(code_result + "Result found: " + result)
req = '{} | intext:"{}" | intext:"{}"'.format(
number, number, internationalNumber)
for result in search(req, stop=10):
print((code_result + "Result found: " + result))
# Documents
print(code_info + "Searching for documents... (limit=10)")
print((code_info + "Searching for documents... (limit=10)"))
if customFormatting:
req = 'intext:"%s" | intext:"%s" | intext:"%s" ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt' % (number,internationalNumber,customFormatting)
req = '[ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt | ext:xls] && [intext:"{}"]'.format(
customFormatting)
else:
req = 'intext:"%s" | intext:"%s" ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt' % (number,internationalNumber)
for result in search('intext:"%s" | intext:"%s" ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt' % (number,internationalNumber), stop=10):
if result:
print(code_result + "Result found: " + result)
req = '[ext:doc | ext:docx | ext:odt | ext:pdf | ext:rtf | ext:sxw | ext:psw | ext:ppt | ext:pptx | ext:pps | ext:csv | ext:txt | ext:xls] && [intext:"{}" | intext:"{}"]'.format(
internationalNumber, localNumber)
for result in search(req, stop=10):
print((code_result + "Result found: " + result))
print(code_info + '---- Reputation footprints ----')
print((code_info + '---- Reputation footprints ----'))
osintReputationScan()
print(code_info + "Generating URL on scamcallfighters.com...")
print code_result + 'http://www.scamcallfighters.com/search-phone-%s.html' % number
print((code_info + "Generating URL on scamcallfighters.com..."))
print(code_result +
'http://www.scamcallfighters.com/search-phone-{}.html'.format(number))
tmpNumAsk = raw_input(code_info + "Would you like to search for temporary number providers footprints ? (Y/n) ")
tmpNumAsk = input(
code_info + "Would you like to search for temporary number providers footprints ? (Y/n) ")
if tmpNumAsk.lower() != 'n' and tmpNumAsk.lower() != 'no':
print(code_info + '---- Temporary number providers footprints ----')
print((code_info + '---- Temporary number providers footprints ----'))
print(code_info + "Searching for phone number on tempophone.com...")
response = requests.request("GET", "https://tempophone.com/api/v1/phones")
data = json.loads(response.content)
for voip_number in data['objects']:
if voip_number['phone'] == formatNumber(number):
print(code_result + "Found a temporary number provider: tempophone.com")
askForExit()
try:
print((code_info + "Searching for phone number on tempophone.com..."))
response = requests.request(
"GET", "https://tempophone.com/api/v1/phones")
data = json.loads(response.content.decode('utf-8'))
for voip_number in data['objects']:
if voip_number['phone'] == formatNumber(number):
print(
(code_result + "Found a temporary number provider: tempophone.com"))
askForExit()
except Exception as e:
print((code_error + "Unable to reach tempophone.com API. Skipping."))
osintDisposableNumScan()
print(code_info + '---- Social media footprints ----')
print((code_info + '---- Social media footprints ----'))
osintSocialMediaScan()
print(code_info + '---- Phone books footprints ----')
print((code_info + '---- Phone books footprints ----'))
if numberCountryCode == '+1':
print(code_info + "Generating URL on True People... ")
print code_result + 'https://www.truepeoplesearch.com/results?phoneno=%s' % internationalNumber.replace(' ', '')
print((code_info + "Generating URL on True People... "))
print(code_result + 'https://www.truepeoplesearch.com/results?phoneno={}'.format(
internationalNumber.replace(' ', '')))
osintIndividualScan()
retry_input = input(
code_info + "Would you like to rerun OSINT scan ? (e.g to use a different format) (y/N) ")
if retry_input.lower() == 'y' or retry_input.lower() == 'yes':
osintScan(True)
else:
return -1
def askForExit():
if not args.output:
user_input = raw_input(code_info + "Continue scanning ? (y/N) ")
user_input = input(code_info + "Continue scanning ? (y/N) ")
if user_input.lower() == 'y' or user_input.lower() == 'yes':
return -1
else:
print code_info + "Good bye!"
print(code_info + "Good bye!")
sys.exit()
def scanNumber(InputNumber):
print code_title + "[!] ---- Fetching informations for %s ---- [!]" % formatNumber(InputNumber)
localScan(InputNumber)
global number
global localNumber
global internationalNumber
global numberCountryCode
global numberCountry
print(code_title +
"[!] ---- Fetching informations for {} ---- [!]".format(formatNumber(InputNumber)))
localScan(InputNumber)
if not number:
print(code_error + "Error: number " + formatNumber(InputNumber) + " is not valid. Skipping.")
print((code_error + "Error: number {} is not valid. Skipping.".format(formatNumber(InputNumber))))
sys.exit()
numverifyScan()
ovhScan()
osintScan()
print code_info + "Scan finished."
print(code_info + "Scan finished.")
print '\n'
if not args.no_ansi and not args.output:
print('\n' + Style.RESET_ALL)
else:
print('\n')
def download_file(url, target_path):
response = requests.get(url, stream=True)
handle = open(target_path, "wb")
for chunk in response.iter_content(chunk_size=512):
if chunk: # filter out keep-alive new chunks
handle.write(chunk)
def updateTool():
print('Updating PhoneInfoga...')
print('Actual version: {}'.format(__version__))
# Fetching last github tag
new_version = json.loads(requests.get(
'https://api.github.com/repos/sundowndev/PhoneInfoga/tags').content)[0]['name']
print('Last version: {}'.format(new_version))
osintFiles = [
'disposable_num_providers.json',
'individuals.json',
'reputation.json',
'social_medias.json'
]
try:
print('[*] Updating OSINT files')
for file in osintFiles:
url = 'https://raw.githubusercontent.com/sundowndev/PhoneInfoga/master/osint/{}'.format(
file)
output_directory = 'osint/{}'.format(file)
download_file(url, output_directory)
print('[*] Updating python script')
url = 'https://raw.githubusercontent.com/sundowndev/PhoneInfoga/master/phoneinfoga.py'
output_directory = 'phoneinfoga.py'
download_file(url, output_directory)
except Exception as e:
print('Update failed. Try using git pull.')
sys.exit()
print('The tool was successfully updated.')
sys.exit()
def main():
scanners = ['any', 'all', 'numverify', 'ovh']
banner()
if sys.version_info[0] < 3:
print(
"\033[1m\033[93m(!) Please run the tool using Python 3" + Style.RESET_ALL)
sys.exit()
# Reset text color at exit
atexit.register(resetColors)
# If any param is passed, execute help command
if not len(sys.argv) > 1:
parser.print_help()
sys.exit()
elif args.version:
print("Version {}".format(__version__))
sys.exit()
requests.packages.urllib3.disable_warnings()
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += 'HIGH:!DH:!aNULL'
try:
requests.packages.urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST += 'HIGH:!DH:!aNULL'
except AttributeError:
# no pyopenssl support used / needed / available
pass
if args.update:
updateTool()
try:
if args.output:
code_info = '[*] '
code_warning = '(!) '
code_result = '[+] '
code_error = '[!] '
code_title = ''
if args.osint:
print '\033[91m[!] OSINT scanner is not available using output option (sorry).'
print(
'\033[91m[!] OSINT scanner is not available using output option (sorry).')
sys.exit()
sys.stdout = args.output
banner()
else:
code_info = '\033[97m[*] '
code_warning = '\033[93m(!) '
code_result = '\033[1;32m[+] '
code_error = '\033[91m[!] '
code_title = '\033[1m\033[93m'
banner() # Output banner again in the file
# Verify scanner option
if not args.scanner in scanners:
print(code_error + "Error: scanner doesn't exists.")
print((code_error + "Error: scanner doesn't exists."))
sys.exit()
if args.number:
@ -499,9 +669,19 @@ try:
elif args.input:
for line in args.input.readlines():
scanNumber(line)
else:
parser.print_help()
sys.exit()
if args.output:
args.output.close()
except KeyboardInterrupt:
print(code_error + "Scan interrupted. Good bye!")
def signal_handler(signal, frame):
print('\n[-] You pressed Ctrl+C! Exiting.')
sys.exit()
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal_handler)
main()

View File

@ -2,3 +2,6 @@ requests
bs4
html5lib
phonenumbers
argparse
urllib3
colorama