WARGAME/FTZ

FTZ level9 풀이

msh1307 2022. 4. 14. 01:37

*FTZ를 공부하면서 배운 것들을 정리했습니다. 틀린 정보가 있을 수 있습니다.

계정/비번: level9/apple

 

로그인을 하고 힌트를 확인했더니 bof의 소스코드가 적혀있네요. 

/usr/bin/bof의 권한을 확인해보니 level 10으로 setuid bit가 걸려있습니다.

힌트에 나온 코드를 보면, buf2와 buf를 선언하고 stdin을 통해 입력을 40바이트만큼 받아 buf에 저장하는 것을 알 수 있습니다.

입력을 받고 나서 buf2와 "go"를 2번째 자리까지 비교합니다. 같다면 "Good Skill!"을 출력하고, setreuid를 통해서 RUID와 EUID를 3010으로 바꿔주고 쉘을 실행시킵니다.

setreuid 함수는 아래 잘 설명되어있습니다.

https://man7.org/linux/man-pages/man2/setreuid.2.html

 

 

setreuid(2) - Linux manual page

setreuid(2) — Linux manual page SETREUID(2) Linux Programmer's Manual SETREUID(2) NAME         top setreuid, setregid - set real and/or effective user or group ID SYNOPSIS         top #include int setreuid(uid_t ruid, uid_t euid); int setregid(gi

man7.org

 

 

 

buf와 buf1이 둘 다 10바이트의 크기를 가집니다. 또한 지역변수이기 때문에 스택 영역에 쌓이게 됩니다. 

https://jinshine.github.io/2018/05/17/%EC%BB%B4%ED%93%A8%ED%84%B0%20%EA%B8%B0%EC%B4%88/%EB%A9%94%EB%AA%A8%EB%A6%AC%EA%B5%AC%EC%A1%B0/

intel x86 아키텍처에서 스택은 높은 주소에서 낮은 주소로 쌓입니다. 힙과 반대 방향으로 자란다고 생각하면 됩니다.

높은 주소부터 순서대로 buf2, buf가 쌓입니다.

그다음 buf로 입력을 받는데, 40바이트만큼 입력을 받을 수 있기 때문에 buf를 다 채우고 buf2에 데이터를 덮어씌울 수 있게 되는 버퍼 오버플로우가 발생하게 됩니다. 

 

gdb를 통해서 더 자세히 분석해보겠습니다.

현재 홈 디렉토리에선 쓰기 권한이 없기 때문에 /tmp로 이동해서 코드를 복사 붙여 넣기 하고 컴파일하겠습니다.

그대로 복사 붙여 넣기 했더니 들여 쓰기가 조금 잘못되었는데 상관없습니다.

esc + :wq를 통해서 저장하고 나가줍니다. 

컴파일을 했으니 gdb로 열어보겠습니다.

AT&T문법은 복잡해서 Intel문법을 사용해서 main함수를 뜯어보겠습니다.

어셈블리 코드를 볼 수 있습니다. 이제 buf와 buf2의 시작 주소를 찾으면 됩니다. 

fgets(buf,40,stdin); 부분과 관련된 부분을 찾아보면 0x0804844f에 fgets를 call 하는 것을 볼 수 있습니다.

그렇다면 그 앞에는 인수가 역순으로 들어간 것들을 찾아보면 됩니다.

main+35에 ds:0x8048320과 main+41에 0x28, main+46에서 인수들을 찾을 수 있습니다.

ds:0x8048320가 stdin 버퍼를 말하는 것 같습니다. 

그리고 0x28은 10진수로 40입니다. 두 번째 인수였죠.

마지막으로 eax는 main+43에서 ebp-40 주소 값이 들어간 것을 알 수 있고, eax를 push하니 이게 첫 번째 buf 인수인 것을 알 수 있습니다.

이를 통해서 buf의 시작 주소는 ebp-40인 것을 알 수 있습니다. fgets한테 buf의 시작 주소를 넘겨줘서 fgets가 40바이트만큼 입력을 받아서 높은 주소 방향으로 데이터가 쌓이고 덮어 씌워지겠죠. 

 

아까 앞에서 sub esp, 0x28을 통해서 스택을 40바이트만큼 확장시켜줬었죠. esp레지스터는 계속 변하니 항상 스택 프레임의 가장 아래를 가리키고 있는 ebp를 통해서 메모리에 접근하는 것도 확인할 수 있습니다.

 

마찬가지로 strncmp함수를 call 하는 main+69 주변을 자세히 보면 main+65에 ebp-24를 마지막에 eax레지스터로 넣었다가 스택에 push 했으니 ebp-24가 buf2의 시작 주소임을 알 수 있습니다.

이제 둘의 시작 주소를 알았으니, 둘 사이의 거리를 계산해봅시다.

[ebp-24]과 [ebp-40]의 거리는 16바이트입니다. 그렇다면 buf에 16바이트를 채워준다면 그때 buf2의 시작 주소에 입력을 넣어줄 수 있겠죠. 

그렇다면 아무거나 16바이트 채우고 go를 적으면 풀 수 있겠네요.

quit를 입력해서 gdb를 나가고 /usr/bin/bof를 실행시켜보았습니다.

입력에 아무 1바이트 문자를 16번 입력하고 뒤에 go를 붙였습니다.

level 10 쉘을 얻을 수 있습니다.

 

'WARGAME > FTZ' 카테고리의 다른 글

FTZ level10 풀이  (0) 2022.05.03
FTZ level8 풀이  (0) 2022.02.26
FTZ level7 풀이  (0) 2022.02.26
FTZ level6 풀이  (0) 2022.02.26
FTZ level5 풀이  (0) 2022.02.24