poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: use case: function replacement in ELF binaries


From: Jose E. Marchesi
Subject: Re: use case: function replacement in ELF binaries
Date: Wed, 02 Oct 2019 01:07:05 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux)

Hello Unai.
Hope you had a good trip back to Bilbao.

    As commented at ORConf last weekend, the purpose of this message is to
    explain a PIE ELF manipulation use case, in order to discuss whether it is
    a suitable target for poke or if it falls out of scope.

Uoh...  challenge accepted!

    [...]
    As a result, I'd like to explore the possibility of modifying the target
    app binary statically. I.e., write a pickle for poke which is equivalent to
    `elf_hook` in the ref above; given the binary and a ` replacement.o`
    object. After the talk and demo last weekend, it seems that poke might
    already be aware of all the details of the ELF format, and the language is
    powerful enough. Nonetheless, my knowledge is pretty limited in this field,
    and I might be missing many issues.

Ok, as preparatory work, I pushed a couple of auxiliary functions to the
elf.pk pickle: elf_section_by_name and elf_section_by_type.  Look for
their definitions in pickles/elf.pk if you are curious.

Then I quickly sketched the following pokeish version of elf_hook.
Disclaimer: I haven't tried it 8-).

/* Note that in the code below the idioms like:
   (Elf64_Addr[1] @ original)[0] = substitution;
   will be substituted by:
   Elf64_Addr @ original = substitution;
   as soon as we support l-value maps.  Soon 8-) */

defun elf_hook = (Elf64_Addr address, string name,
                  Elf64_Addr substitution) Elf64_Addr:
{
 /* This auxiliary function will go away as soon as we support
    compile-time struct flattening.  Also soon!  */
 defun rela_sym = (Elf64_Xword r_info) uint<8>:
 {
   return r_info .>> 8;
 }

 defvar ehdr = Elf64_Ehdr @ 0#B;

 defvar rela_plt = elf_section_by_name (ehdr, ".rela.plt");
 defvar rela_dyn = elf_section_by_name (ehdr, ".rela.dyn");
 defvar plt_relocs = Elf64_Rela[rela_plt.sh_size] @ rela_plt.sh_offset;
 defvar dyn_relocs = Elf64_Rela[rela_dyn.sh_size] @ rela_dyn.sh_offset;

 defvar dynsym = elf_section_by_type (ehdr, SHT_DYNSYM);
 defvar name_index = elf_symbol_index (dynsym, name);

 defvar original = 0#B;

 /* First handle the PIC case.  */
 for (rela in plt_relocs where rela_sym (rela.r_info) == name_index)
   {
     original = address + rela.r_offset;
     (Elf64_Addr[1] @ original)[0] = substitution;
   }

 if (original != 0)
   return original;

 /* Now handle non-PIC.  */
 for (rela in dyn_relocs where rela_sym (rela.r_info) == name_index)
   {
     defvar name_address = address + rela.r_offset;

     if (!original)
       original = Elf64_Addr @ name_address + name_address + original'size;
     (Elf64_Addr[1] @ name_address)[0]
       = substitution - name_address - original'size;
   }
 
 return original;
}

But hang on! I am leaving defining elf_symbol_index in elf.pk as an
exercise for you.  For that, you will need to deftype Elf64_Dynsym (look
in the ELF specification) and then the function itself.  It should be
super easy, and fun.

I'm waiting for your patch ;)

    Precisely, *file patching* is defined as "complex and error prone"
    in the talk from BlackHat2002.

Whaaat!  Not for the intrepid Poker (You).



reply via email to

[Prev in Thread] Current Thread [Next in Thread]