gdb에서 $fs_base 명령어

gdb의 특정 버전 이후로만 fs_base 명령어가 먹히는 것으로 알고 있는데, 만약에 안먹히는 gdb에서는 어떻게 fs_base를 구해야하나요..............?ㅠㅠ

그리고 fs 레지스터의 값을 출력해봐도 아래와 같이만 뜹니다 ㅠㅠ(thread_routine 실행 후 출력해준 값입니다!) image.png

fs는 tls부분 가리키는거 아닌가요? 그런데 왜 저러는지 그 이유도 궁금합니다..

#pwnable
작성자 정보
답변 1
avatar
OSORI
워게임 고인물

답변이 좀 늦었지만, 재밌게 봐주세요.

왜 fs 값이 0인지 알기 위해서는 먼저 세그먼트 레지스터가 왜 있는지부터 알아야됩니다. 운영체제를 공부하면 세그먼테이션과 페이징이라는 메모리 관리기법에 대해서 배울 수 있습니다. 이 세그먼트 레지스터는 세그먼테이션 기법을 사용하기 위한 놈이고요. 그런데 사실 현대의 64비트 리눅스와 윈도우(32비트는 모르겠네요)는 페이징 기법을 주로 사용합니다. 세그먼테이션 기법은 질문자님이 말한 tls와 같은 용도로만 사용되구요.

16비트 모드에서 세그먼트 레지스터의 사용

컴퓨터가 부팅될 때 운영체제는 16-32-64비트 순으로 부팅이 됩니다.
이때는 16비트가 넘어가는 주소에 접근하려고 (세그먼트 레지스터 값)<<4 + 16비트로 접근을 해서, 총 1mb 까지 메모리를 접근했습니다.
mov byte [es:si], 0x10 처럼 말이죠.
사실 이때 사용하려고 만든게 세그먼트 레지스터라고 봐도 됩니다. 지금처럼 메모리가 커질줄 몰랐겠죠...

32비트에서 세그먼트 레지스터의 사용

32비트에서는 세그멘테이션 기법을 좀 제대로(?) 사용합니다. 세그먼트 레지스터는 세그먼트 셀렉터로 불리는데, 어쨌든 세그먼트 레지스터가 담고 있는 값은 세그먼트를 정의하는 세그먼트 디스크립터의 위치 입니다.
세그먼트 디스크립터는 세그먼트의 베이스주소, 크기, 권한등을 가지고 있고 디스크립터 여러개들이 메모리에 모여있습니다. 그래서 위에서 말한대로 fs 레지스터가 0이라면 첫번째 디스크립터를 의미하는 거겠죠. (하지만 첫번째 디스크립터는 null 디스크립터로 사용되지 않습니다.) 그림상으로 보면 아래와 같네요.
image.png
그래서 fs 레지스터의 값은 그냥 세그먼트 디스크립터의 위치입니다.주소는 커널 메모리에 위치해있고요.
그런데 어라? 첫번째 디스크립터는 사용되지 않는다고 했죠. 0이면 안되는거 아닐까요?

64비트에서 세그먼트 레지스터 사용

64비트에서는 뭐... 사용을 안합니다. 그냥 호환성 때문에 존재하구요.
강제로 base 주소가 0 으로 고정되서 그냥 사용 금지입니다 . FS/GS 는 예외입니다. 자세한 내용은 아래 글을 참고해보세요

image.png

세그먼트 셀렉터를 이용한 접근방식의 문제점

문제는 세그먼트 디스크립터가 커널메모리에 있다보니 일반 사용자는 접근이 안됩니다. 그래서 스레드 생성시에 tls 를 생성할 때 필연적으로 시스템콜을 이용해야만 fs에 제대로 된 세그먼트 디스크립터가 위치할 수 있었습니다. 하지만 system call 자체가 비용이 크다보니, 인텔은 ivy bridge 이후 FSGSBASE 라는 걸 내놓아서, 유저모드에서도 fsbase/gsbase 를 변경할 수 있게 했습니다. wrfsbase, rdfsbase 등의 명령어를 통해서 말이죠. 이 FSGSBASE기능이 사용되면 FS/GS 레지스터에 있는 세그먼트 셀렉터 값은 무시됩니다.

결론

fs 레지스터값이 0인 이유는 wrfsbaserdfsbase 명령어로 베이스 주소가 설정됐기 때문입니다.
구버전 gdb에서 fs base 값을 알아 오는법은 직접 사용하지 않는 메모리에 실행권한을 주고 rdfsbase 명령어를 기입한다음, RIP를 돌려서 값만 받고 다시 원래 코드로 복구 또는 fs base로 접근하는 코드에 브포 걸고 해당 메모리 값 찾아서 오프셋 찾기. 정도가 있겠군요. 사실 오프셋 자체는 거의 매번 동일한 곳에 생성되다 보니 한번 구해서 libc base 와의 오프셋 등으로 구했던것 같네요.
궁금한거 있으면 댓글 달아주세요

2023.08.08. 23:36
질문에 대한 답을 알고 계신가요?
지식을 나누고 포인트를 획득해보세요.
답변하고 포인트 받기