Se vuoi limitarti al rilevamento ELF, puoi leggere l' intestazione ELF di /proc/$PID/exete stesso. È abbastanza banale: se il 5 ° byte nel file è 1, è un file binario a 32 bit. Se è 2, è a 64 bit. Per un ulteriore controllo di integrità:
- Se i primi 5 byte sono
0x7f, "ELF", 1: è un binario ELF a 32 bit.
- Se i primi 5 byte sono
0x7f, "ELF", 2: è un binario ELF a 64 bit.
- Altrimenti: è inconcludente.
Potresti anche usare objdump, ma questo toglie la tua libmagicdipendenza e la sostituisce con una libelf.
Un altro modo : puoi anche analizzare il /proc/$PID/auxvfile. Secondo proc(5):
Questo contiene il contenuto delle informazioni sull'interprete ELF trasmesse al processo al momento dell'esecuzione. Il formato è un ID lungo senza segno più un valore lungo senza segno per ogni voce. L'ultima voce contiene due zeri.
I significati delle unsigned longchiavi sono dentro /usr/include/linux/auxvec.h. Tu vuoi AT_PLATFORM, che è 0x00000f. Non citarmi su questo, ma sembra che il valore debba essere interpretato come a char *per ottenere la descrizione della stringa della piattaforma.
Questa domanda StackOverflow può essere utile.
Ancora un altro modo : puoi istruire il linker dinamico ( man ld) a scaricare informazioni sull'eseguibile. Stampa sull'output standard la struttura AUXV decodificata. Attenzione: questo è un trucco, ma funziona.
LD_SHOW_AUXV=1 ldd /proc/$SOME_PID/exe | grep AT_PLATFORM | tail -1
Questo mostrerà qualcosa di simile:
AT_PLATFORM: x86_64
L'ho provato su un binario a 32 bit e ho ottenuto i686invece.
Come funziona: LD_SHOW_AUXV=1indica a Dynamic Linker di scaricare la struttura AUXV decodificata prima di eseguire l'eseguibile. A meno che non ti piaccia davvero rendere la tua vita interessante, vuoi evitare di eseguire effettivamente detto eseguibile. Un modo per caricarlo e collegarlo dinamicamente senza effettivamente chiamarne la main()funzione è eseguirlo ldd(1). Il rovescio della medaglia: LD_SHOW_AUXVè abilitato dalla shell, quindi otterrai dump delle strutture AUXV per: la subshell ldde il tuo binario di destinazione. Quindi siamo grepper AT_PLATFORM, ma manteniamo solo l'ultima riga.
Analisi ausiliaria : se analizzi tu stesso la auxvstruttura (non basandoti sul caricatore dinamico), allora c'è un po 'di enigma: la auxvstruttura segue la regola del processo che descrive, quindi sizeof(unsigned long)saranno 4 per i processi a 32 bit e 8 per 64 processi a bit. Possiamo farlo funzionare per noi. Affinché ciò funzioni su sistemi a 32 bit, tutti i codici chiave devono essere 0xffffffffo meno. Su un sistema a 64 bit, i 32 bit più significativi saranno zero. I computer Intel sono piccoli endian, quindi questi 32 bit seguono quelli meno significativi in memoria.
Pertanto, tutto ciò che devi fare è:
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.
Analizzare il file delle mappe : questo è stato suggerito da Gilles, ma non ha funzionato del tutto. Ecco una versione modificata che lo fa. Si basa sulla lettura del /proc/$PID/mapsfile. Se il file elenca gli indirizzi a 64 bit, il processo è a 64 bit. Altrimenti, sono 32 bit. Il problema sta nel fatto che il kernel semplifica l'output rimuovendo gli zero iniziali dagli indirizzi esadecimali in gruppi di 4, quindi l'hacking di lunghezza non può funzionare del tutto. awkAl salvataggio:
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
Funziona controllando l'indirizzo iniziale dell'ultima mappa di memoria del processo. Sono elencati come 12345678-deadbeef. Quindi, se il processo è a 32 bit, quell'indirizzo avrà una lunghezza di otto cifre esadecimali e il nono sarà un trattino. Se è a 64 bit, l'indirizzo più alto sarà più lungo di quello. Il nono carattere sarà una cifra esadecimale.
Attenzione: tutti tranne il primo e l'ultimo metodo richiedono il kernel Linux 2.6.0 o successivo, poiché il auxvfile non era presente prima.
/proc/[pid]/auxv: "le informazioni sull'interprete ELF sono passate al processo al momento dell'esecuzione. Il formato è un ID lungo senza segno più un valore lungo senza segno per ogni voce" (man proc).