从Cerber勒索软件中学习murmurhash算法[转]

作者:降草
近期,大量国内用户遭受到cerber勒索软件的侵害,cerber作为新起的勒索软件家族,大有后来居上的姿态,网上也有数篇对于cerber勒索软件的行为的分析。这款勒索软件,使用rsa非对称加密加密用户的文件,在没有私钥的情况下,基本上没有可能解密出被勒索的文档。这个勒索软件比较新颖的使用了murmur hash算法,本文本着学习的精神,对murmurhash算法的原理及在此款勒索软件中的使用作了简单的分析。
 

Murmur hash算法介绍

MurmurHash是一种非加密型哈希函数,适用于一般的哈希检索操作。 由Austin Appleby在2008年发明,并出现了多个变种,都已经发布到了公有领域。与其它流行的哈希函数相比,对于规律性较强的key,MurmurHash的随机分布特征表现更良好。当前的版本是MurmurHash3,能够产生出32-bit或128-bit哈希值。
MurmurHash算法具有高运算性能,低碰撞率等特点,这也人使的近些年对MurmurHash的使用风生水起,目前应用MurmurHash 的开源系统包括Hadoop、libstdc++、nginx、libmemcached。

 

Murmur hash 算法实现

根据维基百科上给出的代码伪代码,我们使用python实现 murmur hash算法,如下:
[Python] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
def murmur3_x86_32(data, seed=0):[/size][/align][size=4]    c1 = 0xcc9e2d51
    c2 = 0x1b873593
    r1 = 15
    r2 = 13
    m = 5
    n = 0xe6546b64
    length = len(data)
    h1 = seed
    rounded_end = (length & 0xfffffffc# every block contain 4 bytes
    for i in range(0, rounded_end, 4):
        # translate to little endian load order
        k1 = (ord(data[i]) & 0xff) | ((ord(data[i + 1]) & 0xff) << 8) | \
             ((ord(data[i + 2]) & 0xff) << 16) | (ord(data[i + 3]) << 24)
        k1 *= c1
        k1 = (k1 << r1) | ((k1 & 0xffffffff) >> (32-r1))  # ROTL32(k1,15)
        k1 *= c2
        h1 ^= k1
        h1 = (h1 << r2) | ((h1 & 0xffffffff) >> (32-r2))  # ROTL32(h1,13)
        h1 = h1 * m + n
    # the last block which is < 4 bytes
    k1 = 0
    val = length & 0x03
    # the last block is  3 bytes
    if val == 3:
        k1 = (ord(data[rounded_end + 2]) & 0xff) << 16
    # the last block is  2 bytes
    if val in [2, 3]:
        k1 |= (ord(data[rounded_end + 1]) & 0xff) << 8
    # the last block is  1 bytes
    if val in [1, 2, 3]:
        k1 |= ord(data[rounded_end]) & 0xff  # translate to little endian load order
        k1 *= c1
        k1 = (k1 << r1) | ((k1 & 0xffffffff) >> (32-r1))
        k1 *= c2
        h1 ^= k1
    # finalization
    h1 ^= length
    h1 ^= ((h1 & 0xffffffff) >> 16)
    h1 *= 0x85ebca6b
    h1 ^= ((h1 & 0xffffffff) >> 13)
    h1 *= 0xc2b2ae35
    h1 ^= ((h1 & 0xffffffff) >> 16)
    # for 32 bit, get the last 32 bits
    return h1 & 0xffffffff
对样本中的调用murmurhash的地方下断,可以看到对数据“65 2F3B 3C D1 40 02 4C BA 68 C0 D0”进行hash的结果为“BF35B592
通过我们的脚本验证,对比结果,可以看到我们脚本的运行结果也为“BF35B592”

 

cerber勒索软件中对murmurhash算法的使用

cerber勒索软件对murmurhash函数的使用有两点我们要搞清楚。
1.      Murmurhash函数的seed值为什么?
2.      勒索软件调用murmurhash的作用是什么?


对于第一个问题:
通过对cerber软件中murmurhash算法的逆向,可以看到seed的值为0,在下面的代码中的edx的值就为murmurhash算法的初始化的seed值


对于第二个问题


通过上图可以看出,cerber勒索软件中共有5处使用了murmurhash函数,实际上只在三个函数中调用了murmurhash函数,调用murmurhash函数的函数为:
40B074解密出勒索使用的config内容后,解析config内容
409ADE解密字符串函数中使用
401DB9加密文件时,生成murmurhash保存在加密后的文件中
  • 对于40B074处的算法使用:
通过自定义的数据结构填充加密信息,在这个加密信息的结构体中的一项指定的数据就是murmurhash计算的结果值,随后对使用全局的公钥加密这个数据结构,并将对其base64后的结果写入到注册表中。


  • 对于409ADE解密字符串的使用
在解密字符串中,使用murmur hash获得加密字符串的hash:


  • 对于加密文件函数401DB9中的使用
组成下面的数据结构
对这个数据结构所的块进行加密后,写入加密后的文件

 

总结

本文只是对cerber勒索软件中的murmurhash算法进行了分析,对这款勒索软件家族的描述可以参考网络上的其他文章。由于本人也是第一次听说murmur算法,文章为自己分析cerber勒索遇到新的加密算法时的一点学习总结,有分析不恰当的地方,还望海涵。
此条目发表在经验技术分类目录。将固定链接加入收藏夹。