glibc got overwrite

우리가 흔히 got overwrite를 통해 익스코드를 많이 짠다. 하지만,

C
[*] '/home/gaia/chall'
    Arch:       amd64-64-little
    RELRO:      FULL RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        No PIE (0x400000)
    SHSTK:      Enabled
    IBT:        Enabled
    Stripped:   No

다음과 같이 FULL RELRO로 보안이 강화되어 있으면 해당 방법이 불가능하다. 이럴때,

C
[*] '/home/gaia/libc.so.6'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        PIE enabled
    SHSTK:      Enabled
    IBT:        Enabled

libc도 한번 확인을 해보면 좋다. 만약 Partial RELRO 라면 glibc got overwrite 공격도 충분히 해볼만하다.

일단 기본적인 아이디어는 Arbitrary writable이 가능하다는 점과 glibc의 relocation 영역중 IFUNC의 relocation 영역을 노리는 것이다.

관련 분석글은 다음에 있다.

IFUNC들은 glibc 내부에서도 plt → got 영역을 거치기에 got를 overwrite 한뒤 main 코드에서 자연스럽게 IFUNC을 호출하게 하든가 ( ex, puts 내부에는 strlen이 사용됨 ) 아니면 control flow를 직접 바꿔줘야한다.

keyme님이 사용한 방식으로는 onegadget의 조건 rsi rdx null 을 만족시키기 위해서

iconv/gconv_conf.c 파일의

new_alias->fromname = memcpy ((char *) new_alias + sizeof (struct gconv_alias),     from, wp - from);
C
pwndbg> x/10i 0x2CDC4
   0x2cdc4:    lea     0x10(%r8),%rdi
   0x2cdc8:    mov    %rbx,%rsi
   0x2cdcb:    mov    %r8,0x8(%rsp)
   0x2cdd0:    sub    %rbx,%rbp
   0x2cdd3:    call   0x28620 <ABS+0xa9c90@plt>

다음 부분을 사용하였고 memcpy 의 got를 덮어썼다.

이로써 공격방식이 엄청 다채로워질수 있는데 특히 내가 glibc 코드 중에서 IFUNC을 사용하는 거의 대부분의 코드를 일시적으로 사용할 수 있어진게 정말 좋은 것 같다.