haehet

보안기법 정리 본문

CS

보안기법 정리

haehet 2025. 6. 7. 17:04

이번 글에서는 리눅스의 보안기법에 대해 정리해 보겠다. 

 

1. Canary

(1) canary란?

canary는 스택의 리턴주소를 조작하는 것을 방지하기 위해 생긴 보호 기법이다. 다음 코드를 통해 알아보자.

   0x000000000000117c <+19>:	mov    rax,QWORD PTR fs:0x28
   0x0000000000001185 <+28>:	mov    QWORD PTR [rbp-0x8],rax
   0x0000000000001189 <+32>:	xor    eax,eax

위 코드는 canary가 적용된 실행파일의 어셈블리 코드의 앞부분인다. 카나리는 다음과 같이 SFP 위 8바이트에 위치한다. 

   0x000000000000119a <+49>:	mov    eax,0x0
   0x000000000000119f <+54>:	mov    rdx,QWORD PTR [rbp-0x8]
   0x00000000000011a3 <+58>:	sub    rdx,QWORD PTR fs:0x28
   0x00000000000011ac <+67>:	je     0x11b3 <main+74>
   0x00000000000011ae <+69>:	call   0x1070 <__stack_chk_fail@plt>

어셈블리 코드의 뒷부분이다. 여기서 canary값의 변조 여부를 확인하 만약 변조가 되었다면 __stack_chk_fail 함수를 실행한다.

 

(2) 우회 방법

1. TLS 접근

canary는 TLS에 저장되므로 TLS를 읽고 쓸 수 있으면 카나리를 얻을 수 있다.

 

2. canary leak

카나리의 첫바이트는 널바이트이므로 printf같은 함수가 널바이트까지 읽는다는 성질을 이용해 카나리 값을 얻을 수 있다.

 

2. NX( NO Exectue)

(1) NX란?

NX는 메모리 페이지에 특정권한을 부여해서 공격을 어렵게 만드는 것을 말한다. 운영체제는 메모리를 페이지 단위로 관리한다. 또한 cpu는 가상주소를 물리 주소로 바꿀 때 페이지 테이블 엔트리를 참고하는데 이때 이 페이지 테이블 엔트리에 각 페이지에 대한 권한이 기록된다. 

pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
             Start                End Perm     Size Offset File
    0x555555554000     0x555555555000 r--p     1000      0 /home/haehet/test
    0x555555555000     0x555555556000 r-xp     1000   1000 /home/haehet/test
    0x555555556000     0x555555557000 r--p     1000   2000 /home/haehet/test
    0x555555557000     0x555555558000 r--p     1000   2000 /home/haehet/test
    0x555555558000     0x555555559000 rw-p     1000   3000 /home/haehet/test
    0x555555559000     0x55555557a000 rw-p    21000      0 [heap]
    0x7ffff7c00000     0x7ffff7c28000 r--p    28000      0 /usr/lib/x86_64-linux-gnu/libc.so.6
    0x7ffff7c28000     0x7ffff7dbd000 r-xp   195000  28000 /usr/lib/x86_64-linux-gnu/libc.so.6
    0x7ffff7dbd000     0x7ffff7e15000 r--p    58000 1bd000 /usr/lib/x86_64-linux-gnu/libc.so.6
    0x7ffff7e15000     0x7ffff7e16000 ---p     1000 215000 /usr/lib/x86_64-linux-gnu/libc.so.6
    0x7ffff7e16000     0x7ffff7e1a000 r--p     4000 215000 /usr/lib/x86_64-linux-gnu/libc.so.6
    0x7ffff7e1a000     0x7ffff7e1c000 rw-p     2000 219000 /usr/lib/x86_64-linux-gnu/libc.so.6
    0x7ffff7e1c000     0x7ffff7e29000 rw-p     d000      0 [anon_7ffff7e1c]
    0x7ffff7fa7000     0x7ffff7faa000 rw-p     3000      0 [anon_7ffff7fa7]
    0x7ffff7fbb000     0x7ffff7fbd000 rw-p     2000      0 [anon_7ffff7fbb]
    0x7ffff7fbd000     0x7ffff7fc1000 r--p     4000      0 [vvar]
    0x7ffff7fc1000     0x7ffff7fc3000 r-xp     2000      0 [vdso]
    0x7ffff7fc3000     0x7ffff7fc5000 r--p     2000      0 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    0x7ffff7fc5000     0x7ffff7fef000 r-xp    2a000   2000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    0x7ffff7fef000     0x7ffff7ffa000 r--p     b000  2c000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    0x7ffff7ffb000     0x7ffff7ffd000 r--p     2000  37000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    0x7ffff7ffd000     0x7ffff7fff000 rw-p     2000  39000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
    0x7ffffffde000     0x7ffffffff000 rw-p    21000      0 [stack]
0xffffffffff600000 0xffffffffff601000 --xp     1000      0 [vsyscall]

다음과 같이 gdb에서 vmmap을 통해 메모리를 보면 각 영역에 있는 권한을 확인 가능한다. 여기서 스택에는 실행권한(x)가 없는 것을 볼 수 있다. 

(2) 우회 방법

1. ROP

스택에서의 실행이 불가능 하기 때문에 코드영역 내에 있는 가젯을 이용해서 공격을 한다.

 

3. ASLR( Adress Space Layout Randomization)

(1) ASLR이란?

ASLR은 바이너리가 실행 될 때마다 스택, 힙, 공유 라이브러리 등을 임의의 주소에 할당하는 것이다. ASLR은 커널에서 지원하는 기법이다.  ASLR은 다음 몆가지의 특성이 있다.

 

1. 하위 12비트( hax주소 기준으로 세자리)는 변하지 않는다.

메모리를 페이지 단위로 매핑하기 때문에 멀티레벨페이징에서 페이지 오프셋에 해당하는 하위 12비트 값은 변하지 않는다.

 

2. libc_base 주소와 함수 코드의 주소간의 차이는 변하지 않는다.

라이브러리 파일을 그대로 매핑하는 것이기 때문에 오프셋은 차이가 나지 않는다.

(2) 우회 방법

1. ROP

가젯의 주소는 안바뀌므로 가젯을 이용

 

2. 주소 유출

주소를 유출하여 상대적주소를 이용해 공

 

4. PIE( Position-Independent Executable)

(1) PIE란? 

PIE는 무작위 주소에 매핑되어도 실행 가능한 파일을 말한다. PIE가 적용되면 코드영역의 주소도 계속 무작위로 바뀐다.

 

(2) 우회 방법

1. 코드 베이스 구하기

코드 영역의 임의 주소를 읽고 오프셋을 빼어서 PIE 베이스를 구하기

 

2. partial overwirte

위에서 말했듯이 ASLR의 특성상 하위 12비트는 변하지 않기 때문에 반환주소의 일부 바이트만 덮을 수 있다.

 

5. RELRO ( RELocation Read - Only)

(1) RELRO란?

RELRO란 쓰기 불필요한 데이터 세그먼트에 쓰기 권한을 제거하는 것이다. RELRO에는 다음 두가지의 종류가 있다.

*RELRO가 없으면 .init_array나 .fini_array를 조작하는 것도 가능하다.

 

1. Partial RELRO 

.got.plt, .data, .bss영역에 쓰기 가능( .got.plt에 쓰기 권한이 있는 것은 레이지 바인딩 때문이다.)

 

2. Full RELRO

data와 bss에만 쓰기 권한이 존재한다. 

 

(2) 우회 방법

1. GOT- overwrite(partial RELRO)

got에는 아직 쓰기 권한이 있으므로 GOT 테이블을 조작할 수 있다.

 

2.Hook-overwrite

라이브러리 데이터 영역에 Hook을 가리키는 포인터 변수를 조작할 수 있다.

 

 

이번글에서는 여러 보안 기법을 알아보았다. 위에서 알아본 것 말고도 IBT, SHSTK 같은 기법이 있으니 더 찾아 보도록 하자.

 

'CS' 카테고리의 다른 글

ELF 바이너리 포맷  (1) 2025.05.22
컴파일 과정  (0) 2025.05.21