Ethernuat part 8 (Gatekeeper II & Naught coin)
First to the key, first to the egg
Gatekeeper II
Problem:
จาก code ทำให้ entrant ไม่เท่ากับ address(0)
Solution
GateOne:
อันนี้เราเคยแก้ไปแล้วใน part ที่แล้ว ดังนั้นขอข้ามเลยนะ
GateTwo:
อันนี้จะขัดแย้งกับ GateOne เพราะถ้าเราใช้ proxy contract เราก็จะมี contract size ของ caller ไม่เท่ากับ 0
แต่จาก yellow paper ของ ethereum ตาม link
เราจะพบว่า
ในระหว่างการเรียก function constructor EXTCODESIZE จะเท่ากับ 0
ดังนั้น เราก็แค่เรียก enter จาก constructor ของ proxy contract ก็พอ
GateThree:
อันนี้จะให้เราหา gateKey ที่ถูกต้องมาให้ได้
ซึ่งมีเงื่อนไขคือ
uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ uint64(_gateKey) == type(uint64).max
โดยจากตาราง XOR
เราจะพบว่า จาก A^B = C
จะได้ว่า A^C=B ด้วย
เช่น
จาก msg.sender ^ gateKey = maxInt
ในเมื่อเราไม่รู้ gateKey ดังนั้น หาได้จาก
gateKey = msg.sender ^ maxInt
โอเค เคลียร์ทั้ง 3 gate ละ จะได้ code ประมาณนี้
จากบรรทัด 12: คือการใช้แก้ gateTwo
จากบรรทัด 16–21: คือการใช้แก้ gateThree โดย msg.sender ใน contract ที่ถูกเรียก คือ address(this) ของ contract ที่เรียกนั่นเอง ดังนั้นนำ code ในโจทย์มาแก้จาก msg.sender เป็น address(this)
NaughtCoin
Problem
จาก code มีการ mint ให้เรา 100k Token โดยโจทย์คือ ทำให้ balance Token ของเราเป็น 0
Solution
เมื่อเราลอง transfer ดูจะพบว่า error
โดยเมื่อไปดู code การ transfer จะพบว่ามีการเช็ค msg.sender โดยต้องไม่เท่ากับ player เอง
ดังนั้นเราสามารถ bypass ได้โดยการ approve ให้ proxy contract ก่อน แล้วค่อยสั่ง transferFrom แทน transfer
โดย proxy contract จะมี code ตามนี้
เมื่อเรา deploy แล้ว ก็ทำการ approve ให้ proxy contract
จากนั้นสั่ง attack เป็นการจบกระบวนการ จะได้ว่า balance ของ player เหลือ 0 แล้ว
โอเค ประมาณนี้ละนะ