HackCTF Sysrop
Sunrin/Layer7

HackCTF Sysrop

이미 많이 나와있는 여러가지 write up을 보면서 따라하며 익혔다.

 

1. 실행

실행 화면

sysrop 파일을 실행하면 입력을 받고 끝난다.

 

 

checksec

NX bit가 걸려있다.

NX bit가 걸려있기 때문에 쉘코드는 사용할 수 없다.

NX bit같은 보안 방어가 있는 상태에서는 ROP(코드를 실행할 수 있게 해주는 기술)를 시도할 수 있겠다.

 

 

main

소스코드를 읽어보면 rbp-0x10에 0x78(120)크기 만큼의 데이터를 입력받을 수 있다.
여기에서 overflow가 일어난다.


2. exploit

read 말고는 다른 함수가 없다.

libc 주소를 leak을 하기 위해 사용해야하는 함수가 딱히 없다.

 

이때 시도할 수 있는 방법이 syscall을 이용한 ROP이다. (read 함수 안에서 호출되는 syscall을 이용하는 ROP)

 

더보기

디버깅을 하려고 했는데 안 된다.

 

stripped

그 이유는 안티 디버깅 (anti-debugging)이 걸려있기 때문이다.

 

디버깅을 방지하고 해당 파일을 분석을 하지 못하도록 하는 기술이다.

디버깅을 시도하려고 하면 디버거 프로그램을 종료시키거나 에러를 발생시키는 방법 등으로 분석을 방해한다.

 

1) read@plt read@got

 

info func

info func로 read@plt의 주소를 알아냈고 알아낸 read@plt의 주소를 통해 read@got의 주소도 알아냈다.

오른쪽에 # 0x601018이라고 쓰여있는 것이 got이다. (plt는 got를 참조한다.) 

 

 

disass read

 

 

 

read 함수 안에서 syscall을 발견했다.

syscall의 동작원리에 따라 인자(rdi, rsi, rdx, r8, r9, r10 등)를 세팅하고 rop를 해야한다.

 

system call의 원리를 알기 위해서 구글에 "linux system call table"을 검색했다.

출처 : filippo.io/linux-syscall-table/  

 

 

이렇듯 system call은 rax 레지스터의 값에 따라 (호출하는 값에 따라서) 종류가 결정된다.

 

rax, rdi, rsi, rdx 에는 알맞는 인자값이 들어가게 된다.

나는 /bin/sh를 실행시켜서 쉘을 따야하기 때문에 execve() 함수를 호출해야한다.

execve()는 사용자모드에서 커널모드로 전환하는 역할을 한다.

 

 

2) Gadget 찾기

ROPgadget 명령을 이용해서 sysrop 바이너리에 인자값을 설정할 수 있는 가젯이 있는지 살펴보았다.

 

0x78byte 중 dummy(컴파일 시 생기는 메모리 공간) 0x18byte를 뺀 0x60byte를 쓸 수 있다.

이 0x60byte에 payload를 적어서 보내면 된다.

 

 

3) Exploit Code

[계획]

① bss 영역에 "/bin/sh"를 쓰고

② got의 하위 1byte를 0x5e로 덮고 

③ execve 시스템 콜을 호출한다.

 

 

더보기
extern이랑 got는 다른 건가..?

처음에 extern 오른쪽에 있는 것이 got인줄 알고 했다가 아니어서 직접 got를 구했다.