C

Chainhunters

10 min
Blockchain
blockchain
smartcontracts
reverse engineering
Reverse Engineering van Smart Contracts
Reverse engineering van smart contracts is een belangrijk proces voor iedereen die zich bezighoudt met blockchain-technologie, van forensische onderzoekers tot ontwikkelaars die de veiligheid van hun eigen contracten willen waarborgen.

Inleiding

Reverse engineering van smart contracts is een belangrijk proces voor iedereen die zich bezighoudt met blockchain-technologie, van forensische onderzoekers tot ontwikkelaars die de veiligheid van hun eigen contracten willen waarborgen. In deze blogpost leer je wat smart contracts zijn, waarom je reverse engineering zou toepassen en welke methodes, tools en best practices er bestaan om deze complexe analyse uit te voeren.

Wat zijn Smart Contracts?

Smart contracts vormen de ruggengraat van blockchain-gebaseerde applicaties. Ze automatiseren transacties en leggen afspraken vast zonder de tussenkomst van een derde partij. Met deze automatisering komt echter ook de noodzaak voor veiligheid en transparantie. Eventuele fouten of kwetsbaarheden in smart contracts kunnen direct gevolgen hebben voor de gebruikers en hun middelen.

Lees hier meer over wat Smart Contracts zijn: Wat is een Smart Contract?.

Smart contracts zijn zelfuitvoerende programma’s waarbij de voorwaarden tussen koper en verkoper direct in code zijn geschreven. Deze worden opgeslagen en uitgevoerd op een blockchain-platform (zoals Ethereum), waardoor onafhankelijkheid van traditionele financiële instellingen wordt geboden. Doordat de uitvoering van de code openlijk traceerbaar is, wordt vertrouwen gegarandeerd. Een belangrijk nadeel is echter dat alle functionaliteit (in de meeste gevallen) permanent is zodra het contract is gedeployed.

Waarom Reverse Engineering?

Zodra je een smart contract uploadt naar een platform zoals Ethereum, wordt de bytecode publiekelijk zichtbaar (bijvoorbeeld op Etherscan). Als de ontwikkelaar de code niet verifieert, is de originele broncode onzichtbaar en moet je vertrouwen op de gecompileerde bytecode. Dit gebrek aan transparantie kan problematisch zijn voor:

  • Auditors: Die zeker willen weten dat er geen backdoors of verborgen functies in het contract zitten.
  • Onderzoekers: Die willen begrijpen hoe een bepaald contract werkt of forensisch onderzoek willen doen.
  • Ontwikkelaars: Die willen leren hoe succesvolle of interessante smart contracts zijn opgebouwd.

Eenvoudig Voorbeeld

Hieronder vind je een voorbeeld van een heel simpel smart contract in Solidity en de bijbehorende bytecode. Bij niet-geverifieerde contracten zie je alleen de bytecode, wat de eerste stap is in het reverse-engineeringproces.

contract SimpleStorage {
uint private storedData;

    function set(uint x) public {
        storedData = x;
    }
    
    function get() public view returns (uint) {
        return storedData;
    }
}

Gecompileerde bytecode:

608060405234801561001057600080fd5b50610150806100206000396000f3fe

Wanneer je alleen de bytecode hebt, moet je disassembleren en/of decompileren om de werking van deze code te achterhalen.

Methodes en Tools voor Reverse Engineering

1. Bytecode Analyse

Het analyseren van de bytecode is vaak de eerste stap:

2. Symbolische Executie en Fuzzing

  • Symbolische Executie: Met bijvoorbeeld Manticore of Mythril wordt de uitvoer van een smart contract gesimuleerd aan de hand van symbolische inputs. Zo kunnen path-afhankelijkheden en logische fouten aan het licht komen.
  • Fuzzing: Door grote hoeveelheden semi-willekeurige invoer te genereren, kun je kijken of het contract onder specifieke omstandigheden faalt of onverwacht gedrag vertoont.

3. Manual Code Review

Ondanks de kracht van geautomatiseerde tools blijft handmatig onderzoek essentieel. Veel kwetsbaarheden zijn logisch of contextueel en kunnen alleen ontdekt worden door een ontwikkelaar of onderzoeker die begrijpt welk gedrag er wordt verwacht.

4. Aanvullende Tools en Best Practices

  • Slither: Een statische analysetool voor Solidity die snel veelvoorkomende problemen kan detecteren.
  • Echidna: Een fuzzer voor smart contracts, ontwikkeld door Crytic (Trail of Bits).
  • Testnet Deployments: Als je toegang hebt tot (een deel van) de broncode, kun je deze op een testnet deployen en vergelijken met de originele bytecode.
  • Verifieer via Etherscan: Als de oorspronkelijke ontwikkelaar de code niet heeft geverifieerd, kun je zelf proberen de bytecode met jouw lokale compilatie te matchen.

Reverse Engineering in Actie: Het CryptoKitties Smart Contract

Een van de meest iconische voorbeelden is het contract achter CryptoKitties. Hieronder vind je enkele links naar de bytecode en gedecompileerde code:

Stap 1: Bytecode Inspectie

De EVM-opcodes kunnen bijvoorbeeld als volgt starten:

PUSH1 0x60
PUSH1 0x40
MSTORE
CALLVALUE
DUP1
ISZERO
PUSH2 0x0036
JUMPI

Stap 2: Decompiled Code Analyse

Na decompilatie kan een Solidity-achtig script verschijnen:

function transfer(address _to, uint256 _tokenId) public {
require(_to != address(0));
require(ownerOf(_tokenId) == msg.sender);
_transfer(msg.sender, _to, _tokenId);
}

Stap 3: Symbolische Executie en Fuzzing

Hieronder een voorbeeld van hoe je Manticore zou kunnen gebruiken om symbolische tests te draaien:

from manticore.ethereum import ManticoreEVM

m = ManticoreEVM()
user = m.create_account(balance=1000)
contract = m.solidity_create_contract('''
contract CryptoKitties {
function transfer(address _to, uint256 _tokenId) public {
require(_to != address(0));
// Stel je voor dat er een ownerOf() functie bestaat
require(ownerOf(_tokenId) == msg.sender);
_transfer(msg.sender, _to, _tokenId);
}
}
''', owner=user)

to_addr = m.make_symbolic_value()
token_id = m.make_symbolic_value()

contract.transfer(to_addr, token_id)
m.finalize()

Stap 4: Handmatige Code Review

Wanneer de broncode wel beschikbaar is, blijft een handmatige review onmisbaar om:

  • Contextuele Fouten: Onlogische business rules of verkeerde implementaties van ERC-standaarden te ontdekken.
  • Kwaliteitscontrole: Te controleren of er geen ‘gebruiksvriendelijke’ bugs of opzettelijk schadelijke functionaliteiten zijn.

Praktijkoefening: Bytecode Herleiden

Probeer eens de onderstaande bytecode te herleiden naar de oorspronkelijke Solidity-code en test je reverse-engineeringvaardigheden.

0x608060405234801561000f575f80fd5b5060043610610029575f3560e01c806375cd6fe01461002d575b5f80fd5b61003561004b565b60405161004291906100f8565b60405180910390f35b60606040518060400160405280600d81526020017f476f65642067656461616e212100000000000000000000000000000000000000815250905090565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6100ca82610088565b6100d48185610092565b93506100e48185602086016100a2565b6100ed816100b0565b840191505092915050565b5f6020820190508181035f83015261011081846100c0565b90509291505056fea2646970667358221220e508a7b26b1035deb0de68430764dd686ed8ec2af10b5b70f524b730eaa7cf3564736f6c634300081a0033

Kun je ontdekken wat de functies doen en het verborgen bericht in de code vinden? Tools als disassemblers, decompilers en symbolische executie zijn je beste vrienden bij dit soort uitdagingen.

Conclusie

Reverse engineering van smart contracts is essentieel om:

  • Verborgen Functionaliteit te ontdekken
  • Kwetsbaarheden op te sporen en te analyseren
  • Security Audits uit te voeren
  • Betrouwbaarheid te verifiëren

Een goed begrip van EVM-opcodes, Solidity, tools voor decompilatie en statische analyse, en het toepassen van handmatige audits is cruciaal voor het bouwen aan een veiliger en transparanter blockchain-ecosysteem.