rip 는 instruction pointer
: 메모리 오염을 유발하는 취약점
메모리 오염?
공격자가 메모리를 악의적으로 조작할 수 있다면 조작된 메모리 값에 의해 CPU도 잘못된 동작을 할 수 있다. 이를 메모리가 오염됐다고 표현한다.
Stack Buffer Overflow, Off by One, Format String Bug, Double Free Bug, Use After Free
을 살펴볼 예정!
그 전에 리눅스 메모리 구조를 배워 프로세스 가상메모리의 각 구역이 어떤 정보를 담고 있는지 공부
리눅스에서는 프로세스의 메모리를 크게 5가지의 세그먼트(Segment)로 구분
세그먼트란?
적재되는 데이터의 용도별로 메모리의 구획을 나눈 것
운영체제가 메모리를 용도별로 나누면, 각 용도에 맞게 적절한 권한을 부여
실행 가능한 기계 코드가 위치하는 영역
텍스트 세그먼트라고도 불림
아래에서 정수 31337을 반환하는 main함수가 컴파일 되면 554889e5b8697a00005dc3라는 기계 코드로 변환되는데, 이 기계 코드가 코드 세그먼트에 위치하게 된다.
int main() { return 31337; }
컴파일 시점에 값이 정해진 전역 변수 및 전역 상수들이 위치
전역변수와 같이 프로그램이 실행되면서 값이 변할 수 있는 데이터들이 위치
프로그램이 실행되면서 값이 변하면 안되는 데이터들이 위치
ex) 전역으로 선언된 상수
char *str_ptr = "readonly"; // str_ptr은 data, 문자열은 rodata
readonly는
상수문자열
로 취급되어 rodata segment에 위치하고,
이를 가리키는 str_ptr은전역변수
로 data segment에 위치한다.
Block Started By Symbol Segment
컴파일 시점
에 값이 정해지지 않은 전역 변수가 위치int bss_data; int main(){ printf("%d\n",bss_data); //0 return 0; }
-> bss_data가 여기에 해당
void func() { int choice = 0; scanf("%d", &choice); if (choice) call_true(); else call_false(); return 0; }
->
지역변수
choice가 stack에 저장됨.
동사에 해당하는 명령어(Operation Code, Opcode)와 목적어에 해당하는 피연산자(Operand)로 구성
QWORD PTR [0x8048000]
: 0x8048000의 데이터를 8바이트만큼 참조DWORD PTR [0x8048000]
: 0x8048000의 데이터를 4바이트만큼 참조WORD PTR [rax]
: rax가 가리키는 주소에서 데이터를 2바이트만큼 참조어떤 값을 레지스터나 메모리에 옮기도록 지시
mov dst, src
: src에 들어있는 값을 dst에 대입ex
mov rdi, rsi
: rsi의 값을 rdi에 대입
mov QWORD PTR[rdi], rsi
: rsi의 값을 rdi가 가리키는 주소에 대입
-> 64 bit에선 주소를 8byte로 표현하므로 QWORD 이용
mov QWORD PTR[rdi+8*rcx], rsi
: rsi의 값을 rdi+8*rcx가 가리키는 주소에 대입
lea dst, src
: src의 유효 주소(Effective Address, EA)를 dst에 저장
mov와 lea 차이!
ebp=0x12345, *ebp=100 일 때, eax 값MOV eax, dword ptr ds[ebp]; LEA eax, dword ptr ds[ebp];
-> mov에서는 100, lea에서는 0x12345
lea는 주소를 저장합니다~
add dst, src
: dst에 src의 값을 더함
sub dst, src
: dst에서 src의 값을 뺌
inc op
: op++
dec op
: op--ex)
add ax, WORD PTR[rdi]
: ax += *(WORD*)rdi
sub eax, 3
: eax -= 3
and dst, src
: dst와 src의 비트가 모두 1이면 1, 아니면 0
src를 기준으로! dst랑 비교~
or dst, src