GNU/Linux >> Belajar Linux >  >> Linux

dapatkah suatu program membaca bagian elfnya sendiri?

Bagaimana cara mencetak versi build program (terletak di bagian .note.gnu.build-id elf) dari program itu sendiri?

  1. Anda perlu membaca ElfW(Ehdr) (di awal file) untuk menemukan header program di biner Anda (.e_phoff dan .e_phnum akan memberi tahu Anda di mana letak tajuk program, dan berapa banyak yang harus dibaca).

  2. Anda kemudian membaca header program, sampai Anda menemukan PT_NOTE segmen program Anda. Segmen itu akan memberi tahu Anda offset ke awal semua nada dalam biner Anda.

  3. Anda kemudian perlu membaca ElfW(Nhdr) dan lewati sisa catatan (ukuran total catatan adalah sizeof(Nhdr) + .n_namesz + .n_descsz , disejajarkan dengan benar), hingga Anda menemukan catatan dengan .n_type == NT_GNU_BUILD_ID .

  4. Setelah Anda menemukan NT_GNU_BUILD_ID perhatikan, lewati .n_namesz nya , dan baca .n_descsz byte untuk membaca build-id yang sebenarnya.

Anda dapat memverifikasi bahwa Anda membaca data yang benar dengan membandingkan apa yang Anda baca dengan keluaran readelf -n a.out .

P.S.

Jika Anda akan mengalami kesulitan untuk mendekode build-id seperti di atas, dan jika executable Anda tidak dilucuti, mungkin lebih baik bagi Anda untuk mendekode dan mencetak simbol nama sebagai gantinya (yaitu untuk mereplikasi apa backtrace_symbols tidak) -- ini sebenarnya lebih mudah dilakukan daripada mendekode catatan ELF, karena tabel simbol berisi entri berukuran tetap.


Pada dasarnya, ini adalah kode yang saya tulis berdasarkan jawaban yang diberikan untuk pertanyaan saya. Untuk mengkompilasi kode saya harus membuat beberapa perubahan dan saya harap ini akan berfungsi untuk sebanyak mungkin jenis platform. Namun, itu diuji hanya pada satu mesin build. Salah satu asumsi yang saya gunakan adalah bahwa program dibuat di atas mesin yang menjalankannya sehingga tidak ada gunanya memeriksa kompatibilitas endianness antara program dan mesin.

[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. Bisakah Bash Menulis Ke Aliran Inputnya Sendiri?

  2. Temukan File yang Tidak Dapat Dibaca Pengguna?

  3. Bisakah Skrip Dapat Dieksekusi Tetapi Tidak Dapat Dibaca?

  1. Bagaimana Proses Latar Belakang Mengetahui Pidnya Sendiri?

  2. Bisakah Strace/ptrace Menyebabkan Program Rusak?

  3. header file ELF

  1. Bagaimana pustaka bersama (.so) memanggil fungsi yang diimplementasikan dalam program pemuatannya?

  2. Bisakah saya menguji jaringan saya sendiri?

  3. Bagaimana cara membaca satu file di maildir?