GDB เบื้องต้น

วันนี้ผมจะมาแนะนำเครื่องมือที่ใช้สำหรับการ debug โปรแกรม เพื่อให้เข้าใจขั้นตอนการทำงานของโปรแกรมว่าในโปรแกรมมีการทำงานอะไรยังไงบ้าง เครื่องมือตัวนั้นก็คือ GDB (GNU Debugger) นั่นเอง

Command เบื้องต้น

  1. คำสั่งในการ disassemble
disassemble [Address/Symbol]disas [Address/Symbol]

2. คำสั่งในการ set breakpoint

break [Address/Symbol]b [Address/Symbol]

3. คำสั่งในการแสดงรายการของ breakpoint ที่ถูก set เอาไว้

info breakpointi b

4. คำสั่งในการลบ breakpoint

delete [Breakpoint Number]del

5. คำสั่งในการ run โปรแกรม

runr

6. คำสั่งในการสั่งให้โปรแกรมทำงานต่อ

continuec

7. คำสั่งในการให้โปรแกรม execute instruction ถัดไป โดยเข้าไปทำงานข้างในฟังก์ชันนั้น ๆ ด้วย

stepisi

8. คำสั่งในการให้โปรแกรม execute instruction ถัดไปเลย

nextini

**ผมไม่รู้จะอธิบาย stepi กับ nexti ให้เข้าใจง่าย ๆ ยังไงดี ผมขอแปะลิงค์ไว้เลยละกัน ถ้าใครงง ๆ เข้าไปอ่านในนี้ได้เลยครับhttps://stackoverflow.com/questions/52024529/whats-the-difference-between-nexti-and-stepi-in-gdb

9. คำสั่งสำหรับการดูค่าใน registers

info registeri r

10. คำสั่งในการดูค่าใน memory

x/[FMT] [Address]

ตัวอย่างการใช้ gdb ในการ reverse engineering อย่างง่าย ๆ

ผมมี binary อยู่ตัวนึงที่พอ execute มันจะมีการให้เรา password ไปซึ่งเราไม่รู้ว่า password ที่ถูกต้องคืออะไร ทีนี้ objective คือเราจะต้องหา password ที่ถูกมาให้ได้ เราจะลองใช้ gdb ในการทำความเข้าใจของ binary ตัวนี้กันและใช้ในการหา password ที่ถูกต้องด้วย

มาเริ่มใช้ gdb กันเลย ขั้นแรกเราจะใช้ gdb โดยใช้คำสั่งตามนี้ gdb ./ex1 จากนั้นเราก็จะเข้ามาอยู่ใน gdb

จากนั้นเราจะลองมาดู assembly ของฟังก์ชัน main คร่าว ๆ กัน ใช้คำสั่ง disas main

จะเห็นได้ว่า gdb มีการแสดงโค้ด assembly ของฟังก์ชัน main() จากนั้นเราจะวิเคราะห์การทำงานของโปรแกรมจากส่วนนี้แหละครับ พอดูแล้วจะเห็นเลยว่ามีการเรียกใช้ strcmp() ซึ่งเป็นฟังก์ชันที่ใช้ในการเช็ค string 2 ตัวว่ามันเหมือนกันรึเปล่านั่นเองครับ

ทีนี้เราก็เดาได้แล้วว่า binary ตัวนี้มันน่าจะมีการรับเอา password จากเราไปเช็คกับค่าอะไรซักอย่างอีกตัวนึงว่ามันตรงกันรึเปล่า ถ้างั้นเราลองมา set breakpoint ตอนจังหวะ strcmp กัน แล้วเดี๋ยวเราจะมาลองดูว่า มันเอาค่าอะไรมาเช็คบ้างครับ ใช้คำสั่ง b *main+104 แล้วกด rเพื่อให้โปรแกรมเริ่มทำงาน จากนั้นผมจะใส่ password มั่ว ๆ ไปก่อน

ผมใส่ password เป็น AAAAAAAA จะเห็นว่าโปรแกรมจะมาหยุดที่ breakpoint ที่ผม set ไว้ครับ ทีนี้ขอเกริ่นเรื่องการส่งค่าแบบ x86_64 นิดนึงครับ การส่งค่าไปทำงานที่ฟังก์ชันบน arch แบบ x86_64 นั้นจะส่งผ่าน registers ลำดับประมาณนี้ คือ rdi, rsi, rdx, rcx …, ทีนี้กลับมาที่ strcmp ตามรูปข้างบนโน้น จะเห็นได้ว่าการใช้ strcmp จะมีลักษณะการใช้งานแบบนี้ strcmp(string 1, string 2) เปรียบเทียบให้เห็นภาพง่าย ๆ มันก็จะประมาณนี้ strcmp(rdi, rsi) นั่นเองครับ พอรู้แบบนี้แล้วต่อไปเราจะมาลองดูกันใน rdi และ rsi มันเก็บค่าอะไรเอาไว้ ใช้คำสั่ง info register ในการดูค่า register ต่าง ๆ ซึ่งเรายัง specific register ที่ต้องการดูได้อีกด้วยครับ โดยใช้ info register [register1] [register2] [register N]

ทีนี้จะเห็นว่าใน rdi กับ rsi มันเป็นค่า address ของอะไรซักอย่าง ผมจะใช้ info proc mapping ในการเช็ค memory mapped ของตัวโปรเซสครับ

ให้ลองดูที่อันสุดท้ายครับ จะเห็นว่าค่าใน rdi และ rsi มันอยู่ใน range ของ section นั้นพอดี ก็คือ ส่วนของ stack นั่นเอง (stack เป็นพื้นที่ในการจัดเก็บข้อมูลต่าง ๆ เอาไว้ เช่น local variable, return address ฯลฯ) ทีนี้มาลองดูค่าใน memory ที่ address นั้นกัน การดูค่าใน memory (Examine memory) เราจะใช้คำสั่ง x/[FMT] [Address] ครับ ลองกด help ดู

พอลองมาดู memory ก็จะได้ผลตามนี้

พอจะคุ้น ๆ ละครับ ตรง 0x4141414141414141 ตรงนี้ก็คือค่า hex ของตัวอักษร ‘A’ นั่นเอง ทีนี้มาลองให้มันโชว์เป็น string กันบ้าง

เจอละครับถ้าเอามาเขียนก็จะประมาณว่า

strcmp(“AAAAAAAA”, “s3cr3t_p4ssw0rd”)

แปลว่าโปรแกรมมันเอา user input ที่ผมใส่ไปเป็น ‘A’ * 8 ตัว มาเช็คกับ “s3cr3t_p4ssw0rd” นั่นเอง ทีนี้เราได้ password ที่คาดว่าเป็น password ที่ถูกมาแล้ว มาลองใช้กัน กด run อีกทีครับ เพื่อให้โปรแกรมเริ่มทำงานใหม่

แต่คราวนี้ผมจะใส่ password เป็น “s3cr3t_p4ssw0rd” เสร็จแล้วโปรแกรมจะมาหยุดที่ breakpoint ตรง strcmp เหมือนเดิม จากนั้นให้กด continue ครับเพื่อให้โปรแกรมทำงานต่อตามปกติ

จะเห็นว่าพอ password ถูกโปรแกรมก็จะแสดงคำว่า “Welcome back.” กลับมานั่นเองครับ

นี่เป็นการใช้งาน gdb เบื้องต้น ซึ่งจริง ๆ มันมีคำสั่งต่าง ๆ ให้เรียกใช้ได้เยอะกว่านี้อีกครับ และยังใช้ทำอย่างอื่นได้อีกเยอะเลย ผมก็ยังอ่านและลองใช้ได้ไม่หมด ซึ่งจากตัวอย่างด้านบนนี้เป็น gdb แบบเดิม ๆ เลยไม่ได้มีส่วนเสริมใด ๆ ทีนี้มันก็จะมีส่วนเสริมให้เราได้เลือกใช้อีกเพื่ออำนวยความสะดวกในการใช้งาน gdb เพื่อทำ dynamic analysis/reverse engineering/ctf ด้วยครับ เช่น gef, peda, pwndbg เป็นต้น ซึ่งส่วนตัวแล้วผมใช้เป็นตัว gef มาตลอดเลยครับ ซึ่งหน้าตามันก็จะสวยงามประมาณนี้

พอมาเป็นแบบนี้ก็ดูใช้ง่ายและสะดวกขึ้นใช่มั้ยล่ะครับ ผมบอกเลยว่ามันช่วยให้เวลาเล่น ctf หรือหัดทำ reverse/binary hacking/dynamic analysis นั้นง่ายขึ้นและดูข้อมูลได้ง่ายกว่าเดิมเยอะเลย สำหรับบทความนี้ก็จะเป็นการมาแนะนำ gdb เบื้องต้นถ้าใครมีเทคนิคในการใช้ gdb ก็มาแชร์กันได้นะครับ วันนี้ขอลาไปก่อนไว้เจอกันบทความหน้าครับ

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store