This repository has been archived by the owner on Mar 28, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathdeceptiveidn.py
128 lines (96 loc) · 3.01 KB
/
deceptiveidn.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/env python3
import sys
if sys.version_info < (3, 0):
sys.stderr.write("[!] Please run this script with python3\n")
sys.exit(1)
import os
import encodings.idna as idna
try:
from PIL import Image, ImageDraw, ImageFont, ImageFilter
except:
print("[!] Please install pillow: pip3 install pillow\n")
raise
import glob
import subprocess
import socket
import tempfile
import itertools
# Config
fonts = ("SFText-Regular.otf", "Georgia.ttf", "Times New Roman.ttf", "Helvetica")
font_sizes = (32, 48, 54, 72)
def main():
if len(sys.argv) != 2:
print("Usage: {} idn_to_test | --tests")
sys.exit(1)
if sys.argv[1] == "--tests":
pass
test_inputs = open('test_inputs.txt', 'r', encoding="UTF8").readlines()
test_inputs = map(str.strip, test_inputs) # strip each input
for idn in test_inputs:
test_idn(idn)
else:
idn = sys.argv[1]
if 'xn--' not in idn:
print("Error: Expected idn to start with xn--. Got: {}".format(idn))
sys.exit(1)
test_idn(idn)
def test_idn(s):
# convert idn to unicode
un = idn_to_unicode(s)
idn_host = None
try:
idn_host = socket.gethostbyname(s)
except:
pass
guesses = set()
for font, size in itertools.product(fonts, font_sizes):
im = render_idn(text=un, font_name=font, font_size=size)
guess = make_guess(im)
if not un.endswith(guess):
guesses.add(guess)
hosts = {}
for guess in guesses:
try:
host = socket.gethostbyname(guess)
except:
continue
hosts[guess] = host
print("IDN: {} ({})".format(un, s))
if len(hosts) > 0:
print("\tDeceptive IDN, possible readings: ")
for host in hosts:
print("\t- {} {}".format(host, hosts[host]))
else:
print("\tCould not identify deceptive readings")
def render_idn(text, font_name, font_size):
width = 500
height = 100
bgcolor = (255, 255, 255, 255)
color = (0,0,0, 255)
image = Image.new("RGBA", (width, height), bgcolor)
draw = ImageDraw.Draw(image)
font = ImageFont.truetype(font_name, font_size, encoding="unic")
draw.text((0, 0), text, font=font, fill=color)
out_file = tempfile.NamedTemporaryFile(suffix=".png")
image.save(out_file.name)
return out_file
def make_guess(im):
output = tempfile.NamedTemporaryFile(suffix='.txt')
output_name_sans_suffix = output.name[:-4]
tesseract = ['tesseract', im.name, output_name_sans_suffix,
'--user-patterns', 'urlpatterns.txt', ]
p = subprocess.Popen(tesseract, stderr=subprocess.PIPE)
p.wait()
stdout, stderr = p.communicate()
guess = output.read().decode("UTF8").strip()
return guess
def idn_to_unicode(s):
rv = []
for part in s.split('.'):
if part.startswith('xn--'):
rv.append(idna.ToUnicode(part))
else:
rv.append(part)
return '.'.join(rv)
if __name__ == '__main__':
main()