forked from sethhall/bro-domain-generation
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnewgoz.bro
executable file
·149 lines (120 loc) · 3.7 KB
/
newgoz.bro
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
##! Domain generation algorithm based detection for NewGOZ (Game Over Zeus)
##!
##! Ported from Python script found here:
##! http://www.johannesbader.ch/2014/12/the-dga-of-newgoz/
##!
##! Requires: Bro 2.1+
##! Author: Vlad Grigorescu <[email protected]>
##!
@load ./utils
module DomainGeneration;
export {
## These are the current names based on the number of hours being offset
## and calculated.
global newgoz_current_names: set[string] = set();
redef enum Kit += { NEWGOZ };
}
function hex_to_int(seed_value: string): count
{
local indices = vector(6, 4, 2, 0);
local seed = "";
for ( i in indices )
seed = seed + sub_bytes(seed_value, indices[i] + 1, 2);
return bytestring_to_count(hexstr_to_bytestring(seed));
}
function get_seed(sequence_number: count, year: count, month: count, day: count): string
{
local key = "\x01\x05\x19\x35";
local seed = md5_hash_init();
# 1. Sequence number (uint32 in little-endian format)
md5_hash_update(seed, hexstr_to_bytestring(fmt("%2x", sequence_number % 256)));
md5_hash_update(seed, hexstr_to_bytestring(fmt("%2x", sequence_number / 256)));
md5_hash_update(seed, "\x00\x00");
# 2. Year (uint16 in little-endian format)
md5_hash_update(seed, hexstr_to_bytestring(fmt("%2x", year % 256)));
md5_hash_update(seed, hexstr_to_bytestring(fmt("%2x", year / 256)));
# 3. Key
md5_hash_update(seed, key);
# 4. Month
md5_hash_update(seed, hexstr_to_bytestring(fmt("%2x", month)));
md5_hash_update(seed, "\x00");
# 5. Key
md5_hash_update(seed, key);
# 6. Day
md5_hash_update(seed, hexstr_to_bytestring(fmt("%2x", day)));
md5_hash_update(seed, "\x00");
# 7. Key
md5_hash_update(seed, key);
return md5_hash_finish(seed);
}
function generate_domain_part(seed_value: count, sequence_number: count): string
{
local part = "";
local char = 0;
for ( i in vector(0, 1, 2, 3, 4, 5, 6) )
{
local edx = seed_value % 36;
seed_value = seed_value/36;
if (edx > 9)
char = 97 + (edx - 10);
else
char = edx + 48;
part += fmt("%02x", char);
if ( seed_value == 0 )
break;
}
return reverse(hexstr_to_bytestring(part));
}
function generate_newgoz_domain(sequence_number: count, year: count, month: count, day: count): string
{
local seed_value = get_seed(sequence_number, year, month, day);
local domain = "";
local loop = vector(0, 4, 8, 12);
for ( i in loop )
{
local seed = sub_bytes(seed_value, (loop[i]*2) + 1, 8);
domain += generate_domain_part(hex_to_int(seed), 1);
}
if ( sequence_number % 4 == 0 ) domain += ".com";
else if ( sequence_number % 3 == 0 ) domain += ".org";
else if ( sequence_number % 2 == 0 ) domain += ".biz";
else domain += ".net";
return domain;
}
function generate_newgoz_domains(date: time, offset: interval): set[string]
{
local ts = strftime("%Y %m %d", network_time_for_strftime() + offset);
local parts = split(ts, / /);
local year = to_count(parts[1]);
local month = to_count(parts[2]);
local day = to_count(parts[3]);
local result: set[string] = set();
local daily_domains = 1000;
local todo = vector(0);
local sequence_number: count = 0;
for ( i in todo )
{
local d = generate_newgoz_domain(sequence_number, year, month, day);
++sequence_number;
add result[d];
add newgoz_current_names[d];
domains[d] = NEWGOZ;
# This is our hack for looping over this daily_domains number of times.
--daily_domains;
if ( daily_domains > 0 )
todo[|todo|] = 0;
}
return result;
}
event update_newgoz_current_names()
{
local now = network_time();
newgoz_current_names = set();
for ( offset in day_offsets )
generate_newgoz_domains(now, offset);
schedule 12hrs { update_newgoz_current_names() };
}
event bro_init()
{
event update_newgoz_current_names();
}