[C] Elf linked libraries [RISOLTO]

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Rispondi
Dani
Linux 4.x
Linux 4.x
Messaggi: 1447
Iscritto il: mer 26 apr 2006, 1:52
Desktop: gnome
Distribuzione: arch

[C] Elf linked libraries [RISOLTO]

Messaggio da Dani »

Partendo dal path di un file è possibile riconoscere se il file stesso è un binario che usa librerie condivise o se è altro, senza ricorrere a programmi esterni ?
Devo costruirmi una funzione che abbia un comportamento simile:

- ottenimento del percorso dai parametri (es: f ("/bin/bash") )
- verifica dell'esistenza del file
- se il file esiste, verifica del tipo di file; se non è un binario che usa librerie condivise ritorna
- lettura librerie linkate

Il problema nasce dal terzo punto in poi, non so come riconoscere il tipo di file o come controllare eventuali librerie condivise.

Suggerimenti ? :roll:
Ultima modifica di Dani il sab 5 apr 2008, 6:57, modificato 1 volta in totale.

Avatar utente
Toni
Linux 3.x
Linux 3.x
Messaggi: 999
Iscritto il: lun 30 gen 2006, 22:08
Slackware: slackware-14
Kernel: 3.10.5
Desktop: i3
Località: milano

Re: [C] Distinzione files

Messaggio da Toni »

ogni file in linux comincia con un magic number , con il quale si identifica il tipo di file ( a differenza dei sistemi microsoft che usa le estensioni dei nomi)

Avatar utente
umaga
Packager
Packager
Messaggi: 180
Iscritto il: lun 30 gen 2006, 10:19
Slackware: 13.37
Kernel: 2.6.38.4-smp
Desktop: KDE 4.7
Località: Cagliari

Re: [C] Distinzione files

Messaggio da umaga »

se non ricordo male il comando "file" da informazioni dettagliate su tipo di file... potresti prendere informazioni da li...


ciao

Avatar utente
414N
Iper Master
Iper Master
Messaggi: 2922
Iscritto il: mer 13 feb 2008, 16:19
Slackware: 15.0
Kernel: 5.15.19
Desktop: KDE5
Località: Bulagna
Contatta:

Re: [C] Distinzione files

Messaggio da 414N »

man libmagic

Mario Vanoni
Iper Master
Iper Master
Messaggi: 3174
Iscritto il: lun 3 set 2007, 21:20
Nome Cognome: Mario Vanoni
Slackware: 12.2
Kernel: 3.0.4 statico
Desktop: fluxbox/seamonkey
Località: Cuasso al Monte (VA)

Re: [C] Distinzione files

Messaggio da Mario Vanoni »

Dani ha scritto: - ottenimento del percorso dai parametri (es: f ("/bin/bash") )
- verifica dell'esistenza del file
- se il file esiste, verifica del tipo di file; se non è un binario che usa librerie condivise ritorna
- lettura librerie linkate
1) usando popen(3)
2) usando access(2), ATTENTO: non funziona con files montati via NFS! man 2 access
3) impossibile, e.g. se compilato con make -O2 -s -static (mio standard)
4) illusione se 3) vero, se 3) falso ignoro, se shell script non importa

Dani
Linux 4.x
Linux 4.x
Messaggi: 1447
Iscritto il: mer 26 apr 2006, 1:52
Desktop: gnome
Distribuzione: arch

Re: [C] Distinzione files

Messaggio da Dani »

Non ho intenzione di usare comandi esterni, quindi non mi puo' tornare utile nè il comando file, nè la funzione popen().
Per risolvere il terzo punto devo leggere questo magic number, che tra l'altro nemmeno conoscevo :oops:
Ho fatto una prova al volo ed il tipo di file che cerco sembra avere sempre il primo byte uguale a 0x457F, non so se sia il magic number o meno, ma sta di fatto che tutti i binari che usano librerie condivise iniziano con quel valore.

Esempio:

Codice: Seleziona tutto

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char** argv)
{

FILE* fd;
#define size 255
int i;
unsigned short magic;
char buffer[size + 1] = { 0 };

if (argc < 2) return EXIT_FAILURE;

for (i = 1; i <= argc; i++)
{
	if (!(fd = fopen (argv[i], "rb"))) return EXIT_FAILURE;
	
	fread ((unsigned short*)&magic, sizeof (unsigned short), 1, fd);
	
//	printf ("Magic of %s: 0x%X\n", argv[i], magic);

	if (magic != 0x457F)
	{
		memset (buffer, 0, size);
		snprintf (buffer, size, "ldd %s", argv[i]);
		system (buffer);
	}

	fclose (fd);

}
return EXIT_SUCCESS;
}

Sui files che hanno il primo byte diverso da 0x457F lancio ldd, ed infatti da shell:

Codice: Seleziona tutto

bt ~ # for i in $(ls /usr/bin); do ./a.out /usr/bin/$i; done
       not a dynamic executable
        not a dynamic executable
        not a dynamic executable
        not a dynamic executable
        not a dynamic executable
        not a dynamic executable
        not a dynamic executable
[...]
Prima di passare all'ultimo punto, ovvero alla lettura delle librerie linkate dinamicamente, mi serve una conferma.
Quello che leggo è il magic number ? E' univoco ?

[edit] Piccola precisazione: il codice di sopra va a leggere piu' di un byte, se leggo un solo byte ottengo 0xBF7F.

Avatar utente
absinthe
Iper Master
Iper Master
Messaggi: 2354
Iscritto il: dom 15 mag 2005, 0:00
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze
Località: Prato
Contatta:

Re: [C] Distinzione files

Messaggio da absinthe »

prova a leggere /etc/file/magic. è immenso greppa le informazioni su ELF. io non ci chiappo nienete ma lì dentro c'è la collezione di tutti i magic usati da file per capire di che tipo di file si tratta. forse anche un occhiata al codice di file potrebbe aiutare.

M

Dani
Linux 4.x
Linux 4.x
Messaggi: 1447
Iscritto il: mer 26 apr 2006, 1:52
Desktop: gnome
Distribuzione: arch

Re: [C] Distinzione files

Messaggio da Dani »

absinthe ha scritto:io non ci chiappo nienete
Capisco, sfido chiunque a chiapparci qualcosa in quel file ! :lol:
Fortunatamente ho trovato questa ottima spiegazione, ora so riconoscere il file ELF dal resto del mondo, e ho capito come distinguare l'ELF eseguibile dall'ELF resto del mondo :D

Dunque possiamo passare all'ultimo punto, cioè alla lettura delle librerie collegate all'eseguibile. Any hints ? #-o

Avatar utente
absinthe
Iper Master
Iper Master
Messaggi: 2354
Iscritto il: dom 15 mag 2005, 0:00
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze
Località: Prato
Contatta:

Re: [C] Distinzione files

Messaggio da absinthe »

ma... di fatto te vuoi integrare un subset delle opzioni di readelf! scrutare il codicillo per controllare gli include potrebbe essere un'idea!

M

afterjames
Linux 0.x
Linux 0.x
Messaggi: 64
Iscritto il: lun 14 gen 2008, 14:14

Re: [C] Distinzione files

Messaggio da afterjames »

Se la distinzione fosse semplicemente sul tipo di file(regolare,directory, device file, sym link ..) basterebbe una semplice :

Codice: Seleziona tutto

int lstat(const char *restrict path, struct stat *restrict buf);

Tra l'altro il comando "File" la utilizza.Se è un file oggetto o un eseguibile in genere questi sono in formato elf, quindi usi una readelf.

Dani
Linux 4.x
Linux 4.x
Messaggi: 1447
Iscritto il: mer 26 apr 2006, 1:52
Desktop: gnome
Distribuzione: arch

Re: [C] Distinzione files

Messaggio da Dani »

Il problema della distinzione dei files l'ho risolto, a me interessava solo sapere se il file x era un elf.
Ora sono bloccato alla lettura delle librerie collegate ad esso. Ho provato a guardare il codice di readelf delle binutils, ma non si capisce niente.

Dani
Linux 4.x
Linux 4.x
Messaggi: 1447
Iscritto il: mer 26 apr 2006, 1:52
Desktop: gnome
Distribuzione: arch

Re: [C] Distinzione files

Messaggio da Dani »

Risolto !

Sorgentino dimostrativo :)

Codice: Seleziona tutto

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <elf.h>

#define ERR(s) {perror (s); exit (1);}

void print_hex (Elf32_Ehdr h, unsigned len, char* messaggio)
{
 int i;
 
 printf ("%s[", messaggio);
 
 for (i = 0; i < len; i++)
  printf ("%c", (unsigned char) h.e_ident[i]);
 
 printf ("] ");
 
 
 for (i = 0; i < len - 1; i++)
  printf ("%.2X ", (unsigned char) h.e_ident[i]);
 
 printf ("%.2X\n", h.e_ident[i]);
 
 return;
}

void print_ehdr (Elf32_Ehdr E)
{
	printf ("+----------\n| Elf32_Ehdr\n+----------\n");
	
	print_hex (E, sizeof E.e_ident, 
            "E.e_ident:      ");
	printf ("E.e_type:       %.2X\n", E.e_type);
 	printf ("E.e_machine:    %.2X\n", E.e_machine);
 	printf ("E.e_version:    %.2X\n", E.e_version);
 	printf ("E.e_entry:      0x%.8X\n", E.e_entry);
 	printf ("E.e_phoff:      0x%.8X\n", E.e_phoff);
 	printf ("E.e_shoff:      0x%.8X\n", E.e_shoff);
 	printf ("E.e_flags:      %.2X\n", E.e_flags);
 	printf ("E.e_ehsize:     %.2X\n", E.e_ehsize);
 	printf ("E.e_phentsize:  %.2X\n", E.e_phentsize);
 	printf ("E.e_phnum:      %.2X\n", E.e_phnum);
 	printf ("E.e_shentsize:  %.2X\n", E.e_shentsize);
 	printf ("E.e_shnum:      %.2X\n", E.e_shnum);
 	printf ("E.e_shstrndx:   %.2X\n", E.e_shstrndx);
}

void print_phdr (Elf32_Phdr P, unsigned entry)
{
	printf ("\n+----------\n| Elf32_Phdr [%uth entry]\n+----------\n", entry);
	
	printf ("P.p_type :   %.2X %s\n", P.p_type, (P.p_type == PT_DYNAMIC) ? "[DYNAMIC SECTION]" : "");
	printf ("P.p_offset:  0x%.8X\n", P.p_offset);
	printf ("P.p_vaddr:   0x%.8X\n", P.p_vaddr);
	printf ("P.p_paddr:   0x%.8X\n", P.p_paddr);
	printf ("P.p_filesz:  %.2X\n", P.p_filesz);
	printf ("P.p_memsz:   %.2X\n", P.p_memsz);
	printf ("P.p_flags:   %.2X\n", P.p_flags);
	printf ("P.p_align:   %.2X\n", P.p_align);
}
	
	
void print_shdr (Elf32_Shdr S, unsigned entry)
{
	printf ("\n+----------\n| Elf32_Shdr [%uth entry]\n+----------\n", entry);
	
	printf ("S.sh_name:       %.2X\n", S.sh_name);
 	printf ("S.sh_type:       %.2X %s\n", S.sh_type, (S.sh_type == SHT_DYNAMIC) ? "[DYNAMIC SECTION]" : "");
 	printf ("S.sh_flags:      %.2X\n", S.sh_flags);
 	printf ("S.sh_addr:       0x%.8X\n", S.sh_addr);
 	printf ("S.sh_offset:     0x%.8X\n", S.sh_offset);
 	printf ("S.sh_size:       0x%.8X\n", S.sh_size);
 	printf ("S.sh_link:       0x%.2X\n", S.sh_link);
 	printf ("S.sh_info:       %.2X\n", S.sh_info);
 	printf ("S.sh_addralign:  %.2X\n", S.sh_addralign);
 	printf ("S.sh_entsize:    %.2X\n", S.sh_entsize);
 	
}

char* get_str (FILE* fd, unsigned long offset)
{
	char c, *s = NULL;
	int i;
	
	if (fseek (fd, offset, SEEK_SET))
	 ERR ("Cannot seek file");
	
	while (1)
	{
		if (fread ((char*)&c, 1, 1, fd) != 1)
		 ERR ("Cannot read from file");
		
		if (!c)
		 break;
		
		i++;
		putchar (c);
	} 
	
	 
	return s;
}
	   
	

int main (int argc, char** argv)
{

FILE* fd;
unsigned char c;
int rval = 0, i, j, n, p_dynamic_index, s_dynamic_index;
unsigned long set;
char *data = NULL;
Elf32_Ehdr E;
Elf32_Phdr *P;
Elf32_Shdr *S;
Elf32_Dyn  *D;

char *str = NULL;

if (argc < 2 || !(fd = fopen (argv[1], "rb"))) 
 return EXIT_FAILURE;

 
 if (fread ((Elf32_Ehdr*)&E, sizeof (Elf32_Ehdr), 1, fd) != 1)
  ERR ("Unable to read elf header"); 
 print_ehdr (E);
 
 
 
 printf ("\nFound %d entries in program header:", E.e_phnum);
 if (fseek (fd, E.e_phoff, SEEK_SET))
  ERR ("Unable to seek file");
 P = (Elf32_Phdr*) malloc (E.e_phnum * sizeof (Elf32_Phdr));
 for (i = 0; i < E.e_phnum - 1; i++)
 {
 	if (fread ((Elf32_Phdr*)&P[i], E.e_phentsize, 1, fd) != 1)
  	 ERR ("Cannot read program section header");
 	
 	
 	if (P[i].p_type == PT_DYNAMIC)
 	{
 		print_phdr (P[i], i);
 		p_dynamic_index = i;
	}
 	 
 }
  
 printf ("\nFound %d entries in section header:", E.e_shnum);
 if (fseek (fd, E.e_shoff, SEEK_SET))
  ERR ("Unable to seek file");
 S = (Elf32_Shdr*) malloc (E.e_shnum * sizeof (Elf32_Shdr));
 for (i = 0; i < E.e_shnum - 1; i++)
 {
 	if (fread ((Elf32_Shdr*)&S[i], E.e_shentsize, 1, fd) != 1)
  	 ERR ("Cannot read program section header");
 	
 	if (S[i].sh_type == SHT_DYNAMIC)
 	{
 		print_shdr (S[i], i);
 		s_dynamic_index = i;
 		
 		if (S[i].sh_link)
 		 print_shdr (*(S + S[i].sh_link), S[i].sh_link);
	}
 	 
 }
  

 n = S[s_dynamic_index].sh_size / S[s_dynamic_index].sh_entsize;

 puts ("\n------------\n");
 if (fseek (fd, P[p_dynamic_index].p_offset, SEEK_SET))
  ERR ("Unable to seek file");
 D = (Elf32_Dyn*) malloc (E.e_shnum * sizeof (Elf32_Dyn));
 for (i = 0; i < n; i++)
 {
 	if (fread ((Elf32_Dyn*)&D[i], sizeof (Elf32_Dyn), 1, fd) != 1)
  	 ERR ("Unable to read dynamyc section");
 	if (D[i].d_tag == DT_NEEDED)
 	{
 		printf ("[D.d_tag: DT_NEEDED] d_val: 0x%.8X\n", D[i].d_un.d_val);
 	}
 }

 puts ("\n------------\n");
 
 for (i = 0; i < n; i++)
 {
 	if (D[i].d_tag != DT_NEEDED)
 	 continue;
 	 
 	set = S[S[s_dynamic_index].sh_link].sh_offset + D[i].d_un.d_val;
 	str = get_str (fd, set);
    
    putchar ('\n');
 }
 
 
 fclose (fd);
 putchar ('\n');
 return EXIT_SUCCESS;
}


Rispondi