読者です 読者をやめる 読者になる 読者になる

撤退

情報系学科所属

katagaitai #7, #8 に行った

katagaitai #7, #8 に行った

今回は2日連続で長丁場になりましたが,最後まで濃密でとても面白かったです. 引き続き頑張っていきます.

blinkroot (HITCON CTF 2015 Quals)

CTFTimeへのリンク

glibc の elf/dl_runtime.c を読むと

DL_FIXUP_VALUE_TYPE
attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
_dl_fixup (
# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
     ELF_MACHINE_RUNTIME_FIXUP_ARGS,
# endif
     struct link_map *l, ElfW(Word) reloc_arg)
{
    ...
    void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
    ...
    if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0) {
        ...
    } else {
        value = DL_FIXUP_MAKE_VALUE (l, l->l_addr + sym->st_value);
    }
    ...
    return elf_machine_fixup_plt (l, result, reloc, rel_addr, value);
}

となっていて,

static inline ElfW(Addr)
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
           const ElfW(Rela) *reloc,
           ElfW(Addr) *reloc_addr, ElfW(Addr) value)
{
  return *reloc_addr = value;
}

から,それぞれ

l->l_addr + reloc->r_offset

を書き込み可能なアドレス (r_offset の設定時に delta で引く理由. 0x600b90 は書き込み可能)

l->l_addr + sym->st_value

system() のアドレスにすればよい.

sym->st_other については,

elf/elf.h:
  617  /* How to extract and insert information held in the st_other field.  */
  618  
  619: #define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
  620  
  621  /* For ELF64 the definitions are the same.  */
  622: #define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
  623  
  624  /* Symbol visibility specification encoded in the st_other field.  */

なので sym->st_other の最下位 3 bit のいずれかが立っている必要がある.

また r_offsetマジックナンバー 7 については,

elf/dl_runtime.c
   73: const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];

elf/elf.h:
  672: #define ELF64_R_SYM(i)     ((i) >> 32)

から上位 4 バイトが index となっていて,実際の値は

0000| 0x400408 --> 0x600b58 --> 0x4004e6 (<_exit@plt+6>:  push   0x0)
0008| 0x400410 --> 0x100000007 
0016| 0x400418 --> 0x0 
0024| 0x400420 --> 0x600b60 --> 0x4004f6 (<puts@plt+6>: push   0x1)
0032| 0x400428 --> 0x200000007 
0040| 0x400430 --> 0x0 
0048| 0x400438 --> 0x600b68 --> 0x400506 (<__stack_chk_fail@plt+6>: push   0x2)
0056| 0x400440 --> 0x300000007 

のようになっていることから,index を 0 とするために 7 に設定されている.