[어설픈] 해커스쿨 FTZ level9 문제풀이

2019. 1. 20. 23:32System Hacking/FTZ

안녕하세요! 오늘은 FTZ level 9 

풀이를 해보도록 하겠습니다!


문제의 코드를 보니

아래처럼 적혀있네요!

main 함수 안에

main 함수안에 지역변수로 

buf2가 10바이트 선언되고

buf가 10바이트 선언되네요!


지역변수는 stack에 쌓이는데!

먼저 선언된 순서로 stack에 쌓이게 되니!

buf가 buf2보다 위에 있겠네요!

스택은 높은주소에서 낮은 주소로 쌓이니!

아래처럼요!


<스택 구조>

 [낮은 주소]  buf[10]

buf2[10]

(saved) EBP

[높은 주소] EIP(return address)


그리고 출력을 하네요! 

오버플로우가 가능하다 = it can be overflow

그리고 fgets함수로 사용자로부터 입력을 받네요!

stdin=standard input(표준 입력)으로 40 byte를 입력받아

buf에 저장하네요!


그러면 여기서 왜 overflow가 발생할까요?

1) buf의 크기를 보세요! 몇 byte죠? 10!

2) 표준 입력으로 받아서 buf에 저장하는 데이터는 몇 byte죠? 40!

그릇의 크기가 10인데 40을 담죠!

그러면 나머지 30은 어디에 담길까요?

바로 뒤에 있는 장소에 담기겠죠!


이 상태에서 바로 밑에 있는 

코드를 보면, strncmp를 하네요!

문자를 비교한다= string compare!

buf2 와 문자열 go를 앞에서부터 2글자!

buf2의 앞에서 두 글자와, 문자열 go의 두 글자!

strcmp은 비교문자가 같으면 0이 나오거든요!

그래서 같으면 good skill이라고 출력!


setuid 함수원리는 정확히는 모르겠지만

level10으로 권한상승시켜주고

level10의 쉘이 떨어지네요!



자 일단 가서! 봅시다!

/usr/bin 폴더로 가서!

bof를 실행시키고

a를 12개 넣었어요!

왜냐? 


위의 스택구조에서 buf아래에 바로 buf2니까

buf를 10글자로 채우고

 그 이후부터 입력은 buf2에 입력되니까요!

즉 buf에 a 10글자 + buf2에 a 2글자 넣으면

buf2 앞에 2글자가 

aa가 되니까요!


물론 buf2의 2글자가 go여야지 

문제가 풀리지만 

일단은 실험용으로 다른 값을 넣어보고

반응을 살펴봤습니다!

근데 저는 일단 해당 소스를 컴파일하고

gdb로 분석해보고 싶어서

hint에 있는 소스코드 긁어와서

tmp 파일로 이동해서 vi 9.c 

파일을 생성하고


아래와 같이 소스를 붙여넣었습니다!

나와서 gcc로 -g -o 설정주고 컴파일을 해서

9라는 파일이 생성 될걸 확인하였고,

저는 이것을 바로 gdb로 분석해보기로 하였습니다!


뭐 시작에는 프롤로그가 있죠

push %ebp 

mov %esp, %ebp


%가 있으면 intel 방식이 아니라 

왼쪽에서 오른쪽으로 진행되요!


sub $0x28, %esp

0x28만큼 스택공간을 

ebp 주소에서 빼서

지역변수와 다른 것들을 사용하기 위해

할당한 건데, 

공학용 계산기로 돌려보면

Hex(16진수) 28은 = 40이네요!

 20 바이트만 할당해도 되는데 

buf,  buf2가 각각 10이니까요..

왜 40을 했을까????

흠...


어찌 됐든, 저희는 buf2의 시작주소

buf의 시작주소를 알아내면 문제는 쉽게 풀립니다!

여기서 저는 이렇게 풀었습니다!

buf의 주소는 fgets의 인자로 넘어가고

buf2의 주소는 strncmp의 인자로 넘어가기에

그때를 딱 포착하기로 했습니다!


원래 함수를 call 하기 이전에 

함수의 인자들을 push 하거든요!

함수인자는 역순으로 push 돼요!


fgets(buf,40,stdin)이면

stdin이 제일먼저 push 

40이 다음 push

buf가 마지막으로 push


fgets <main+47> 에서 마지막으로 push되는 eax

0xffffffd8의 값을 갖고 있구요!

strncmp <main+69> 에서 마지막으로 push되는 것도

eax인데 이 값의 경우

0xffffffe8이네요!


그러면 다 나왔네요!

0xffffffe8-0xffffffd8=하면 두 버퍼간의 거리!

그 거리만큼 채워주고 바로 그 뒤에 go를 넣으면

문제가 풀리겠네요!

공학용 계산기에서  16진수

e8-d8하니까 = 16(10진수) 나오네요!

즉 buf의 시작 지점과 buf2의 시작 지점 

사이는 16byte!


그래서 일단 제가 아까 컴파일한 

9를 실행시키고 16글자 a+go를 입력하니

아래와 같이 good skill!이 뜨네요!

이제 이걸 원래 프로그램가서 실행시키면 문제가 풀려요!!

근데 이 방법 말고도 좀 야매로 푸는 방법도 있어요!

어차피 buf와 buf2 사이에 공간을 모르니

일단 시도를 계속 해보는거죠!


왜 멍청하게 시도하는데?!

어차피 처음에 ebp에서 40만큼만 빼서

buf buf2가 각각 10 바이트인데 

일일이 손으로 해봐도 풀릴 것 같아서요 ㅎ


그래서 계속 시도하다 보니 아래와 같이

4번째 시도에서 아래와 같이 성공이 뜨네요!

사실 더 야매인 방법은 계속 go를 넣는거죠! 

"어차피 go가 buf2 자리에 들어가야하는데

어딘지 모르니 그냥 모든 공간을 go로 채우자"

라고 생각해서 go만 주구장창 떄려박으면 풀리죠 ㅎㅎ


어쨌든 이렇게 문제를 풀어보았고 

오늘도 고생하셨습니다!