Come trovare la differenza tra un file di script e un file binario?


11
$ ls -l /usr/bin
total 200732

-rwxr-xr-x 1 root   root     156344 Oct  4  2013 adb
-rwxr-xr-x 1 root   root       6123 Oct  8  2013 add-apt-repository
 list goes long ---------

Quanto sopra adbè un file binario ed add-apt-repositoryè un file di script. Ricevo queste informazioni visualizzando i file tramite nautilus. Ma attraverso la riga di comando, non ho trovato alcuna differenza. Non sono in grado di prevedere se un file è un file binario o un file di script.

Quindi, come faccio a distinguere tra file di script e file binari attraverso la riga di comando?

Risposte:


16

Usa solo file:

$ file /usr/bin/add-apt-repository
/usr/bin/add-apt-repository: Python script, ASCII text executable
$ file /usr/bin/ab
/usr/bin/ab: ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=569314a9c4458e72e4ac66cb043e9a1fdf0b55b7, stripped

Come spiegato in man file:

NAME
   file — determine file type

DESCRIPTION
 This manual page documents version 5.14 of the file command.

 file tests each argument in an attempt to classify it.  There are three
 sets of tests, performed in this order: filesystem tests, magic tests,
 and language tests.  The first test that succeeds causes the file type to
 be printed.

 The type printed will usually contain one of the words text (the file
 contains only printing characters and a few common control characters and
 is probably safe to read on an ASCII terminal), executable (the file con‐
 tains the result of compiling a program in a form understandable to some
 UNIX kernel or another), or data meaning anything else (data is usually
 “binary” or non-printable).  Exceptions are well-known file formats (core
 files, tar archives) that are known to contain binary data.  When adding
 local definitions to /etc/magic, make sure to preserve these keywords.
 Users depend on knowing that all the readable files in a directory have
 the word “text” printed.  Don't do as Berkeley did and change “shell
 commands text” to “shell script”.

Puoi anche usare un trucco per eseguirlo direttamente sul nome dell'eseguibile nel tuo $PATH:

$ file $(type -p add-apt-repository | awk '{print $NF}')
/usr/local/bin/add-apt-repository: Python script, ASCII text executable
$ file $(type -p ab | awk '{print $NF}')
/usr/bin/ab: ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=569314a9c4458e72e4ac66cb043e9a1fdf0b55b7, stripped

Per trovare il tipo di file di tutti gli eseguibili che puoi trovare nelle directory del tuo $PATH, puoi farlo:

find $(printf "$PATH" | sed 's/:/ /g') -type f | xargs file

E per eseguire filesu tutti i file in una directory particolare ( /usr/binad esempio), basta

file /usr/bin/*

Ma dobbiamo eseguire fileper ogni file per vedere che tipo di file è questo. Esiste un metodo semplice per tutti i file?
Avinash Raj,

3
@AvinashRaj per tutti i file in una determinata directory? Fallo e basta file /usr/bin/*. Proprio come qualsiasi altro comando.
terdon,

5

In realtà, le differenze tra quelle non sono così grandi.

Su un tipico sistema Unix o Linux, ci sono meno di cinque eseguibili reali. Su Ubuntu, questi sono /lib/ld-linux.so.2e /sbin/ldconfig.

Tutto il resto contrassegnato come eseguibile viene eseguito attraverso un interprete , per il quale sono supportati due formati:

  1. I file che iniziano con #!avranno il nome dell'interprete tra questo e il primo carattere di nuova riga (esatto, non è necessario che gli "script" siano file di testo).
  2. I file ELF hanno un PT_INTERPsegmento che fornisce il percorso all'interprete (di solito /lib/ld-linux.so.2).

Quando viene eseguito un tale file, il kernel trova il nome dell'interprete e lo chiama invece. Ciò può avvenire in modo ricorsivo, ad esempio quando si esegue uno script di shell:

  1. Il kernel apre lo script, trova #! /bin/shall'inizio.
  2. Il kernel si apre /bin/sh, trova il PT_INTERPsegmento che punta a /lib/ld-linux.so.2.
  3. Il kernel si apre /lib/ld-linux.so.2, trova che non ha un PT_INTERPsegmento, carica il suo segmento di testo e lo avvia, passando l'handle aperto a /bin/she la riga di comando per l'invocazione dello script.
  4. ld-linux.so.2carica i segmenti di codice da /bin/sh, risolve i riferimenti alla libreria condivisa e avvia la sua funzione principale
  5. /bin/sh quindi riapre il file di script e inizia a interpretarlo riga per riga.

Dal punto di vista del kernel, l'unica differenza è che per il file ELF viene passato il descrittore di file aperto anziché il nome del file; questa è principalmente un'ottimizzazione. Se l'interprete decida quindi di passare a un segmento di codice caricato dal file o di interpretarlo riga per riga viene deciso solo dall'interprete e principalmente basato sulla convenzione.


Buone informazioni, ma non proprio una risposta a questa domanda.
OrangeDog,

La risposta è Mu .
Simon Richter,

1

Il comando File è ottimo, ma per uno strumento di analisi più professionale, vorrei che tu provassi il pacchetto TrID che è uno strumento di Identificazione file.

TrID è un'utilità progettata per identificare i tipi di file dalle loro firme binarie ed è facile da usare.

Per ulteriori informazioni e il pacchetto basta visitare: Sito

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.