Exploit Technique : Return Oriented Programming

Lia·2022년 5월 13일
0

System_Hacking

목록 보기
5/5

지난 포스팅에서는 "/bin/sh"가 미리 정의되어 있고
plt에 system 함수가 등록이 되어있는 상태에서 익스플로잇을 진행했었습니다.

그러나 리얼 월드에서는 보안상의 이유로 system 함수의 사용이 지양되고 또한
"/bin/sh" 문자열을 정의하는 경우가 거의 없습니다.

따라서 이번 포스팅에서는 리얼월드와 거의 비슷한 코드환경에서
ROP(Return Oriented Programming)를 이용하여 셸을 획득하도록 하겠습니다.


Return Oriented Programming Demonstration

다음은 버퍼 오버플로우 취약점이 존재하는 코드입니다.

이번 포스팅에서는 카나리와 NX 모두 우회하도록 하겠습니다.

지난 포스팅과 달리 system 함수를 호출하지 않으므로 시스템함수의 plt 주소를
알 수 없습니다.

system("/bin/sh")를 호출하기 위한 공격 과정은 다음과 같습니다.

먼저 plt 테이블에 등록되어 있는 함수인 puts 혹은 printf 함수를 이용하여
rop 체인을 구성한 후 read 함수의 got 주소값을 읽어 냅니다.

이후 read 함수의 오프셋을 이용하여 libc의 베이스 주소를 구한 후
system 함수의 오프셋을 이용하여 system함수의 실제 주소를 구합니다.

이후의 공격과정은 크게 두가지로 나뉩니다.


GOT Overwrite

GOT Overwrite는 함수가 호출되었을때 GOT 테이블에 등록되어있는 함수의 주소를
불러오는 과정에서 함수의 주소를 검증하지 않는다는 취약점을 이용한 공격입니다.

예제 코드에서는 read 함수를 호출하고 있으므로 read 함수를 이용하여
read 함수의 got 주소를 system 함수의 got 주소로 변경 후
read 함수를 호출하여 최종적으로 system 함수를 호출할 수 있습니다.

먼저 rop 체인 구성을 위한 리턴 가젯들을 확인하겠습니다.

read 함수의 파라미터 갯수는 3개 이므로 rdi, rsi, rdx 리턴 가젯이 필요하지만
일반적으로 rdx 레지스터와 관련된 리턴 가젯은 바이너리에서 찾기 어렵습니다.

이때는 libc의 코드 가젯이나 libc_csu_init 가젯 혹은 rdx값을 변화시키는 함수
예를들어 strncmp 함수를 사용할 수 있습니다.

이번 예제에서는 read 함수의 got를 읽은 후 rdx값이 매우 크게 설정되므로
rdx를 설정하는 가젯을 추가하지 않아도 됩니다.

GOT Overwrite 공격기법의 전체 익스플로잇 코드는 다음과 같습니다.


Return To Main (ret2main)

예제 코드에서는 사용자로부터 총 두번의 입력을 받습니다.
canary leak을 위해서 한번, read 함수의 got 주소를 leak 하기 위해서 한번
이렇게 총 두번 입력을 하고난 뒤에는 이미 메인함수가 종료된 후 입니다.

따라서 rop 체인을 구성할 때에 main 함수의 주소를 입력하여 메인함수를
다시 실행하여 페이로드를 입력해야 합니다.

ret2main을 이용한 공격 코드는 아래와 같습니다.

profile
하고싶은게 많아요

0개의 댓글