ret2dl理论学习
struct link_map {
    Elf64_Addr l_addr;
    char *l_name;
    Elf64_Dyn *l_ld;//Dynamic的地址
    struct link_map *l_next;
    struct link_map *l_prev;
    struct link_map *l_real;
    Lmid_t l_ns;
    struct libname_list *l_libname;
    Elf64_Dyn *l_info[76];//l_info 里面包含的就是动态链接的各个表的信息,实际就是.dynmic节
    const Elf64_Phdr *l_phdr;
    Elf64_Addr l_entry;
    Elf64_Half l_phnum;
    Elf64_Half l_ldnum;
    struct r_scope_elem l_searchlist;
    struct r_scope_elem l_symbolic_searchlist;
    struct link_map *l_loader;
    struct r_found_version *l_versions;
    unsigned int l_nversions;
    Elf_Symndx l_nbuckets;
    Elf32_Word l_gnu_bitmask_idxbits;
    Elf32_Word l_gnu_shift;
    const Elf64_Addr *l_gnu_bitmask;
    union {
        const Elf32_Word *l_gnu_buckets;
        const Elf_Symndx *l_chain;
    };
    union {
        const Elf32_Word *l_gnu_chain_zero;
        const Elf_Symndx *l_buckets;
    };
    unsigned int l_direct_opencount;
    enum {lt_executable, lt_library, lt_loaded} l_type : 2;
    unsigned int l_relocated : 1;
    unsigned int l_init_called : 1;
    unsigned int l_global : 1;
    unsigned int l_reserved : 2;
    unsigned int l_phdr_allocated : 1;
    unsigned int l_soname_added : 1;
    unsigned int l_faked : 1;
    unsigned int l_need_tls_init : 1;
    unsigned int l_auditing : 1;
    unsigned int l_audit_any_plt : 1;
    unsigned int l_removed : 1;
    unsigned int l_contiguous : 1;
    unsigned int l_symbolic_in_local_scope : 1;
    unsigned int l_free_initfini : 1;
    struct r_search_path_struct l_rpath_dirs;
    struct reloc_result *l_reloc_result;
    Elf64_Versym *l_versyms;
    const char *l_origin;
    Elf64_Addr l_map_start;
    Elf64_Addr l_map_end;
    Elf64_Addr l_text_end;
    struct r_scope_elem *l_scope_mem[4];
    size_t l_scope_max;
    struct r_scope_elem **l_scope;
    struct r_scope_elem *l_local_scope[2];
    struct r_file_id l_file_id;
    struct r_search_path_struct l_runpath_dirs;
    struct link_map **l_initfini;
    struct link_map_reldeps *l_reldeps;
    unsigned int l_reldepsmax;
    unsigned int l_used;
    Elf64_Word l_feature_1;
    Elf64_Word l_flags_1;
    Elf64_Word l_flags;
    int l_idx;
    struct link_map_machine l_mach;
    struct {
        const Elf64_Sym *sym;
        int type_class;
        struct link_map *value;
        const Elf64_Sym *ret;
    } l_lookup_cache;
    void *l_tls_initimage;
    size_t l_tls_initimage_size;
    size_t l_tls_blocksize;
    size_t l_tls_align;
    size_t l_tls_firstbyte_offset;
    ptrdiff_t l_tls_offset;
    size_t l_tls_modid;
    size_t l_tls_dtor_count;
    Elf64_Addr l_relro_addr;
    size_t l_relro_size;
    unsigned long long l_serial;
    struct auditstate l_audit[];
}
typedef struct
{
  Elf64_Word	st_name;		/* 在.Dynstr中的偏移,指向一个str,占4字节*/
  unsigned char	st_info;		/* Symbol type and binding 占1字节*/
  unsigned char st_other;		/* Symbol visibility 占1字节*/
  Elf64_Section	st_shndx;		/* Section index 占2字节*/
  Elf64_Addr	st_value;		/* Symbol value 占8字节*/
  Elf64_Xword	st_size;		/* Symbol size 占8字节*/
} Elf64_Sym;
typedef struct
{
  Elf64_Sxword	d_tag;			/* Dynamic entry type */
  union
    {
      Elf64_Xword d_val;		/* Integer value */
      Elf64_Addr d_ptr;			/* Address value */
    } d_un;
} Elf64_Dyn;
typedef struct
{
  Elf64_Addr	r_offset;		/*r_offset+l_addr为一个指向got表的指针,记录着该函数在got表中的位置,正常情况下l_addr=0*/
  Elf64_Xword	r_info;			/*r_info>>32就是在dynsym中的下标,最低位要为7*/
  Elf64_Sxword  r_append                /*Addend */
} Elf64_Rela;

Dynmic节由Elf64_Dyn结构体构成

Dynsym节由Elf64_Sym结构体构成

.rel.plt节由Elf64_Rela结构体构成

_dl_runtime_resolve(link_map,reloc_arg)实际上就是执行了_dl_fixup

进行动态链接的流程:

1.根据想要连接的函数确定偏移reloc_arg(体现在plt[1]表里面的push)

2.找到.rel.plt里对应的ELF64_Rela表项

3.根据ELF64_Rela里的r_info确定该函数对应.dynsym里的哪一个Elf64_sym项(在64位中r_info>>32即为表项下标)

4.在32位程序中会根据Elf32_sym里的st_name在跳转到.dynstr里寻找字符串,再根据这个字符串到libc中去进行匹配查询,最后把libc基址+st_value作为该函数的真实地址写入r_offset这一指针指向的位置,正常情况下该指针指向got表对应的表项

5.而在64位程序中,由于要绕开保护(令st_other!=0),所以不会经过查找字符串这一步骤,最终地址的计算方式变成了l_addr+st_value。在Elf64_sym结构体中,st_value与表头的间隔为8字节,所以如果能让sym指向a函数的got-8位置(假设a是任意一个已解析的函数),那么st_value恰好就是a的got位置,其值就是a函数的真实地址,那么只要让l_addr为system函数与a函数在libc里面的偏移offset,最终解析出来的地址就是真正的system地址了

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇