TGViewer
Из Solidity в AI и дальше Из Solidity в AI и дальше @solidityset · 2.47K subscribers
Post #403 167
Ethernaut. Задача 14. Gatekeeper 2

Отступление. Чем больше я разбираю задачи, тем яснее понимаю, что еще многого не знаю. Поэтому некоторые задачи я сейчас пропущу и вернусь к ним, как пройду остальные. Например, с gatekeeper 1 я вчера долго возился, разобрал, но не понял как объяснить ее, и значит "не понял".

Но вернемся к Gatekeeper 2.

В этой задаче нам нужно пройти через все проверки, чтобы наш адрес записался в переменную entrant.
Ссылка на задачу

В чем суть?

Первые два модификатора пройти достаточно просто. GateOne - сделан по примеру задачи Telephone, а gateTwo, с его "ужасным" assembly {x := extcodesize(caller())} - просит, чтобы байткод нашего контракта был равен 0, что бывает в том случае, если там нет никаких функций. Кстати, на extcodesize нельзя полагаться в вопросе безопасности! Не делайте так!

С обоими "воротами" мы можем справиться, вызвав constructor в нашем контракте на GatekeeperTwo.

С третьими воротами сложнее.

Требуется выполнить равенство:

uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ uint64(_gateKey) == uint64(0) - 1

Т.е. мы берем адрес вызывающего функцию, кодируем, получаем хеш через keccac256, потом берем первые 8 байтов. Все это оборачиваем в uint64 и... Приводим к равенству.

Но, что обозначает эта каретка "^". И тут, если не знаешь, то не пройдешь дальше.

А означает она - XOR, или сложение по модулю 2, или исключающее "или". Звучит замысловато, но по сути это побитовое сложение, когда отдельные разряды складываются независимо от других. Например, у нас есть такой порядок бит:

010101

И нужно сложить его с этим

101101

У нас получится:

111000

т.е. "1+1"= 0, "1+0"=1, "0+0"=0.

Самое интересное, что, если мы сложим результат, например со вторым значением, то получим первое. Это мы и должны использовать в задаче.

Получается, что:

uint64(_gateKey) будет равен

uint64(bytes8(keccak256(abi.encodePacked(address(this))))) ^ uint64(0) - 1

Отсюда мы можем получить итоговый контракт для взлома:

contract Hack {
constructor (GatekeeperTwo _gates ) {
bytes8 key;
unchecked {
key = bytes8(uint64(bytes8(keccak256(abi.encodePacked(address(this))))) ^ uint64(0) - 1);
}
_gates.enter(key);
}
}

P.S. unchecked нужен для Solidity 0.8, для защиты от overflow в uint64(0) - 1.

Задача может показаться сложной, если не знаешь про эти побитовые операции. А сколько людей вообще про них знает?!

#ethernaut
  • ❤ 1
More from @solidityset
  1. Oct 8, 2026Промо видео для SaaS и других ваших проектов Хочу поделить с вами одним из своих открытий…
  2. Oct 8, 2026video post
  3. Oct 2, 2026Вторая сложность — как доказать, что установилось именно опубликованное. В первом варианте…
  4. Oct 2, 2026Задача с полуоткрытым кодом На днях, в процессе создания одного приложения, столкнулся с и…
  5. Sep 22, 2026Какой язык программирования учить сейчас? На днях в Твиттере увидел небольшой пост о разви…
  6. Sep 18, 2026Интересная модель Jev Буквально пару дней назад в Твиттере многие начали обсуждение новой…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →