FTZ 18 Level
ID : level18
Passwd : why did you do it
접속해서 ls 명령으로 파일과 디렉터리를 확인합니다.
코드를 보면 입력을 받고 x에 하나하나 저장한 후 switch-case문으로 돌리네요.
그리고 check의 값이 0xdeadbeef이면 쉘을 실행해줍니다.
그럼 check와 string의 위치를 알아내기 위해 tmp로 옮기고 디스어셈블 해봅시다.
이 부분이 check와 0xdeadbeef 와 비교하는 구문입니다. check는 ebp-104 겠죠.
그럼 string[count] = x; 이 부분을 찾기 위해서 switch-case 부분을 찾겠습니다.
비교와 점프가 밀집해 있습니다. 여기가 switch-case문인 것 같습니다. 그럼 default일 경우 jmp 0x8048743 을 실행하겠죠? 즉 string[count] = x; 이 코드는 main+499에 위치할 것입니다.
ebp-100. 즉, string[100]의 시작 주소를 eax에 담고 있네요. string은 ebp-100 입니다.
| check | string | SFP | RET |
이런 메모리 구조를 가지고 있겠네요.
실행해서 ABCD를 입력하면
입력한 순서대로 count가 증가하면서
| check |ABCD string | SFP | RET |
이렇게 저장되겠죠.
여기서 A는 string[0], B는 string[1], C는 string[2], D는 string[3]에 위치하게 됩니다. 대충 감이 오시나요? 어떻게 check를 변조해야 할지
포인터와 배열의 본질은 같습니다. Base 주소에 Offset이 추가된 형태로 주소에 있는 값을 참조할 수 있습니다.
ex) *(string+3) == string[3]
이걸 이용해서 &check == *(string-4) == string[-4] 이렇게 나타낼 수 있습니다.
그럼 count를 -4까지 감소하게 만들어야 하는데, case 0x08 일 때, count--; 가 일어납니다.
payload는 0x08 4개 + 0xdeadbeef가 되겠네요. 근데 0xdeadbeef의 값을 리틀 엔디안으로 넣어야 하나 빅 엔디안으로 넣어야 하나 잘 모르실 수 있습니다. 그래서 tmp에서 직접 한번 해보겠습니다.
payload라는 파일을 만들어 실행시킬 때 박아줍니다.
breakpoint를 main+499에 걸어준 이유는 0x08 case를 전부 실행한 뒤 string[count] = x; 부분을 실행시키며 분석하기 위함입니다.
continue를 해주고 x/x $ebp-104를 이용해서 check 값의 변화를 지켜봅시다.
거꾸로 채워지는 걸 볼 수 있습니다. 빅 엔디안으로 실패했으니 리틀 엔디안으로 구성하면 성공하겠네요.
payload : (python –c ‘print “\x08”*4 + “\xef\xbe\xad\xde”’; cat) | ./attackme
원본 파일에 공격해봅시다.
exploit!
감사합니다.
'System&Write up > FTZ' 카테고리의 다른 글
FTZ level20 -> clear Write up (0) | 2017.09.27 |
---|---|
FTZ level19 -> level20 Write up (0) | 2017.09.27 |
FTZ level17 -> level18 Write up (0) | 2017.09.27 |
FTZ level16 -> level17 Write up (0) | 2017.09.25 |
FTZ level15 -> level16 Write up (0) | 2017.09.25 |