การใช้ gdb กับโค้ดแอสเซมบลีขั้นตอนเดียวที่นอกเหนือจากปฏิบัติการที่ระบุทำให้เกิดข้อผิดพลาด“ ไม่พบขอบเขตของฟังก์ชันปัจจุบัน”


88

ฉันอยู่นอกเป้าหมายปฏิบัติการของ gdb และฉันไม่มีสแต็กที่ตรงกับเป้าหมายนั้นด้วยซ้ำ ฉันต้องการทำทีละขั้นตอนเพื่อที่ฉันจะได้ตรวจสอบว่าเกิดอะไรขึ้นในรหัสแอสเซมบลีของฉันเพราะฉันไม่ใช่ผู้เชี่ยวชาญในการประกอบ x86 น่าเสียดายที่ gdb ปฏิเสธที่จะทำการดีบักระดับแอสเซมบลีอย่างง่ายนี้ ช่วยให้ฉันสามารถตั้งค่าและหยุดบนเบรกพอยต์ที่เหมาะสมได้ แต่ทันทีที่ฉันพยายามทำทีละขั้นตอนเป็นต้นไป gdb รายงานข้อผิดพลาด "ไม่พบขอบเขตของฟังก์ชันปัจจุบัน" และ EIP จะไม่เปลี่ยนแปลง

รายละเอียดเพิ่มเติม:

รหัสเครื่องถูกสร้างขึ้นโดยคำสั่ง gcc asm และฉันคัดลอกไปยังตำแหน่งหน่วยความจำเคอร์เนลที่มันทำงานจากเอาต์พุตของ objdump -d ฉันไม่รังเกียจวิธีง่ายๆในการใช้ตัวโหลดเพื่อโหลดรหัสออบเจ็กต์ของฉันไปยังที่อยู่ที่ย้ายตำแหน่ง แต่จำไว้ว่าการโหลดจะต้องทำในโมดูลเคอร์เนล

ฉันคิดว่าอีกทางเลือกหนึ่งคือการสร้างโมดูลเคอร์เนลปลอมหรือไฟล์ข้อมูลการดีบักเพื่อมอบให้กับ gdb เพื่อทำให้เชื่อว่าพื้นที่นี้อยู่ในโค้ดโปรแกรม gdb ทำงานได้ดีบนเคอร์เนลที่รันได้เอง

(สำหรับผู้ที่ต้องการทราบจริงๆฉันกำลังแทรกโค้ดที่รันไทม์ลงในพื้นที่ข้อมูลเคอร์เนลของลินุกซ์ภายใน VMware VM และทำการดีบักจาก gdb รีโมตดีบักเคอร์เนลผ่าน gdb ในตัวของ VMware Workstation หมายเหตุฉันไม่ได้เขียนเคอร์เนล หาประโยชน์ฉันเป็นนักศึกษาระดับบัณฑิตศึกษาด้านความปลอดภัยที่เขียนต้นแบบ)

(ฉันสามารถตั้งค่าเบรกพอยต์สำหรับแต่ละคำสั่งภายในแอสเซมบลีของฉันได้ซึ่งใช้งานได้ แต่จะค่อนข้างลำบากหลังจากนั้นสักครู่เนื่องจากขนาดของคำแนะนำการประกอบ x86 จะแตกต่างกันไปและตำแหน่งของการประกอบจะเปลี่ยนไปทุกครั้งที่รีบูต)


ชาวksplice.com ที่ชาญฉลาดจะฉีดข้อมูลและโค้ดลงในเคอร์เนลโดยการประกอบโมดูลเคอร์เนล "ปลอม" แล้วโหลดขึ้นมา และถ้าพวกเขาทำได้ทำไมคุณถึงทำไม่ได้? ;-)
ชั่วคราว

คำตอบ:


118

คุณสามารถใช้stepiหรือnexti(ซึ่งสามารถย่อsiหรือni) เพื่อก้าวผ่านรหัสเครื่องของคุณ


1
ว้าว. ในการหวนกลับฉันไม่รู้ว่าฉันลืม stepi ได้อย่างไร ฉันเดาว่าฉันแค่สันนิษฐานเพราะ gdb ไม่มีซอร์สโค้ดขั้นตอนนั้นจะเปลี่ยนกลับเป็นคำแนะนำในการประกอบ
พอล

1
หมายเหตุ: คุณมักจะพิมพ์ "break main", "run" สำหรับโปรแกรมประกอบไม่ได้ พิมพ์ "layout asm", "start" แทน ฉันได้รับสิ่งนี้จากการอ่านข้อความด้านล่าง แต่คนอื่นที่อ่านโพสต์นี้อาจไม่อดทนเท่า
Dmitry

1
@Dmitry startเทียบเท่ากับtbreak mainตามด้วยrun(หมายเหตุ: tbreakแทนbreak)
Ruslan

154

แทนการวิ่งgdb gdbtuiหรือเรียกใช้gdbด้วย-tuiสวิตช์ หรือกดหลังจากที่เข้ามาC-x C-a gdbตอนนี้คุณอยู่ในโหมดTUIของ GDB

Enter layout asmเพื่อสร้างแอสเซมบลีการแสดงหน้าต่างด้านบน - สิ่งนี้จะเป็นไปตามตัวชี้คำสั่งของคุณโดยอัตโนมัติแม้ว่าคุณจะสามารถเปลี่ยนเฟรมหรือเลื่อนไปมาได้ กดC-x sเพื่อเข้าสู่โหมด SingleKey โดยที่run continue up down finishฯลฯ ย่อเป็นปุ่มเดียวช่วยให้คุณเดินผ่านโปรแกรมของคุณได้อย่างรวดเร็ว

   + ------------------------------------------------- -------------------------- +
B +> | 0x402670 <main> ดัน% r15 |
   | 0x402672 <main + 2> mov% edi,% r15d |
   | 0x402675 <main + 5> กด% r14 |
   | 0x402677 <main + 7> กด% r13 |
   | 0x402679 <หลัก + 9> mov% rsi,% r13 |
   | 0x40267c <main + 12> กด% r12 |
   | 0x40267e <main + 14> ดัน% rbp |
   | 0x40267f <main + 15> ดัน% rbx |
   | 0x402680 <main + 16> ย่อย $ 0x438,% rsp |
   | 0x402687 <หลัก + 23> mov (% rsi),% rdi |
   | 0x40268a <หลัก + 26> movq $ 0x402a10,0x400 (% rsp) |
   | 0x402696 <main + 38> movq $ 0x0,0x408 (% rsp) |
   | 0x4026a2 <หลัก + 50> movq $ 0x402510,0x410 (% rsp) |
   + ------------------------------------------------- -------------------------- +
child process 21518 In: main Line: ?? พีซี: 0x402670
(gdb) ไฟล์ / opt / j64-602 / bin / jconsole
การอ่านสัญลักษณ์จาก /opt/j64-602/bin/jconsole...done
(ไม่พบสัญลักษณ์การดีบัก) ... เสร็จแล้ว
(gdb) เค้าโครง asm
(gdb) เริ่มต้น
(gdb)

26

สิ่งที่มีประโยชน์ที่สุดที่คุณสามารถทำได้ที่นี่คือdisplay/i $pcก่อนใช้stepiตามที่แนะนำไว้แล้วในคำตอบของ R Samuel Klatchko สิ่งนี้บอกให้ gdb ถอดคำสั่งปัจจุบันก่อนพิมพ์พรอมต์ทุกครั้ง จากนั้นคุณสามารถกด Enter เพื่อทำซ้ำstepiคำสั่ง

(ดูคำตอบของฉันสำหรับคำถามอื่นสำหรับรายละเอียดเพิ่มเติม - บริบทของคำถามนั้นแตกต่างกัน แต่หลักการเหมือนกัน)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.