Menggunakan gdb ke kode perakitan satu langkah di luar yang dapat dieksekusi menyebabkan kesalahan "tidak dapat menemukan batas fungsi saat ini"

88

Saya berada di luar target gdb yang dapat dieksekusi dan saya bahkan tidak memiliki tumpukan yang sesuai dengan target itu. Saya ingin melakukan satu langkah, sehingga saya dapat memverifikasi apa yang terjadi dalam kode assembly saya, karena saya bukan ahli dalam perakitan x86. Sayangnya, gdb menolak melakukan proses debug tingkat rakitan sederhana ini. Ini memungkinkan saya untuk menyetel dan berhenti pada breakpoint yang sesuai, tetapi segera setelah saya mencoba satu langkah ke depan, gdb melaporkan kesalahan "Tidak dapat menemukan batas fungsi saat ini" dan EIP tidak berubah.

Detil tambahan:

Kode mesin dihasilkan oleh pernyataan gcc asm dan saya menyalinnya ke lokasi memori kernel tempat ia dijalankan, dari keluaran objdump -d. Saya tidak keberatan dengan cara sederhana menggunakan loader untuk memuat kode objek saya ke alamat yang direlokasi, tetapi perlu diingat bahwa pemuatan harus dilakukan dalam modul kernel.

Saya kira alternatif lain adalah menghasilkan modul kernel palsu atau file info debug untuk diberikan kepada gdb, agar percaya bahwa area ini ada di dalam kode program. gdb berfungsi dengan baik pada kernel yang dapat dieksekusi itu sendiri.

(Bagi mereka yang benar-benar ingin tahu, saya menyisipkan kode saat runtime ke dalam ruang data kernel Linux di dalam VMware VM dan men-debugnya dari debugging jarak jauh gdb kernel melalui rintisan gdb bawaan VMware Workstation. Catatan Saya tidak menulis kernel eksploitasi; Saya seorang mahasiswa pascasarjana keamanan yang menulis prototipe.)

(Saya dapat mengatur breakpoint pada setiap instruksi di dalam assembly saya. Ini berfungsi tetapi akan menjadi sangat melelahkan setelah beberapa saat, karena ukuran instruksi perakitan x86 bervariasi dan lokasi perakitan akan berubah setiap kali saya reboot.)

Paul
sumber
Orang- orang ksplice.com yang pintar menyuntikkan data dan kode ke dalam kernel dengan merakit modul kernel "palsu" dan memuatnya. Dan jika mereka bisa melakukannya, mengapa Anda tidak? ;-)
ephemient

Jawaban:

118

Anda dapat menggunakan stepiatau nexti(yang dapat disingkat menjadi siatau ni) untuk menelusuri kode mesin Anda.

R Samuel Klatchko
sumber
1
Wow. Dalam retrospeksi saya tidak bagaimana saya lupa tentang stepi. Saya kira saya hanya berasumsi karena gdb tidak memiliki kode sumber, langkah itu akan kembali ke instruksi perakitan.
Paul
1
Catatan: Anda sering tidak bisa mengetik "break main", "run" untuk program assembly. Ketik "layout asm", "start" sebagai gantinya. Saya mendapat ini dari membaca pesan di bawah tetapi orang lain yang membaca posting ini mungkin tidak bersabar.
Dmitry
1
@Dmitry startsetara dengan tbreak maindiikuti oleh run(catatan: tbreakbukan break)
Ruslan
154

Alih-alih gdb, lari gdbtui. Atau jalankan gdbdengan -tuisakelar. Atau tekan C-x C-asetelah masuk gdb. Sekarang Anda berada dalam mode TUI GDB .

Enter layout asmuntuk membuat perakitan tampilan jendela atas - ini secara otomatis akan mengikuti penunjuk instruksi Anda, meskipun Anda juga dapat mengubah bingkai atau menggulir saat debugging. Tekan C-x suntuk masuk ke mode SingleKey, di mana run continue up down finishdll. Disingkat menjadi satu tombol, memungkinkan Anda menjalankan program dengan sangat cepat.

   + ------------------------------------------------- -------------------------- +
B +> | 0x402670 <main> dorong% r15 |
   | 0x402672 <utama + 2> mov% edi,% r15d |
   | 0x402675 <main + 5> dorong% r14 |
   | 0x402677 <main + 7> dorong% r13 |
   | 0x402679 <utama + 9> mov% rsi,% r13 |
   | 0x40267c <main + 12> dorong% r12 |
   | 0x40267e <main + 14> dorong% rbp |
   | 0x40267f <main + 15> dorong% rbx |
   | 0x402680 <main + 16> sub $ 0x438,% rsp |
   | 0x402687 <main + 23> mov (% rsi),% rdi |
   | 0x40268a <utama + 26> movq $ 0x402a10,0x400 (% rsp) |
   | 0x402696 <utama + 38> movq $ 0x0,0x408 (% rsp) |
   | 0x4026a2 <utama + 50> movq $ 0x402510,0x410 (% rsp) |
   + ------------------------------------------------- -------------------------- +
proses anak 21518 Dalam: Jalur utama: ?? PC: 0x402670
(gdb) file / opt / j64-602 / bin / jconsole
Membaca simbol dari /opt/j64-602/bin/jconsole...done.
(tidak ada simbol debugging yang ditemukan) ... selesai.
(gdb) tata letak asm
(gdb) mulai
(gdb)
singkat
sumber
26

Hal paling berguna yang dapat Anda lakukan di sini adalah display/i $pc, sebelum menggunakan stepiseperti yang telah disarankan dalam jawaban R Samuel Klatchko. Ini memberitahu gdb untuk membongkar instruksi saat ini sebelum mencetak prompt setiap kali; maka Anda dapat terus menekan Enter untuk mengulangi stepiperintah.

(Lihat jawaban saya untuk pertanyaan lain untuk lebih detail - konteks pertanyaan itu berbeda, tetapi prinsipnya sama.)

Matthew Slattery
sumber