def DGA ():
seed = GetSystemTime()
for counter in range(0x320):
domain = get_domain(seed[0:7], counter)La semilla («seed») resulta de la llamada a la función API de Windows «GetSystemTime» para inicializarse. La API de Windows lo guarda en una estructura SYSTEMTIME mientras que nosotros para más comodidad, lo guardamos en una lista que llamamos «seed». Los dos primeros índices corresponden al año (2014 = 0x07*0x100 + 0xDE), el tercero al mes, el quinto al día de la semana, el séptimo al día, y el resto a los segundos y milisegundos. En la API de Windows, enero corresponde a 1, febrero a 2, etc. El domingo corresponde a 0, lunes a 1, etc. El día depende del mes y varia entre 1 y 28, 30 o 31. Abajo es el ejemplo de un seed:
Seed = [0xDE, 0x07, wMonth, 0x00, wDayOfWeek, 0x00, wDay, 0x00, 0x0F, 0x00, 0x31,
0x00, 0x33, 0x00, 0xD1, 0x03]
En la función «get_domain», la primera parte define una lista «data_to_hash» que esta inicializada con la semilla y el contador y luego se hace un XOR con los bytes 0xB1, 0xA4, 0xD7, etc. Finalmente, se realiza el «hash» de esta lista con el algoritmo MD5 y el «hash» resultante se usa para generar el dominio.
def get_domain(seed, counter):
//Primera parte
data_to_hash = [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
data_to_hash[0] = (seed[0] + 0x30) & 0xff
data_to_hash[1] = seed[2] & 0xff
data_to_hash[2] = seed[6] & 0xff
data_to_hash[3] = 0x00
data_to_hash[4] = counter & 0xfe
data_to_hash[5] = (counter >> 8) & 0xff
data_to_hash[0] = (data_to_hash[0] ^ 0xB1) & 0xff
data_to_hash[1] = (data_to_hash[1] ^ 0xA4) & 0xff
data_to_hash[2] = (data_to_hash[2] ^ 0xD7) & 0xff
data_to_hash[3] = (data_to_hash[3] ^ 0xD6) & 0xff
data_to_hash[4] = (data_to_hash[4] ^ 0xB1) & 0xff
data_to_hash[5] = (data_to_hash[5] ^ 0xA4) & 0xff
data_to_hash[6] = (data_to_hash[6] ^ 0xD7) & 0xff
data_to_hash[7] = (data_to_hash[7] ^ 0xD6) & 0xff
hash_md5 = hashlib.md5(array.array('B', data_to_hash).tostring()).hexdigest()
bytes_array = array.array('B', hash_md5.decode("hex"))
En la segunda parte, el algoritmo itera todos los bytes del «hash» con los cuales construye el nombre del dominio. Pone el límite de 0x7a que corresponde a la ultima letra del alfabeto (z) y añade un offset 0x 61 (letra a) para solo generar letras. La extensión del dominio esta basada sobre el valor del contador. El DGA distingue 5 casos: la extensión “.org”, “.com”, “.net”, “.info”, o “.biz”. Concatenando el nombre y la extensión, conseguimos el dominio.
//Segunda parte
#Generate the name
for byte in bytes_array:
al = (byte & 0xF) + (byte>>4) + 0x61
if al <= 0x7A:
name = "%s%c" % (name, chr(al))
#Generate the extension
if (counter % 5 != 0):
if (counter & 0x3 != 0):
if (counter % 3 == 0):
extension = ".org"
else:
if (counter & 0x1 == 0x1):
extension = ".com"
else:
extension = ".net"
else:
extension = ".info"
else:
extension = ".biz"
domain = "%s%s" % (name, extension)
return domainEjecutando el script Python, sobre el año 2014 entero, hemos notado que un dominio (epmmxkoszqyown.org) aloja un servidor nginx/1.6.0 activo, pero no pudimos recoger ningún ejecutable. Es la maquina de una victima, es decir sin instrumentación del algoritmo, la victima podría haberse infectado el día 14 de Agosto 2014.
Deja una respuesta