Capture The Ether. Miscellaneous
Задача 1
Тут нужно захватить ownership.
Такие задачи мы уже решали. Обратите внимание на написание функции, которая должна выполнять роль конструктора. Нам не потребуется даже писать другой контракт.
Задача 2
Пример контракта на атаку reentrancy.
Здесь нужно знать различия ERC20 и ERC223, которое заключается в том, что при отправке токенов вызывается дополнительная функция tokenFallback(). Из этого можно подготовить атаку.
Создать контракт и от его имени пополнить банк на весь доступный баланс токенов (500к). Создать свою функцию tokenFallback(), которая будет отправлять дополнительный запрос на вывод средств. Затем просто вызвать withdraw().
#capture #cte
Задача 1
Тут нужно захватить ownership.
Такие задачи мы уже решали. Обратите внимание на написание функции, которая должна выполнять роль конструктора. Нам не потребуется даже писать другой контракт.
Задача 2
Пример контракта на атаку reentrancy.
Здесь нужно знать различия ERC20 и ERC223, которое заключается в том, что при отправке токенов вызывается дополнительная функция tokenFallback(). Из этого можно подготовить атаку.
Создать контракт и от его имени пополнить банк на весь доступный баланс токенов (500к). Создать свою функцию tokenFallback(), которая будет отправлять дополнительный запрос на вывод средств. Затем просто вызвать withdraw().
#capture #cte
Как узнать публичный ключ из транзакции?
Нашел интересный сайт, который позволяет получать публичный ключ из raw hash транзакции.
Нужно для начала провести транзакцию с адреса, затем получить на etherscan или где-то еще raw hash, потом заходите на сайт, выбираете пункт Transaction и вставляете туда хеш.
Сайт проекта.
#public #key #tx #raw
Нашел интересный сайт, который позволяет получать публичный ключ из raw hash транзакции.
Нужно для начала провести транзакцию с адреса, затем получить на etherscan или где-то еще raw hash, потом заходите на сайт, выбираете пункт Transaction и вставляете туда хеш.
Сайт проекта.
#public #key #tx #raw
Заметка от меня
В последнее время на канале было большое количество задач, разборов и поиска уязвимостей в контрактах. Предполагаю, что некоторым участникам это могло немного надоесть. Теперь я хочу немного разбавить контент на канале.
Задача все также останутся на канале. После всего пройденного я более чем уверен, что разборы заданий помогут нам смотреть на контракты под другим углом и видеть "проблемы" там, где обычные разработчики их упускают. При этом мы будем брать только одну задачу в день. Чтобы все смогли посмотреть ее и попробовать решить самим.
Вместе с этим будут появляться материалы по другим основам блокчейн разработки, как например, сегодня я планирую сделать несколько постов про использование дебагера в ремиксе, а чуть позже поговорить про опкод.
Также мне интересно в ближайшее время вспомнить и подучить ethers, и как его использовать на фроненде.
Другими словами, хочется сделать чтобы на канале за день проходили посты: разбор уязвимости контракта, новое по блокчейну и кодингу, работа с фронтендом, и, возможно, будем поднимать знания по биржам и экономическим факторам. Первые два обязательно, остальные - по силам.
Вот как-то так.
Всем приятного дня и легкого обучения!
В последнее время на канале было большое количество задач, разборов и поиска уязвимостей в контрактах. Предполагаю, что некоторым участникам это могло немного надоесть. Теперь я хочу немного разбавить контент на канале.
Задача все также останутся на канале. После всего пройденного я более чем уверен, что разборы заданий помогут нам смотреть на контракты под другим углом и видеть "проблемы" там, где обычные разработчики их упускают. При этом мы будем брать только одну задачу в день. Чтобы все смогли посмотреть ее и попробовать решить самим.
Вместе с этим будут появляться материалы по другим основам блокчейн разработки, как например, сегодня я планирую сделать несколько постов про использование дебагера в ремиксе, а чуть позже поговорить про опкод.
Также мне интересно в ближайшее время вспомнить и подучить ethers, и как его использовать на фроненде.
Другими словами, хочется сделать чтобы на канале за день проходили посты: разбор уязвимости контракта, новое по блокчейну и кодингу, работа с фронтендом, и, возможно, будем поднимать знания по биржам и экономическим факторам. Первые два обязательно, остальные - по силам.
Вот как-то так.
Всем приятного дня и легкого обучения!
🔥3
Задача на день
Эта задача была в Paradigm CTF 2021.
Я прикрепил два файла контрактов для тех, кто захочет сам посмотреть и решить их. Вообще, это задание на внимательность и знание стандарта ERC20.
Целью является заполучить 50 Эфиров на баланс контракта Setup.
Маленькая подсказка: не усложняйте! Все проще, чем кажется.
Ну, и вопрос по такому формату: Нужно ли прикладывать решение или делать пост с ним в конце дня?
UPD. Решение.
После пары часов поиска уязвимости в контракте, я осознал, что все решение кроется в условии задачи. Нужно просто пополнить счет контракта на нужную сумму. Контракт wallet вам вообще не нужен для этого. Создайте свой контракт и напишите функцию, которая делает депозит, типа такой:
setup.WETH().deposit.value(msg.value)();
setup.WETH().transfer(address(setup), setup.WANT());
Порой нужно просто читать условие внимательно...
#task #paradigm2021 #ctf
Эта задача была в Paradigm CTF 2021.
Я прикрепил два файла контрактов для тех, кто захочет сам посмотреть и решить их. Вообще, это задание на внимательность и знание стандарта ERC20.
Целью является заполучить 50 Эфиров на баланс контракта Setup.
Маленькая подсказка: не усложняйте! Все проще, чем кажется.
Ну, и вопрос по такому формату: Нужно ли прикладывать решение или делать пост с ним в конце дня?
UPD. Решение.
setup.WETH().deposit.value(msg.value)();
setup.WETH().transfer(address(setup), setup.WANT());
Порой нужно просто читать условие внимательно...
Описание Remix Debugger. Часть 1
Несколько раз, то в процессе решения задач, то в просмотре каких-либо уроков по Solidity, авторы открывали дебаггер Ремикса и показывали там изменения, которые происходят в коде контракта. Хоть на тот момент и было все понятно, но общую суть плагина я не понимал. Давайте вместе пройдемся по его окошкам.
Итак, после того, как вы сделали деплой контракта в Ремиксе и провели транзакцию, то в терминале ниже, можно будет увидеть информацию о ней и кнопочку Debug. Нажмем ее и откроется новый раздел в окне с кучей непонятных окошек.
1. Навигация. Она представлена полем, где указан хеш транзакции и навигационными стрелками.
- Ползунком можно управлять мышью, чтобы пройтись по всем шагам транзакций контракта. После версии 0.7 ваш код в контракте также будет подсвечиваться в соотношении текущего шага дебага.
Стрелочки (слева-направо):
- Step over back. Переход на предыдущий опкод. Если на предыдущем шаге вызывалась функция, то сейчас она вызвана НЕ будет.
- Step back. Шаг назад на предыдущий опкод.
- Step into. Переход на следующий опкод. Если существует вызов функции, то он будет совершен.
- Step over forward. Переход на следующий опкод. Если существует вызов функции, то он НЕ будет совершен.
- Jump to the previous breakpoint. Брейкпойнты расположены внутри Редактора кода. Если текущий брейкпоинт был пройден, то кнопка переместит слайдер на последний пройденный брейкпоинт.
- Jump out. Когда совершается вызов функции и вы нажимаете эту кнопку, то слайдер переместится в конец данного вызова.
- Jump to the next breakpoint. Если есть последующий брейкпоинт, то слайдер переместится туда.
Как я понял, брейкпоинты - это некие места в коде, по которым ориентируется дебаггер. Мы можем сами устанавливать их, нажав на строку в коде (или ее номер). Должна появиться небольшая точка слева от номера строки в коде.
Далее поговорим об окошках.
#remix #debugger
Несколько раз, то в процессе решения задач, то в просмотре каких-либо уроков по Solidity, авторы открывали дебаггер Ремикса и показывали там изменения, которые происходят в коде контракта. Хоть на тот момент и было все понятно, но общую суть плагина я не понимал. Давайте вместе пройдемся по его окошкам.
Итак, после того, как вы сделали деплой контракта в Ремиксе и провели транзакцию, то в терминале ниже, можно будет увидеть информацию о ней и кнопочку Debug. Нажмем ее и откроется новый раздел в окне с кучей непонятных окошек.
1. Навигация. Она представлена полем, где указан хеш транзакции и навигационными стрелками.
- Ползунком можно управлять мышью, чтобы пройтись по всем шагам транзакций контракта. После версии 0.7 ваш код в контракте также будет подсвечиваться в соотношении текущего шага дебага.
Стрелочки (слева-направо):
- Step over back. Переход на предыдущий опкод. Если на предыдущем шаге вызывалась функция, то сейчас она вызвана НЕ будет.
- Step back. Шаг назад на предыдущий опкод.
- Step into. Переход на следующий опкод. Если существует вызов функции, то он будет совершен.
- Step over forward. Переход на следующий опкод. Если существует вызов функции, то он НЕ будет совершен.
- Jump to the previous breakpoint. Брейкпойнты расположены внутри Редактора кода. Если текущий брейкпоинт был пройден, то кнопка переместит слайдер на последний пройденный брейкпоинт.
- Jump out. Когда совершается вызов функции и вы нажимаете эту кнопку, то слайдер переместится в конец данного вызова.
- Jump to the next breakpoint. Если есть последующий брейкпоинт, то слайдер переместится туда.
Как я понял, брейкпоинты - это некие места в коде, по которым ориентируется дебаггер. Мы можем сами устанавливать их, нажав на строку в коде (или ее номер). Должна появиться небольшая точка слева от номера строки в коде.
Далее поговорим об окошках.
#remix #debugger
👍2
Описание Remix Debugger. Часть 2
Поговорим об окошках дебаггера.
Function Stack. Показывает все функции, которые задействованы в транзакции.
Solidity Locals. Показывает локальные переменные внутри функции.
Solidity State. Показывает все переменные состояния в контракте.
Opcodes. Показывает шаг и опкод, который используется в данный момент.
Step details. Показывает больше информации о шаге опкода.
Stack. Отображает стек EVM.
Memory. Отображает состояние памяти. Первые два слота, по правилам языка, всегда путые (до 0x40), третий слот (0х40) - указывает на пустое место в памяти, куда можно вести запись. Записи хранятся в формате Hex.
Также в памяти отображается три колонки: первая - место в памяти, вторая - hex значение, третье - расшифровка значения. Если в третьем стоят знаки "?", это означает, что значения не существует.
Storage. Постоянное хранилище.
Call Stack. Все вычисления с массивами данных тут называются Stack. Он может быть максимальным размером в 1024 элемента и содержать слова в 256 бит.
Call Data. Содержит параметры функции.
Return Value. Отображает то, что возвращает функция.
Full Storage Changes. Отображает состояние хранилища на момент завершения выполнения функции.
Global Variables. Глобальные переменные доступные на данный момент.
Далее поговорим о том, как его использовать в своей работе с контрактом.
#remix #debugger
Поговорим об окошках дебаггера.
Function Stack. Показывает все функции, которые задействованы в транзакции.
Solidity Locals. Показывает локальные переменные внутри функции.
Solidity State. Показывает все переменные состояния в контракте.
Opcodes. Показывает шаг и опкод, который используется в данный момент.
Step details. Показывает больше информации о шаге опкода.
Stack. Отображает стек EVM.
Memory. Отображает состояние памяти. Первые два слота, по правилам языка, всегда путые (до 0x40), третий слот (0х40) - указывает на пустое место в памяти, куда можно вести запись. Записи хранятся в формате Hex.
Также в памяти отображается три колонки: первая - место в памяти, вторая - hex значение, третье - расшифровка значения. Если в третьем стоят знаки "?", это означает, что значения не существует.
Storage. Постоянное хранилище.
Call Stack. Все вычисления с массивами данных тут называются Stack. Он может быть максимальным размером в 1024 элемента и содержать слова в 256 бит.
Call Data. Содержит параметры функции.
Return Value. Отображает то, что возвращает функция.
Full Storage Changes. Отображает состояние хранилища на момент завершения выполнения функции.
Global Variables. Глобальные переменные доступные на данный момент.
Далее поговорим о том, как его использовать в своей работе с контрактом.
#remix #debugger
👍1
Описание Remix Debugger. Часть 3
Я сам еще мало работал с дебаггером, поэтому каких-либо супер детальных примеров привести не смогу. Скорее опишу, для каких задач он может быть полезен.
Отлавливание ошибок
Наверное, это его самая явная цель создания. Когда мы получаем ошибку в проведении транзакции, то есть четыре способа ее решить: просмотреть код в поисках недочетов, заглянуть в дебаггер, погуглить и спросить в чате.
В отличие от трех остальных, дебаггер позволит не только исправить ошибку, но и понять, как она вообще произошла в коде.
Особенно это будет полезно, когда у вас несколько перекликающихся контрактов (наследование), и нужно отследить этап, в точности до опкода, когда происходит ошибка и где.
Переменные
Также при помощи дебаггера можно отслеживать изменения состояний локальных переменных и переменных состояния. Очень часто при написании кода, его редактировании или наследовании, разработчики забывают удалить ненужные переменные или же они обновляются без предупреждения. И также часто это приводит к взлому.
Слоты памяти
Еще одна киллер-фича дебаггера. Мы уже не понаслышке знаем, что слоты памяти являются одним из самых уязвимых мест в Solidity. Одна не инициализированная структура, перегрузка массива или делегирование может стоить больших денег. Дебаггер поможет отловить такие изменения.
Если вы встречали другие примеры использования дебаггера в Ремиксе, то буду рад, если напишите о своем опыте в комментариях.
#remix #debugger
Я сам еще мало работал с дебаггером, поэтому каких-либо супер детальных примеров привести не смогу. Скорее опишу, для каких задач он может быть полезен.
Отлавливание ошибок
Наверное, это его самая явная цель создания. Когда мы получаем ошибку в проведении транзакции, то есть четыре способа ее решить: просмотреть код в поисках недочетов, заглянуть в дебаггер, погуглить и спросить в чате.
В отличие от трех остальных, дебаггер позволит не только исправить ошибку, но и понять, как она вообще произошла в коде.
Особенно это будет полезно, когда у вас несколько перекликающихся контрактов (наследование), и нужно отследить этап, в точности до опкода, когда происходит ошибка и где.
Переменные
Также при помощи дебаггера можно отслеживать изменения состояний локальных переменных и переменных состояния. Очень часто при написании кода, его редактировании или наследовании, разработчики забывают удалить ненужные переменные или же они обновляются без предупреждения. И также часто это приводит к взлому.
Слоты памяти
Еще одна киллер-фича дебаггера. Мы уже не понаслышке знаем, что слоты памяти являются одним из самых уязвимых мест в Solidity. Одна не инициализированная структура, перегрузка массива или делегирование может стоить больших денег. Дебаггер поможет отловить такие изменения.
Если вы встречали другие примеры использования дебаггера в Ремиксе, то буду рад, если напишите о своем опыте в комментариях.
#remix #debugger
👍1
Чтение событий в mainnet
Нашел интересный пример для чтения событий (event) в контрактах, которые уже были загружены в сеть. Для этого используются такие сервисы как Alchemy или Infura. Если я правильно понял, то для этого случая, все бесплатно.
Чтобы подключить прослушивание событий в сети, вам нужно зарегистрировать в одном из этих сервисов, создать API и получить ссылку WebSocket. Все это будет в вашем личном кабинете.
Также нам потребуется адрес контракта и его ABI, которые можно найти на etherscan. В нижеследующем примере был взят адрес контракта USDT.
Далее в js файле потребуется написать такой код:
const ethers = require("ethers");
const usdtAbi = require("pathToAbiFile");
async function main() {
const usdtAddress = "tokenAdress";
const provider = new ethers.providers.WebSocketProvider("linkToSocket");
const contract = new ethers.Contract (usdtAddress, usdtAbi, provider);
contract.on("Transfer", (from, to, value, event) => {
let info = {
from: from,
to: to,
value: ethers.utils.formatUnits(value, 6),
data: event
};
console.log(JSON.stringify(info, null, 4));
});
}
main();
Теперь, как только будет происходить события transfer, мы будем получать сообщение об этом.
Также рекомендую использовать dotenv для сокрытия важной информации в файлах, типа API используемого сервиса.
#ethers #ethersjs #alchemy #event
Нашел интересный пример для чтения событий (event) в контрактах, которые уже были загружены в сеть. Для этого используются такие сервисы как Alchemy или Infura. Если я правильно понял, то для этого случая, все бесплатно.
Чтобы подключить прослушивание событий в сети, вам нужно зарегистрировать в одном из этих сервисов, создать API и получить ссылку WebSocket. Все это будет в вашем личном кабинете.
Также нам потребуется адрес контракта и его ABI, которые можно найти на etherscan. В нижеследующем примере был взят адрес контракта USDT.
Далее в js файле потребуется написать такой код:
const ethers = require("ethers");
const usdtAbi = require("pathToAbiFile");
async function main() {
const usdtAddress = "tokenAdress";
const provider = new ethers.providers.WebSocketProvider("linkToSocket");
const contract = new ethers.Contract (usdtAddress, usdtAbi, provider);
contract.on("Transfer", (from, to, value, event) => {
let info = {
from: from,
to: to,
value: ethers.utils.formatUnits(value, 6),
data: event
};
console.log(JSON.stringify(info, null, 4));
});
}
main();
Теперь, как только будет происходить события transfer, мы будем получать сообщение об этом.
Также рекомендую использовать dotenv для сокрытия важной информации в файлах, типа API используемого сервиса.
#ethers #ethersjs #alchemy #event
👍1
Лезем в опкод!
Со вчерашнего дня у меня в голове засела идея узнать больше про опкод в EVM. К тому же еще та задача из ethernaut не давала покоя. Поэтому я решил покопаться в этой теме чуть глубже.
К моему удивлению, про опкод и работу в ним довольно мало информации. Большинство из них приводят примеры списка всех опкодов, вот он. А как он работает никто не говорит.
Ну, как никто, скорее никто не говорит понятным языком. Да и какой "понятный язык" может быть в технической части.
Тем не менее, я нашел несколько интересных ресурсов про опкод и сегодня хочу сделать несколько постов по этой теме.
И для начала представляю вам очень хорошее видео с летней конференции в Нью-Йорке от разработчика в Macro. Да, видео на английском языке, но, если вы не понимаете, то можно включить довольно сносные субтитры. Более того на слайдах все достаточно понятно.
Видео: Демистификация опкода EVM
Приятного просмотра!
#evm #opcode
Со вчерашнего дня у меня в голове засела идея узнать больше про опкод в EVM. К тому же еще та задача из ethernaut не давала покоя. Поэтому я решил покопаться в этой теме чуть глубже.
К моему удивлению, про опкод и работу в ним довольно мало информации. Большинство из них приводят примеры списка всех опкодов, вот он. А как он работает никто не говорит.
Ну, как никто, скорее никто не говорит понятным языком. Да и какой "понятный язык" может быть в технической части.
Тем не менее, я нашел несколько интересных ресурсов про опкод и сегодня хочу сделать несколько постов по этой теме.
И для начала представляю вам очень хорошее видео с летней конференции в Нью-Йорке от разработчика в Macro. Да, видео на английском языке, но, если вы не понимаете, то можно включить довольно сносные субтитры. Более того на слайдах все достаточно понятно.
Видео: Демистификация опкода EVM
Приятного просмотра!
#evm #opcode
YouTube
🎤 Demystifying EVM Opcodes
Join Gilbert G of Macro for a talk noscriptd, "Demystifying EVM Opcodes."
This workshop is part of ETHNewYork 2022, a three-day in person hackathon that will feature hackers, mentors, enthusiasts, sponsors and speakers who are all gathering in New York June…
This workshop is part of ETHNewYork 2022, a three-day in person hackathon that will feature hackers, mentors, enthusiasts, sponsors and speakers who are all gathering in New York June…
👍1
Опкод из байткода
Понравился этот слайд из видео, где объясняется конструкция опкода.
Если говорить кратко, то код нашего смарт контракта в сети Эфира представлен в виде байткода. Например, сложение (add) выглядит так:
0000 0001
В опкодах мы берем каждые 4 символа бинарного кода и приравниваем его к 1 символу в hex, и добавляем "0х", для указания EVM на то, что это конкретно hex код, а не какой-нибудь другой. И получается:
0х01
В итоге, все опкоды равны 1 байту, или 2 hex символам. Более того, каждому опкоду (этому hex) соответствует понятное для разработчика название.
Opcode 01 = name "Add"
Вот эти человекопонятные обозначения мы и видим в дебаггере Ремикса, когда проходим по шагам контракта.
#evm #opcode
Понравился этот слайд из видео, где объясняется конструкция опкода.
Если говорить кратко, то код нашего смарт контракта в сети Эфира представлен в виде байткода. Например, сложение (add) выглядит так:
0000 0001
В опкодах мы берем каждые 4 символа бинарного кода и приравниваем его к 1 символу в hex, и добавляем "0х", для указания EVM на то, что это конкретно hex код, а не какой-нибудь другой. И получается:
0х01
В итоге, все опкоды равны 1 байту, или 2 hex символам. Более того, каждому опкоду (этому hex) соответствует понятное для разработчика название.
Opcode 01 = name "Add"
Вот эти человекопонятные обозначения мы и видим в дебаггере Ремикса, когда проходим по шагам контракта.
#evm #opcode
Магические 6080604052
Уверен, никто не прочитал число в заголовке поста. А зря...
Это число является байткодом, с которого начинается байткод любого смарт контракта. Ну, иногда с легкими изменениями в 6060604052. Хотите узнать что это такое?
И это тоже относится к опкоду EVM. В другом формате это можно было бы записать так:
PUSH1 0x60 PUSH1 0x80 MSTORE
Как мы можем убедиться из таблицы опкодов, PUSH1 = 60, MSTORE = 52.
PUSH1 (0x60) - кладет 0х60 в Stack (мы же помним о форматах памяти?);
PUSH1 (0x60) - потом кладет 0х80 в Stack;
MSTORE (0x52) - берет 0х60 из памяти и перемещает в слот 0х80;
Если выполнить все эти действия по порядку, получится именно 6080604052.
Далее чуть сложнее.
0х80 и 0х60 не могут быть использованы, как простые числа 80 или 60. Так как они hexadecimal, то в переводе в decimal 60 будет ровняться 96, а 80 - 128.
Короче говоря, PUSH1 0x60 PUSH1 0x80 MSTORE берет 96 байтов памяти и перемещает указатель в начало 128 байта. Именно поэтому в памяти первые 64 байта всегда пустые, следующие 32 являются указателем, и потом уже идет запись контракта в саму память.
#evm #opcode
Уверен, никто не прочитал число в заголовке поста. А зря...
Это число является байткодом, с которого начинается байткод любого смарт контракта. Ну, иногда с легкими изменениями в 6060604052. Хотите узнать что это такое?
И это тоже относится к опкоду EVM. В другом формате это можно было бы записать так:
PUSH1 0x60 PUSH1 0x80 MSTORE
Как мы можем убедиться из таблицы опкодов, PUSH1 = 60, MSTORE = 52.
PUSH1 (0x60) - кладет 0х60 в Stack (мы же помним о форматах памяти?);
PUSH1 (0x60) - потом кладет 0х80 в Stack;
MSTORE (0x52) - берет 0х60 из памяти и перемещает в слот 0х80;
Если выполнить все эти действия по порядку, получится именно 6080604052.
Далее чуть сложнее.
0х80 и 0х60 не могут быть использованы, как простые числа 80 или 60. Так как они hexadecimal, то в переводе в decimal 60 будет ровняться 96, а 80 - 128.
Короче говоря, PUSH1 0x60 PUSH1 0x80 MSTORE берет 96 байтов памяти и перемещает указатель в начало 128 байта. Именно поэтому в памяти первые 64 байта всегда пустые, следующие 32 являются указателем, и потом уже идет запись контракта в саму память.
#evm #opcode
👍1
Задача из Ethernaut - Magiс Number. Часть 1
Напомню, что эту задачу мы оставили на потом, так как нужно было разобраться с опкодом. Теперь мы понимаем его чуть лучше, и можно попробовать разобрать задачу.
P.S. Уже не сегодня, но мы порой будем возвращаться к опкоду в будущем, когда появится более интересный материал по этой теме.
Итак, целью задачи было написать код смарт контракта, чтобы он возвращал нам число "42", при этом уложившись в 10 байтов. Это можно сделать только с помощью опкода. Поехали.
Мы помним, что 1 опкод = 1 байту, а число 42 в hex = 0х2а.
Нам потребуется два набора байткода:
1. Байткод инициализации: тот, который подготовит смарт контракт и вернет runtime байткод.
2. Runtime байткод: тот, который используется после создания контракта, и где лежат все наши функции.
Посмотри на runtime сперва.
Для того, чтобы поместить что-то в память нам потребуется минимум три действия: сделать push данных, сделать push места, выполнить mstore, который принимает значение первых двух.
Кладем значение в память:
1. 0x60 - PUSH1 --> PUSH(0x2a) --> 0x602a
2. 0x60 - PUSH1 --> PUSH(0x80) --> 0x6080
3. 0x52 - MSTORE --> MSTORE --> 0x52
И возвращаем его из памяти:
1. 0x60 - PUSH1 --> PUSH(0x20) --> 0x6020
(размер значение в 32 байтах)
2. 0x60 - PUSH1 --> PUSH(0x80) --> 0x6080
3. 0xf3 - RETURN --> RETURN --> 0xf3
RETURN еще один новый для нас опкод, который принимает значения: слота памяти, где хранится значение, а также длину / размер данного значение.
В итоге runtime байткод будет выглядеть так:
602a60805260206080f3
Все "0х" мы удаляем, не забыли?
#evm #opcode
Напомню, что эту задачу мы оставили на потом, так как нужно было разобраться с опкодом. Теперь мы понимаем его чуть лучше, и можно попробовать разобрать задачу.
P.S. Уже не сегодня, но мы порой будем возвращаться к опкоду в будущем, когда появится более интересный материал по этой теме.
Итак, целью задачи было написать код смарт контракта, чтобы он возвращал нам число "42", при этом уложившись в 10 байтов. Это можно сделать только с помощью опкода. Поехали.
Мы помним, что 1 опкод = 1 байту, а число 42 в hex = 0х2а.
Нам потребуется два набора байткода:
1. Байткод инициализации: тот, который подготовит смарт контракт и вернет runtime байткод.
2. Runtime байткод: тот, который используется после создания контракта, и где лежат все наши функции.
Посмотри на runtime сперва.
Для того, чтобы поместить что-то в память нам потребуется минимум три действия: сделать push данных, сделать push места, выполнить mstore, который принимает значение первых двух.
Кладем значение в память:
1. 0x60 - PUSH1 --> PUSH(0x2a) --> 0x602a
2. 0x60 - PUSH1 --> PUSH(0x80) --> 0x6080
3. 0x52 - MSTORE --> MSTORE --> 0x52
И возвращаем его из памяти:
1. 0x60 - PUSH1 --> PUSH(0x20) --> 0x6020
(размер значение в 32 байтах)
2. 0x60 - PUSH1 --> PUSH(0x80) --> 0x6080
3. 0xf3 - RETURN --> RETURN --> 0xf3
RETURN еще один новый для нас опкод, который принимает значения: слота памяти, где хранится значение, а также длину / размер данного значение.
В итоге runtime байткод будет выглядеть так:
602a60805260206080f3
Все "0х" мы удаляем, не забыли?
#evm #opcode
👍1
Задача из Ethernaut - Magiс Number. Часть 2
Теперь разберем байткод инициализации. Он отвечает за загрузку нашего runtime кода в память и возвращает его в EVM.
Для этого нам потребуется скопировать код с помощью опкода CODECOPY, который принимает 3 значения:
1. Слот назначения, куда код будет помещен в памяти, для примера возьмем 0х00.
2. Текущая позиция опкода runtime, которую мы не знаем в данный момент.
3. Размер нашего кода в байтах, и его длина сейчас ровно 10 байтов.
Вот так это выглядит:
1. 0x60 - PUSH1 --> PUSH(0x0a) --> 0x600a
(0x0a - это размер нашего кода - 10 байтов)
2. 0x60 - PUSH1 --> PUSH(0x??) --> 0x60??
(?? - позиция, которую мы еще не знаем)
3. 0x60 - PUSH1 --> PUSH(0x00) --> 0x6000
(0x00 выбранный нами ранее слот памяти)
4. 0x39 - CODECOPY --> CODECOPY --> 0x39
Далее возвращаем этот код:
1. 0x60 - PUSH1 --> PUSH(0x0a) --> 0x600a
(размер нашего опкода в 10 байтов)
2. 0x60 - PUSH1 --> PUSH(0x00) --> 0x6000
(значение было сохранено в слоту 0х00)
3. 0xf3 - RETURN --> RETURN --> 0xf3
(возвращает значение в 0х00 и длинной в 0х0а)
Если сложить текущий опкод, мы получим 600a60__600039600a6000f3. Он будет равняться 12 байтам. Это означает, что мы нашли недостающее значение, которое мы ранее пометили, как ??.
12 или 0x0c в hex позволяет закончить создание нашего кода:
600a600c600039600a6000f3
Теперь можно сложить два байткода и получить то, что потребуется нам для решения:
602a60805260206080f3 + 600a600c600039600a6000f3 = 600a600c600039600a6000f3602a60505260206050f3
Говоря кратно, решение задачи можно теперь представить так:
bytes memory code = "\x60\x0a\x60\x0c\x60\x00\x39\x60\x0a\x60\x00\xf3\x60\x2a\x60\x80\x52\x60\x20\x60\x80\xf3";
address solver;
assembly {
solver := create(0, add(code, 0x20), mload(code))
}
Мы используем assembly для создания контракта через create, который принимает три параметра: значение, положение и длину, возвращая адрес контракта после его деплоя.
Надеюсь, эта задача и работа с опкодом стала для вас чуточку понятнее.
#evm #opcode
Теперь разберем байткод инициализации. Он отвечает за загрузку нашего runtime кода в память и возвращает его в EVM.
Для этого нам потребуется скопировать код с помощью опкода CODECOPY, который принимает 3 значения:
1. Слот назначения, куда код будет помещен в памяти, для примера возьмем 0х00.
2. Текущая позиция опкода runtime, которую мы не знаем в данный момент.
3. Размер нашего кода в байтах, и его длина сейчас ровно 10 байтов.
Вот так это выглядит:
1. 0x60 - PUSH1 --> PUSH(0x0a) --> 0x600a
(0x0a - это размер нашего кода - 10 байтов)
2. 0x60 - PUSH1 --> PUSH(0x??) --> 0x60??
(?? - позиция, которую мы еще не знаем)
3. 0x60 - PUSH1 --> PUSH(0x00) --> 0x6000
(0x00 выбранный нами ранее слот памяти)
4. 0x39 - CODECOPY --> CODECOPY --> 0x39
Далее возвращаем этот код:
1. 0x60 - PUSH1 --> PUSH(0x0a) --> 0x600a
(размер нашего опкода в 10 байтов)
2. 0x60 - PUSH1 --> PUSH(0x00) --> 0x6000
(значение было сохранено в слоту 0х00)
3. 0xf3 - RETURN --> RETURN --> 0xf3
(возвращает значение в 0х00 и длинной в 0х0а)
Если сложить текущий опкод, мы получим 600a60__600039600a6000f3. Он будет равняться 12 байтам. Это означает, что мы нашли недостающее значение, которое мы ранее пометили, как ??.
12 или 0x0c в hex позволяет закончить создание нашего кода:
600a600c600039600a6000f3
Теперь можно сложить два байткода и получить то, что потребуется нам для решения:
602a60805260206080f3 + 600a600c600039600a6000f3 = 600a600c600039600a6000f3602a60505260206050f3
Говоря кратно, решение задачи можно теперь представить так:
bytes memory code = "\x60\x0a\x60\x0c\x60\x00\x39\x60\x0a\x60\x00\xf3\x60\x2a\x60\x80\x52\x60\x20\x60\x80\xf3";
address solver;
assembly {
solver := create(0, add(code, 0x20), mload(code))
}
Мы используем assembly для создания контракта через create, который принимает три параметра: значение, положение и длину, возвращая адрес контракта после его деплоя.
Надеюсь, эта задача и работа с опкодом стала для вас чуточку понятнее.
#evm #opcode
👍2🔥1
Задача на день
Ну, и небольшая задача-вопрос на вечер: где уязвимость в данном коде?
Решение
Вместо знака >= необходимо использовать просто >. В представленном коде, любой участник может отправить сумму равную текущему победителю и занять его место, что, вероятнее всего, нарушит логику игры.
#task
Ну, и небольшая задача-вопрос на вечер: где уязвимость в данном коде?
Решение
❤3👍1
Из чего состоит транзакция? Часть 1
После последних двух задач в "CTE Account" меня заинтересовал вопрос о том, из чего вообще состоит транзакция, и как из нее можно получить публичный и приватный ключи. Да, я кратно описывал решения, но это было лишь поверхностным касанием. Давайте попробуем углубиться в эту тему.
Для начала, если вы зайдете на etherscan и кликните любую транзакцию, то увидите информацию о ней, включая хеш, типа такого:
0xb3e9dad434ce64f0f886e5b3bafced3bc72fee467cf1739d0f8f5a141784fbad
В правом углу транзакции будет небольшое окошко меню, где можно найти дополнительные параметры, одним из которых будет Get Raw Tx Hex. Откроется окно и мы увидим более длинную запись, типа такой:
0xf86d822c858502eeae9847826b6c94388c818ca8b9251b393131c08a736a67ccb192978732bdda0cd1511e8026a0220a666d6dd188222bba14b0f77e378aac1910bba8d646edcd0a90d937cf2f15a07d8396243c8b0ced7d7c955ee27b67a4989e49eaf41aa8396191e0a5a40064db
Все это пригодится нам в разборе транзакции на составные части.
Итак, по сути, транзакция состоит из двух больших захэшированных частей:
1. Информация о транзакции
2. Подпись
Генерируется она по формуле:
Keccak256(RLP(nonce,gasPrice,gasLimit,to,value,data,v,r,s))
Техническую часть о транзакциях можно прочесть в Yellow Pages и EIP-155.
Далее подробнее поговорим подробнее о каждой части.
#transaction #rlp #ecdsa
После последних двух задач в "CTE Account" меня заинтересовал вопрос о том, из чего вообще состоит транзакция, и как из нее можно получить публичный и приватный ключи. Да, я кратно описывал решения, но это было лишь поверхностным касанием. Давайте попробуем углубиться в эту тему.
Для начала, если вы зайдете на etherscan и кликните любую транзакцию, то увидите информацию о ней, включая хеш, типа такого:
0xb3e9dad434ce64f0f886e5b3bafced3bc72fee467cf1739d0f8f5a141784fbad
В правом углу транзакции будет небольшое окошко меню, где можно найти дополнительные параметры, одним из которых будет Get Raw Tx Hex. Откроется окно и мы увидим более длинную запись, типа такой:
0xf86d822c858502eeae9847826b6c94388c818ca8b9251b393131c08a736a67ccb192978732bdda0cd1511e8026a0220a666d6dd188222bba14b0f77e378aac1910bba8d646edcd0a90d937cf2f15a07d8396243c8b0ced7d7c955ee27b67a4989e49eaf41aa8396191e0a5a40064db
Все это пригодится нам в разборе транзакции на составные части.
Итак, по сути, транзакция состоит из двух больших захэшированных частей:
1. Информация о транзакции
2. Подпись
Генерируется она по формуле:
Keccak256(RLP(nonce,gasPrice,gasLimit,to,value,data,v,r,s))
Техническую часть о транзакциях можно прочесть в Yellow Pages и EIP-155.
Далее подробнее поговорим подробнее о каждой части.
#transaction #rlp #ecdsa
👍5
Из чего состоит транзакция? Часть 2
Из выше представленной формулы мы узнаем тот минимум информации, который нужно предоставить, чтобы транзакция успешно прошла. А именно:
- Nonce. Значение, которое равняется количеству транзакций, отправленных с данного адреса.
- Gas Price. Цена за газ в Wei.
- Gas Limit. Максимальное количество газа, которое может использоваться в этой транзакции.
- To. Адрес назначения транзакции.
- Amount. Количество Эфира отправляемого в транзакции.
- Data. Опциональное поле, в котором можно передать какие-либо данные для проведения транзакции, в том числе и функцию, которую необходимо выполнить.
Как я уже написал, это необходимый минимум данных для транзакции, так как в Etherscan мы можем увидеть немного больше информации, как например, статус, номер блока, временная метка, от кого, оплаченный газ и пара других атрибутов.
Далее поговорим о данных v, r и s в формуле.
#transaction #rlp #ecdsa
Из выше представленной формулы мы узнаем тот минимум информации, который нужно предоставить, чтобы транзакция успешно прошла. А именно:
- Nonce. Значение, которое равняется количеству транзакций, отправленных с данного адреса.
- Gas Price. Цена за газ в Wei.
- Gas Limit. Максимальное количество газа, которое может использоваться в этой транзакции.
- To. Адрес назначения транзакции.
- Amount. Количество Эфира отправляемого в транзакции.
- Data. Опциональное поле, в котором можно передать какие-либо данные для проведения транзакции, в том числе и функцию, которую необходимо выполнить.
Как я уже написал, это необходимый минимум данных для транзакции, так как в Etherscan мы можем увидеть немного больше информации, как например, статус, номер блока, временная метка, от кого, оплаченный газ и пара других атрибутов.
Далее поговорим о данных v, r и s в формуле.
#transaction #rlp #ecdsa
❤1👍1
Из чего состоит транзакция? Часть 3
Теперь немного сложная для понимания информация, которую, возможно, придется перечить пару раз.
Символы v, r и s отвечают за подпись транзакции для ее авторизации / подтверждения. Для генерации подписи используется специальный алгоритм Elliptic Curve Digital Signature Algorithm (ECDSA).
С помощью ECDSA формируются значения для R и S по формуле:
C = kG, r=Cx, s = (e + rd) / k
где k - случайное число, g - точка генерации, e - данные для подписи, d - приватный ключ.
Подробное описание расчетов можно найти в этой статье.
Значение для V можно найти в документации для EIP-155 и рассчитывается по формуле v = CHAIN_ID * 2 + 35.
Chain_Id для всех сетей разный. Так для mainnet он равен 1, для Goerly - 5. Поддерживаемые сети можно найти все в том же документе EIP-155.
Теперь для проведения транзакции у нас есть все значения.
#transaction #rlp #ecdsa
Теперь немного сложная для понимания информация, которую, возможно, придется перечить пару раз.
Символы v, r и s отвечают за подпись транзакции для ее авторизации / подтверждения. Для генерации подписи используется специальный алгоритм Elliptic Curve Digital Signature Algorithm (ECDSA).
С помощью ECDSA формируются значения для R и S по формуле:
C = kG, r=Cx, s = (e + rd) / k
где k - случайное число, g - точка генерации, e - данные для подписи, d - приватный ключ.
Подробное описание расчетов можно найти в этой статье.
Значение для V можно найти в документации для EIP-155 и рассчитывается по формуле v = CHAIN_ID * 2 + 35.
Chain_Id для всех сетей разный. Так для mainnet он равен 1, для Goerly - 5. Поддерживаемые сети можно найти все в том же документе EIP-155.
Теперь для проведения транзакции у нас есть все значения.
#transaction #rlp #ecdsa
👍2
Из чего состоит транзакция? Часть 4
После того, как мы собрали все значения для проведения транзакции, требуется зашифровать ее.
Для этого на помощь приходит Recursive Length Prefix (RLP). Помните же формулу генерации транзакции Keccak256(RLP(...))?
RLP - это специальный алгоритм для кодирования объектов в чистые байты. Не уверен на все 100%, но в одной из статей я прочитал, что для кодировки в RLP данные уже заранее должны быть преобразованы в HEX формат.
И вот, когда мы кодируем информацию о нашей транзакции через RLP мы получаем Raw Tx Hex, то длинное значение из etherscan.
А, если прогнать его через kessac256 мы получаем хеш транзакции из 32 байтов.
Вот так это и работает. Далее попробуем разобраться, как получить публичный и приватный ключи из транзакций, как было в задачах CTE.
#transaction #rlp #ecdsa
После того, как мы собрали все значения для проведения транзакции, требуется зашифровать ее.
Для этого на помощь приходит Recursive Length Prefix (RLP). Помните же формулу генерации транзакции Keccak256(RLP(...))?
RLP - это специальный алгоритм для кодирования объектов в чистые байты. Не уверен на все 100%, но в одной из статей я прочитал, что для кодировки в RLP данные уже заранее должны быть преобразованы в HEX формат.
И вот, когда мы кодируем информацию о нашей транзакции через RLP мы получаем Raw Tx Hex, то длинное значение из etherscan.
А, если прогнать его через kessac256 мы получаем хеш транзакции из 32 байтов.
Вот так это и работает. Далее попробуем разобраться, как получить публичный и приватный ключи из транзакций, как было в задачах CTE.
#transaction #rlp #ecdsa
👍3
Из чего состоит транзакция? Часть 5
Узнать публичный ключ не составляет труда, если с аккаунта была хоть раз отправленная какая-либо транзакция, так как raw tx hex уже содержит всю необходимую информацию. Для этих целей мы использовали библиотеку ethereumjs-tx, а также я делился отдельным сервисом, который все это может делать онлайн.
С приватным ключом дела обстоят сложнее.
В последней задаче CTE Account, где нужно было захватить приватный ключ для отправки транзакций, первым делом мы переходили в etherscan и смотрели транзакции.
Разбивая каждую транзакцию на детали (nonce, gasPrice, gasLimit, to, value, data, v, r, s), можно было заметить, что в некоторых из них значения R совпадали. Это могло происходить из-за того, что в формуле случайное число (или nonce) было одинаковым.
Для получения приватного ключа из этих транзакций потребуется использовать софт, который работает с ECDSA и может получать данные из хеша.
Очень многие источники ссылаются на эту страницу, где при помощи Python пользователь получает приватный ключ из хеша. Я не особо знаком с Питоном, но остальным это может многое объяснить.
Надеюсь, сегодня вы чуточку больше узнали о транзакциях вместе со мной.
#transaction #rlp #ecdsa
Узнать публичный ключ не составляет труда, если с аккаунта была хоть раз отправленная какая-либо транзакция, так как raw tx hex уже содержит всю необходимую информацию. Для этих целей мы использовали библиотеку ethereumjs-tx, а также я делился отдельным сервисом, который все это может делать онлайн.
С приватным ключом дела обстоят сложнее.
В последней задаче CTE Account, где нужно было захватить приватный ключ для отправки транзакций, первым делом мы переходили в etherscan и смотрели транзакции.
Разбивая каждую транзакцию на детали (nonce, gasPrice, gasLimit, to, value, data, v, r, s), можно было заметить, что в некоторых из них значения R совпадали. Это могло происходить из-за того, что в формуле случайное число (или nonce) было одинаковым.
Для получения приватного ключа из этих транзакций потребуется использовать софт, который работает с ECDSA и может получать данные из хеша.
Очень многие источники ссылаются на эту страницу, где при помощи Python пользователь получает приватный ключ из хеша. Я не особо знаком с Питоном, но остальным это может многое объяснить.
Надеюсь, сегодня вы чуточку больше узнали о транзакциях вместе со мной.
#transaction #rlp #ecdsa
👍3