level19로 로그인한 후 hint를 확인해보면 소스코드가 나온다. 전 단계에서 많은 양의 코드를 보여줬기에 19 level은 더 많거나 복잡할 줄 알았지만 예상보다 간단했다. 소스코드도 작고 대놓고 gets 함수가 보여서 bof가 일어남을 알 수 있다. 공격은 gets를 통해 overflow를 일으켜 ret를 쉘 코드가 들어간 환경변수의 주소로 변조하면 될 것 같다. 이번 단계는 setuid가 없기 때문에 setuid가 포함된 쉘 코드를 써야겠다. main의 함수 프롤로그 부분과 gets 함수 부분에 bp를 걸고 실행한다면 ret와 buf의 스택 주소를 알 수 있다. ret : 0xbffff45c buf : 0xbffff430 따라서 ret와 buf 사이의 거리는 44byte인 것을 알 수 있다. r..
Wargame/FTZ
level18로 로그인하고 힌트를 보면 굉장히 긴 코드가 나온다. 다른 level에 없던 긴 코드에 조금 쫄았으나, 취약점은 굉장히 간단하다. #include #include #include #include void shellout(void); int main() { char string[100]; int check; int x = 0; int count = 0; fd_set fds; printf("Enter your command: "); fflush(stdout); while(1) { if(count >= 100) printf("what are you trying to do?\n"); if(check == 0xdeadbeef) shellout(); else { FD_ZERO(&fds); FD_SET(..
level17로 로그인한 후 hint 파일을 확인해보면, 역시 소스코드가 주어져 있다. level16과 마찬가지로 call에 printit가 들어가고 fgets를 통해 overflow가 일어나는데, 이번에는 shell을 얻게 해주는 함수가 없다. shell을 얻게 해주는 함수가 없으므로 쉘 코드를 환경변수에 삽입한 뒤 주소를 구한 뒤, stack overflow를 통해 call의 값을 쉘 코드가 들어간 환경변수의 주소로 변조해주면 될 것 같다. export 명령어로 쉘 코드를 환경변수에 등록한 뒤 미리 빌드해둔 tmp 폴더 내 env 파일을 실행해서 쉘 코드가 들어 있는 환경변수의 주소를 구했다.(앞에 \x90을 추가해준 이유는 \x90 없이 쉘 코드만 넣어준다면 제대로 쉘이 얻어지지 않기 때문이다.) ..
level16으로 로그인한 후 hint 파일을 확인하면 마찬가지로 소스코드가 주어져 있다. 이번에는 shell을 얻게 해주는 shell 함수가 있어서 ret overwrite인가 했는데, 그게 아니라 bof를 통해 call 포인터의 값을 shell 함수의 주소로 변조하는 것이었다. 소스코드를 확인해보면 void형 포인터 변수 call에 printit 함수의 주소를 넣어주는데, 프로그램의 마지막에서 이 call에 들어 있는 주소의 함수를 실행해 준다. 참고로 이 printit 함수는 "Hello there!\n"를 출력시켜주는 기능을 한다. 마찬가지로 fgets 함수로 buf의 크기보다 큰 48byte 입력을 받는데, 여기서 buf의 크기는 20byte이므로 28byte의 overflow가 일어난다. 이를..
level15로 로그인한 후 hint 파일을 확인하면 level14의 힌트 코드와 비슷한 코드가 나온다. 다른 점은 0xdeadbeef와 비교하는 대상이 check의 값이 아닌 포인터를 써줘서 check의 값이 가리키는 주소의 값이다. 마찬가지로 buf의 크기는 20이지만 fgets 함수를 통해 45byte만큼 입력을 받기 때문에 25byte overflow 된다. 원래는 hint 파일의 소스 코드를 복사해 tmp 폴더에서 새 파일을 빌드하고 디버깅했지만, 이번 문제의 경우 주소가 굉장히 중요하므로 똑같은 환경에서 분석하기 위해 cp 명령어로 문제 파일을 tmp 폴더에 복사했다. (처음에는 멋모르고 복사해서 새로 빌드했다가 주소 값이 안 맞아 exploit에 난항을 겪었다) gdb를 통해 buf와 che..
level14로 로그인한 후 hint 파일을 확인해보면 마찬가지로 attackme의 소스코드가 나온다. 딱 봐도 char형 배열인 buf의 크기가 20이지만 fgets 함수로 45byte만큼 입력을 받기 때문에 stack buffer overflow가 일어난다. fgets 아랫줄에서 check 변수의 값이 0xdeadbeef라면 쉘을 얻게 해 주는데, check 변수의 값은 0xdeadbeef가 아니므로 정상적인 입력으로는 쉘을 얻을 수 없다. 하지만 fgets 함수를 통해 buf에서 bof가 일어나므로 check의 값을 변조해 0xdeadbeef로 만들어 쉘을 얻을 수 있다. 일단 문제 파일은 디버깅이 불가능하므로 소스 코드를 복사해서 tmp 폴더에 파일을 빌드하고 gdb로 열었다. fgets 함수 호..
level13으로 로그인 후 hint 파일을 확인해보면 마찬가지로 소스코드가 주어진다. 확인해보면 인자 값을 1024 크기의 char형 배열 buf로 strcpy 함수를 이용해 복사하는데, 문제는 strcpy 함수가 bof에 취약한 함수라는 것이다. 이를 통해 stack buffer overflow를 일으켜 ret를 쉘 코드의 스택 위치나 환경 변수의 주소로 변조한다면 쉘을 얻을 수 있을 것이다. 하지만 문제는 ssp 보호기법의 canary와 비슷한 로직이 존재하다는 것이다. i에 0x1234567을 넣고 마지막 함수를 끝내기전에 i의 값이 그대로인지 검사하는데, 만약 bof를 일으켜 더미 값을 채워 ret를 조작하려 시도한다면, buf와 ret 사이에 있는 i를 변조하게 돼 canary 검증 로직을 통..
level11과 비슷하게 로그인 후 ls 명령어를 통해 파일 들을 확인해보면 setuid가 걸린 파일 attackme와 hint가 존재하는 것을 알 수 있다. hint에는 attackme의 소스코드가 들어있다. 딱 봐도 알 수 있듯이 bof에 취약한 함수 gets를 쓴다. 입력을 받는 변수는 256byte 크기의 char형 배열 str이지만 gets 함수는 입력 값의 길이를 제한해주지 않기 때문에 256byte 넘는 입력 값을 준다면 stack bufferoverflow가 발생할 것이다. 마찬가지로 쉘을 얻게 해주는 함수가 없으므로 환경 변수에 쉘 코드를 넣고 ret를 해당 환경 변수로 overwrite하는 방법으로 exploit하면 될 것 같다. ret와 str 배열의 거리를 확인하기 위해 hint에 ..
level 10에서 얻은 패스워드로 로그인한다면 setuid가 걸려있는 attackme 파일과 hint 파일을 볼 수 있다. hint 파일을 확인해보면 bof에 취약한 strcpy를 통해 인자 값을 str 변수에 복사하는데, 이 str 변수는 256 크기다. strcpy 함수를 사용하기 때문에 bof 공격을 하면 될 것 같고, 쉘을 얻게 해주는 함수가 따로 없으므로 shellcode를 이용하면 되겠다. 일단 bof 공격이 통하는지를 확인하기 위해 인자로 더미 값을 256byte 넘게 주었다. 그러니 Segmentation fault가 발생한 것을 알 수 있다. bof 공격이 맞는 것 같다. 권한 문제 때문에 attackme 파일은 gdb로 디버깅 할 수 없으므로 tmp 폴더에 소스 코드를 이용해 똑같은 ..
Level9에서 얻은 패스워드를 이용해 level10으로 로그인하면 hint 파일과 program 디렉터리가 존재한다. hint 파일을 cat 명령어로 읽어보니 공유 메모리(key_t : 7530)를 이용해 두 명의 사용자가 대화를 나누고 있는데, 주어진 키 값을 이용해 대화를 도청한 후 권한을 얻는 것이 목적이다. 처음에는 리눅스 공유 메모리의 존재를 몰랐기에 level10 폴더에 존재하는 program 디렉터리에 들어가려 하거나, find 명령어로 level11로 Setuid가 걸린 파일을 찾았다. 하지만 보이지 않았고, 몇 번 삽질을 하다 힌트에 나와있던 공유 메모리를 구글링해봤다. 공유 메모리란 여러 프로그램이 사용할 수 있는 메모리로, key 값을 통해 메모리를 읽을 수 있다. #include ..