[시스템 해킹] STAGE 2 Background - Computer Science

zzoni·2022년 7월 10일
0

시스템해킹

목록 보기
1/15
post-thumbnail

⭕ Computer Architecture

rip 는 instruction pointer








⭕ Linux Memory Layout

💠 2.1 메모리 오염(Memory Corruption) 취약점

: 메모리 오염을 유발하는 취약점

  • 메모리 오염?
    공격자가 메모리를 악의적으로 조작할 수 있다면 조작된 메모리 값에 의해 CPU도 잘못된 동작을 할 수 있다. 이를 메모리가 오염됐다고 표현한다.

    • 많은 공격기법이 메모리 오염을 기반으로 한다.
  • Stack Buffer Overflow, Off by One, Format String Bug, Double Free Bug, Use After Free
    을 살펴볼 예정!

  • 그 전에 리눅스 메모리 구조를 배워 프로세스 가상메모리의 각 구역이 어떤 정보를 담고 있는지 공부



💠 2.2 리눅스 프로세스의 메모리 구조

◼ 세그먼트란

리눅스에서는 프로세스의 메모리를 크게 5가지의 세그먼트(Segment)로 구분

  • 세그먼트란?
    적재되는 데이터의 용도별로 메모리의 구획을 나눈 것

    • 코드 세그먼트, 데이터 세그먼트, BSS 세그먼트, 힙 세그먼트, 스택 세그먼트
  • 운영체제가 메모리를 용도별로 나누면, 각 용도에 맞게 적절한 권한을 부여

    • 읽기, 쓰기, 실행
      • ex) 데이터 세그먼트의 경우 읽기 권한이 부여되지만 실행권한은 부여되지 않음.



◼ 코드 세그먼트 : rx

실행 가능한 기계 코드가 위치하는 영역
텍스트 세그먼트라고도 불림

아래에서 정수 31337을 반환하는 main함수가 컴파일 되면 554889e5b8697a00005dc3라는 기계 코드로 변환되는데, 이 기계 코드가 코드 세그먼트에 위치하게 된다.

int main() { return 31337; }



◼ 데이터 세그먼트

컴파일 시점에 값이 정해진 전역 변수 및 전역 상수들이 위치

- data segment : r

전역변수와 같이 프로그램이 실행되면서 값이 변할 수 있는 데이터들이 위치

- rodata (read-only data) segment : rw

프로그램이 실행되면서 값이 변하면 안되는 데이터들이 위치
ex) 전역으로 선언된 상수

char *str_ptr = "readonly";  // str_ptr은 data, 문자열은 rodata

readonly는 상수문자열로 취급되어 rodata segment에 위치하고,
이를 가리키는 str_ptr은 전역변수로 data segment에 위치한다.




◼ BSS 세그먼트 : rw

Block Started By Symbol Segment

  • 컴파일 시점에 값이 정해지지 않은 전역 변수가 위치
    (여기에는 개발자가 선언만 하고 초기화하지 않은 전역변수 등이 포함됨)
    이 세그먼트의 메모리 영역은 프로그램이 시작될 때, 모두 0으로 값이 초기화된다.
int bss_data;
int main(){
	printf("%d\n",bss_data); //0
    return 0;
}

-> bss_data가 여기에 해당




◼ 스택 세그먼트 : rw

  • 프로세스의 스택이 위치하는 영역
    함수의 인자나 지역 변수와 같은 임시 변수들이 실행중에 여기에 저장

  • 스택 프레임(Stack Frame)
    스택 세그먼트는 스택 프레임이라는 단위로 사용
    스택 프레임은 함수가 호출될 때 생성되고, 반환될 때 해제
  • 아래로 자람
void func() {
  int choice = 0;
  scanf("%d", &choice);
  if (choice)
    call_true();
  else
    call_false();
  return 0;
}

-> 지역변수 choice가 stack에 저장됨.




◼ 힙 세그먼트 : rw

  • 동적할당한 애들
  • 위로 자람



세그먼트 정리






⭕ x86 Assembly

2. x64 어셈블리 언어

◼ 기본구조

동사에 해당하는 명령어(Operation Code, Opcode)와 목적어에 해당하는 피연산자(Operand)로 구성

◼ 명령어

◼ 피연산자

  • 상수(Immediate Value)
  • 레지스터(Register)
  • 메모리(Memory)
    메모리 피연산자는 []으로 둘러싸인 것으로 표현되며, 앞에 크기 지정자(Size Directive) TYPE PTR이 추가될 수 있다.
    여기서 타입에는 BYTE, WORD, DWORD, QWORD가 올 수 있으며,
    각각 1바이트, 2바이트, 4바이트, 8바이트의 크기를 지정한다.
    • ex)
      QWORD PTR [0x8048000] : 0x8048000의 데이터를 8바이트만큼 참조
      DWORD PTR [0x8048000] : 0x8048000의 데이터를 4바이트만큼 참조
      WORD PTR [rax] : rax가 가리키는 주소에서 데이터를 2바이트만큼 참조



3. x86-64 어셈블리 명령어

◼ 데이터이동

어떤 값을 레지스터나 메모리에 옮기도록 지시

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

◼ 비교

◼ 분기


‼ Quiz 2 풀이

profile
모든 게시물은 다크모드에서 작성되었습니다!

0개의 댓글