[Mitigation] Stack Canary

2024. 8. 24. 17:56·Hacking/Pwnable
728x90
반응형

Definition | 정의

스택 버퍼와 반환 주소 사이에 임의의 값을 삽입하여 함수의 에필로그에서 해당 값의 변조를 확인하는 보호기법

만약, 스택 카나리의 값이 변조되었다면 프로세스는 강제 종료됨

 

스택 버퍼오버플로우로 반환 주소를 덮으면서, 스택 카나리의 값을 덮는 것을 피할 수 없음

→ 에필로그에서 변조가 확인되며 해커가 실행 흐름을 가져올 수 없음

 

카나리를 잘못 덮어쓰면 

stack smashing detected

라는 경고와 함께 종료된다

 

카나리 정적 분석

스택 카나리를 만드는 과정이 프롤로그에, 변조를 확인하는 과정이 에필로그에 추가됨

프롤로그

mov    rax,QWORD PTR fs:0x28
mov    QWORD PTR [rbp-0x8],rax
xor    eax,eax
lea    rax,[rbp-0x10]

fs 세그먼트 레지스터가 가리키는 값의 오프셋 0x28 값(카나리 값)을 rax로 이동

rax에 저장된 값을 rbp(base pointer)의 0x8 떨어진 곳에 저장

eax를 초기화하고, rax에 rbp-0x10의 값을 넣는다

더보기

[ mov vs lea ]

mov : op2를 op1로 이동

lea : op2의 주소를 op1로 이동 - 주소 자체를 가져옴

에필로그

mov    rcx,QWORD PTR [rbp-0x8]
xor    rcx,QWORD PTR fs:0x28
je     0x6f0 <main+70>
call   __stack_chk_fail@plt

rbp-0x8의 값, 즉 아까 저장한 카나리의 값을 rcx에 넣는다

rcx값, 즉 스택에서 얻어온 값과 원래 카나리의 값을 비교하여 같으면 다음 줄을 실행하고 아니라면 프로세스를 종료한다

 

카나리 동적 분석

프롤로그

► 0x5555555546b2 <main+8>     mov    rax, qword ptr fs:[0x28] <0x5555555546aa>
   0x5555555546bb <main+17>    mov    qword ptr [rbp - 8], rax
   0x5555555546bf <main+21>    xor    eax, eax

fs:0x28의 값을 읽어서 rax에 저장함

pwndbg> ni
   0x5555555546b2 <main+8>     mov    rax, qword ptr fs:[0x28] <0x5555555546aa>
 ► 0x5555555546bb <main+17>    mov    qword ptr [rbp - 8], rax
   0x5555555546bf <main+21>    xor    eax, eax
pwndbg> print /a $rax
$1 = 0xf80f605895da3c00

이를 실행한 후, rax를 확인해보면 시작이 null (0x00)인 바이트가 저장되어 있음 (little endian)

이를 rbp-0x8에 저장한다

pwndbg> ni
   0x5555555546b2 <main+8>     mov    rax, qword ptr fs:[0x28] <0x5555555546aa>
   0x5555555546bb <main+17>    mov    qword ptr [rbp - 8], rax
 ► 0x5555555546bf <main+21>    xor    eax, eax
pwndbg> x/gx $rbp-0x8
0x7fffffffe238:	0xf80f605895da3c00

rbp-0x8의 값이 아까 rax값과 같다는 것을 확인할 수 있음

이 값이 카나리이다

에필로그

현재 오버플로우가 일어나서 카나리에 다른 값이 덮이도록 해놓은 상태라고 가정한다

 ► 0x5555555546dc <main+50>    mov    rcx, qword ptr [rbp - 8] <0x7ffff7af4191>
   0x5555555546e0 <main+54>    xor    rcx, qword ptr fs:[0x28]
   0x5555555546e9 <main+63>    je     main+70 <main+70>
    ↓
   0x5555555546f0 <main+70>    leave
   0x5555555546f1 <main+71>    ret

rcx에 스택에 있는 카나리 값을 저장한다

   0x5555555546dc <main+50>    mov    rcx, qword ptr [rbp - 8] <0x7ffff7af4191>
 ► 0x5555555546e0 <main+54>    xor    rcx, qword ptr fs:[0x28]
   0x5555555546e9 <main+63>    je     main+70 <main+70>
pwndbg> print /a $rcx 
$2 = 0x4848484848484848

rcx를 확인해보면, 원래 카나리 값이 저장되어 있어야하는 스택 위치에 오버플로우 된 값이 저장되어있음을 알 수 있음

 ► 0x5555555546eb <main+65>    call   __stack_chk_fail@plt <__stack_chk_fail@plt

카나리가 잘못 덮인 것을 확인하면 프로세스가 종료된다

 

카나리 생성 과정

fs 레지스터 (segment register의 일종) → TLS

리눅스에서 fs의 값은 쉽게 알아낼 수 없음 ex) info register fs, print $fs 등으로 알아낼 수 없음

 

fs의 값을 설정할 때 호출되는 시스템 콜

arch_prctl(int code, unsiged long addr)

해당 시스템콜로 설정한다. code 부분에 FS를 넣어주면 addr로 fs가 설정된다

arch_prctl(ARCH_SET_FS, addr)

fs의 값은 addr이 됨

 

동적 분석으로 확인

catch syscall arch_prctl

catch 명령어로 확인할 수 있음. arch_prctl를 실행하기 전에 멈춤

해당 시스템 콜은 init_tls() - tls를 초기화해주는 함수 안에서 실행됨

인자1 (rdi) : ARCH_SET_FS는 상수값으로 0x1002

인자2 (rsi) : TLS의 저장 위치, fs가 가리킬 공간

카나리 : fs + 0x28의 값이므로 rsi+0x28의 값을 확인 가능

pwndbg> x/gx 0x7ffff7d7f740 + 0x28
0x7ffff7d7f768: 0x0000000000000000

하지만, 아직 카나리값이 저장되지 않았기 때문에 해당 부분에 아무것도 설정되지 않음을 확인 가능

 watch *(0x7ffff7d7f740+0x28)

watch 명령어로 확인할 수 있음

watch : 특정 주소에 저장된 값이 변경되면 프로세스를 중간시킴

Hardware watchpoint 4: *(0x7ffff7d7f740+0x28)
Old value = 0
New value = 2005351680
security_init () at rtld.c:870
870	in rtld.c

즉 이때, TLS+0x28의 값을 확인할 수 있음

pwndbg> x/gx 0x7ffff7d7f740+0x28
0x7ffff7d7f768:	0x8ab7f53277873d00

이 값이 카나리의 값과 같다는 것을 확인할 수 있음

 

카나리 우회

Brute Force 무차별 대입

카나리는 맨 처음이 null byte 이므로 x64는 \(256*7\), x86은 \(256^3\)이라고 가정할 수 있음

TLS 접근

카나리는 TLS에 전역변수로 저장됨

TLS의 주소는 매 실행 시마다 바뀌기 때문에 TLS 주소를 알 수 있다면 가능

스택 카나리 릭 (인포릭)

인포릭과 똑같은 방식으로 진행됨

오버플로우를 내면, canary의 값이 출력되는 경우가 발생함

카나리의 맨 앞부분은 null이기 때문에 한바이트 오버플로우로 나머지를 알아낼 수 있음

728x90
반응형
저작자표시 비영리 변경금지 (새창열림)

'Hacking > Pwnable' 카테고리의 다른 글

[Mitigation] ASLR  (0) 2024.08.25
[Mitigation] NX  (0) 2024.08.25
gdb를 pwntools와 디버깅하기  (0) 2024.07.26
[ Domato ] 사용법  (5) 2024.05.18
[Memory Corruption] Stack Buffer Overflow  (1) 2024.01.29
'Hacking/Pwnable' 카테고리의 다른 글
  • [Mitigation] ASLR
  • [Mitigation] NX
  • gdb를 pwntools와 디버깅하기
  • [ Domato ] 사용법
min_zu
min_zu
  • min_zu
    민주제도
    min_zu
  • 전체
    오늘
    어제
    • ._. (176)
      • AI (2)
        • DeepLearning (2)
        • CS231n (0)
      • Web (2)
        • ReactJS (0)
      • CS (83)
        • OS (7)
        • Data Structure (23)
        • Computer Architecture (8)
        • Computer Network (20)
        • Algorithm (25)
      • Linux (3)
        • KaliLinux (0)
        • Docker (1)
      • Hacking (83)
        • Write Up (25)
        • Pwnable (13)
        • Reversing (2)
        • Cryptography (12)
        • Web Hacking (4)
        • Window (6)
        • Network (7)
        • Web3 (13)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    AI
    DeepLearning
    Linux
    OS
    Mac
    ComputerArchitecture
    UTM
    Sort
    Tree
    WinAFL
    Graph
    Search
    Web
    DataStructure
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
min_zu
[Mitigation] Stack Canary
상단으로

티스토리툴바