일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 배경 그림
- MLFQ
- frequency-domain spectrum analysis
- Rr
- AINCAA
- STCF
- linear difference equation
- MAC
- DSP
- Double free
- DP
- sampling theory
- 유니티
- dtft
- RBAC
- 언리얼엔진
- ret2libc
- pdlc
- 운영체제
- 메카님
- dirty cow
- 게임 개발
- 유스케이스
- Unity #Indie Game
- 게임개발
- CTF
- stride
- TSet
- Security
- Race condition
- Today
- Total
다양한 기록
Return-Oriented Programming (ROP) 본문
공격자는 system()을 쓰고 싶은데 libc에 없음..
=> fork 다음 exec을 할 수 있음
공격자 입장
- 악의적인 코드 주입, 라이브러리 함수 호출도 안하고, 본래 코드 조작도 안하고 임의의 연산을 하는 방법을 만들어보자
-> ROP
* 그러나 여전히 스택 내용은 변조해야 함
명령어의 조각을 찾아야 함
명령어들의 순차 .. 각 sequence는 2~5개의 명령이고, return 으로 끝남
시퀀스들이 체이닝되어 모여 가젯 (gadget)
가젯은 특정한 일을 수행 (ex. 로드, 스토어, xor, branch)
=> 가젯들을 결합하여 원하는 액션을 강제로
시퀀스들을 차례차례 실행하게 하고 싶으면 버퍼를 넘치게해서 각 시퀀스들의 시작 주소들을 넣으면 됨
ROP
- 인스트럭션 시퀀스와 가젯의 관계
- Instruction sequence : ret instruction(return)으로 끝나는 명령어들의 시퀀스
- Gadget : 여러 인스트럭션 시퀀스로 구성
Input example:
pattern1 + pattern2 + ret_addr_1 + ret_addr_2 + ret_addr_3 + Argument + ret_addr_4 + ret_addr_5 + ret_addr_6
pattern1 : 버퍼 덮기 .. 80바이트
pattern2 : Saved ebp 덮기 .. 4바이트
시퀀스 시작 주소 6개 : 4*6 = 24 바이트
인자 1개 : 4바이트
80 + 4 + 24 + 4 = 112
인자는 왜 필요한가?
pop이 있는 시퀀스가 있어서 스택에 인자가 하나 빠지게 됨
아무거나 일단 넣어줘야 해서 필요
결과적으로 스택은 위 이미지처럼 바뀜
Unintended instruction sequences (의도되지 않은 명령 순차들)
- 프로그래머가 의도하지 않은 ret 명령으로 끝나는 명령어의 순차
- 유효한 명령의 중간으로 점프하여 찾아지고, 새로운 의도되지 않은 명령 순차를 생성
x86 아키텍처에서 의도되지 않은 명령 순차가 발견 되는 이유 (.. CISC라.. RISC는 더 적음)
1. 가변 길이 명령어 (variable-lenth instructions)
- 명령어의 크기가 고정되어 있지 않음
2. 비정렬 메모리 접근 (unaligned memory access)
- 워드 크기 N일때, 주소가 N으로 나누어 떨어지지 않는 곳에서 읽는 것을 의미
b8 13 00 00 00 mov $0x13, %eax // eax에 0x13 넣기
e9 c3 f8 ff ff jmp 3aae9 // 상대주소 3aaae9로 점프
이런 명령어들이 존재한다고 가정 ..
00 00 00 e9 c3 을 분리해가면?
00 00 add %al, (%eax) // eax가 가리키는 메모리 주소에 al의 값 쓰기, 간접 주소 지정
00 e9 add %ch, %cl // cl에 ch값 더함
c3 ret // return instruction
아예 다른 명령을 만들어버릴 수 있음
개발자가 만든 명령의 중간에 점프하여 새로운 시퀀스를 만들 수 있음
예시: 메모리 로드
목표: %eax 레지스터에 0xDEADBEEF (pointed to by 0x8010ABCD)
1)
첫번째 리턴 어드레스가 eip에 들어감 => 첫번째 시퀀스 시작
2)
pop 작동, eax 값 변경
3)
ret 후 다음 시퀀스로 이동
4)
movl 64(%eax), %eax에 의해 eax 값에서 64 위에 있는 값을 eax에다 집어넣음
=> 로드 성공
ROP 방어 기법
가장 쉬운 건 리턴을 다 없애기 .. 리턴 대신 jmp를 넣음
그런데 이러니까 JOP(Jump-Oriented Programming) 발생
아니면
In-Place Code Randomization
- ASLR의 finer-grained level 확장, 서드 파티 애플리케이션 적용 가능, 실질적으로 0의 오버헤드
* Instruction Substituition
- 다양한 명령어를 동일한 길이의 기능적으로 동등한 명령어로 대체 -> 코드 이미지의 바이트를 변경, 공격자의 예상 순서로부터 변형
* Instruction Reordering
- 베이직 블럭 내 재배열
- Register prevention code 재배열 (특정 레지스터의 값을 안전하게 보존하기 위한 코드)
정리
- Non-executable-stack을 우회하는 기법
- 함수 호출과 관련하여 로우 레벨 이해가 필요
- ROP는 일반화된 기법
'운영체제보안' 카테고리의 다른 글
ToCTToU (Time of Check-to-Time of Use) Vulnerability (0) | 2024.12.06 |
---|---|
Race Condition Problem (0) | 2024.12.06 |
Chaining Function Calls (without arguments) (0) | 2024.12.05 |
Ret2Libc 정리 및 ROP 개념 (0) | 2024.12.05 |
Ret2Libc - Func's Prologue & Epilogue (0) | 2024.12.05 |