มาลองแกะ code Oyente กันเถอะ (Part 3 construct CFG dynamic edges)

Nattawat Songsom
3 min readDec 10, 2022

--

โอเค ก่อนอื่นมา recap กันก่อนว่าเราแกะส่วนไหนไปแล้วบ้าง และเหลืออะไรบ้าง

ก่อนอื่นมาเริ่มกันจาก

ภาพรวม Oyente

Oyente ทำงานดังนี้

  • นำ bytecode และ state ของ contract ไปสร้าง CFG
  • นำ CFG นั้นไปทำ symbolic execution เพื่อหา unreachable path และ symbolic values ของ path นั้นๆ
  • นำ CFG และ symbolic values ไป detect ช่องโหว่
  • กรอง false positive

โดยตอนนี้เราอยู่ที่ part นำ bytecode และ state ของ contract ไปสร้าง CFG

เราแกะส่วนไหนไปแล้วบ้าง ?

เริ่มจาก code ส่วนที่แปลง solidity เป็น bytecode ด้วย solc

จากนั้นแปลง bytecode เป็น opcode

ซึ่ง opcode ที่ได้มาจะเป็น list เรียงลงไปเรื่อยๆ

แต่ flow ในการรันโปรแกรมจริงๆจะมีการกระโดดบรรทัด ไปมา ในลักษณะต้นไม้แบบ CFG

ดังนั้นเราต้องแปลง opcode เป็น CFG

โดยประกอบด้วย 2 ขั้นตอนคือ

  1. แบ่ง opcode เป็น nodeๆ
  2. ลากเส้นเชื่อมแต่ละ node

โดยในการแบ่ง opcode เป็น nodeๆ จะใช้การแบ่งที่บรรทัดที่มีการกระโดดในแบบต่างๆ

เราจะได้ node และคำสั่งใน node นั้นๆมา

ต่อมาในการลากเส้นเชื่อมในแต่ละ node เราใช้เทคนิค construct static edges ในการลากเส้นของ case ที่ไม่มีการกระโดดบรรทัดที่ต้องคำนวณค่าจาก stack

เราจะแกะส่วนไหนต่อ ?

เราจะแกะ code ในส่วน

  • การลากเส้น CFG ที่ต้องคำนวณค่าจาก stack
  • เอา path ที่ unreachable ออกด้วย z3

โอเค มาเริ่มกัน

เริ่มจากการประกาศตัวแปรไว้

  • ทดค่าใน stack
  • เป็น input เงื่อนไขการทำงานของยอด balance ของ evm
  • จำ node ที่เคยไปแล้ว
  • ทดค่าใน memory

จากนั้นป้อน input เงื่อนไขการทำงานของยอด balance ของ evm ให้ z3

เริ่มรันจาก node แรก

โดยในแต่ละ node จะจำลองการทำงานของ evm เมื่อรันแต่ละ opcode โดยทดค่าใน stack memory และ storage

ซึ่งผลลัพธ์จากการทดค่าของ stack ทำให้เราสามารถลากเส้น CFG ได้ถูก เช่น JUMP ก็จะ pop ค่าจาก stack แล้วไปยังตำแหน่งนั้น

หรือ JUMPI ก็จะ pop position ที่จะ jump และ condition ในการ jump ออกมา ซึ่งเราจะจำ condition นั้นไว้ก่อน เพื่อใช้ตอน symbolic execution

เมื่อเรากระโดดไปยัง node ต่อไปเรื่อยๆ ก็จะลาก CFG ครบในที่สุด

นอกจากวาด CFG แล้วเราจะกรอง unreachable path ออกจาก CFG โดยใช้ z3 ด้วย

โดยจะเช็คเงื่อนไขว่าการ JUMP สามารถทำได้มั้ย เช่น if(2 > 3) เนี่ย JUMP ไม่ได้

โอเค ประมาณนี้ก่อน ใน part หน้าเราจะมาเริ่มการหา pattern ของช่องโหว่จาก CFG กัน

Referrences:

https://eprint.iacr.org/2016/633.pdf

Useful resource:

เจอ cfg builder https://github.com/crytic/evm_cfg_builder ที่ทีม trail of bits ใช้กันด้วยแหะ น่าลองใช้เหมือนกันนะ

--

--

No responses yet