This is the second part of the investigation into variety of clearnet scams. This time we focus on phone numbers - what information we can obtain to establish more connections, and try to de-anonymize people behind the fraudauilent websites.
Part one is available below
We start from phone numbers (from previous part) and associated domains. We will use tools like IntelX, WAtools, CNAM & HLR lookup and other to get as much intel as we can, to move the investigation further. I will present most convenient ways to use different techniques and collect information, as well as, how to visualize connections between them.
Also, we will take a look on other methods to confirm our assumptions about scams and find who is responsible for this illegal activity.
Moreover, I will present why thoughtlessly use of recommended, by lot of OSINT experts, websites are not the best idea and why you should test all the tools you use.
In previous part, we have started from scraping domains from message board Voy, collected info about them from WHOIS (email, phone number) and presented connections in Maltego. What brought my attention was that, just couple phone numbers were tied to many similar scams but with different email addresses. So, in this part we will focus exclusively on obtaining information about phone numbers and what we can do more to track people behind them.
Let's ask a question, what do you do, from OSINT perspective, when you have only a phone number and you don't know whom it belongs to? I don't think many of you thought about WHOIS, but it's the first thing we are going to do.
Since we know, the numbers are somehow connected and used in many frauds, we have to present it in a clear way. This is the part, where D3js comes into play together with Intelx.
So, we have bunch of phone numbers, domains, emails and corresponding WHOIS information about them like addresses, names etc, from initial research from previous part. We know that phone numbers are reused by scammers with different emails. So first thing we should do, is to find more domains with these specific phone numbers in WHOIS and look for additional data. Moreover, to make our investigation more interesting and more readable to audience we will show it as a graph.
I really do enjoy Maltego but this time we make something different - create our own connection graph in D3js based on the collected data.
We gathered the phone numbers that are not WHOIS protected and put it in text file, you can check these numbers below:
password: nVhC6vK5bL
The next thing is to run it against IntelX and grab WHOIS information, it's only service that allows you to search WHOIS records by phone number, so this way we will have all domains that are associated with given number.
To query IntelX and their WHOIS database we can write code like this. This is first function just to search IntelX
def search(term, maxresults=100000000000000, buckets=[], timeout=5, datefrom="", dateto="", sort=4, media=0,
terminate=[]):
results = []
done = False
search_id = intelx.INTEL_SEARCH(term, maxresults, buckets, timeout, datefrom, dateto, sort, media, terminate)
if (len(str(search_id)) <= 3):
print(f"[!] intelx.INTEL_SEARCH() Received {intelx.get_error(search_id)}")
while done == False:
time.sleep(1) # lets give the backend a chance to aggregate our data
r = intelx.query_results(search_id, maxresults)
for a in r['records']:
results.append(a)
maxresults -= len(r['records'])
if (r['status'] == 1 or r['status'] == 2 or maxresults <= 0):
if (maxresults <= 0):
intelx.INTEL_TERMINATE_SEARCH(search_id)
done = True
return {'records': results}
which will return storages ID, we have to query it to obtain the data.
with open('numbers.txt','r') as f: # load phone numbers
for number in f.readlines():
res = search(number.rstrip()) # pass it to 'search' function to obtain storage IDs
print(number.rstrip())
for c, i in enumerate(res['records']):
if i['bucket'] == 'whois':
view = intelx.FILE_VIEW(i['type'], i['media'], i['storageid'], i['bucket']) # view the data related to the result
print("[i] Checking " + str(c))
for line in view.splitlines(): # iterate over line in results
if number.rstrip()[2:] in line.lower(): # if number (without prefix) is in data
spl = line.split(",") # split the line when number exists to get other data
if "@" in spl[17]: # look for email in splitted data
ret = {"domain_name": spl[1], "create_date": spl[2], "domain_registrar_name": spl[7], "registrant_company": spl[11],
"registrant_address": spl[12],
"registrant_city": spl[13], "registrant_country": spl[16], "registrant_email": spl[17], "registrant_phone": spl[18]} # make a dict with the obtained results
ret_list.append(ret) # append to the list
else:
pass
After running above we can print it as json
print(json.dumps(ret_list))
and have following output. We discovered more domains and emails that are tied to the phone numbers.
{
"domain_name": "dolorendo.com",
"create_date": "2020-02-13 18:39:49",
"domain_registrar_name": "NetEarth One Inc. d/b/a NetEarth",
"registrant_company": "",
"registrant_address": "20735 Stevens Creek Blvd",
"registrant_city": "Cupertino",
"registrant_country": "United States",
"registrant_email": "[email protected]",
"registrant_phone": "+1.2133736580"
},
{
"domain_name": "kaiserpharma.com",
"create_date": "2020-01-23 17:02:20",
"domain_registrar_name": "NetEarth One Inc. d/b/a NetEarth",
"registrant_company": "KAISER PHARMA",
"registrant_address": " MIAMI",
"registrant_city": " FLORIA",
"registrant_country": "United States",
"registrant_email": "[email protected]",
"registrant_phone": "+1.2133736580"
},
{
"domain_name": "petsloveuae.com",
"create_date": "2021-06-23 15:43:40",
"domain_registrar_name": "NetEarth One Inc. d/b/a NetEarth",
"registrant_company": "",
"registrant_address": "new york new york 10001",
"registrant_city": "new york",
"registrant_country": "United States",
"registrant_email": "[email protected]",
"registrant_phone": "+1.9852550364"
},
{
"domain_name": "adorablemonkey.us",
"create_date": "2020-09-04 21:07:27",
"domain_registrar_name": "NameCheap",
"registrant_company": "Morgan Edward",
"registrant_address": "10001 New York",
"registrant_city": " USA",
"registrant_country": "10001",
"registrant_email": "[email protected]",
"registrant_phone": "+1.9852550364"
},
You can see we have a four different domains in above snippet and four different email ddresses but only two phone numbers. So we have to write an algorithm to transform the output to the one compatible with our visualiation template, which looks like this
"nodes": [
{
"name": "dolorendo.com",
"group": 1,
"id": 1,
"photo": "https://icon-icons.com/downloadimage.php?id=4886&root=38/PNG/512/&file=domain_5448.png",
"size": 60,
"info": ""
},
{
"name": "[email protected]",
"group": 2,
"id": 2,
"photo": "https://www.pinclipart.com/picdir/big/209-2098523_kids-sleeping-clip-art.png",
"size": 60,
"info": ""
},
{
"name": "+1.2133736580",
"group": 2,
"id": 3,
"photo": "https://www.pinclipart.com/picdir/big/209-2098523_kids-sleeping-clip-art.png",
"size": 60,
"info": ""
}],
"links": [
{
"source": 3,
"target": 1,
"value": 0
},
{
"source": 3,
"target": 2,
"value": 0
},
It's very easy to understand the JSON, every node have ID and we can connect them via links. For example, phone number has ID 3 and it's connectedto ID 1 - domain and ID 2 - email address via keys source and target in "links" list.
First, we have to extract all emails, domains and phone numbers and put it as a nodes, but only the unique ones, we don't need any repetitiveness, because graph won't be readable and it won't make any sense.
Second phase is to connect them to corresponding data, phone number to email, email to domain and phone number to domain. It sounds complex and it really is, but if you read my previous articles where I did similar graphs you should know how we can move on.
We start from couple assumptions:
So let's start writing code to transform our WHOIS JSON file to the format (nodes and links) compatible with the visualization.
import json
id = 0
with open('template.json', 'r+') as template:
with open("numbers.json", 'r') as data:
template_json = json.loads(template.read())
data_json = json.loads(data.read())
First we import json, assign 0 for ID, open empty template for graph as well as file with WHOIS info.
for i in data_json:
email_exists = False
phone_exists = False
id = id + 1
domain_id = id
template_json['nodes'].append({
"name": i['domain_name'],
"group": 1,
"id": id,
"photo": "https://icon-icons.com/downloadimage.php?id=4886&root=38/PNG/512/&file=domain_5448.png",
"size": 60,
"info": ""
})
Then we iterate over the previously collected WHOIS data, set helper 'email_exists' and 'phone_exists' to False (it will be needed later to check if email or number has been already added), increment id and create a new node for each domain. Domain names are unique because they are gathered directly from IntelX.
for j in template_json['nodes']:
if i['registrant_email'] in j['name']:
email_id2 = j['id']
email_exists = True
break
else:
email_exists = False
if not email_exists:
id = id +1
template_json['nodes'].append({
"name": i['registrant_email'],
"group": 2,
"id": id,
"photo": "https://www.pinclipart.com/picdir/big/209-2098523_kids-sleeping-clip-art.png",
"size": 60,
"info": ""
})
email_id = id
Above snippet is responsible for iterating over nodes and checking if email already exists in our JSON. If it does, we assign new ID, otherwise set 'email_exists' flag to False, and at the end add it to the template with the ID and the email as a name.
for j in template_json['nodes']:
if i['registrant_phone'] in j['name']:
phone_id2 = j['id']
phone_exists = True
break
else:
phone_exists = False
if not phone_exists:
id = id + 1
phone_id = id
template_json['nodes'].append({
"name": i['registrant_phone'],
"group": 3,
"id": id,
"photo": "https://www.pinclipart.com/picdir/big/59-598828_timeout-clipart.png",
"size": 60,
"info": ""
})
template_json['links'].append({
"source": domain_id,
"target": phone_id,
"value": 0
})
else:
template_json['links'].append({
"source": domain_id,
"target": phone_id2,
"value": 0
})
if not email_exists:
template_json['links'].append({
"source": domain_id,
"target": email_id,
"value": 0
})
else:
template_json['links'].append({
"source": domain_id,
"target": email_id2,
"value": 0
})
We do the same trick with phone number, and at the end connecting them in 'links' with previously assigned IDs. I figured out this algorithm really fast so it might not be the perfect way but it works. Each case requires different thinking and depends of the input format. This time we came from WHOIS records in JSON format to interactive graph that shows associations phone numbers --> domain names --> email addresses.
Full JSON you can find below
https://pastebin.com/raw/GwzLRApW
I made similar graphs for other investigations
Graph is working only on web version, does not load properly on mobile.
For better visibility, turn on light mode on bottom left corner and zoom out website in your browser.
Now I think it's clear what I meant in first part that phone numbers are tied to many domains and email addresses. If you hover on the phone number you can see all the connections to domains and if you want to see what email is tied to, hover on domain name.
The most intriguing phone numbers are:
They are associated with multiple domains and these domain to lot of email addresses. First of all, I don't know why actor(s) didn't use WHOIS protection, it might be OPSEC mistake but it's not our problem. Second, they have to be in control of the phone number, if not they could use services for temp numbers like 5sim or smspva.
Honestly, when I found Voy message board, I didn't think the spam post and included domains are connected in any way, but after deeper investigation we had graph as above.
What we can do to gather more information about these numbers?
The funniest thing in OSINT community is when people share links and tools without actually test it, and use it in real world investigation.
So, let's compare some tools and websites that were shared multiple times and promise to show you detailed information about phone number. Services are from intelframework, aware-online, recommended by people from r/osint and from i-intelligence OSINT Handbook
https://i-intelligence.eu/uploads/public-documents/OSINT_Handbook_2020.pdf
Basically, I tested every source mentioned on these websites and I can confirm that 90% are not worth your time. They are scams, give outdated information, are paid, sign up you for subscription or just simply do not work.
What you are looking for depends of the investigation, for some cases game changer might be to find carrier provider, but this time we want to get as much information as possible and compare different services offering OSINT on phone numbers.
We don't have to be OSINT experts to deduce that all of the numbers are from US (+1 prefix) and from following states Wisconsin, Florida, Ohio and Maryland adequately. Full list of are code you can find here
Remember, no website or tools can replace your mindset, with proper query or dork you can gather more info than from some shady tools you just waste time on.
Phone number can have a different format, during investigation you must try to look it up in different search engines providing number in different format. There are plenty of possibilities you have to think of
So you have a plenty of possibilities to transform the numbers, they might be posted in different format and if you do OSINT you should think about it.
A lot of results are repetitiveness from second screenshot but it's your task to review them and compare the results.
CNAM (Caller Name Delivery) is used to provide ID of the caller, mostly used in United States. It can be a person name or organization, depends of the settings. You can read more about this system here
https://www.numeracle.com/insights/whats-in-a-name-is-it-caller-id-cnam-or-rcd
and
There are plenty of free CNAM lookup services, including ones with API, but most of them are paid or require account.
I tried many websites that allows to check Caller ID for free but best one, in my opinion, is calleridtest
It shows Caller ID and city it is from. User interface is simple and very easy to use giving reliable results.
Interesting match is for second number, it shows number comes from Delphi Corp in Wisconsin, which is quite intriguing knowing what this number was used for. However, we cannot take it as granted, CNAM can be spoofed so it's important to cross check with previously gathered information.
So we didn't have a good results regarding CNAM, no names (except one that ends on 2172) only location but let's move further.
Other services
It's another simple technique to check what carrier operates given phone numbers. You don't have to be an expert in telecommunications to do phone carrier lookup and know technical details, but it's a good way to learn how things work. For more in depth information about this method you can go here
There are plenty of free lookup services so don't go for the paid ones unless you have large amount of data and need automation.
First service I tested was https://textrapp.com/free-carrier-lookup-tool/ which gives result as below. You can see city, as it was in previous example but also carrier which is bandwith.com
Another free carrier lookup (https://freecarrierlookup.com/) gives quite different result. It shows Google as a carrier and after some digging you can learn that google voice use bandwith.com.
We know right now that numbers have been registered in google Voice.
The HLR Lookup is the service that dynamically contacts the central HLR database at the network operator’s side to check if a particular subscriber is authorized to use the GSM core network.
Thanks to that we can collect useful information but not actually important for our case.
However, if you want to use it, I recommend https://www.free-hlr.com/
And now we can move to tools to fit our purpose, i.e. de-anonymization of the owners behind the phone numbers.
There are tons of such services and most of them are scam but still advertised on variety of forums as a reliable source to check for phone number.
They state, they search billions of records and will give you exact name, location and social media. You have to click through lot of windows imitating search engine or whatever to find out you have to pay for the extensive report. No matter if there will be match or no, you have to pay anyway. In some services you also subscribe for $30 per month.
I don't know if there are any matches from these services, but everyone who has IQ above room temperature might see that something is off.
Most recommended sites are Spokeo, Intellius, PeopleFinder but you can find more of them.
It's just one of the review from Trustpilot for such service. I really don't know why people still recommend it as a reliable source.
Back to the real OSINT, we need to test plenty of services to see which one is not a scam and contains some useful information.
Spydialer is one of such tool, it's free, quite fast and has couple features including name lookup or possibility to hear voicemail. Why I'm saying it gives reliable results? Let's take a look
If you carefully looked on the graph you would notice, that above phone number is associated with email [email protected][.]com, so the name fits to our case. They might get this information from WHOIS as well, they don't disclose their sources.
Same case as with Justin, the number is tied to email [email protected][.]com via WHOIS.
This name tho, does not appear in WHOIS or anywhere, it's first time I saw this, so it might give a new lead. For the records, WHOIS for this number contains completely different names.
Watools.io is a set of tools to gather intelligence about phone number that might be registered in Whatsapp. It supports following features:
It works as you would add the number to your contact and check whatsapp but without any action from your side. You just give a phone number and all of the available information will be returned.
This method allows to grab profile photo of the target and take a step forward to find real identity of the person who owns the number. It works only if the number set his profile to public.
For Telegram tho, I didn't find any automated way to obtain status information and profile picture so we have to add it to the contacts and hijack picture and photo.
So, in our case I found couple profile picture in WA, let's take a look.
These images do help a lot to identify the people or at least the nature of the person behind the number. For one number we have a actual photo of the person which we can cross check with facial recognition or look for the same image in social media via different services.
First picture is a Chinese word, I assume for Buddhism nirvana but the last one is more interesting, because it shows it can help you pass NCLEX exam. It's an examination for the licensing of nurses in the United States, Canada and Australia. If you remember, this phone number was given in WHOIS infromation for domain offering fake documents.
It's no secret that many social media platforms allow to check if phone number exists, i.e. has been registered on particular website. In some cases, it might disclose additional details about the account. It's easier to search by email but this article focus on phone numbers so lets stick with it.
For example, Twitter allows both - email and phone number. We can check whether number exist on Twitter via forgotten password form
If it exists, it asks you to enter your Twitter username, if not, shows a pop up, it couldn't find any account with provided phone number.
Same trick you can do for Facebook.
You can discover on your own, what platforms give what kind of information to move further with the investigation.
It can be used by law enforcement to make sure that number or email is registered and obtain warrant for this particular account. Social media services must provide LE information about the account or at least metadata.
There is one more thing to mention about different aspects of such websites. Nowadays, social media it's the easiest way to get to the people and scammers know this as well, so you should search numbers in different platforms.
For example, above screenshot shows our phone number was posted to advertise illegal goods. It also includes Wickr username, and of course, Twitter profile, which we can cross check with other sources to discover online footprint of this person.
I cannot count cases when leaks from variety of websites helped me during investigation. Thanks to this I was able to find super useful details about the email/phone number or even real identity of the person.
For me, the most useful data leaks are Facebook, Linkedin, USA People, Verifications.io and many many more, depends of the person you try to find.
You don't have to collect all of them on your own, but this is a good option as well because you will be able to do a full text search in every field that suits your purpose. If you don't have time and capabilities, I recommend to buy subscription for IntelX. I don't regret any cent spent on it the money have already returned during my freelancer work. So, let's take a look how it can help with our phone numbers.
Unfortunately, there are no matches in FB phone number leak, it would give us Facebook profile and we will have a lot of information about the person, we need to look deeper. Only one number (4102313786) exists in IntelX database and being precise in Apollo leak and 123rf - stock photo service.
{
"_index": "contacts_v5",
"_type": "contact",
"_id": "5b48a86873f4752476e7d6b2",
"_score": 1,
"_source": {
"person_name": "Fresh Kelbch",
"person_first_name_unanalyzed": "fresh",
"person_last_name_unanalyzed": "kelbch",
"person_name_unanalyzed_downcase": "fresh kelbch",
"person_title": null,
"person_functions": [],
"person_seniority": null,
"person_email_status_cd": "Verified",
"person_extrapolated_email_confidence": 0,
"person_email": "[email protected]",
"person_phone": "4102313786",
"person_sanitized_phone": "+14102313786",
"person_email_analyzed": "[email protected]",
"organization_name": "A76YE8777",
"sanitized_organization_name_unanalyzed": "a76ye8777",
"person_location_city": "Pittsfield charter Township",
"person_location_city_with_state_or_country": "Pittsfield charter Township, Michigan",
"person_location_state": "Michigan",
"person_location_state_with_country": "Michigan, US",
"person_location_country": "United States",
"person_location_postal_code": "48108",
"contact_stage_id": "5b3dd63a9d79680a616e08a6",
"contact_created_at": "2018-07-13T13:26:00.774Z",
"contact_phone_numbers": [
{
"sanitized_number": "+14102313786",
"status": "no_status",
"type": "other"
}
]
}
}
('francis70333
','','Todd','sherman','1110 Lucas st','','Calumet City','IL','US','60409','4102313786',
'[email protected]','Y','',0.00,0,'','','','','N','2019-01-27
06:19:39',,'37.212.79.61','',1,0,'',0,'BY'
,'[email protected]','','115992542972561070980','',0,0)
The actor behind the phone number gave same email address for both services but different location, Michigan and Illinois, probably both fake.
Now we have a email addresses, we can pivot to find more information and move forward with the investigation.
This part focuses only on OSINT for phone number so we will end here, I did more research, than I wrote here, to completely deanonymize the people behind the scams but you should know right now what to do when you have a phone number and how to proceed with your research.
We have made a long journey, from old message board and spam message to the network of websites advertising variety of scam services - fake documents, exotic pets, firearms and drugs. This way we can completely examine and deanonymize people that are engaged in criminal activities online.
When someone say it's no victim crime, I disagree, many poeple lost their money and trust in online shopping. In addition, it's worth to report such scams to proper authorities and people do face jail time for such crimes.