-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDGADetective.js
210 lines (181 loc) · 5.58 KB
/
DGADetective.js
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
const request = require('request');
//Get largest domain
function getDomain(domain){
var dom = "";
domain.split(".").forEach(function (doma){
if (dom.length <= doma.length) dom = doma;
}); // Get largest subdomain for checking DGA
return dom;
}
// Check if domain is Hexadecimal
function isHex(domain){
var h = domain.match(/[\dabcdef]+/i);
if (h && h[0] == domain) return true;
return false;
}
// Check if domain is a hash
function isHash(domain){
var ih = isHex(domain);
var lengths = [ 40, //sha1
32, //md5
64, //sha
128, //sha3
]
if (ih && domain.indexOf(domain.length) != -1) return true;
return false;
}
// Check number of numbers
function checkNums(domain){
var nums = domain.match(/\d/g);
if (nums) return nums.length;
return 0;
}
// Check low Frecuency letter
function checkLowFrecLets(domain){
var let_frec = 0;
var letters = ["z", "x", "j", "k", "q"]
letters.forEach(function(letter){ // Check how many of each letter
var indexes = domain.split('').map((e, i) => e === letter ? i : '').filter(String);
if (indexes.length > 0) let_frec = indexes.length;
});
return let_frec;
}
// Check consonants
function checkConsonats(domain){
arr_cons = domain.match(/[qwrtypsdfghjklzxcvbnm]{4}[qwrtypsdfghjklzxcvbnm]*/g);
return (arr_cons) ? arr_cons : [];
}
//Check unique chars
function checkEntropy(domain){
if (domain.length > 10){
var uni_lets = [];
domain.split('').forEach(function(letter){
if (uni_lets.indexOf(letter) == -1) uni_lets.push(letter);
});
perct = uni_lets.length / domain.length;
return perct;
}
else return 0;
}
//Check repeated chars
function checkRepeated(domain){
letters = [];
rep = []
domain.split('').forEach(function(letter){
if (letters.indexOf(letter) == -1){
var indexes_len = domain.split('').map((e, i) => e === letter ? i : '').filter(String).length;
rep.push(indexes_len);
letters.push(letter);
}
});
return rep;
}
/*
Algorithm to detect DGA statically:
- If length > 10 --> Suspicious
- If domain is Hex --> More suspicious
- If domain is Hash --> Very suspicios
(If this 3 are met, val > 100 --> is DGA)
- If more than 3 numbers in domain
- Check if low frecuency letters are contained
- Check if more than 4 consonants together
- Check if a char is repeated more than 4 times
- Check if high entropy (with length > 10)
- Check if records in Ecosia
*/
// Check if domain could be created using DGA
function checkDGASync(domain){
domain = getDomain(domain);
var val = 0;
if (domain.length > 10){
val += domain.length * 1.5;
///-console.log("Domain length > 10: +" +val);
}
if (isHex(domain)){
val += 30;
///-console.log("Is Hex: +30");
}
if (isHash(domain)){
val += 30;
///-console.log("Is Hash: +30");
}
// Check if 4 or more numbers
var nums = checkNums(domain);
if (nums > 6){
val += nums * 10;
///-console.log(nums+ " nums in the domain: +" +nums * 10);
}
else if (nums > 3){
val += nums * 8;
///-console.log(nums+ " nums in the domain: +" +nums * 8);
}
// Check if low frecuency letters contained
var let_frec = checkLowFrecLets(domain);
if (let_frec > 0) ///-console.log("Low Frec letters contained: +" +let_frec*20);
val += let_frec*20;
// Check if several consonants together (+3)
var arr_cons = checkConsonats(domain)
arr_cons.forEach(function(cons){
val += cons.length*8;
///-console.log("Consonants together: +" +cons.length*8);
})
//Check if several repetitions of a char
checkRepeated(domain).forEach(function(num_rep){
if (num_rep > 4){
val += num_rep*num_rep*1.5;
///-console.log("-- Chars repeated: +" +num_rep*num_rep*2);
}
});
var perct = checkEntropy(domain);
if (perct > 0.75){
val += 20;
///-console.log("Entropy: +25");
}
else if (perct > 0.80){
val += 30;
///-console.log("Entropy: +35");
}
else if (perct > 0.90){
val += 40;
///-console.log("Entropy: +50");
}
else if (perct > 0.95){
val += 50;
///-console.log("Entropy: +60");
}
return val;
}
function checkDGA(domain){
domain = getDomain(domain);
var promise = new Promise(function(resolve, reject) {
var val = checkDGASync(domain);
if (val > 50){
var url = "https://www.ecosia.org/search?q="+domain;
request({url: url}, function (error, response, body) {
if (error) reject(Error("Error checking ecosia: "+error));
if (body){
if (body.indexOf(">No results found<") != -1){
val += 50;
///-console.log("No results in ecosia: +50");
}
resolve(val);
}
});
} else resolve(val);
});
return promise;
}
function isDGAlowSync(domain){
return checkDGA(domain) > 60 ? true : false;
}
function isDGAmediumSync(domain){
return checkDGA(domain) > 100 ? true : false;
}
function isDGAhighSync(domain){
return checkDGA(domain) > 150 ? true : false;
}
exports.checkDGA = checkDGA;
exports.checkDGASync = checkDGASync;
exports.isDGAlowSync = isDGAlowSync;
exports.isDGAmediumSync = isDGAmediumSync;
exports.isDGAhighSync = isDGAhighSync;