Stack pivoting
Sunrin/Layer7

Stack pivoting


Stack pivoting 관련 문서
https://www.lazenca.net/display/TEC/16.Stack+pivot 
https://eclipsemode.tistory.com/55

기타 참고 자료


 

 

 

 

1. ROP, Gadget


1-1) Return Oriented Programming (ROP)

NX bit같은 보안 방어가 있는 상태에서 코드를 실행할 수 있게 해주는 기술

공격자는 프로그램의 흐름을 변경하기 위해서 Stack Overflow 취약점과 가젯이 필요하다.

 

 

1-2) Gadget

코드 조각; 해당 프로그램이 사용하는 메모리의 기계 명령어이다.

 

① 특징

가젯은 일반적으로 ret으로 끝난다.

주로 ret으로 끝나는 연속된 명령어를 의미한다.

가젯은 기존 프로그램 또는 공유 라이브러리 코드 내의 서브 루틴에 있다.

 

서브루틴 (Sub-routine)
: 메인루틴과 대비되는 개념이다.
C언어에서 서브루틴은 함수와 같은 뜻으로 쓰인다.

 

64 bit 함수 호출 규약 때문에 피연산자가 매우 중요해졌다.

 

(리눅스) 64bit 함수 호출 규약 : rdi, rsi, rdx, rcx, r8, r9 (그 이상은 stack을 통해서 인자를 전달한다.)

 

② 예시

pop rdi; ret 호출할 함수의 첫번째 인자 값을 저장

pop rdx; ret 호출할 함수의 세번째 인자 값을 저장

 

③ 64bit ROP에서 POP 명령어의 역할

레지스터에 호출할 함수의 인자 값을 넣는다.
ESP 레지스터의 값을 증가시켜서 함수를 연속으로 호출한다.

 

ESP : normaldy.tistory.com/4 의 I-1번, I-3번 참고

 

 

 

 

2. Stack pivot


2-1) Stack pivot

 - 간단한 가젯을 이용하여 stack의 흐름을 변경하는 기술이다.

 - EAX, RAX의 값을 변경해서 코드의 흐름을 변경하는 기술이다.

 

EAX : 32bit register
RAX : 64bit register

 - Overflow 기법을 사용하고 싶지만, 입력 버퍼가 부족할 때 Stack pivoting을 사용한다.

 - 읽기 쓰기 권한이 있어서 stack처럼 사용할 수 있는 Fake stack을 찾고 chainig한다.

 - Stack pivoting을 할 때는 gadget을 꼭 이용해야 한다.

 

Chainig (RTL Chaining) | chain : 묶다, 일련, 띠(이어진 것)
: RTL 기법의 연장선으로, RTL을 응용하여 함수와 함수를 연결하는 기법이다. 

 

 

2-2) Fake Stack으로 쓸만한 곳을 찾기

읽기권한(r)과 쓰기 권한(w)이 있는 빈 공간을 찾아야 한다.

이 빈 공간을 Stack pivoting을 할 때 fake stack으로 사용할 것이다.

 

주로 bss 영역을 사용한다고 한다.
BSS 영역 : 초기화 되지 않은 전역변수가 있는 영역

<특징>
초기화가 되지 않은 전역변수를 모두 0 으로 초기화한다.
bss 영역의 주소값은 변하지 않는다.
임시 스택이라고도 부른다.

 

vmmap을 통해서 권한을 확인하고

r권한, w권한이 있는 곳(0x602000)을 찾는다.

vmmap : 가상 메모리의 레이아웃을 출력해준다.

 

vmmap

 

objdump 명령어를 통해 바이너리 파일의 정보를 본다.

-h는 섹션의 헤더만 출력되게 해주는 옵션이다.

 

objdump -h ./binary

VMALMA 각각이 의미하는 바와 차이점을 정확히 모르겠다.
다시 한 번 찾아봐야겠다.

VMA (Virtual Memmory Address)
: 섹션이 최종 결과 파일에 올려진 뒤 존재하는 주소를 말한다.
0000000000601060

LMA (Load Memmory Address)
: 섹션이 실제 메모리에 올려지는 물리적인 메모리 주소를 가리킨다. 
0000000000601060

 

 

2-3) Gadget 찾기

Stack pivot Gadget(예시)인 leave; ret 찾는다.

 

objdump -d 옵션을 사용해서 어셈블리어 코드 목록을 출력한다.

grep을 이용해서 "ret"과 "ret 한 줄 전"를 출력한다.

 

leave의 주소 400837