GNU/Linux >> Znalost Linux >  >> Linux

může program číst vlastní elfí sekci?

Jak mohu vytisknout verzi sestavení programu (umístěnou v sekci .note.gnu.build-id elf) ze samotného programu?

  1. Musíte si přečíst ElfW(Ehdr) (na začátku souboru), abyste našli záhlaví programu ve vašem binárním souboru (.e_phoff a .e_phnum vám řekne, kde jsou hlavičky programů a kolik jich ke čtení).

  2. Potom čtete hlavičky programů, dokud nenajdete PT_NOTE segmentu vašeho programu. Tento segment vám řekne offset na začátek všech not ve vaší binární soustavě.

  3. Poté si musíte přečíst ElfW(Nhdr) a přeskočte zbytek poznámky (celková velikost poznámky je sizeof(Nhdr) + .n_namesz + .n_descsz , správně zarovnané), dokud nenajdete poznámku s .n_type == NT_GNU_BUILD_ID .

  4. Jakmile najdete NT_GNU_BUILD_ID poznámka, přeskočte za jeho .n_namesz a přečtěte si .n_descsz bajtů ke čtení skutečného ID sestavení.

Můžete ověřit, že čtete správná data, porovnáním toho, co čtete, s výstupem readelf -n a.out .

P.S.

Pokud se chystáte projít problémy s dekódováním build-id, jak je uvedeno výše, a pokud váš spustitelný soubor není odstraněn, může být pro vás lepší pouze dekódovat a vytisknout symbol názvy (tj. replikovat to, co backtrace_symbols ano) – ve skutečnosti je to jednodušší než dekódování poznámek ELF, protože tabulka symbolů obsahuje položky s pevnou velikostí.


V podstatě je to kód, který jsem napsal na základě odpovědi na mou otázku. Abych mohl kód zkompilovat, musel jsem provést nějaké změny a doufám, že to bude fungovat pro co nejvíce typů platforem. Byl však testován pouze na jednom stavebním stroji. Jedním z předpokladů, které jsem použil, bylo, že program byl postaven na stroji, na kterém je spuštěn, takže nemá smysl kontrolovat kompatibilitu endianness mezi programem a strojem.

[email protected]:~/$ uname -s -r -m -o
Linux 3.2.0-45-generic x86_64 GNU/Linux
[email protected]:~/$ g++ test.cpp -o test
[email protected]:~/$ readelf -n test | grep Build
    Build ID: dc5c4682e0282e2bd8bc2d3b61cfe35826aa34fc
[email protected]:~/$ ./test
    Build ID: dc5c4682e0282e2bd8bc2d3b61cfe35826aa34fc
#include <elf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>

#if __x86_64__
#  define ElfW(type) Elf64_##type
#else
#  define ElfW(type) Elf32_##type
#endif

/*
detecting build id of a program from its note section
http://stackoverflow.com/questions/17637745/can-a-program-read-its-own-elf-section
http://www.scs.stanford.edu/histar/src/pkg/uclibc/utils/readelf.c
http://www.sco.com/developers/gabi/2000-07-17/ch5.pheader.html#note_section
*/

int main (int argc, char* argv[])
{
  char *thefilename = argv[0];
  FILE *thefile;
  struct stat statbuf;
  ElfW(Ehdr) *ehdr = 0;
  ElfW(Phdr) *phdr = 0;
  ElfW(Nhdr) *nhdr = 0;
  if (!(thefile = fopen(thefilename, "r"))) {
    perror(thefilename);
    exit(EXIT_FAILURE);
  }
  if (fstat(fileno(thefile), &statbuf) < 0) {
    perror(thefilename);
    exit(EXIT_FAILURE);
  }
  ehdr = (ElfW(Ehdr) *)mmap(0, statbuf.st_size, 
    PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(thefile), 0);
  phdr = (ElfW(Phdr) *)(ehdr->e_phoff + (size_t)ehdr);
  while (phdr->p_type != PT_NOTE)
  {
    ++phdr;
  }
  nhdr = (ElfW(Nhdr) *)(phdr->p_offset + (size_t)ehdr); 
  while (nhdr->n_type != NT_GNU_BUILD_ID)
  {
    nhdr = (ElfW(Nhdr) *)((size_t)nhdr + sizeof(ElfW(Nhdr)) + nhdr->n_namesz + nhdr->n_descsz);
  }
  unsigned char * build_id = (unsigned char *)malloc(nhdr->n_descsz);
  memcpy(build_id, (void *)((size_t)nhdr + sizeof(ElfW(Nhdr)) + nhdr->n_namesz), nhdr->n_descsz);
  printf("    Build ID: ");
  for (int i = 0 ; i < nhdr->n_descsz ; ++i)
  {
    printf("%02x",build_id[i]);
  }
  free(build_id);
  printf("\n");
  return 0;
}

Linux
  1. Může Bash zapisovat do svého vlastního vstupního streamu?

  2. Najít soubory, které uživatel nemůže číst?

  3. Může být skript spustitelný, ale nečitelný?

  1. Jak to, že každý program nebo služba má svůj vlastní účet v /etc/passwd?

  2. Záhlaví souborů ELF

  3. Přidání sekce do souboru ELF

  1. Může read(2) vrátit nulu, když není na EOF?

  2. Nástroj pro úpravu dynamické části binárního souboru ELF

  3. Jak spustit proces ve vlastní skupině procesů?