Якщо ви хочете обмежити себе виявлення ELF, ви можете прочитати ELF заголовок з /proc/$PID/exeсебе. Це досить тривіально: якщо 5-й байт у файлі дорівнює 1, це 32-бітний двійковий файл. Якщо це 2, це 64-бітний. Для додаткової перевірки здорового стану:
- Якщо перші 5 байтів
0x7f, "ELF", 1: це 32-бітний дворядовий ELF.
- Якщо перші 5 байтів
0x7f, "ELF", 2: це 64-бітний двофакторний ELF.
- Інакше: це непереконливо.
Ви також можете використовувати objdump, але це забирає вашу libmagicзалежність і замінює її на libelfодну.
Інший спосіб : ви також можете розібрати /proc/$PID/auxvфайл. Відповідно до proc(5):
Тут міститься вміст інформації перекладача ELF, переданої в процес у виконаний час. Формат - це один неподписаний довгий ідентифікатор плюс одне довге неподписане значення для кожного запису. Останній запис містить дві нулі.
Значення unsigned longклавіш в /usr/include/linux/auxvec.h. Хочеш AT_PLATFORM, що є 0x00000f. Не цитуйте мене з цього приводу, але, здається, значення слід інтерпретувати як а, char *щоб отримати рядковий опис платформи.
Це питання StackOverflow може бути корисним.
Ще один спосіб : ви можете доручити динамічному лінкеру ( man ld) скинути інформацію про виконуваний файл. Він виводить на стандартний вихід декодовану структуру AUXV. Попередження: це хакер, але він працює.
LD_SHOW_AUXV=1 ldd /proc/$SOME_PID/exe | grep AT_PLATFORM | tail -1
Це покаже щось на кшталт:
AT_PLATFORM: x86_64
Я спробував це на 32-бітному бінарному і отримав i686замість цього.
Як це працює: LD_SHOW_AUXV=1інструктує Dynamic Linker скидати декодовану структуру AUXV перед запуском виконуваного файлу. Якщо ви дійсно не хочете зробити ваше життя цікавою, ви хочете , щоб уникнути фактично працює сказав виконуваним. Один із способів завантаження та динамічного зв’язку, фактично не викликаючи його main()функції, - це запуск ldd(1)на ньому. Мінус: LD_SHOW_AUXVувімкнено оболонкою, тому ви отримаєте скидання структур AUXV для: нижньої оболонки lddта цільового бінарного файлу . Таким чином, ми grepдля AT_PLATFORM, але зберігаємо лише останній рядок.
Розбір auxv : якщо ви auxvсамі розбираєте структуру (не покладаючись на динамічний завантажувач), то є трохи головоломки: auxvструктура слідує правилу описаного процесу, тому sizeof(unsigned long)буде 4 для 32-бітних процесів і 8 для 64 -бітові процеси. Ми можемо зробити цю роботу за нас. Для того, щоб це працювало в 32-бітних системах, всі ключові коди повинні бути 0xffffffffабо меншими. У 64-бітовій системі найбільш значущі 32 біти будуть нульовими. Машини Intel - мало ендіатів, тому ці 32 біти слідують за найменш значущими пам'яттю.
Все, що вам потрібно зробити:
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.
Розбір файлу карт : це було запропоновано Гіллем, але це не спрацювало. Ось модифікована версія. Він покладається на читання /proc/$PID/mapsфайлу. Якщо файл містить 64-бітні адреси, процес становить 64 біти. Інакше це 32 біти. Проблема полягає в тому, що ядро спростить вихід, позбавивши провідні нулі з шестигранних адрес у групах по 4, тому злом довжини не може працювати. awkна допомогу:
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
Це працює, перевіряючи початкову адресу останньої карти пам'яті процесу. Вони перераховані як 12345678-deadbeef. Отже, якщо процес 32-розрядний, ця адреса матиме вісім шістнадцяткових цифр, а дев'ята - дефіс. Якщо це 64-бітний, найвища адреса буде довшою за це. Дев'ятий символ буде шістнадцятковим числом.
Будьте в курсі: всі, окрім першого та останнього методів, потребують ядра Linux 2.6.0 або новішого, оскільки цього auxvфайлу раніше не було.
/proc/[pid]/auxv: "Інформація інтерпретатора ELF, передана процесу в exec час. Формат - це один неподписаний довгий ідентифікатор плюс одне довге неподписане значення для кожного запису" (man proc).