https://dreamhack.io/

 

해커들의 놀이터, DreamHack

해킹과 보안에 대한 공부를 하고 싶은 학생, 안전한 코드를 작성하고 싶은 개발자, 보안 지식과 실력을 업그레이드 시키고 싶은 보안 전문가까지 함께 공부하고 연습하며 지식을 나누고 실력 향상을 할 수 있는 공간입니다.

dreamhack.io

 

FSB 문제에 대해서 설명을 듣고 제가 생각해 본 내용을 정리해보았습니다!

문제와 출력 화면

Input은 buf라는 변수인데 이것이 출력될 때 printf_stackframe, buf, auth순으로 데이터가 구성되어 있습니다.

우리의 목표는 buf에 입력한 값을 특정한 주소에 입력되도록 하는 것입니다.

하지만 그냥 %x를 통해 값을 찾는다면 printf_stackframe에서부터 8byte씩 출력되기 때문에 %x를 여러번 사용하여 buf의 시작 위치를 확인해줘야 합니다.

buf의 시작 위치를 찾기 위한 과정

AAAA|%x|%x|%x|%x|%x|%x|%x|%x|%x

이렇게 입력해서 AAAA를 가리키는 값이 어디있는지 찾아보게 되면 5번째 %x의 값이 41414141로 AAAA의 ASCII코드를 나타내고 있는것을 알 수 있으며 따라서 5번째 %x부터가 buf값의 시작인 것을 알 수 있습니다.

 

다음을 설명하기 전에 %n에 대해서 설명하자면 %n은 자신이 확인하는 위치의 데이터를 주소값으로 하는 위치에 이전까지 카운트된 값을 집어넣는 자료형입니다.

이 문제만을 위해서 말해준다면 각 문자는 1로 카운트하고, %(값)x는 (값)만큼 카운트합니다. 예를 들어 %10x는 10으로 카운트 하는것처럼요. 따라서 AAAA%8x%8x%8x%8x%n은 4+8+8+8+8로 36의 값을 집어넣게 됩니다.

 

만약에 printf_stackframe에 32바이트가 할당되었고 AAAA%8x%8x%8x%8x%n으로 계산하게 되면 36이라는 값을 주소값 AAAA에 넣게 됩니다.

 

참고로 주소값을 입력하기 전에 주소는 0xfffdd030 이런 16진수로 표현되어 있다면 이를 문자로 바꿔주고, 역순으로 배열해줘야 합니다. fffdd030을 문자로 바꾸게 되면 ÿýÐ0이나오게되는데 input에 입력하기 위해서는 0Ðýÿ 이렇게 거꾸로 해주셔야 합니다.

이 내용은 밑에서 동일하게 다시 말합니다.

 

이제 이 문제에 대한 풀이를 설명해보겠습니다.

 

풀이과정은 다음과 같습니다.

주소값찾기

1. 목표하는 위치의 주소값을 찾아야합니다.

(원래는 이것도 여러 과정이 있지만 위의 문제에서는 주소값을 그냥 알려주고 시작합니다)

2. 주소값이 16진수로 구성되어 있으므로, 문자로 바꿔줍니다.

3. 주소값을 사용하기 위해 문자를 역순으로 배치해줍니다.

 

FSB 실행

1. %x를 여러번 사용하여 buf의 시작지점이 어디인지 찾아줍니다.

(AAAA%x%x%x%x%x 했을 때 마지막에 41414141이 떴으므로 5번째 %x가 buf의 시작지점이라는 것을 알 수 있습니다.)

2. input의 시작지점에 주소값을 넣고, %x를 통해 %n이 주소값에 위치하도록 넣는다.

(5번째 %x가 input인 buf의 시작점이라면 %x%x%x%x%n처럼 말이죠.)

3. 넣을 값이 255라고 할 때 입력한 카운트된 값의 합이 255이어야 합니다.

(%13x는 13으로 인식하는것처럼 계산을 해주면 됩니다. 문자는 각각 1로 계산하시면 됩니다. 만약에 255라는 값을 넣으려면 [주소값 문자 4개]%8x%8x%8x%227x%n을 해주면 4+8+8+8+227로 255의 값을 주소에 넣게 되는거죠.)

(printf에서 %x는 기본적으로 8의 값을 갖지만 %x가 향하고 있는 메모리에 아무런 데이터가 없다면 1로 인식한다고 합니다. 이 부분에 대해서는 조금 더 공부를 해야합니다.)

 


문제에서는 0xfffdd030 주소에 값을 넣어야하므로 16진수 fffdd030을 문자로 바꿔줘서 

이렇게 나오게 됩니다.

위에서 5번째 %x에서 buf가 시작된다는 것을 알 수 있었으므로 

input에 주소를 넣고 %x를 4번 적어준 뒤 %n을 적어주게 되면 %n이 값을 넣을 주소가 input의 시작점, 즉 주소를 입력한 위치로 정해집니다.

ÿýÐ0이 값이 주소가 되게 되는데, 주소를 인식하는 방향은 거꾸로라 역순으로 재배치해줘야 한다고 합니다.

따라서 0Ðýÿ가 저희가 입력할 주소값이 되는거죠.

0Ðýÿ%x%x%x%x%n으로 해주게 되면 %n이 목표로 하는 위치가 0Ðýÿ이 주소가 되며 이제 넣을 값만 바꿔주면 된다.

(따라서 저희가 목표로 한 위치에 현재 값을 %n이 넣어주고 있는겁니다.)

'0Ðýÿ%8x%8x%8x%227x%n' 넣어주게 되면 4+8+8+8+227 = 255이므로 255라는 값이 0Ðýÿ이 주소에 들어가게 됩니다.

(참고로 한군데의 %x에만 값을 넣지 않은 이유는 printf_frame 부분에 데이터가 들어가있지 않으면 %x를 1로 인식한다고 하기 때문입니다. 그 외에 일반적으로 8로 인식하기 때문에 모두 일단 8로 넣어주고 값을 찾았습니다.)

 

이렇게! 문제를 해결할 수 있었습니다!


참고로 이 문제풀이는 제가 풀이를 듣고 저의 생각을 정리해서 작성한 것이기 때문에 많은 부분에서 원래의 내용과 다를 수 있습니다. '저는 이런 생각을 가지고 있다' 라는 식으로 설명한 것이므로 내용을 그대로 가져가시면 안됩니다. 제대로 사실확인을 해보세요.

 

만약 제가 틀린 내용을 작성했다면 댓글로 가감없이 어느 부분에서 어떻게 바꿔야하는지 설명해주시면 감사하겠습니다.

'Hacking-기초 > Pwnable' 카테고리의 다른 글

Linux Exploitation & Mitigation Part 1 (2)  (0) 2020.04.14
Linux Exploitation & Mitigation Part 1 (1)  (1) 2020.04.13
Buffer Overflow Attack 기초(1)  (0) 2020.04.11
Memory Corruption - C (2)  (1) 2020.04.11
Memory Corruption - C (1)  (0) 2020.04.11

+ Recent posts