1번 메뉴에서 thread_routine 스레드 함수에 의해 global_buffer 전역변수에 thread 스택 주소가 저장된다.
2번 과정에서 스레드 스택에 값을 넣기 위해 필요한 과정이다.
2. canary leak
먼저 스레드 스택에서 하위로 내려가서 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을 획득할 수 있다.
'A'*0x28(buf) + canary 값(canary) + 'C'*8(SFP) + &get_shell(return address)으로 데이터를 준 후 스택 모습이다.
4. get shell
rbp-0x8에 저장된 값과 fs:0x28에 저장된 canary 값을 비교하는 로직을 통과한 후 ret 시 get_shell 함수가 호출된다.