외로운 Nova의 작업실

dreamhack 시스템해킹 - 10(Canary) 본문

Computer App Penetesting/System Vulnerability

dreamhack 시스템해킹 - 10(Canary)

Nova_ 2023. 1. 18. 18:13

- 카나리

스택 카나리는 함수의 프롤로그에서 스택 버퍼와 반환 주소 사이에 임의의 값을 삽입하고, 함수의 에필로그에서 해당 값의 변조를 확인하는 보호 기법입니다. 카나리 값의 변조가 확인되면 프로세스는 강제로 종료됩니다. 카나리값의 첫번째 값은 leak을 방지하기위해 보통 null값입니다. 

 

- 카나리 할당 과정

1. 프로세스는 프로그램을 실행하고 카나리를 fs 세그먼트의 주소값을 설정합니다. 이때 fs 주소값이 설정되면 시스템은 arch_prctl()함수를 호출합니다. 

2. 이후 fs 세그먼트 공간이 확보되면 프로그램이 작동하면서 fs세그먼트 시작부분으로부터 0x28번째 공간에 임의의 값으로 넣습니다.

3. 이후 카나리를 사용해야하는 프로그램은 이 카나리값을 사용합니다.

 

- 카나리가 적용된 프로그램과 미 적용된 프로그램 비교

<c프로그램>

#include <unistd.h>
int main() {
  char buf[8];
  read(0, buf, 32);
  return 0;
}

<미적용>

push   rbp
mov    rbp,rsp
sub    rsp,0x10
mov    rax,QWORD PTR fs:0x28
mov    edx,0x20
mov    rsi,rax
mov    edi,0x0
call   read@plt
mov    eax,0x0
leave
ret

<적용>

push   rbp
mov    rbp,rsp
sub    rsp,0x10
mov    rax,QWORD PTR fs:0x28		//fs:0x28에 저장되어있는 카나리값을 rax로 가져옵니다.
mov    QWORD PTR [rbp-0x8],rax		//sfp위에 카나리를 저장합니다.
xor    eax,eax
lea    rax,[rbp-0x10]
lea    rax,[rbp-0x8]
mov    edx,0x20
mov    rsi,rax
mov    edi,0x0
call   read@plt
mov    eax,0x0
mov    rcx,QWORD PTR [rbp-0x8]	//스택에 저장된 카나리값을 rcx로 가져옵니다.
xor    rcx,QWORD PTR fs:0x28	//rcx와 fs:0x28에 저장된 카나리값을 xor합니다. 모두 같으면 z=1
je     0x6f0 <main+70>			//만약 같으면 0x6f0으로 넘어가고 정상 종료됩니다.
call   __stack_chk_fail@plt		//다르면 fail을 일으킵니다.
leave
ret

 

- 카나리 우회

카나리는 무차별 대입공격으로 때려맞추거나 오버플로로 덮어쓰기전에 stack-leak을 유도하여 카나리 값을 알아낼 수 있습니다.  실습 모듈로 한번 알아보겠습니다.

name에 a를 9개 입력해주면 마지막a가 카나리의 null을 대체함으로 카나리 값이 유출됩니다.즉 카나리값은 "\x00tTc(xU8"인것을 알 수 있습니다. askii코드를 16진수로 변경하면 \x00\x74\x54\x63\x28\x78\x55\x38인 것을 알 수 있습니다. 카나리를 고려하여 ret을 조작하는 코드를 memo에 넣는다면 ret 조작이 가능하지만 실제적으로 \x00을 값으로 줘도 각각 '\' 'x' 값으로 인식해버려서 안됬습니다. 즉, 키보드로 null값을 줄 수 없기때문에 불가능햇습니다. null값을 줄 수 있는 방법이 있을까요?

Comments