상세 컨텐츠

본문 제목

[Dreamhack] master_canary

SYSTEM HACKING/Dreamhack

by koharin 2022. 1. 5. 22:11

본문

728x90
반응형

Master canary 글을 참고하면 좋다.

Master canary

SSP(Stack Smashing Protector) 보호기법은 스택 버퍼오버플로우를 방지하기 위해 개발된 기법이다. SSP는 스택 buffer와 SFP(Stack Frame Pointer) 사이에 랜덤 값인 canary를 넣어서 함수 종료 시점에서 __stack..

koharinn.tistory.com

🔍 코드 분석


int __cdecl main(int argc, const char **argv, const char **envp) { const char **v4; // [rsp+0h] [rbp-60h] __int64 v5; // [rsp+18h] [rbp-48h] pthread_t newthread; // [rsp+20h] [rbp-40h] __int64 v7; // [rsp+28h] [rbp-38h] char buf; // [rsp+30h] [rbp-30h] unsigned __int64 canary; // [rsp+58h] [rbp-8h] v4 = argv; canary = __readfsqword(0x28u); initialize();
  • rbp-0x8에 위치한 canary가 있다.
  • 어셈블리 코드로 확인해보면 rax 레지스터에 저장된 값을 rbp+canary 메모리에 저장한다. rax 레지스터에는 fs:0x28이 참조하는 주소에서 가져왔으며, 해당 주소는 TLS 영역의 header.stack_guard이다.
  • master canary는 main 함수 호출 전 랜덤으로 생성된 canary를 thread 마다 전역변수로 사용되는 TLS(Thread Local Storage)에 저장하는데, 모든 thread 가 하나의 canary를 사용하기 위해서이다.
  • security_init 함수에서 dl_setup_stack_chk_guard 함수에서 반환한 랜덤 canary 값(stack_chk_guard)을, THREAD_SET_STACK_GUARD(stack_chk_guard) 함수에서 TLS 영역의 header.stack_guard에 삽입한다.
  • master canary 값을 몰라도 master canary 값을 조작하여 fs:0x28을 참조하여 비교하는 SSP 보호기법을 우회할 수 있다.

 while ( 1 ) { while ( 1 ) { puts("1. Create thread"); puts("2. Input"); puts("3. Exit"); printf("> ", v4); __isoc99_scanf("%d", &v7); if ( v7 != 2 ) break; printf("Size: ", &v7); __isoc99_scanf("%d", &v5); printf("Data: ", &v5); read_bytes(global_buffer, v5); printf("Data: %s", global_buffer); } if ( v7 == 3 ) break; if ( v7 == 1 ) { if ( pthread_create(&newthread, 0LL, thread_routine, 0LL) < 0 ) { perror("thread create error"); exit(0); } } else { puts("Nope"); } } printf("Leave comment: ", &v7); read(0, &buf, 0x400uLL); return 0; }
  • Create thread 메뉴
    • pthread_create 함수로 스레드 생성
    • 스레드 생성 시 tcbhead_t 구조체의 stack_guard(master canary)를 복사해서 사용하므로 이를 덮으면 master canary를 원하는 값으로 조작이 가능하다.
    • thread_routine 함수: 스레드 스택 변수 v2 주소를 global_buffer(전역변수)에 복사한다.
char *__fastcall thread_routine(void *a1) { char *result; // rax char v2; // [rsp+0h] [rbp-110h] result = &v2; global_buffer = (__int64)&v2; return result; }
  • Input 메뉴
    • Size를 입력받고, size와 global_buffer을 인자로 read_bytes 함수를 호출한다.
    • read_bytes 함수: global_buffer에 저장된 주소(스레드 스택 변수 주소)에 데이터를 입력받는다. 즉, 스레드 스택 변수 v2에 size만큼 데이터를 입력하게 된다. 
    • 스레드 스택변수에 입력한 데이터를 출력한다. 스레드 스택에 main 스택과 동일한 canary가 저장되어 있기 때문에, offset을 적절히 구해서 print 시 스레드 스택 내의 canary 값을 읽을 수 있을 것이다.
unsigned __int64 __fastcall read_bytes(__int64 global_buf, unsigned __int64 size) { unsigned __int64 result; // rax unsigned __int64 v3; // [rsp+18h] [rbp-18h] __int64 v4; // [rsp+20h] [rbp-10h] v3 = 0LL; v4 = 0LL; while ( 1 ) { result = v3; if ( v3 >= size ) break; if ( read(0, (void *)(global_buf + v4), 1uLL) != 1 ) exit(-1); ++v4; ++v3; } return result; }


🚩 Exploit Flow


1. 스레드 생성

  • 1번 메뉴에서 thread_routine 스레드 함수에 의해 global_buffer 전역변수에 thread 스택 주소가 저장된다.
  • 2번 과정에서 스레드 스택에 값을 넣기 위해 필요한 과정이다.

2. canary leak

offset 구하기
  • 먼저 스레드 스택에서 하위로 내려가서 canary 값 가지고 있는 주소와 스레드 스택 주소와의 offset(0x8e8)을 구해준다.

  • canary는 main 스택에서나 스레드 스택에서나 동일하게 fs:0x28에서 가져오기 때문에 스레드 스택에서 데이터 릭이 가능한 것으로 canary leak을 한다.
  • canary 하위를 B로 덮는다. canary 하위 비트는 항상 \x00이기 때문에 덮은 후 leak 시 하위 비트를 \x00으로 바꿔서 구하면 된다.
  • Input으로 size를 0x8e8+1로 주고, data를 ‘A’*0x8e8 + ‘B’를 준다.
  • global_buffer에 저장된 주소(스레드 스택)의 데이터를 출력 시 %s는 NULL을 만나기 전까지 출력해주므로 canary leak을 할 수 있다.
  • 위 사진의 오른쪽 화면에서 canary가 구해진 것을 확인할 수 있다.

3. return address overwrite by BOF

  • dreakhack master canary 강의 예제처럼 스레드 스택 하위에 존재하는 canary를 특정 값으로 덮은 후, read로 buf에 데이터 줄 때 canary 위치에 덮은 값을 줘도 stack smashing detected 오류가 발생한다. 그 이유는 스레드 스택에서의 canary를 덮어서 main 스택에서의 canary와 위치가 다르기 때문이다.
  • 3번으로 반복문 종료 후 read 시 canary를 1번 과정에서 구한 canary를 데이터 상의 canary 위치에 준 후 return address에 get_shell 주소를 주면 shell을 획득할 수 있다.
buf 버퍼에 데이터 입력 후
  • 'A'*0x28(buf) + canary 값(canary) + 'C'*8(SFP) + &get_shell(return address)으로 데이터를 준 후 스택 모습이다.

4. get shell

  • rbp-0x8에 저장된 값과 fs:0x28에 저장된 canary 값을 비교하는 로직을 통과한 후 ret 시 get_shell 함수가 호출된다.

  • 쉘 실행해서 flag 획득!
728x90
반응형

'SYSTEM HACKING > Dreamhack' 카테고리의 다른 글

[Dreamhack] pwn-library  (0) 2024.01.10
[Dreamhack] shell-basic  (2) 2024.01.10
[Dreamhack] welcome  (0) 2021.02.09
[Dreamhack] tcache_dup2  (0) 2020.08.29
[Dreamhack] basic_heap_overflow  (0) 2020.07.08

관련글 더보기