From 4ff9c1cc98fdec3861034eb811538c35d61f145d Mon Sep 17 00:00:00 2001 From: Patrick Mylund Nielsen Date: Thu, 27 Jul 2017 14:46:07 -0400 Subject: [PATCH] Add Porosity examples --- examples/7nodes/porosity/README.md | 4 +++ .../7nodes/porosity/deploy-nonvulnerable.js | 19 ++++++++++++ examples/7nodes/porosity/deploy-vulnerable.js | 16 ++++++++++ examples/7nodes/porosity/scan.js | 29 +++++++++++++++++++ examples/7nodes/script1.js | 20 ++++++------- 5 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 examples/7nodes/porosity/README.md create mode 100644 examples/7nodes/porosity/deploy-nonvulnerable.js create mode 100644 examples/7nodes/porosity/deploy-vulnerable.js create mode 100644 examples/7nodes/porosity/scan.js diff --git a/examples/7nodes/porosity/README.md b/examples/7nodes/porosity/README.md new file mode 100644 index 0000000..21dc763 --- /dev/null +++ b/examples/7nodes/porosity/README.md @@ -0,0 +1,4 @@ +This demonstrates how to use Matt Suiche's Porosity decompiler from +inside Quorum. Try to `runscript.sh porosity/deploy-vulnerable.js`, +then `runscript.sh porosity/scan.sh` to see it in action, or use it +interactively in the console with `quorum.runPorosity`. diff --git a/examples/7nodes/porosity/deploy-nonvulnerable.js b/examples/7nodes/porosity/deploy-nonvulnerable.js new file mode 100644 index 0000000..a1c5f8b --- /dev/null +++ b/examples/7nodes/porosity/deploy-nonvulnerable.js @@ -0,0 +1,19 @@ +a = eth.accounts[0] +web3.eth.defaultAccount = a; + +var simpleSource = 'contract simplestorage { uint public storedData; function simplestorage(uint initVal) { storedData = initVal; } function set(uint x) { storedData = x; } function get() constant returns (uint retVal) { return storedData; } }' +var simpleCompiled = web3.eth.compile.solidity(simpleSource); +var simpleRoot = Object.keys(simpleCompiled)[0]; +var simpleContract = web3.eth.contract(simpleCompiled[simpleRoot].info.abiDefinition); +var simple = simpleContract.new(42, {from:web3.eth.accounts[0], data: simpleCompiled[simpleRoot].code, gas: 300000, privateFor: ["ROAZBWtSacxXQrOe3FGAqJDyJjFePR5ce4TSIzmJ0Bc="]}, function(e, contract) { + if (e) { + console.log("err creating contract", e); + } else { + if (!contract.address) { + console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined..."); + } else { + console.log("Contract mined! Address: " + contract.address); + console.log(contract); + } + } +}); diff --git a/examples/7nodes/porosity/deploy-vulnerable.js b/examples/7nodes/porosity/deploy-vulnerable.js new file mode 100644 index 0000000..984f1b7 --- /dev/null +++ b/examples/7nodes/porosity/deploy-vulnerable.js @@ -0,0 +1,16 @@ +var src = 'contract SendBalance { mapping ( address => uint ) userBalances ; bool withdrawn = false ; function getBalance (address u) constant returns ( uint ){ return userBalances [u]; } function addToBalance () { userBalances[msg.sender] += msg.value ; } function withdrawBalance (){ if (!(msg.sender.call.gas(0x1111).value ( userBalances [msg . sender ])())) { throw ; } userBalances [msg.sender ] = 0; } }'; +var compiled = web3.eth.compile.solidity(src); +var root = Object.keys(compiled)[0]; +var contract = web3.eth.contract(compiled[root].info.abiDefinition); +var c = contract.new(42, {from:web3.eth.accounts[0], data: compiled[root].code, gas: 300000, privateFor: ["ROAZBWtSacxXQrOe3FGAqJDyJjFePR5ce4TSIzmJ0Bc="]}, function(e, contract) { + if (e) { + console.log("err creating contract", e); + } else { + if (!contract.address) { + console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined..."); + } else { + console.log("Vulnerable contract mined! Address: " + contract.address); + console.log(contract); + } + } +}); diff --git a/examples/7nodes/porosity/scan.js b/examples/7nodes/porosity/scan.js new file mode 100644 index 0000000..dbf42f0 --- /dev/null +++ b/examples/7nodes/porosity/scan.js @@ -0,0 +1,29 @@ +function scanBlock(blockNumber) { + var b = eth.getBlock(blockNumber); + for (var i = 0; i < b.transactions.length; i++) { + var tx = eth.getTransaction(b.transactions[i]); + var code; + if (tx.v == 37 || tx.v == 38) { // private + code = quorum.getPrivatePayload(tx.input); + if (code === "0x") { + continue // we weren't a party to this transaction + } + } else { + // code = tx.input; + continue; // skip public transactions + } + var isVulnerable = quorum.runPorosity({"code": code, "decompile": true, "silent": true}) + if (isVulnerable) { + console.log("Reentrant vulnerability in block " + tx.blockNumber + + ":\nTransaction: " + tx.hash + + "\nFrom: " + tx.from + + "\nTo: " + (tx.to === null ? "Contract creation" : tx.to) + ); + } + } +} + +console.log("Scanning all private transactions for vulnerabilities"); +for (var i = 0; i < eth.blockNumber; i++) { + scanBlock(i); +} diff --git a/examples/7nodes/script1.js b/examples/7nodes/script1.js index c260796..a1c5f8b 100644 --- a/examples/7nodes/script1.js +++ b/examples/7nodes/script1.js @@ -6,14 +6,14 @@ var simpleCompiled = web3.eth.compile.solidity(simpleSource); var simpleRoot = Object.keys(simpleCompiled)[0]; var simpleContract = web3.eth.contract(simpleCompiled[simpleRoot].info.abiDefinition); var simple = simpleContract.new(42, {from:web3.eth.accounts[0], data: simpleCompiled[simpleRoot].code, gas: 300000, privateFor: ["ROAZBWtSacxXQrOe3FGAqJDyJjFePR5ce4TSIzmJ0Bc="]}, function(e, contract) { - if (e) { - console.log("err creating contract", e); - } else { - if (!contract.address) { - console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined..."); - } else { - console.log("Contract mined! Address: " + contract.address); - console.log(contract); - } - } + if (e) { + console.log("err creating contract", e); + } else { + if (!contract.address) { + console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined..."); + } else { + console.log("Contract mined! Address: " + contract.address); + console.log(contract); + } + } });