So simulieren Sie den DAO-Angriff mit Truffle und testRPC [geschlossen]

Ich möchte den rekursiven DAO-Angriff simulieren. Können Sie bitte die Schritte zum Simulieren des Angriffs mit Truffle mithilfe von TestRPC definieren.

Dies ist ein gutes Beispiel dafür, wie ein DAO-Exploit funktioniert ethernaut.zeppelin.solutions/level/…
@cleanunicorn füge dies bitte als Antwort hinzu.
Ich habe den Link als Antwort mit einer Erklärung hinzugefügt

Antworten (2)

  1. Erstellen Sie Ihren Vertrag DAOHack.solund speichern Sie ihn im Vertragsordner .
  2. Erstellen Sie eine 2_deploy.jsMigrationsdatei und speichern Sie sie im Migrationsordner .
  3. Geben Sie Netzwerkparameter in an truffle.js.
  4. Kompilieren Sie Verträge, indem Sie truffle compile.
  5. Auf ganache-clidem in angegebenen Port ausführen truffle.js.
  6. Stellen Sie Verträge für das Testnetzwerk bereit, indem Sie Folgendes ausführen: truffle migrate.

Wenn Sie später eine Adresse von Smart Contracts benötigen, können Sie diese in diesem Schritt kopieren.


Als nächstes können Sie entweder einen Test machen oder eine kleine App erstellen.

  • Im Falle eines Tests müssen Sie Ihren Test erstellen und einfach ausführen truffle test test/DAOHack.js.
  • Es wäre zu weit gefasst zu beschreiben, wie man eine App erstellt, um es auf den Punkt zu bringen, wenn die App fertig ist, werden Sie Ihren Server einfach wie ausführen lite-server.

Für eine detailliertere Erklärung sollten Sie in die Truffle-Dokumentation eintauchen .

Beachten Sie, dass TestRPCdies jetzt der Fall ist Ganache-cli.

es funktioniert nicht richtig. Außerdem müssen wir viele Änderungen vornehmen, um den Vertrag bereitzustellen.

Ein sehr guter Proof of Concept, wie der DAO-Hack funktioniert, ist dieser https://ethernaut.zeppelin.solutions/level/0xf70706db003e94cfe4b5e27ffd891d5c81b39488

Es gibt ein paar Schritte, um dies zu reproduzieren.

Sie brauchen einen Vertrag wie diesen

pragma solidity ^0.4.18;

contract Reentrance {

mapping(address => uint) public balances;

function donate(address _to) public payable {
    balances[_to] += msg.value;
}

function balanceOf(address _who) public constant returns (uint balance) {
    return balances[_who];
}

function withdraw(uint _amount) public {
    if(balances[msg.sender] >= _amount) {
    if(msg.sender.call.value(_amount)()) {
        _amount;
    }
    balances[msg.sender] -= _amount;
    }
}

function() payable {}
}

Dann müssen Sie ein Vertragskonto erstellen, das Gelder an den ReentranceVertrag sendet. Dies wird Ihr Angriffspunkt sein.

Ihr Vertrag muss Folgendes können:

  • Senden Sie Geld an Reentrance, insbesondere rufen Sie donate()mit Ether-Wert an. Dieser Wert wird für Ihre Adresse gespeichert
  • withdraw()Haben Sie eine standardmäßige kostenpflichtige Funktion, die erneut aufruft
  • Anruffunktion withdraw()einReentrance

Wenn Sie die standardmäßige kostenpflichtige Funktion haben, die aufruft, withdraw()entsteht eine Endlosschleife . Es ist eine Endlosschleife, aber sie stoppt, wenn das gesamte Gas verbraucht ist. Je mehr Gas Sie senden, desto mehr Schleifen können iterieren und somit mehr Geld abheben.

Da das Gas aufgebraucht ist, wird die Bilanz nie aktualisiert, aber der Ether bleibt gesendet.