Pagina 1 di 1

[C] Elf linked libraries [RISOLTO]

Inviato: dom 23 mar 2008, 2:09
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:

Re: [C] Distinzione files

Inviato: dom 23 mar 2008, 2:24
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)

Re: [C] Distinzione files

Inviato: dom 23 mar 2008, 6:29
da umaga
se non ricordo male il comando "file" da informazioni dettagliate su tipo di file... potresti prendere informazioni da li...


ciao

Re: [C] Distinzione files

Inviato: dom 23 mar 2008, 10:15
da 414N
man libmagic

Re: [C] Distinzione files

Inviato: dom 23 mar 2008, 15:14
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

Re: [C] Distinzione files

Inviato: mar 25 mar 2008, 0:59
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.

Re: [C] Distinzione files

Inviato: mar 25 mar 2008, 9:04
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

Re: [C] Distinzione files

Inviato: mer 26 mar 2008, 1:31
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

Re: [C] Distinzione files

Inviato: mer 26 mar 2008, 8:55
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

Re: [C] Distinzione files

Inviato: mar 1 apr 2008, 20:42
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.

Re: [C] Distinzione files

Inviato: mer 2 apr 2008, 4:46
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.

Re: [C] Distinzione files

Inviato: sab 5 apr 2008, 6:56
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;
}