ssoL2 TISTORY

[FTZ] LEVEL 9 완벽 분석 본문

challenge/pwn

[FTZ] LEVEL 9 완벽 분석

ssoL2 2021. 1. 28. 22:56

level9 / apple


cat hint 명령어로 hint를 봅시다.

/usr/bin/bof 실행파일의 소스를 주었다. 딱 보니 fgets 함수로 buffer overflow = bof 를 일으키려는 모양입니다!

bof 란 buffer overflow로 말 그대로 버퍼를 넘치게 해서 취약점을 얻는 해킹 방법입니다! 

main 함수를 보면 buf2랑 buf를 10 bytes씩 할당하고, fgets 함수로 10 bytes 밖에 안되는 buf에 최대 40 bytes만큼 입력받아서 buf2까지 덮어씌워지게 하는 문제. if 문에 있는 strncmp 함수를 보면 buf에 'go'가 있도록 해야 setuid를 얻을 수 있겠죠?

여기서 10bytes씩 나란히 할당했다고 해서 실제 스택에 buf와 buf2가 붙어 있는 건 아닙니다. 실제 스택을 직접 알아봐야 합니다 ! /usr/bin/bof의 코드를 복사하여 tmp 파일에 가서 소스 파일을 만들어 gdb를 사용해 스택을 알아봅시다.

(tmp에서 해야하는 이유는 아마 모든 권한이 사용가능하기 때문에 개발자가 /home/level9/tmp를 만들어 놓은듯 싶습니다!

참고로 현재 주소 /home/level9에서 파일을 만들 수 없습니다.)

tmp => 임시로 파일 저장 ( 권한 없이 누구나 사용 가능 )

출처: https://ssol2-jjanghacker.tistory.com/entry/ftz-trainer1 [ssoL2 TISTORY]

 

test.c 파일이 잘 생성되었군요. 현재 주소는 /home/level9/tmp 입니다.

 

gcc로 컴파일하니 초록색깔 실행파일이 나왔습니다! 그러면 실행파일을 gdb로 확인해볼까유?

gdb test 명령어로 gdb에 들어와서 set disassembly-flavor intel로 선호하는 어셈블리 형태로 변경합니다.

gdb란 ? GNU 소프트웨어 시스템을 위한 디버거로, 프로그램의 내부를 볼 수 있다.
x86 어셈블리 코드에는 at&t 문법과 intel 문법이 존재한다.

 

이제 main 함수를  살펴볼 차례입니다.....

main 함수의 스택이 처음부터 끝까지 출력되는데요, 처음부터 다 해석할 필요가 없는 이유는 buf와 buf2 사이의 간격을 알기만 하면 bof를 일으킬 수 있기 때문입니다. 어셈블리에서는 buf나 buf2 처럼 변수 선언 시 '자 이게 너의 자리이다' 라고 티를 내지 않아요.

그래서 직접 함수 호출 시 인자로 참조될 때 참고할 수 있습니다.

ebp : 현재 스택에 가장 바닥을 가리키는 포인터
esp : 현재 스택의 가장 위에 들어있는 데이터를 가리키는 포인터

 

실제 코드에서 보면 buf는 fgets 함수로 stdin 입력 받습니다.

어셈블리를 보면 <fgets> 함수를 call 하기 이전에 [ebp-40] 위치에 있는 값을 eax에 담고 이 eax를 push 해줍니다.

참고로 어셈블리에서 함수의 인자는 반대 순서로 push합니다.

즉, fgets(buf, 40, stdin) 를 보면, stdin은 push ds:8049698에 해당되구요

40은 push 0x28이며

buf가 lea eax, [ebp-40]에 해당되는 것이죠

정말 인자 순서의 반대로 push 하는 것 보셨죠?

그러면 buf 변수는 ebp-40의 위치해 있음을 알았습니다.

 

다음은 buf2의 변수를 알아보기 위해 <strncmp> 함수를 call 해주기 전을 봅시다.

코드에서 strncmp(buf2, 'go', 2) 라고 되어 있었습니다.

이번에도 인자 순서 반대로 참조하여 push 0x2 하고

'go' 에 해당되는 push 0x804856a하고

마지막으로 lea eax, [ebp-24]를 합니다.

따라서 buf2의 주소는 ebp-24임을 알 수 있습니다.

 

 

이제 최종적으로 정리해봅시다. buf는 ebp-40에 10bytes를 갖고 있으며 buf2는 ebp-24의 위치에서 10bytes를 갖고 있습니다.

이해가 잘 되도록 그림판으로 간단히 스택 구조를 그려봤습니다. 

1. buf는 ebp-40에 위치합니다. 

2. buf2는 ebp-24에 위치합니다.

3. buf와 buf2는 각각 10bytes를 가집니다.

4. 따라서 buf와 buf2의 시작점의 간격은 총 40-24 = 16 bytes이며

buf(10) + 6 + buf2(10) + 14 = 40 이 되는 것입니다.

그러면 buf에 입력할 때 16bytes를 아무거나 입력하고 'go'를 넣어주면 buf2에 'go'로 buffer overflow 되겠죠?

 

저는 작성할 때 쉽게 파이썬 페이로드로 풀었습니다. 

파이썬 페이로드는 stdin과 argv 2 가지로 나뉩니다. 이 문제에서는 표준 입력으로 프로그램이 동작하면서 필요한 내용을 입력받도록 해야합니다. argv는 프로그램 시작 시에 파라미터를 넣는 것을 말하지요.

 

왼쪽 명령어의 결과를 오른쪽에 전달하는 파이프를 이용합니다. 중간에 있는 cat은 python의 결과를 프로그램으로 넘겨주는 역할을 합니다. cat을 사용하지 않는다면 출력한 내용이 가만히 있어 프로그램에 직접 '입력' 되지 않아요.

(python -c 'print ~~~~';cat) | 실행파일명 

 

Good Skill! 이라 뜨며 엔터를 치면 아무것도 안나오는 것을 보니 level10 권한으로 넘어간 것 같습니다.

id 명령어로 확인하니 정답 ! my-pass 명령어로 다음 패스워드까지 얻으면 끝

'challenge > pwn' 카테고리의 다른 글

[FTZ] LEVEL 11 완벽분석  (1) 2021.02.01
[FTZ] LEVEL 10 풀이  (0) 2021.01.29
[FTZ] LEVEL 8 풀이  (0) 2021.01.28
[FTZ] LEVEL 7 풀이  (0) 2021.01.28
[FTZ] LEVEL 6 풀이  (0) 2021.01.28
Comments