Jika Anda ingin membatasi diri Anda untuk deteksi ELF, Anda dapat membaca judul ELF dari /proc/$PID/exe
diri Anda sendiri. Ini cukup sepele: jika byte ke-5 dalam file adalah 1, itu adalah biner 32-bit. Jika 2, 64-bit. Untuk pemeriksaan kewarasan tambahan:
- Jika 5 byte pertama adalah
0x7f, "ELF", 1
: ini adalah biner ELF 32 bit.
- Jika 5 byte pertama adalah
0x7f, "ELF", 2
: itu adalah biner ELF 64 bit.
- Jika tidak: tidak dapat disimpulkan.
Anda juga bisa menggunakan objdump
, tetapi itu menghilangkan libmagic
ketergantungan Anda dan menggantinya dengan yang lain libelf
.
Cara lain : Anda juga dapat mem-parsing /proc/$PID/auxv
file. Menurut proc(5)
:
Ini berisi isi informasi penerjemah ELF yang diteruskan ke proses pada waktu exec. Formatnya adalah satu ID panjang yang tidak ditandatangani ditambah satu nilai panjang yang tidak ditandatangani untuk setiap entri. Entri terakhir berisi dua nol.
Arti unsigned long
kunci ada di /usr/include/linux/auxvec.h
. Anda ingin AT_PLATFORM
, yang 0x00000f
. Jangan mengutip saya tentang itu, tetapi tampaknya nilai harus ditafsirkan sebagai char *
untuk mendapatkan deskripsi string dari platform.
Anda mungkin menemukan pertanyaan StackOverflow ini bermanfaat.
Namun cara lain : Anda dapat menginstruksikan dynamic linker ( man ld
) untuk membuang informasi tentang executable. Ini mencetak ke output standar struktur AUXV yang di-decode. Peringatan: ini peretasan, tetapi berhasil.
LD_SHOW_AUXV=1 ldd /proc/$SOME_PID/exe | grep AT_PLATFORM | tail -1
Ini akan menunjukkan sesuatu seperti:
AT_PLATFORM: x86_64
Saya mencobanya pada biner 32-bit dan i686
sebagai gantinya.
Bagaimana ini bekerja: LD_SHOW_AUXV=1
menginstruksikan Dynamic Linker untuk membuang struktur AUXV yang didekodekan sebelum menjalankan executable. Kecuali Anda benar - benar ingin membuat hidup Anda menarik, Anda ingin benar-benar menjalankan kata executable. Salah satu cara untuk memuat dan menautkannya secara dinamis tanpa benar-benar memanggil main()
fungsinya adalah dengan menjalankannya ldd(1)
. The downside: LD_SHOW_AUXV
diaktifkan oleh shell, sehingga Anda akan mendapatkan kesedihan dari struktur AUXV untuk: subkulit ldd
,, dan biner target Anda. Jadi kami grep
untuk AT_PLATFORM, tetapi hanya menjaga baris terakhir.
Parsing auxv : jika Anda menguraikan auxv
struktur sendiri (tidak mengandalkan loader dinamis), maka ada sedikit teka-teki: auxv
struktur mengikuti aturan proses yang dijelaskan, sehingga sizeof(unsigned long)
akan menjadi 4 untuk proses 32-bit dan 8 untuk 64 proses-bit. Kita dapat membuat ini bekerja untuk kita. Agar ini bekerja pada sistem 32-bit, semua kode kunci harus 0xffffffff
atau kurang. Pada sistem 64-bit, 32 bit yang paling signifikan adalah nol. Mesin Intel adalah endian kecil, jadi 32 bit ini mengikuti yang paling tidak signifikan dalam memori.
Dengan demikian, yang perlu Anda lakukan adalah:
1. Read 16 bytes from the `auxv` file.
2. Is this the end of the file?
3. Then it's a 64-bit process.
4. Done.
5. Is buf[4], buf[5], buf[6] or buf[7] non-zero?
6. Then it's a 32-bit process.
7. Done.
8. Go to 1.
Mem-parsing file peta : ini disarankan oleh Gilles, tetapi tidak berhasil. Ini versi modifikasi yang bisa. Itu bergantung pada membaca /proc/$PID/maps
file. Jika file mencantumkan alamat 64-bit, prosesnya adalah 64 bit. Kalau tidak, itu 32 bit. Masalahnya terletak pada kernel yang akan menyederhanakan output dengan melepaskan nol terkemuka dari alamat hex dalam kelompok 4, sehingga panjang hack tidak bisa bekerja. awk
untuk menyelamatkan:
if ! [ -e /proc/$pid/maps ]; then
echo "No such process"
else
case $(awk </proc/$pid/maps -- 'END { print substr($1, 0, 9); }') in
*-) echo "32 bit process";;
*[0-9A-Fa-f]) echo "64 bit process";;
*) echo "Insufficient permissions.";;
esac
fi
Ini berfungsi dengan memeriksa alamat awal dari peta memori terakhir dari proses. Mereka terdaftar seperti 12345678-deadbeef
. Jadi, jika prosesnya 32-bit, alamat itu akan menjadi delapan digit hex, dan kesembilan akan menjadi tanda hubung. Jika itu 64-bit, alamat tertinggi akan lebih lama dari itu. Karakter kesembilan akan menjadi digit hex.
Waspadalah: semua kecuali metode pertama dan terakhir membutuhkan kernel Linux 2.6.0 atau yang lebih baru, karena auxv
file tersebut tidak ada sebelumnya.
/proc/[pid]/auxv
: "informasi penerjemah ELF diteruskan ke proses pada waktu exec. Formatnya adalah satu ID panjang yang tidak ditandatangani ditambah satu nilai panjang yang tidak ditandatangani untuk setiap entri" (man proc
).