Sqix

FTZ Level18 본문

Wargame/FTZ

FTZ Level18

Sqix_ow 2018. 7. 20. 12:13


소스코드가 꽤 긴데, 여기서는 fd를 이용해서 input을 받아왔습니다.


크게 어려울 건 없네요. fd_set 구조체를 FD_ZERO 매크로로 초기화하고 FD_SET을 이용해서 STDIN_FILENO(0) 소켓번호를 fds에 추가합니다.


select 함수를 이용해서 fds를 감시하도록 하였고(FD_SETSIZE, &fds만 argument로 있으므로, io stream 다중화라기보단 fds 감시 목적인 것 같습니다)


FD_ISSET(fileno(stdin),&fds)을 통해서 fds가 표준입력으로 정의된 경우에만 read함수를 이용해서 사용자 입력을 받도록 하였습니다.


즉, exploit을 짤 때 C 소스에 대해서 크게 고민할 필요 없이 표준입력을 넣으면 되는 상황입니다. 


결국 untrusted input에 영향을 받는 경우는 switch문 안의 case, default뿐이라는 결론이 나왔습니다. 


다시 원점으로 돌아와서 shellout 함수를 실행시키려면 check를 0xdeadbeef로 만들어야 합니다.


변수들을 보면 100bytes의 string, check, x, count 각각 4 bytes씩 12 bytes, fd_set 구조체 32bytes로 총 144 bytes를 생성합니다.


string - check - x - count - fd_set 순서대로 스택에 들어가겠네요.


입력은 x에 들어오고, 우리는 check를 덮어야 합니다. 여기어 untrust input에 영향을 받는 것은 count와 그 count에 영향을 받는 string이죠.


일단 어셈블리를 정확히 읽어서 dummy의 위치를 파악해야 합니다.


0x0804855c <main+12>: mov    DWORD PTR [ebp-108],0x0

0x08048563 <main+19>: mov    DWORD PTR [ebp-112],0x0


-> x의 위치는 ebp - 8, count의 위치는 ebp - 112입니다.


0x080485ab <main+91>: cmp    DWORD PTR [ebp-104],0xdeadbeef


-> check의 위치는 ebp - 4입니다. 따라서 check와 string 사이에는 dummy가 없습니다. 

스택은 대략 이런식으로 구성되어 있겠네요.

[ string 100 ] [ check 4 ] [ dummy 4 ] [ x 4 ] [ count 4 ] [ dummy ] [ fd_set ] [ SFP ] [ RET ]

이제 저 input을 가지고 어떻게 check에 접근을 할 것이냐가 문제인데, 우리는 count를 이용할 것입니다.

string[count]는 *string + count라고 생각할 수 있습니다. 즉, count에 -4를 넣어 주면 check로 접근할 수 있습니다.

따라서 입력에서 0x08을 4번 넣고 0xdeadbeef를 넣어 주면 성공적으로 exploit할 수 있을 것이라고 생각합니다.

exploit code : (python -c 'print "\x08" * 4 + "\xef\xbe\xad\xde"'; cat) | ./attackme




성공!


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

FTZ All Clear!  (0) 2018.07.21
FTZ Level19  (0) 2018.07.21
FTZ Level17  (0) 2018.07.20
FTZ Level16  (0) 2018.07.20
FTZ Level15  (0) 2018.07.10
Comments