Compare commits
143 Commits
Author | SHA1 | Date |
---|---|---|
|
dab7d35e02 | |
|
cb823066b4 | |
|
1c2ec491b5 | |
|
aaaf9304bd | |
|
937b3abe4f | |
|
3a63bd036d | |
|
2e17453143 | |
|
be44f64d58 | |
|
719135c4c3 | |
|
e02b4edaeb | |
|
f020a1ec85 | |
|
dc6c226252 | |
|
303c583201 | |
|
8bac8eb377 | |
|
c553ca1e85 | |
|
22c8bcfccb | |
|
384370eaa1 | |
|
1ca83be4da | |
|
1d69e2708d | |
|
006fd8bd91 | |
|
ec85cdbd23 | |
|
ec2ff93a87 | |
|
e1b10a5d50 | |
|
e1559004fb | |
|
a5bf2d4918 | |
|
e3b4778cd4 | |
|
6309f6f960 | |
|
85ba7478d9 | |
|
ea78993e47 | |
|
c1efb3650d | |
|
9116d5654b | |
|
942d7f8edc | |
|
807c2a1a6d | |
|
6fe97094eb | |
|
2b119cc913 | |
|
5ced4f7aec | |
|
e108c1e36c | |
|
9872168db6 | |
|
4e2869cba7 | |
|
2a6ecf15dd | |
|
00cc280c40 | |
|
ff06854856 | |
|
c505ef1be8 | |
|
4fdab3bf34 | |
|
3cfb11355f | |
|
0eec71535b | |
|
f09c96f826 | |
|
8e1cae6b9c | |
|
27b39208b0 | |
|
bdc0bf8b23 | |
|
922186ca79 | |
|
170a94b702 | |
|
f0b54fbef4 | |
|
17c11ec794 | |
|
58f35cb634 | |
|
c9a8441f36 | |
|
74904549a9 | |
|
ac3eff13de | |
|
11b47c0562 | |
|
a8a3015f12 | |
|
f2dd168491 | |
|
96406c4e23 | |
|
7eadfa502b | |
|
31eb7425c6 | |
|
51f76150e4 | |
|
347d0e87bf | |
|
ea3e0a0024 | |
|
45875a1d62 | |
|
e9b42d078c | |
|
89baab6f87 | |
|
bcf11a938b | |
|
6cce114a7a | |
|
59ac083ccd | |
|
fd999a1d05 | |
|
eb7ba13ee9 | |
|
dee05839ec | |
|
ed79a4f23f | |
|
01f60ef4bf | |
|
120e190c29 | |
|
7a14c7c5bd | |
|
ec227c0782 | |
|
4e5994347c | |
|
b51d475695 | |
|
76eb594566 | |
|
89e1b2b7f1 | |
|
c7029aca68 | |
|
79c89e2dd7 | |
|
268787dce8 | |
|
30226cc436 | |
|
92d1683a86 | |
|
c53d514cfc | |
|
feddcbed9b | |
|
692480457f | |
|
47ceb86dd5 | |
|
21ebdf881f | |
|
1f8cdb6cf4 | |
|
d911cd9b7e | |
|
20495f1024 | |
|
d50ed5d576 | |
|
68fa969b39 | |
|
aa0485ba9d | |
|
f03061dd00 | |
|
3964c4a504 | |
|
aa155692cc | |
|
93462b5ed4 | |
|
14f9cce67c | |
|
de64c10be8 | |
|
1a8197f295 | |
|
faffddbd8a | |
|
1b456e3695 | |
|
7a02a9f101 | |
|
e6d64a1336 | |
|
97ef5579a8 | |
|
69af4036a4 | |
|
5a8a76e44a | |
|
cff4e8f227 | |
|
11b41963c2 | |
|
bcb4c398b1 | |
|
31dd315c18 | |
|
358fa08996 | |
|
588d02d739 | |
|
63b6987d68 | |
|
851005603a | |
|
37684992ba | |
|
f493009dce | |
|
28186896b8 | |
|
55db8b7b6a | |
|
5105f1772d | |
|
a0d41b9650 | |
|
8d1c269b2c | |
|
c5f4205e34 | |
|
ff3ae39e14 | |
|
d7cc63a025 | |
|
be14c51803 | |
|
cbacbcaa46 | |
|
9dc719804f | |
|
34f4a81e96 | |
|
4adb27213f | |
|
b7929a45c2 | |
|
6379c53266 | |
|
3bc1bf6ea3 | |
|
0f61fc3388 | |
|
0e768cdf3b |
|
@ -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:
|
|
@ -0,0 +1,7 @@
|
|||
language: python
|
||||
python:
|
||||
- "3.6"
|
||||
- "3.7-dev"
|
||||
install:
|
||||
- pip install -r requirements.txt
|
||||
script: bash ./examples/generate.sh
|
146
README.md
146
README.md
|
@ -1,54 +1,62 @@
|
|||
# PhoneInfoga
|
||||
<h1 align="center">PhoneInfoga</h1>
|
||||
|
||||
Advanced information gathering & OSINT reconnaissance tool for phone numbers. Designed for Social Engineering and red teaming.
|
||||
<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>
|
||||
|
||||
### Hello, friend. Next time cover your tracks.
|
||||
<h4 align="center">Information gathering & OSINT reconnaissance tool for phone numbers</h4>
|
||||
|
||||
<img src="https://images.complex.com/complex/images/c_limit,w_680/f_auto,fl_lossy,pg_1,q_auto/robotophone_egpp8m/mr-robot-elliot-on-phone" width="350" />
|
||||
<div align="center">
|
||||
<sub>For the love of open source investigations. Built with ❤︎ by
|
||||
<a href="https://twitter.com/sundowndev">@sundowndev</a>
|
||||
</div>
|
||||
|
||||
## The project
|
||||
<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>
|
||||
|
||||
Building the most advanced tool to scan phone numbers using only free resources. The goal is to first identify basic informations such as country, area, carrier and line type on any international phone numbers with a very good accuracy, and then detect the VoIP provider or search for footprints on search engines to try identify the owner.
|
||||
## About
|
||||
|
||||
**This tool requires python 2.x**
|
||||
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
|
||||
|
||||
- Check if phone number exists
|
||||
- Check if phone number exists and is possible
|
||||
- Gather standard informations such as country, line type and carrier
|
||||
- Check several numbers at once
|
||||
- Set an output for result(s)
|
||||
- Check if number is from a VoIP provider
|
||||
- OSINT reconnaissance using external APIs, Google Hacking, phone books & search engines
|
||||
- Use custom formatting for more effective OSINT reconnaissance
|
||||
|
||||

|
||||
|
||||
## Formats
|
||||
|
||||
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]
|
||||
|
||||
|
@ -70,92 +78,8 @@ optional arguments:
|
|||
-u, --update Update the tool & databases
|
||||
```
|
||||
|
||||
Example :
|
||||
|
||||
```
|
||||
python phoneinfoga.py -n +42837544833
|
||||
```
|
||||
|
||||
Check several numbers at once :
|
||||
|
||||
```
|
||||
python ./phoneinfoga.py -i numbers.txt -o results.txt
|
||||
```
|
||||
|
||||
Check for a number range on OVH (just put some zeros) :
|
||||
|
||||
```
|
||||
python phoneinfoga.py -n +42837544833 -s ovh
|
||||
```
|
||||
|
||||
## 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, here’s a US-based number in standard local formatting: (415) 555-2671
|
||||
|
||||

|
||||
|
||||
Here’s the same phone number in E.164 formatting: +14155552671
|
||||
|
||||

|
||||
|
||||
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, here’s a UK-based number in standard local formatting: 020 7183 8750
|
||||
|
||||

|
||||
|
||||
Here’s the same phone number in E.164 formatting: +442071838750
|
||||
|
||||

|
||||
|
||||
## License
|
||||
|
||||
This tool is licensed under the GNU General Public License v3.0.
|
||||
|
||||
## Resources
|
||||
|
||||
Regular expression : `^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\./0-9]*$`
|
||||
|
||||
### Docs
|
||||
|
||||
- http://whitepages.fr/phonesystem/
|
||||
- https://support.twilio.com/hc/en-us/articles/223183008-Formatting-International-Phone-Numbers
|
||||
- https://en.wikipedia.org/wiki/National_conventions_for_writing_telephone_numbers
|
||||
|
||||
### open data
|
||||
|
||||
- https://api.ovh.com/console/#/telephony
|
||||
- `/telephony/number/ranges`
|
||||
- `/telephony/number/detailedZones`
|
||||
- `/telephony/number/specificNumbers`
|
||||
- https://countrycode.org/
|
||||
- http://www.countryareacode.net/en/
|
||||
- http://directory.didww.com/area-prefixes
|
||||
- http://hs3x.com/
|
||||
|
||||
### Scanners
|
||||
|
||||
- https://www.phonevalidator.com/
|
||||
- https://freecarrierlookup.com/
|
||||
- https://www.411.com/
|
||||
- https://www.washington.edu/home/peopledir/
|
||||
|
||||
### OSINT
|
||||
|
||||
- https://osintframework.com/
|
||||
- http://raidersec.blogspot.com/2012/12/automated-open-source-intelligence.html#google_api
|
||||
|
||||
#### Google dork requests
|
||||
|
||||
- `insubject:"+XXXXXXXXX" | insubject:"+XXXXX" | insubject:"XXXXX XXX XXX`
|
||||
- `insubject:"{number}" | intitle:"{number}"`
|
||||
- `intext:"{number}" 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:html`
|
||||
- voip provider check: `site:"hs3x.com" intext:"+61437954897"`
|
||||
- scam number check:`site:signal-arnaques.com intext:"0682649478" intitle:" | Phone Fraud"`
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fsundowndev%2FPhoneInfoga?ref=badge_large)
|
||||
|
|
1647
data/area_codes.json
1647
data/area_codes.json
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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."
|
|
@ -1,6 +1,6 @@
|
|||
+856 20 99 453 217
|
||||
+59172768361
|
||||
+33679368233
|
||||
+32474123456
|
||||
+1 (541) 754-3010
|
||||
+86 591 2284 8571
|
||||
+7 496 4819375
|
|
@ -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.
|
||||
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
[
|
||||
{
|
||||
"site": "hs3x.com",
|
||||
"request": "site:\"hs3x.com\" intext:\"+$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "receive-sms-now.com",
|
||||
"request": "site:\"receive-sms-now.com\" intext:\"$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "smslisten.com",
|
||||
"request": "site:\"smslisten.com\" intext:\"$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "smsnumbersonline.com",
|
||||
"request": "site:\"smsnumbersonline.com\" intext:\"+$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "freesmscode.com",
|
||||
"request": "site:\"freesmscode.com\" intext:\"+$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "catchsms.com",
|
||||
"request": "site:\"catchsms.com\" intext:\"+$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "smstibo.com",
|
||||
"request": "site:\"smstibo.com\" intext:\"+$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "smsreceiving.com",
|
||||
"request": "site:\"smsreceiving.com\" intext:\"+$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "getfreesmsnumber.com",
|
||||
"request": "site:\"getfreesmsnumber.com\" intext:\"+$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "sellaite.com",
|
||||
"request": "site:\"sellaite.com\" intext:\"+$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "receive-sms-online.info",
|
||||
"request": "site:\"receive-sms-online.info\" intext:\"+$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "receivesmsonline.com",
|
||||
"request": "site:\"receivesmsonline.com\" intext:\"+$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "receive-a-sms.com",
|
||||
"request": "site:\"receive-a-sms.com\" intext:\"+$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "sms-receive.net",
|
||||
"request": "site:\"sms-receive.net\" intext:\"+$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "receivefreesms.com",
|
||||
"request": "site:\"receivefreesms.com\" intext:\"+$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "receive-sms.com",
|
||||
"request": "site:\"receive-sms.com\" intext:\"+$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "receivetxt.com",
|
||||
"request": "site:\"receivetxt.com\" $n",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "freephonenum.com",
|
||||
"request": "site:\"freephonenum.com\" intext:\"$n\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "freesmsverification.com",
|
||||
"request": "site:\"freesmsverification.com\" $n",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"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
|
||||
}
|
||||
]
|
|
@ -0,0 +1,38 @@
|
|||
[
|
||||
{
|
||||
"site": "numinfo.net",
|
||||
"request": "site:\"numinfo.net\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
|
||||
"dialCode": null,
|
||||
"stop": 2
|
||||
},
|
||||
{
|
||||
"site": "sync.me",
|
||||
"request": "site:\"sync.me\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
|
||||
"dialCode": null,
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"site": "whocallsyou.de",
|
||||
"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
|
||||
}
|
||||
]
|
|
@ -0,0 +1,17 @@
|
|||
[
|
||||
{
|
||||
"title": "reputation report on whosenumber.info",
|
||||
"request": "site:whosenumber.info intext:\"$n\" intitle:\"who called\"",
|
||||
"stop": 1
|
||||
},
|
||||
{
|
||||
"title": "phone fraud footprints",
|
||||
"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
|
||||
}
|
||||
]
|
|
@ -0,0 +1,22 @@
|
|||
[
|
||||
{
|
||||
"site": "facebook.com",
|
||||
"request": "site:\"facebook.com\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
|
||||
"stop": 5
|
||||
},
|
||||
{
|
||||
"site": "twitter.com",
|
||||
"request": "site:\"twitter.com\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
|
||||
"stop": 5
|
||||
},
|
||||
{
|
||||
"site": "linkedin.com",
|
||||
"request": "site:\"linkedin.com\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
|
||||
"stop": 5
|
||||
},
|
||||
{
|
||||
"site": "instagram.com",
|
||||
"request": "site:\"instagram.com\" intext:\"$i\" | intext:\"$n\" | intext:\"$l\"",
|
||||
"stop": 5
|
||||
}
|
||||
]
|
745
phoneinfoga.py
745
phoneinfoga.py
|
@ -1,26 +1,32 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
__version__ = '0.6-dev'
|
||||
__version__ = 'v1.0.2'
|
||||
|
||||
def banner():
|
||||
print " ___ _ _____ __ "
|
||||
print " / _ \ |__ ___ _ __ ___ \_ \_ __ / _| ___ __ _ __ _ "
|
||||
print " / /_)/ '_ \ / _ \| '_ \ / _ \ / /\/ '_ \| |_ / _ \ / _` |/ _` |"
|
||||
print " / ___/| | | | (_) | | | | __/\/ /_ | | | | _| (_) | (_| | (_| |"
|
||||
print " \/ |_| |_|\___/|_| |_|\___\____/ |_| |_|_| \___/ \__, |\__,_|"
|
||||
print " |___/ "
|
||||
print " PhoneInfoga Ver. %s " % __version__
|
||||
print " Coded by Sundowndev "
|
||||
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()
|
||||
print "\033[94m\n"
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
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,
|
||||
|
@ -39,230 +45,643 @@ 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()
|
||||
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
|
||||
|
||||
import requests
|
||||
import hashlib
|
||||
import json
|
||||
from bs4 import BeautifulSoup
|
||||
import re
|
||||
import phonenumbers
|
||||
from phonenumbers import carrier
|
||||
from phonenumbers import geocoder
|
||||
from phonenumbers import timezone
|
||||
googleAbuseToken = ''
|
||||
customFormatting = ''
|
||||
|
||||
scanners = ['any', 'all', 'numverify', 'ovh']
|
||||
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 formatNumber(number):
|
||||
return re.sub("(?:\+)?(?:[^[0-9]*)", "", number)
|
||||
|
||||
def localScan(number):
|
||||
print code_info + 'Running local scan...'
|
||||
def banner():
|
||||
print(" ___ _ _____ __ ")
|
||||
print(" / _ \ |__ ___ _ __ ___ \_ \_ __ / _| ___ __ _ __ _ ")
|
||||
print(" / /_)/ '_ \ / _ \| '_ \ / _ \ / /\/ '_ \| |_ / _ \ / _` |/ _` |")
|
||||
print(" / ___/| | | | (_) | | | | __/\/ /_ | | | | _| (_) | (_| | (_| |")
|
||||
print(" \/ |_| |_|\___/|_| |_|\___\____/ |_| |_|_| \___/ \__, |\__,_|")
|
||||
print(" |___/ ")
|
||||
print(" PhoneInfoga Ver. {}".format(__version__))
|
||||
print(" Coded by Sundowndev")
|
||||
print("\n")
|
||||
|
||||
PhoneNumber = dict();
|
||||
|
||||
FormattedPhoneNumber = "+" + formatNumber(number)
|
||||
def resetColors():
|
||||
if not args.output:
|
||||
print(Style.RESET_ALL)
|
||||
|
||||
|
||||
def search(req, stop):
|
||||
global googleAbuseToken
|
||||
global uagent
|
||||
|
||||
chosenUserAgent = random.choice(uagent)
|
||||
|
||||
reqSession = requests.Session()
|
||||
headers = {
|
||||
'User-Agent': chosenUserAgent,
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'Accept-Language': 'en-us,en;q=0.5',
|
||||
'Accept-Encoding': 'gzip,deflate',
|
||||
'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:
|
||||
REQ = urlencode({'q': req})
|
||||
URL = 'https://www.google.com/search?tbs=li:1&{}&gws_rd=ssl&gl=us '.format(
|
||||
REQ)
|
||||
r = reqSession.get(URL + googleAbuseToken, headers=headers)
|
||||
|
||||
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 = reqSession.get(URL + googleAbuseToken, headers=headers)
|
||||
|
||||
soup = BeautifulSoup(r.text, 'html5lib')
|
||||
|
||||
results = soup.find("div", id="search").find_all("div", class_="g")
|
||||
|
||||
links = []
|
||||
counter = 0
|
||||
|
||||
for result in results:
|
||||
counter += 1
|
||||
|
||||
if int(counter) > int(stop):
|
||||
break
|
||||
|
||||
url = result.find("a").get('href')
|
||||
url = re.sub(r'(?:\/url\?q\=)', '', url)
|
||||
url = re.sub(r'(?:\/url\?url\=)', '', url)
|
||||
url = re.sub(r'(?:\&sa\=)(?:.*)', '', url)
|
||||
url = re.sub(r'(?:\&rct\=)(?:.*)', '', url)
|
||||
|
||||
if re.match(r"^(?:\/search\?q\=)", url) is not None:
|
||||
url = 'https://google.com' + url
|
||||
|
||||
if url is not None:
|
||||
links.append(url)
|
||||
|
||||
return links
|
||||
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
|
||||
global internationalNumber
|
||||
global numberCountryCode
|
||||
global numberCountry
|
||||
|
||||
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
|
||||
|
||||
PhoneNumber['full'] = phonenumbers.format_number(PhoneNumberObject, phonenumbers.PhoneNumberFormat.E164).replace('+', '')
|
||||
PhoneNumber['countryCode'] = phonenumbers.format_number(PhoneNumberObject, phonenumbers.PhoneNumberFormat.INTERNATIONAL).split(' ')[0]
|
||||
PhoneNumber['number'] = phonenumbers.format_number(PhoneNumberObject, phonenumbers.PhoneNumberFormat.E164).replace(PhoneNumber['countryCode'], '')
|
||||
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))
|
||||
|
||||
print code_result + 'Local format: (0)' + PhoneNumber['number']
|
||||
print code_result + 'Country code: ' + PhoneNumber['countryCode']
|
||||
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 '\033[1;32m[+] Timezone: %s, %s' % (timezone.time_zones_for_number(PhoneNumberObject)[0],timezone.time_zones_for_number(PhoneNumberObject)[1])
|
||||
localNumber = phonenumbers.format_number(
|
||||
PhoneNumberObject, phonenumbers.PhoneNumberFormat.E164).replace(numberCountryCode, '0')
|
||||
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: {}'.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: {}'.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.')
|
||||
|
||||
return PhoneNumber
|
||||
|
||||
def numverifyScan(PhoneNumber):
|
||||
def numverifyScan():
|
||||
global number
|
||||
|
||||
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(PhoneNumber + 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, text/javascript, */*; q=0.01",
|
||||
'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=" + PhoneNumber, 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)
|
||||
|
||||
data = json.loads(response.content.decode('utf-8'))
|
||||
except Exception as e:
|
||||
print(code_error + 'Numverify.com is not available')
|
||||
return -1
|
||||
|
||||
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).")
|
||||
sys.exit()
|
||||
|
||||
data = json.loads(response.content)
|
||||
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, or 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, or a VoIP.")
|
||||
print((code_warning + "This is most likely a mobile number, but it can still be a VoIP number."))
|
||||
|
||||
|
||||
def ovhScan():
|
||||
global localNumber
|
||||
global numberCountry
|
||||
|
||||
def ovhScan(countryCode, number):
|
||||
if not args.scanner == 'ovh' and not args.scanner == 'all':
|
||||
return -1
|
||||
|
||||
print code_info + 'Running OVH scan...'
|
||||
print(code_info + 'Running OVH scan...')
|
||||
|
||||
#cc
|
||||
|
||||
querystring = {"country":"fr"}
|
||||
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" + number.replace(number[-4:], 'xxxx')
|
||||
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
|
||||
global numberCountryCode
|
||||
global customFormatting
|
||||
|
||||
dorks = json.load(open('osint/individuals.json'))
|
||||
|
||||
for dork in dorks:
|
||||
if dork['dialCode'] is None or dork['dialCode'] == numberCountryCode:
|
||||
if customFormatting:
|
||||
dorkRequest = replaceVariables(
|
||||
dork['request']) + ' | intext:"{}"'.format(customFormatting)
|
||||
else:
|
||||
dorkRequest = replaceVariables(dork['request'])
|
||||
|
||||
print(
|
||||
(code_info + "Searching for footprints on {}...".format(dork['site'])))
|
||||
|
||||
for result in search(dorkRequest, stop=dork['stop']):
|
||||
print((code_result + "URL: " + result))
|
||||
else:
|
||||
return -1
|
||||
|
||||
|
||||
def osintReputationScan():
|
||||
global number
|
||||
global internationalNumber
|
||||
global customFormatting
|
||||
|
||||
dorks = json.load(open('osint/reputation.json'))
|
||||
|
||||
for dork in dorks:
|
||||
if customFormatting:
|
||||
dorkRequest = replaceVariables(
|
||||
dork['request']) + ' | intext:"{}"'.format(customFormatting)
|
||||
else:
|
||||
dorkRequest = replaceVariables(dork['request'])
|
||||
|
||||
print((code_info + "Searching for {}...".format(dork['title'])))
|
||||
for result in search(dorkRequest, stop=dork['stop']):
|
||||
print((code_result + "URL: " + result))
|
||||
|
||||
|
||||
def osintSocialMediaScan():
|
||||
global number
|
||||
global internationalNumber
|
||||
global customFormatting
|
||||
|
||||
dorks = json.load(open('osint/social_medias.json'))
|
||||
|
||||
for dork in dorks:
|
||||
if customFormatting:
|
||||
dorkRequest = replaceVariables(
|
||||
dork['request']) + ' | intext:"{}"'.format(customFormatting)
|
||||
else:
|
||||
dorkRequest = replaceVariables(dork['request'])
|
||||
|
||||
print(
|
||||
(code_info + "Searching for footprints on {}...".format(dork['site'])))
|
||||
|
||||
for result in search(dorkRequest, stop=dork['stop']):
|
||||
print((code_result + "URL: " + result))
|
||||
|
||||
|
||||
def osintDisposableNumScan():
|
||||
global number
|
||||
|
||||
dorks = json.load(open('osint/disposable_num_providers.json'))
|
||||
|
||||
for dork in dorks:
|
||||
dorkRequest = replaceVariables(dork['request'])
|
||||
|
||||
print(
|
||||
(code_info + "Searching for footprints on {}...".format(dork['site'])))
|
||||
|
||||
for result in search(dorkRequest, stop=dork['stop']):
|
||||
print((code_result + "Result found: {}".format(dork['site'])))
|
||||
print((code_result + "URL: " + result))
|
||||
askForExit()
|
||||
|
||||
|
||||
def osintScan(rerun=False):
|
||||
global number
|
||||
global localNumber
|
||||
global internationalNumber
|
||||
global numberCountryCode
|
||||
global customFormatting
|
||||
|
||||
def osintScan(countryCode, number):
|
||||
if not args.osint:
|
||||
return -1
|
||||
|
||||
import urllib
|
||||
from googlesearch import search
|
||||
print(code_info + 'Running OSINT footprint reconnaissance...')
|
||||
|
||||
print code_info + 'Running OSINT reconnaissance...'
|
||||
# OSINT recon
|
||||
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(' ', '-')))
|
||||
|
||||
# social profiles: facebook, twitter, linkedin, instagram
|
||||
# websites
|
||||
# emails
|
||||
askingCustomPayload = input(
|
||||
code_info + 'Would you like to use an additional format for this number ? (y/N) ')
|
||||
|
||||
#social
|
||||
#rep
|
||||
#whitepages
|
||||
#voip providers
|
||||
if rerun or askingCustomPayload == 'y' or askingCustomPayload == 'yes':
|
||||
customFormatting = input(code_info + 'Custom format: ')
|
||||
|
||||
print(code_info + "Searching for owner on 411.com...")
|
||||
#https://www.411.com/phone/33-6-79-36-82-33
|
||||
print((code_info + '---- Web pages footprints ----'))
|
||||
|
||||
print(code_info + "Searching for reputation page on whosenumber.info...")
|
||||
for result in search('site:whosenumber.info intext:"%s" intitle:"who called"' % number, stop=20):
|
||||
if result:
|
||||
print(code_result + "Found 1 result on whosenumber.info.")
|
||||
print(code_info + "This usually means you are not the first to search about this number. Check the URL for eventual comments.")
|
||||
print(code_result + "URL: " + result)
|
||||
print((code_info + "Searching for footprints on web pages... (limit=10)"))
|
||||
if customFormatting:
|
||||
req = '{} | intext:"{}" | intext:"{}" | intext:"{}"'.format(
|
||||
number, number, internationalNumber, customFormatting)
|
||||
else:
|
||||
req = '{} | intext:"{}" | intext:"{}"'.format(
|
||||
number, number, internationalNumber)
|
||||
|
||||
print(code_info + "Searching for results on hs3x.com...")
|
||||
for result in search('site:"hs3x.com" intext:"+%s"' % number, stop=20):
|
||||
if result:
|
||||
print(code_result + "Found 1 result on hs3x.com.")
|
||||
print(code_info + "This number seems to be a VoIP number from hs3x.")
|
||||
print(code_result + "URL: " + result)
|
||||
for result in search(req, stop=10):
|
||||
print((code_result + "Result found: " + result))
|
||||
|
||||
def scanNumber(number):
|
||||
print code_title + "[!] ---- Fetching informations for %s ---- [!]" % formatNumber(number)
|
||||
# Documents
|
||||
print((code_info + "Searching for documents... (limit=10)"))
|
||||
if 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 = '[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))
|
||||
|
||||
PhoneNumber = localScan(number)
|
||||
print((code_info + '---- Reputation footprints ----'))
|
||||
|
||||
if not PhoneNumber:
|
||||
print(code_error + "Error: number " + formatNumber(number) + " is not valid. Skipping.")
|
||||
osintReputationScan()
|
||||
|
||||
print((code_info + "Generating URL on scamcallfighters.com..."))
|
||||
print(code_result +
|
||||
'http://www.scamcallfighters.com/search-phone-{}.html'.format(number))
|
||||
|
||||
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 ----'))
|
||||
|
||||
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 ----'))
|
||||
|
||||
osintSocialMediaScan()
|
||||
|
||||
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={}'.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 = 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!")
|
||||
sys.exit()
|
||||
|
||||
|
||||
def scanNumber(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 {} is not valid. Skipping.".format(formatNumber(InputNumber))))
|
||||
sys.exit()
|
||||
|
||||
numverifyScan(PhoneNumber['full'])
|
||||
ovhScan(PhoneNumber['countryCode'], PhoneNumber['number']) # TODO: replace 1st parameter to be dynamic
|
||||
osintScan(PhoneNumber['countryCode'], PhoneNumber['full'])
|
||||
numverifyScan()
|
||||
ovhScan()
|
||||
osintScan()
|
||||
|
||||
print '\n'
|
||||
print(code_info + "Scan finished.")
|
||||
|
||||
# Verify scanner option
|
||||
if not args.scanner in scanners:
|
||||
print(code_error + "Error: scanner doesn't exists.")
|
||||
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()
|
||||
|
||||
if args.output:
|
||||
code_info = '[*] '
|
||||
code_warning = '(!) '
|
||||
code_result = '[+] '
|
||||
code_error = '[!] '
|
||||
code_title = ''
|
||||
|
||||
sys.stdout = args.output
|
||||
else:
|
||||
code_info = '\033[97m[*] '
|
||||
code_warning = '\033[93m(!) '
|
||||
code_result = '\033[1;32m[+] '
|
||||
code_error = '\033[91m[!] '
|
||||
code_title = '\033[1m\033[93m'
|
||||
def main():
|
||||
scanners = ['any', 'all', 'numverify', 'ovh']
|
||||
|
||||
if args.number:
|
||||
scanNumber(args.number)
|
||||
elif args.input:
|
||||
for line in args.input.readlines():
|
||||
scanNumber(line)
|
||||
banner()
|
||||
|
||||
if args.output:
|
||||
args.output.close()
|
||||
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()
|
||||
|
||||
if args.output:
|
||||
if args.osint:
|
||||
print(
|
||||
'\033[91m[!] OSINT scanner is not available using output option (sorry).')
|
||||
sys.exit()
|
||||
|
||||
sys.stdout = args.output
|
||||
banner() # Output banner again in the file
|
||||
|
||||
# Verify scanner option
|
||||
if not args.scanner in scanners:
|
||||
print((code_error + "Error: scanner doesn't exists."))
|
||||
sys.exit()
|
||||
|
||||
if args.number:
|
||||
scanNumber(args.number)
|
||||
elif args.input:
|
||||
for line in args.input.readlines():
|
||||
scanNumber(line)
|
||||
else:
|
||||
parser.print_help()
|
||||
sys.exit()
|
||||
|
||||
if args.output:
|
||||
args.output.close()
|
||||
|
||||
|
||||
def signal_handler(signal, frame):
|
||||
print('\n[-] You pressed Ctrl+C! Exiting.')
|
||||
sys.exit()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
main()
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
requests
|
||||
ovh
|
||||
bs4
|
||||
html5lib
|
||||
phonenumbers
|
||||
argparse
|
||||
urllib3
|
||||
colorama
|
||||
|
|
Loading…
Reference in New Issue