OZ1NG의 뽀나블(Pwnable)

64bit환경에서 FSB 할때 주의점 (32bit와 차이점) 본문

Pwn Study

64bit환경에서 FSB 할때 주의점 (32bit와 차이점)

OZ1NG 2019. 6. 25. 02:30

Format String Bug(이하 fsb)의 주축이 되는 printf함수는 널문자를 기준으로 문자열의 끝을 판단한다. 

 

당연한건데 왜 주의해야 하는가?
32bit에서는 모든 주소들이 4바이트였고 한 주소를 판단하는 크기 또한 4바이트였기 
때문에 크게 문제가 되지 않았지만, 
64bit에서는 스택과 실제 함수 주소 제외한 대부분의 주소들이 3바이트이고,
한 주소를 판단하는 크기는 8바이트이기 때문에 무조건 1바이트 이상은 널문자로 채워지게 된다. 이게 문제가 된다.

 

예시를 들어 보자!

만약 fsb페이로드의 순서를 [어딘가의 주소]+[%???c%?$ln] 이런식으로 짰다고 치자, 
그렇다면 fsb페이로드는 스택에 
"0x0000000000606060(어딘가의 주소) 0x????????????????(%???c%?$ln)" <- 이런식으로 저장이 될 것이다. 

그렇다면 printf함수는 이 곳에서 0x606060까지만 문자열이라고 판단하고 그 이후의 [%???c%?$ln]는 읽어오지 않는다. 즉, %n은 사용되지 않을 것이고, 결과적으로 64bit환경에서의 fsb는 실패하게 된다.  

 

그럼 어떻게 해결해야 하는가?

나는 아래와 같은 해결 방법을 생각했다. 
[어딘가의 주소]+[%???c%?$ln] 이런식이던 원래의 페이로드를 아래와 같이 
[%???c%?$ln]+[어딘가의 주소]로 순서를 바꿔 주었다. 

(만약 [%???c%?$ln]를 입력한 것의 크기가 8바이트 단위가 아니라면 추가로 문자 몇개를 더해줘서 맞춰주면 된다.)


그럼 printf는 널바이트를 만나기 전에 %n을 올바르게 실행 할 수 있을 것이고 64bit fsb는 성공할 수 있다. 
(참고로 당연하지만 $플래그를 쓸때 위치는 바뀌었을 때 기준으로 바꿔줘야 한다.) 

 

[+추가]

%ln으로 값을 입력하려 한다고 모든게 되는게 아니였다.
만약 입력하려는 값(%[입력하려는 값]c)이 6바이트를 넘어간다면, %ln을 쓴다고 해도 fsb공격이 되지 않는다. 
(6바이트 예시 : 함수의 실제 주소, 스택의 주소, one_gadget_addr 등)
아무래도 값이 너무 커서 그런가 보다. 
(스택에는 숫자 하나하나가 ASCII 문자 값으로 저장되는데,
hex값으로 6byte 정도면 10진수바꿨을때 최소 15byte정도 된다. 
)
3바이트 정도라면 무난하게 %ln으로도 가능하다.

Comments