Formato binário: ELF

Em computação, o Executable and Linking Format (ELF, também chamado de Extensible Linking Format) é um padrão comum de arquivo para executáveis, código objeto, bibliotecas compartilhadas, e core dumps. Publicado pela primeira vez na especificação para a interface binária de aplicação (Application Binary Interface - ABI) da versão denominada System V Release 4 (SVR4) do sistema operacional Unix, e posteriormente no Padrão de Interface de Ferramenta, foi rapidamente aceito entre diferentes fornecedores de sistemas Unix. [https://pt.wikipedia.org/wiki/Executable_and_Linkable_Format]

Cada arquivo ELF é composto de um cabeçalho ELF, seguido pelos dados do arquivo.

Os dados podem incluir:

Entre os dados referidos pelas entradas de cabeçalho do programa (ou de tabela de cabeçalho de seção), encontraremos o payload, que consiste nas instruções em linguagem de máquina (para cada arquitetura) que codifica os fragmentos de código (text) que representam o programa.

O respectivo formato de arquivo para sistemas da Microsoft (Windows) é o PE. [https://en.wikipedia.org/wiki/Portable_Executable]

Seguindo formato ELF, shared objects e executáveis possuem duas tabelas de símbolos: “.symtab” e “.dynsym”.

A tabela .dynsym é uma versão reduzida da tabela .symtab que contém apenas símbolos globais. A informação encontrada em .dynsym é também disponibilizada em .symtab, enquanto o contrário nem sempre é válido.

A ideia da tabela .dynsym é facilitar o processo de carga dinâmica em tempo de execução, provendo lista de símbolos que deverão ser resolvidos pelo carregador. Por ser reduzida, quando comparada com .symtab, permite otimizar o processo de disparo de execução da aplicação.

Neste exercício, você deverá criar uma aplicação capaz de receber um parâmetro em linha de comando, que será o nome do binário a ser analisado: meubinario.

A partir do parâmetro recebido, sua aplicação deverá analisar o cabeçalho ELF do binário e deverá listar, na sequência de registro, os símbolos constantes na tabela .dynsym.

Um exemplo típico de linha de comando pode ser encontrado abaixo:

$ ./meu_programa ./minhalib.so 

A aplicação deverá responder da seguinte forma:

Instrumento de validação cruzada

Tomemos como referência uma aplicação (64 bits) do tipo “Alo mundo” provida pelo binário ./alo.

A execução do comando readelf -s ./alo retorna:

(...)
Tabela de símbolo ".dynsym" contém 7 entradas:
   Número: Tamanho do Valor do Tipo de Vínculo Nome Vis Ndx
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTab
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.2.5 (2)
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)
     4: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     5: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
     6: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@GLIBC_2.2.5 (2)
(...)

A saída esperada pela aplicação solução ao exercício será:


_ITM_deregisterTMCloneTable
puts
__libc_start_main
__gmon_start__
_ITM_registerTMCloneTable
__cxa_finalize

Perceba que as 7 entradas da tabela .dynsym são listadas.

A entrada 0 existe, mas não possui string vinculada. Logo, como saída, imprime-se linha vazia.

Para as demais entradas, imprime-se a string vinculada. Observe que não se imprime os caracteres depois do @.

Entrada

A entrada é uma chamada de linha de comando para a execução da aplicação, chamada na qual é informado o caminho do binário cujo cabeçalho ELF será analisado.

Saída

A saída é a lista dos símbolos constantes na tabela .dynsym do binário apontado na linha de comando da aplicação.

Exemplo de Entrada

$ ./meu_programa naoexiste.exe

Exemplo de Saída

nao disponivel

Exemplo de Entrada

$ ./meu_programa ./minhalib.so 

Exemplo de Saída


_ITM_deregisterTMCloneTable
puts
__gmon_start__
_ITM_registerTMCloneTable
__cxa_finalize
calcula
imprime

Exemplo de Entrada

$ ./meu_programa ./alo 

Exemplo de Saída


_ITM_deregisterTMCloneTable
puts
__libc_start_main
__gmon_start__
_ITM_registerTMCloneTable
__cxa_finalize

Exemplo de Entrada

$ ./meu_programa ./libpthread.so 

Exemplo de Saída


__libc_siglongjmp
__tsearch
__clone
free
__getrlimit
abort
unlink
_ITM_deregisterTMCloneTable
_exit
__sched_getscheduler
__libc_dlclose
errno
__libc_fatal
__statfs
__sched_get_priority_max
__mempcpy
__resp
getpid
__sigtimedwait
__mmap
fclose
strlen
__getpid
__stack_chk_fail
__libc_system
getuid
mmap
strchr
__munmap
__assert_fail
memset
__libc_fork
_IO_enable_locks
__write_nocancel
__register_atfork
sched_yield
_dl_deallocate_tls
__call_tls_dtors
__sched_getparam
_setjmp
calloc
__getdelim
__getmntent_r
__fxstat64
__libc_stack_end
strcmp
__twalk_r
__libc_thread_freeres
__endmntent
memcpy
__mprotect
_rtld_global_ro
__clock_gettime
__libc_fcntl64
prctl
__libc_current_sigrtmax_private
__tdelete
__sched_setscheduler
__libc_dlopen_mode
__getpagesize
malloc
__read_nocancel
_dl_make_stack_executable
__isoc99_sscanf
__libc_pthread_init
__ctype_init
realloc
__libc_dlsym
__tfind
munmap
__open64_nocancel
__libc_current_sigrtmin_private
__madvise
__h_errno
fopen
__mktemp
_dl_allocate_tls
__setmntent
__tunable_get_val
sched_setparam
_dl_get_tls_static_info
sprintf
link
exit
getrlimit
_ITM_registerTMCloneTable
__libc_alloca_cutoff
_dl_allocate_tls_init
__close_nocancel
_rtld_global
__libc_allocate_rtsig_private
__libc_longjmp
__cxa_finalize
__sched_get_priority_min
pthread_getattr_np
pthread_condattr_getpshared
pthread_attr_setaffinity_np
pthread_attr_setaffinity_np
pthread_rwlockattr_init
pthread_timedjoin_np
pthread_attr_setguardsize
pthread_rwlock_clockwrlock
pthread_attr_getstackaddr
pthread_condattr_setclock
thrd_join
write
cnd_init
__open64
__errno_location
pthread_sigqueue
__close
pthread_attr_setscope
pthread_barrierattr_setpshared
send
pause
pthread_condattr_setpshared
pthread_rwlock_destroy
sigwait
pthread_barrierattr_destroy
pthread_setaffinity_np
pthread_rwlock_init
pthread_setaffinity_np
mtx_timedlock
pthread_mutex_setprioceiling
tss_set
cnd_destroy
__libc_current_sigrtmin
GLIBC_2.11
pthread_mutex_trylock
pthread_rwlockattr_getpshared
GLIBC_2.12
__lseek
close
fsync
pthread_mutexattr_setpshared
GLIBC_2.18
flockfile
pthread_attr_getguardsize
__pthread_mutexattr_settype
pthread_clockjoin_np
__pthread_unregister_cancel_restore
pthread_attr_getschedpolicy
pthread_yield
accept
pthread_attr_setschedpolicy
__pthread_rwlock_destroy
_pthread_cleanup_pop_restore
pthread_attr_getstack
system
pthread_rwlock_unlock
sem_close
lseek
pthread_spin_destroy
pthread_mutex_destroy
pthread_kill
GLIBC_2.28
cnd_signal
pthread_sigmask
raise
pthread_getspecific
__fork
tss_delete
mtx_unlock
sem_open
pthread_setattr_default_np
sem_destroy
sem_wait
pthread_join
GLIBC_2.30
GLIBC_2.31
__pthread_unregister_cancel
pthread_cond_wait
pthread_cond_wait
pthread_rwlock_clockrdlock
__fcntl
__pthread_barrier_init
__pthread_rwlock_unlock
thrd_exit
__pthread_mutex_destroy
pthread_spin_lock
pthread_condattr_destroy
pthread_create
pthread_barrierattr_getpshared
__pthread_rwlock_trywrlock
open64
pthread_mutexattr_getrobust_np
__libpthread_freeres
pthread_setname_np
cnd_timedwait
pthread_detach
_pthread_cleanup_push
_pthread_cleanup_push_defer
__sigaction
__libpthread_version_placeholder
fcntl
pthread_rwlock_timedrdlock
pthread_mutex_timedlock
_IO_flockfile
pthread_mutexattr_getrobust
mtx_lock
pthread_spin_unlock
pthread_mutexattr_destroy
pthread_mutexattr_getpshared
tss_create
pthread_cond_broadcast
pthread_cond_broadcast
GLIBC_2.2.5
GLIBC_2.2.6
pthread_cond_signal
pthread_cond_signal
__send
pthread_getconcurrency
pthread_rwlock_trywrlock
pthread_setconcurrency
_IO_ftrylockfile
pthread_getcpuclockid
pthread_tryjoin_np
pthread_rwlock_timedwrlock
pthread_spin_trylock
pthread_mutex_lock
__pthread_key_create
tss_get
_pthread_cleanup_pop
ftrylockfile
longjmp
pthread_rwlock_wrlock
pthread_barrier_wait
msync
sem_clockwait
pthread_mutex_consistent
pthread_kill_other_threads_np
pthread_exit
pthread_barrierattr_init
pthread_mutex_unlock
mtx_destroy
recvfrom
GLIBC_2.3.2
pthread_mutexattr_setrobust_np
GLIBC_2.3.3
GLIBC_2.3.4
pthread_getschedparam
__pthread_unwind_next
__pthread_mutex_trylock
sem_timedwait
pthread_attr_setstack
__pthread_setspecific
__pthread_mutex_lock
__pthread_rwlock_tryrdlock
sem_trywait
__pthread_rwlock_wrlock
__pthread_mutexattr_destroy
pthread_mutex_clocklock
siglongjmp
tcdrain
pthread_getname_np
__pthread_get_minstack
pthread_setschedprio
pthread_condattr_init
pread64
GLIBC_PRIVATE
sem_init
__pread64
__pthread_register_cancel_defer
__libc_current_sigrtmax
sem_post
read
pthread_cond_init
pthread_cond_init
open
pthread_setcancelstate
pthread_rwlock_tryrdlock
pthread_mutexattr_getprioceiling
pthread_mutexattr_setprioceiling
pthread_rwlockattr_getkind_np
__pwrite64
pthread_mutexattr_setkind_np
__pthread_mutex_unlock
cnd_wait
pthread_rwlock_rdlock
pthread_condattr_getclock
__res_state
pthread_cancel
sem_unlink
__pthread_once
recvmsg
pthread_rwlockattr_setkind_np
__pthread_rwlock_init
pthread_testcancel
pthread_once
pthread_attr_getscope
__libc_allocate_rtsig
pthread_attr_getaffinity_np
pthread_attr_getaffinity_np
pwrite
cnd_broadcast
mtx_trylock
pthread_spin_init
pthread_barrier_destroy
pthread_mutexattr_gettype
pwrite64
pthread_cond_destroy
pthread_cond_destroy
__pthread_rwlock_rdlock
pthread_getaffinity_np
pthread_getaffinity_np
pthread_mutexattr_getprotocol
pthread_mutex_getprioceiling
recv
pthread_setcanceltype
sem_getvalue
pthread_rwlockattr_destroy
pthread_mutexattr_setprotocol
pthread_barrier_init
pthread_mutex_consistent_np
__h_errno_location
mtx_init
pthread_getattr_default_np
__pthread_register_cancel
__pthread_getspecific
sendto
__pthread_initialize_minimal
funlockfile
lseek64
pthread_key_delete
sigaction
pthread_rwlockattr_setpshared
pthread_mutex_init
pthread_attr_setstacksize
pthread_mutexattr_init
pthread_cond_clockwait
__pthread_unwind
pthread_mutexattr_getkind_np
fork
pthread_atfork
thrd_create
pthread_setschedparam
__pthread_barrier_wait
__pthread_cleanup_routine
pread
pthread_attr_setstackaddr
pthread_setspecific
_IO_funlockfile
thrd_detach
connect
__connect
__read
__shm_directory
sendmsg
__open
pthread_mutexattr_settype
GLIBC_2.4
pthread_cond_timedwait
pthread_cond_timedwait
__write
__pthread_mutexattr_init
pthread_attr_getstacksize
call_once
pthread_mutexattr_setrobust
__pthread_mutex_init
pthread_key_create