首页 > 其他分享 >挖矿流量分析之Stratum挖矿协议

挖矿流量分析之Stratum挖矿协议

时间:2024-05-05 14:44:26浏览次数:21  
标签:hash 流量 哈希 Stratum 矿池 区块 id 挖矿

目录

前言

之前做了一个关于“挖矿行为检测”的大创训练项目,在这里记录一下我关于挖矿检测相关内容的学习。

区块链和挖矿相关概念

区块链

首先需要了解一些关于区块链的内容。注意,区块链和挖矿是两个紧密相关但又各自独立的概念,它们并不是同一件事。

区块链是一种分布式账本技术,它通过去中心化的方式安全地记录交易数据。每个区块包含一组交易记录,并通过加密的方式与前一个区块链接起来,形成一个不可篡改的链式结构。这种设计使得区块链具有很高的安全性和透明性。

简单地说,区块链就好比一个公共的账簿,任何人都可以查看账簿中的记录,但一旦记录被写入,就很难更改或删除。这本账簿由网络中的许多人共同维护,每个人都持有账簿的副本。如果想要修改某一条记录,那么就要修改所有的人手中账簿的记录,这是很难做到的。因此很难对其进行篡改。

区块链的几个核心特点:去中心化、不可篡改、透明性、共识机制、智能合约等。

区块

区块链的一个核心组成部分就是区块,区块链也可以说是由多个区块按照时间顺序连接形成的链式数据结构。

每个区块通常包含以下内容:

  • 区块头(Block Header):区块头包含了区块的元数据:
    版本号:表示区块遵循的协议版本
    前一区块的哈希值:前一区块的哈希值确保了区块的顺序和不可篡改性
    Merkle根:一种哈希树的根节点,它代表了区块中所有交易的集合,通过它可以快速验证区块中交易的存在性和有效性
    时间戳:记录区块被创建的时间
    难度目标(Target):挖矿难度的表示,用于挖矿过程中的工作量证明
    Nonce(随机数):挖矿过程中使用的一个随机数,用于生成满足特定条件的区块哈希值

  • 交易列表(Transaction List):区块中包含的交易,它们是区块的主体部分:
    发送者和接收者的公钥或地址
    交易金额
    交易的附加信息,如交易费用、时间戳等

  • 区块大小:区块中所有交易数据的总大小,这个大小通常有最大限制,以保证网络的效率

  • 区块哈希(Block Hash):区块头通过哈希函数加密后得到的哈希值,代表了整个区块的独特标识

访问这个网站:https://blockchair.com/ 可以浏览各类加密货币的区块情况。

比如下图中的Bitcoin blocks,可以清晰的看到此时最新的一个比特币块为842040,这个块的哈希值为00000...e11a0,时间戳为2024-05-04 10:30:57UTC,由矿工Foundry USA Pool挖到。

image

区块链相关概念就了解这么多,接下来看看挖矿是怎么回事。

挖矿相关术语

  • 矿机:矿机是专门用于挖矿的硬件设备,矿机通常有强大的计算能力。

  • 矿池:是一群矿工联合起来共同挖矿的平台,通过提供他们的计算能力合作解决问题,然后按贡献的大小分配奖励。

  • 钱包:在区块链和加密货币领域,钱包是用于管理用户的公有和私有密钥、发送和接受数字货币、查看余额等。

挖矿 是个将待确认的交易数据包含到区块链中,从而完成对这些交易进行确定的分布式共识系统。

挖矿的目的是什么?

通过挖矿,可以强制性保证块链中的数据按时间顺序存储,保持比特币网络的中立性,且允许比特币网络上不同的计算机对系统状态达成一致。交易要获得确认,必须要被打包到一个符合非常严格的密码学规则的区块中,并通过比特币网络进行验证。这些规则可以防止对已有块的修改,因为一旦有改动,之后所有的块都将失效。挖矿的难度和中彩票相当,没人可以轻易地、连续地将新块加入到块链中。因此,没有集体和个人可以控制块链中包含什么样的内容或者替换掉块链中的部分内容以达到撤销他们交易的目的。

这就是一个达到共识的过程,网络中的节点通过共识机制来验证和记录新的交易,常见的共识机制包括工作量证明(PoW)和权益证明(PoS)。

下面这个脚本大致描述了挖矿的过程:

# 挖矿函数示例工作量证明(PoW)
def mine_block(version, previous_block_hash, merkle_root_hash, time_stamp, difficulty):
    '''
    计算当前的区块头数据的SHA-256哈希值,改变nonce随机数,直到计算出小于目标值的hash

    version 版本
    previous_block_hash 前一个区块头的哈希值
    merkle_root_hash 当前块默克尔树根的哈希值,当前区块所有交易产生的默克尔树根节点的哈希值
    time_stamp 时间戳
    difficulty 当前区块PoW算法的难度值
    nonce 随机数
    '''

    # 根据当前难度值计算出一个目标值(控制在大约10分钟的计算量)
    # 难度值受到网络上的总计算能力的影响,挖矿的难度会根据网络上的总计算能力进行自动调整
    target = calculate_target(difficulty)
    nonce = 0

    while True:
        # 构建区块头数据
        block_header = f"{version}{previous_block_hash}{merkle_root_hash}{time_stamp}{difficulty}{nonce}".encode('utf-8')
        # 计算SHA-256哈希值(两次)
        hash_temp = hashlib.sha256(block_header).hexdigest()
        hash_result = hashlib.sha256(hash_temp.encode()).hexdigest()
        # 将哈希值转换为大整数与target比较,是否达到目标
        hash_int = int(hash_result, 16)
        if hash_int < target:
            print("Nonce:", nonce)
            print("Hash:", hash_result)
            break

        # 随机数+1(运算在千亿次数量级)
        nonce += 1

简单地说,挖矿就是不断修改区块头中的参数,并计算区块头的散列值,直到其散列值与目标难度相匹配的过程。散列函数的结果无法提前得知,也没有能得到一个特定散列值的模式,所以这个过程十分消耗计算资源。

聊了这么多,区块链和挖矿的概念这些都不是重点,大概了解就好。重点是恶意的挖矿木马会对的主机造成严重的影响,要通过一些手段把识别这些恶意程序,并做出应急的处置。

挖矿木马

市面上除了比特币,还有很多其他加密货币。比如以太坊(ETH)、莱特币(LTC)、门罗币(XMR)等。

挖矿木马的常见样本

  • CoinHive:这是最常见的挖矿病毒之一,它通过JavaScript在用户的浏览器中运行来挖取Monero。

  • XMRig:此病毒通常以开源软件的形式提供,用于CPU挖矿,专门针对Monero加密货币。

  • WannaMine:这是一种基于WannaCry勒索软件的挖矿病毒。它使用EternalBlue漏洞来传播,并在受感染的机器上秘密挖矿。

还有非常多各种类型的挖矿木马,这里不介绍了。

挖矿木马控制机器挖矿的方式

  1. 可执行文件:存储在机器上的典型恶意程序,通常通过设置计划任务或修改注册表项实现持久化,长期进行加密货币的挖矿作业。

  2. 基于浏览器的挖矿木马:使用JavaScript(或类似技术)的挖矿木马是在浏览器中执行。只要浏览器打开被植入挖矿木马的网站,就会执行挖矿执行,持续消耗资源。

  3. 无文件挖矿木马:利用如PowerShell等合法工具在机器的内存中执行挖矿作业,具有不落地、难检测等特点。

挖矿木马行为特征

挖矿木马显著的行为特征就是极大的占用CPU及GPU资源。主要包括:CPU和GPU使用率高、响应速度慢、 崩溃或频繁重新启动、系统过热、异常网络活动。其次是在网络流量中,挖矿木马通信过程采用专门的通信协议,因此存在一定的网络通信特征。

检测方法

  • 方法1 网络侧检测:通信内容检测和矿池地址域名请求DNS请求历史记录检测。

  • 方法2 主机检测:对应进程CPU使用率长时间居高不下,部分挖矿木马采用多方式隐藏进程,且具备多种持久化驻留方式。

我们采用的是基于网络侧检测的方案,主要是分析挖矿数据包中的一些特征值进行检测。

挖矿协议Stratum

Stratum协议在2012年被提出,目的是扩展对矿池挖矿的支持,并取代了旧的getwork协议。Stratum协议允许矿机通过TCP连接与矿池使用 JSON-RPC 2.0 消息编码进行通信,从而接收挖矿任务并提交工作证明。

Stratum工作过程

1. 矿机连接服务器

矿机使用 mining.subscribe 方法连接矿池,订阅当前连接。

{
    "id": 1,
    "method": "mining.subscribe",
    "params": []
}

矿池返回相关信息,需要矿工记录在本地。

{
  "id": 1,
  "result": [
    [
      "mining.set_difficulty",
      "subscription id 1"
    ],
    [
      "mining.notify",
      "subscription id 2"
    ]
  ],
  "08000002": 4,
  "error": null
}

mining.set_difficulty:用于矿池去设置矿机当前提交任务的最大难度值。

mining.notify:用于矿池向矿机发送新的挖矿任务。

extranonce1:十六进制编码,每个连接唯一的字符串,稍后将用于创建生成的事务。

extranonce2_size:指定在挖矿过程中使用的额外随机数(extranonce2)的大小。

在上面这个示例 "08000002": 4 其中 08000002 表示extranonce1的值,4 表示extranonce2的长度为4字节。

2. 矿工认证

矿机使用 mining.authorize 方法向矿池提供登录凭证,矿池根据提供的信息验证矿工的权限。

{
    "id": 2,
    "params": [
        "miner",
        "password"
    ],
    "method": “mining.authorize”
}

矿池返回授权。

{
   "error": null,
   "id": 2,
   "result": true
}

注意这里的这个id号是用来区矿工和矿池的应答消息的,并不是矿工的id。因为矿池的应答消息结构有些很类似,矿机就是通过消息的id来区别这些消息是对应哪个发送消息的应答。

还有通过 jsonrpc 方式登录的,下面会提到。

3. 矿池向矿机下发挖矿工作任务

当矿池在被订阅之后,会使用 mining.notify 方法给矿机发送最少一个工作任务。

{
    "params": [
        "bf",
        "4d16b6f85af6e2198f44ae2a6de67f78487ae5611b77c6c0440b921e00000000",
        "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff20020862062f503253482f04b8864e5008",
        "072f736c7573682f000000000100f2052a010000001976a914d23fcdf86f7e756a64a7a9688ef9903327048ed988ac00000000",
        [],
        "00000002",
        "1c2ac4af",
        "504e86b9",
        false
    ],
    "id": null,
    "method": "mining.notify"
}

按顺序描述 params 中每个字段:

  • job_id:任务号id,每一次任务都有唯一的标识符

  • prevhash:前一个区块的hash值

  • coinb1:coinbase币基交易的最初部分

  • coinb2:coinbase币基交易的最后部分

  • merkle_branch:交易列表(hash),用于计算merkle根

  • version:区块版本号

  • nbits:当前区块难度,也是当前每个矿池全网的难度

  • ntime:当前的时间戳

  • clean_jobs:如果为true,矿工应该退出当前工作,立即开始新的工作,如果为false,矿工仍然可以继续当前的挖矿工作

4. 矿机开始挖矿

  1. 构建 coinbase 信息

为什么需要构造coinbase信息?

coinbase交易的存在是网络共识算法的一部分,coinbase交易是每个新区块中的第一个交易,它确认了区块的创建和挖矿过程的成功。在挖矿过程中,矿工需要找到一个特定的哈希值,就修改coinbase交易中的Nonce字段并重新计算区块哈希。

总之,构造coinbase信息对于挖矿过程至关重要,它不仅是矿工获得奖励的手段,也是维护区块链安全性和完整性的关键环节。

构建coinbase信息要用到的数据:coinb1,extranonce1,extranonce2_size,coinb2

在上面的交互过程中已知extranonce2_size,所以能够产生有效的extranonce2。构造coinbase只需要把这几个部分拼接起来:

coinbase =  coinb1 + extranonce1 + extranonce2 + coinb2

当然这个conbase还需要进行2次hash运行,投入后面的使用:

# python脚本示例

import hashlib
import binascii
coinbase_hash_bin = hashlib.sha256(hashlib.sha256(binascii.unhexlify(coinbase)).digest()).digest()
  1. 计算 Merkle 根

基本的coinbase构建完毕了,现在就需要把区块中的其他交易给联系起来,需要计算一个merkleroot。

为什么是 Merkle 根?

Merkle树(也称为二叉哈希树)是一种数据结构,从区块内所有交易的哈希值开始构建,将这些哈希值配对,然后计算每个配对的哈希值,形成第二层。这个过程递归地重复,直到生成单个哈希值,即Merkle根(Merkle Root)。Merkle树允许通过Merkle证明快速验证区块中单个交易的存在性,任何对树中数据的更改都会导致Merkle根的变化。

所以说只要Merkle根没变,区块中的交易就没变。想要证明某个交易是区块的一部分时,就只需要提供Merkle根,无需提供整个区块的数据,这大大提高了效率。

构建Merkle根,利用 coinbase 和 merkle_branch 两两配对,然后把配对完成后进行2次hash运算,得到上一层的结果,然后重复上面的过程,继续配对计算,最终得到Merkle根。

# python脚本示例

import binascii
def build_merkle_root(self, merkle_branch, coinbase_hash_bin):
        merkle_root = coinbase_hash_bin
        for h in self.merkle_branch:
                merkle_root = doublesha(merkle_root + binascii.unhexlify(h))
        return binascii.hexlify(merkle_root)
  1. 构建区块头

填充余下的5个字段:

block_header = version + prevhash + merkle_root_hash + ntime + nbits + nonce

5. 矿机向矿池提交工作量

当矿工发现符合请求难度的任务,会使用 mining.submit 方法提交给矿池这样的share:

{
    "params": [
        "miner",
        "bf",
        "00000001",
        "504e86ed",
        "b2957c02"
    ],
    "id": 4,
    "method": "mining.submit"
}

按顺序描述 params 中每个字段:

  • worker_name:之前认证过的账号

  • job_id:任务号id

  • extranonce2:随机数extranonce2的值

  • ntime:时间戳

  • nonce:随机值

矿池拿到以上5个字段后,首先根据任务号id找出之前分配任务前存储的信息,然后重构区块,再验证share难度,对于符合难度要求的share,在检测是否符合全网难度。

默认share难度是1(难度1的目标是0x00000000ffff0000000000000000000000000000000000000000000000000000),矿池偶尔可以要求矿工更改share难度:

{
    "id": null,
    "method": "mining.set_difficulty",
    "params": [2]
}

这意味着收到服务器工作任务的矿工下一条任务讲改为难度2,这个数字的意思是派给矿机的任务难度是1个单位难度值的2倍。

关于更多Stratum的内容参考:https://en.bitcoin.it/wiki/Stratum_mining_protocol#mining.subscribe

标签:hash,流量,哈希,Stratum,矿池,区块,id,挖矿
From: https://www.cnblogs.com/smileleooo/p/18172605

相关文章

  • NSSCTF流量分析
    1.[BSidesSF-CTF2019]Zippync-l-p4445>flag.zipunzip-Psupercomplexpasswordflag.zipArchive:flag.zipinflating:flag.txtPK.... ...NdbN..,.%...........flag.txtUT ....z\..z\ux...............(.y..z....F.......:...#Bz..:......
  • 在Windows防火墙设置中,允许单播响应(Unicast Response)是一个控制选项,用于允许或禁止系
    在Windows防火墙设置中,允许单播响应(UnicastResponse)是一个控制选项,用于允许或禁止系统对多播或广播网络流量的单播响应。让我详细解释一下允许和禁止单播响应的区别:允许单播响应(是):当设置为“是”时(默认值),Windows系统会允许对多播或广播网络流量的单播响应。这意味着当系......
  • 容器网络流量转发分析
    1、docker容器bridge网络模式【docker】#同一节点不同容器流量转发1.1、通过iptables-tnat-nvL|grep6008查看端口服务的转发规则,可查到对应的容器ip、端口和网卡1.2、查看容器路由表,172.17.0.x目标网段,流量会从eth0出去和进来【veth网络设备接口的一端】 1.3、查看......
  • 技术探秘:如何利用仪表构造InfiniBand流量在数据中心测试中的应用
    一、什么是Infiniband?在当今数据爆炸的时代,数据中心作为信息处理的中心枢纽,面临着前所未有的挑战。传统的通信方式已经难以满足日益增长的数据传输需求,而InfiniBand技术的出现,为数据中心带来了全新的通信解决方案。InfiniBand(IB)是一种高性能计算和数据中心网络架构,其设计目标是......
  • linux实战-挖矿
    简介应急响应工程师在内网服务器发现有台主机cpu占用过高,猜测可能是中了挖矿病毒,请溯源分析,提交对应的报告给应急小组虚拟机账号密码rootwebsecyjxyweb端口为80811、黑客的IP是?flag格式:flag{黑客的ip地址},如:flag{127.0.0.1}2、黑客攻陷网站的具体时间是?flag格式:flag......
  • 流量特征分析-常见攻击事件 tomcat
    简介1、在web服务器上发现的可疑活动,流量分析会显示很多请求,这表明存在恶意的扫描行为,通过分析扫描的行为后提交攻击者IPflag格式:flag{ip},如:flag{127.0.0.1}2、找到攻击者IP后请通过技术手段确定其所在地址flag格式:flag{城市英文小写}3、哪一个端口提供对web服务器管......
  • 流量特征分析-蚁剑流量分析
    简介1.木马的连接密码是多少2.黑客执行的第一个命令是什么3.黑客读取了哪个文件的内容,提交文件绝对路径4.黑客上传了什么文件到服务器,提交文件名5.黑客上传的文件内容是什么6.黑客下载了哪个文件,提交文件绝对路径步骤#1.1步骤#1.2黑客执行的第一个命令是什么,因为找的......
  • Windows 防火墙是Windows操作系统中内置的网络安全功能,用于保护服务器免受网络攻击和
    Windows 防火墙是Windows 操作系统中内置的网络安全功能,用于保护服务器免受网络攻击和未经授权的访问。它可以帮助管理员限制进入和离开服务器的网络流量,以及监控网络通信并采取相应的安全措施。以下是Windows 防火墙的一些特点和功能:网络流量过滤:防火墙可以根据管......
  • 精武杯-流量手机介质
    介质1.请综合分析计算机和手机检材,计算机最近一次登录的账户名是admin2.请综合分析计算机和手机检材,计算机最近一次插入的USB存储设备串号是S3JKNX0JA05097Y 3.请综合分析计算机和手机检材,谢弘的房间号是()室201在文档中存在一个加密容器storage和三个压缩文件,全部导......
  • 1500PLC通过Modbus转Profinet网关与流量计Modbus通讯
     Modbus转Profinet网关(XD-MDPN100)是一种能够实现Modbus协议和Profinet协议之间转换的设备。通过使用Modbus转Profinet网关,可以实现流量计与1500PLC之间的高效通讯,使得设备之间的数据交换更加便捷和高效。1500PLC作为控制器,与Modbus转Profinet网关的结合,为工业控制系统的稳定运行......