IT 그리고 정보보안/Knowledge base

RTL (Return-to-Libc) Attack

plummmm 2021. 4. 15. 21:26
반응형

이번에 이야기할 기법은 RTL(Return-to-Libc) 이다.

이름 그대로 라이브러리를 반환한다? 머 이런뜻.

 

우리가 사용하는 함수들은 (printf 같은) 모두 라이브러리에 들어있는 것은 알 것이다.

RTL의 기본적인 개요는

"RET에 라이브러리 함수를 덮어씌워 실행되도록 하는 공격 기법"이다.

 

기본적으로 RTL을 사용하기 위해서는 RET보다 높은 주소에 코드를 덮어씌울 수 있어야 한다.

 

그렇다면 이건 왜 사용하는 것일까?

 

가장 큰 이유는 NX bit (Non-executable Stack)

즉, 스택 상에 코드 실행 불가능 할 때 사용한다.

우리가 가장 기초적으로 배운 BOF 공격은 스택 공간에 셸코드를 삽입하여

코드가 스택 상에서 실행되도록 하는 것인데, 이 공격을 막기 위한 방어법이 NX bit이다.

이 방어기법을 우회하기 위해 쓴다.

 

그리고 RTL은 브루트포스가 없다. 무조건 원킬

공유 라이브러리가 올라오는 주소는 안바뀐다. 그래서 한방이다.

운영체제가 달라져도 스택크기는 변하지 않는다.

 

보통은 RTL을 쓸 때 SYSTEM()함수를 많이 쓴다. shell 실행 함수

 

위에서 말했다시피 RET자리에 함수주소를 넣어서 실행 시키게끔 하는게 RTL이라고 했다.

일단 공격에 들어가기 전에 RTL 과정 중의 스택의 꼬라지가 어떤지 정확하게 잘 알아야 한다.

 

 

일단 RET에 함수 주소가 들어오기 전의 스택이다.

이제 함수를 RET에 불러올 것이니.. 일단 에필로그가 일어나야 겠지?

leave와 ret

 

leave는

mov esp, ebp

pop ebp 

지역변수들과 그외 것들이 스택에 쌓여있을게 아닌가. 고것을 싹 정리해주고

ebp에 SFP 즉, 이전 함수의 ebp를 다시 ebp에 pop연산 한다. (이전 스택프레임을 복원해야쥐?)

 

 

 

그리고 난 후 RET,

pop eip

jmp eip

정확히 말하면 현재 eip 다음에 실행될 명령어 주소를 eip레지스터에 저장하고

eip 주소로 점프한다.

 

그 뒤 라이브러리에 있는 함수주소를 RET에 넣는다.

CALL 명령으로 함수를 호출하는 것이 아니고 RET를 변조하여 함수를 호출하는 것이다.

이 경우, 정상적으로 함수가 종료되어 라이브러리의 exit함수를 통하여 종료되는 것이 아니고

값이 변조되어 그대로 함수가 불러지므로 RET자리에 호출된 함수의 SFP가 쌓이고

그 위(ebp+4)로 호출된 함수의 RET와 또 그 위로 (ebp+8)에 함수의 인자가 쌓인다. 

(printf 함수를 부른다고 가정하겠다.)

 

 

그럼 이제 RTL에 대해서 다시 들어가보자.

RET자리에 라이브러리 함수를 넣어 변조시키는 공격이라고 했다.

 

그럼 우리가 필요한 것은? 일단 함수의 주소, 그리고 함수의 인자이다.

이번에 SYSTEM함수를 사용한다고 했으니

system 함수에 인자를 "/bin/sh"로 넣어줘야 할 것이다.

 

먼저 system 함수를 찾아보자.

예제로 LOB gate를 이용하여 풀어보겠다.

 

 

RTL의 사용조건에 딱히 어긋나는 부분이 없어 보인다.

gdb 로 main 첫번째에 브레이크포인트를 걸고 라이브러리 함수를 찾아볼 것이다.

 

 

print 명령어를 이용하여 system 함수의 위치를 찾았다. ( 공유 라이브러리 영역에 있다.)

libc_system. -> 0x40058ae0

 

그럼 이제 함수 인자를 넣을 차례이다.

"/bin/sh"는 어떤 방식으로 인자로 넣어주어야 할까?

아마 문자열을 따로 저장해두고 그 주소로 접근하는 방식을 생각했을 것이다.

근데 그렇게 하면 안된다. 프로그램이 실행될 때 마다 문자열 위치가 어디에 있을줄 알고..

처음에 말했다시피, RTL은 한방코드이다. 공격방식과 어긋나는 발상임.

 

그럼 어떻게 넣어야 하나? 힌트는 system함수를 이용하는 것이다.

SYSTEM함수는 내부적으로 execve함수를 쓴다. (셸코드 작성법에서 언급했음)

이 execve함수의 동작은 "/bin/sh"를 통해서 하는 것이다. 명령어를 실행하는 함수니까.

(셸코드는 /bin/sh 셸을 이용해서 /bin/sh 라는 문자열을 실행하는 것이다.)

그러니까, system함수 내부에, 정확하게 말하면 execve함수 내부에 "/bin/sh"라는 문자열이 존재한다.

그걸 찾아내어 거기있는 "/bin/sh"를 사용하면 된다.

 

그럼 "/bin/sh"가 어딨는지 찾아보아야 할 것임.

일단 system함수의 위치는 알고 있으니까.. 간단한 소스코드를 하나 짜보자.

 

 

이것은.. memcmp함수를 이용하여 system함수 내부에 있는 /bin/sh를 찾는 코드이다.

long형 변수 shell에 system함수의 주소를 넣고, "/bin/sh" (널 포함 8바이트)를 계속해서 shell을 증가시키며

비교하는 코드이다. 이걸 돌려보면 아래와 같은 결과가 나온다.

 

 

400fbff9

 

자..이제 필요한 것들을 모두 구했다.

뭐 일단 공격하기 이전에 

함수호출했을때 그 함수가 참조하는 인자가 어디에 위치하냐가 관건이다.

아까 함수 인자가 어디있다고 했나? ebp+8 위치에 있다고 했다. 괄호에 굵게 표시까지 해뒀다.

그럼 머리속에서 페이로드를 어떻게 구성해야하는지 감이 좀 오는가??

 

[nop 260] [SYSTEM 함수 주소] [nop 4] ["/bin/sh" 주소]

이렇게 페이로드를 구성하면 될것 같다.

여기서 궁금증이 생긴다. 호출된 함수의 RET자리에는 왜 쓰레기값을 넣는지??

일단 셸이 따지고나면 그 후에 세그먼트 폴트가 뜨든 말든 내 알바가 아니기 때문에...

물론 이를 이용하여 RTL 체인 이라는 기법도 있다고 한다.

RET자리에 또다른 함수를 계속 호출하는.. 일단 여기선 그 부분에 대해선 언급하지 않고 (아직 공부도 덜됐고..)

페이로드를 실행 시켜보겠음.

공격코드도 이렇게 깔끔하고 이쁠수가..ㅎㅎ

./gremlin `perl -e 'print "\x90"x260,"\xe0\x8a\x05\x40","\x90"x4,"\xf9\xbf\x0f\x40"'`

 

 

성공

반응형

'IT 그리고 정보보안 > Knowledge base' 카테고리의 다른 글

RET Sled  (0) 2021.04.15
Omega Project  (0) 2021.04.15
Shellcode 작성  (0) 2021.04.15
기계어코드 작성  (0) 2021.04.15
버퍼 오버플로우 (Buffer Overflow) 개요  (0) 2021.04.15