본문 바로가기

리눅스34

해커스쿨 F.T.Z level 11 FSB(Format String Bug) level 11을 이미 BOF로 해결했다. level 20에서 포맷 스트링 버그를 다루기 때문에 level 20을 해결하고 포맷 스트링 버그 복습 차원으로 level 11에는 링크로 남겨두었던 포맷 스트링 버그도 발생하기에 BOF가 아닌 포맷 스트링 버그를 사용해서 해결해 보기 위해 level 11에서 포스팅 하지 않고 level 20을 해결 하고 포스팅한다. FSB를 level 20에서 이해한 만큼 설명했으므로 바로 문제로 넘어간다. level 11 로그인 후 hint를 본다. level 20과 같이 level 11에서도 printf 함수에서 포맷 스트링을 사용하지 않았기 때문에 여기서 FSB가 일어나게 된다. 포맷 스트링을 입력해본다. 포맷 스트링을 입력하게 되면 메모리의 다음 4바이트 위치를 참조하.. 2020. 3. 3.
해커스쿨 F.T.Z Level 20 level 20 로그인 후 hint를 본다. bleh 배열 80byte, fgets에서 79byte를 받는다. BOF를 할 수 없는 조건이다. 다른 방법을 찾으면 level 11에서 링크로 대체했던 포맷 스트링 버그(FSB)를 발생시킬 수 있다. 포맷 스트링 버그(Format String Bug, FSB) 포맷 스트링 버그는 printf 함수에서 발생하는데 printf 함수를 사용할 때 포맷 스트링을 사용하지 않고 위 hint와 같이 print(bleh)를 사용하면 취약점이 일어난다. 이때 입력 값을 포맷 스트링으로 넣으면 입력 값을 문자로 취급하는 게 아닌, 서식문자로 취급한다. 포맷 스트링(Format String) parameter 변수 형식 %d 정수형 10진수 상수 (int) %f 실수형 상수 .. 2020. 3. 2.
해커스쿨 F.T.Z Level 19 level 19 로그인 후 hint를 본다. level 18에 비해 코드가 엄청나게 간단해졌다. 그러나 간단해져도 너무 간단해졌다. 사용자를 바꾸는 setreuid 함수까지 없는 간단한 코드가 되어서 level 11에서 만들었던 쉘코드만으로는 해결할 수가 없다. level 11 쉘코드로 실행하면 사용자 변경 없이 그냥 쉘코드가 실행된다. level 19 hint와 같이 글로 준 hint를 합쳐 생각하면 setreuid를 실행하는 쉘코드를 만들어 이전 쉘코드와 함께 사용하면 된다. setreuid 쉘코드 사용자 ID를 바꾸는 setreuid 함수의 인자로는 사용자 ID에 해당하는 uid이다. 쉘코드를 만들기 위해서는 얻고 싶은 ID의 uid를 알아야 한다. level 20의 uid는 3100이다. 인자를 .. 2020. 2. 29.
해커스쿨 F.T.Z Level 18 level 18 로그인 후 hint를 본다. 엄청나게 긴 hint가 나온다. 코드가 긴 만큼 gdb 분석도 길어서 겁먹기에 십상이다. 모르는 함수들이 많고 코드가 길어도 시스템 해킹에서는 언제나 "root의 권한으로 쉘을 실행시킨다"라고 생각하면 쉽다. 위와 같이 생각하고 코드를 보게 되면 변수들이 선언되고 변수 check 값이 0xdeadbeef면 shellout 함수가 실행되는 아주 간단한 코드가 된다. 여기서 알아야 할 것은 "먼저 선언된 변수가 높은 메모리 주소를 가진다"는 것이다. 이것을 알면 스택 구조도 쉽게 파악할 수 있다. 스택 구조를 보게 되면 아래와 같다. 스택 구조 fds 4byte count 4byte x 4byte check 4byte string[100] 100byte SFP 4.. 2020. 2. 29.
해커스쿨 F.T.Z Level 17 level 17 로그인 후 hint를 본다. level 16 hint 코드에서 shell 함수가 빠지고 setreuid는 main으로 들어오게 됐다. 이렇게 되면 level 16처럼 shell 함수의 주소도 없고 level 14처럼 글자를 대조하는 것도 아니고 level 15처럼 주소를 넣는 것도 할 수 없다. 여기서 해야 하는 건 setreuid가 실행되고 쉘을 실행해야 level 18의 uid를 얻을 수 있다는 것이다. 일단 gdb를 확인해 본다. main+3에서 0x38(56)byte 확보하고 main+6에서 0x8048490 주솟값을 ebp-16에 저장한다. main+57에서 ebp-16을 eax에 저장하고 eax를 call 해서 call 함수를 불러온다. 코드는 다르지만, 프로그램의 메커니즘은 .. 2020. 2. 27.
해커스쿨 F.T.Z Level 16 level 16 로그인 후 hint를 본다. level 16에서는 함수를 선언해 main에서 함수를 불러 실행한다. hint에서는 shell 함수가 사용되지 않고 있고 printit 함수만 사용된다. 이 정도만 봐도 hint는 대충 파악이 될 것으로 생각한다. 이제 gdb를 열어본다. gdb에서 중요한 것은 main+3, main+6, main+36, main+39다. main+3에서 0x38(56)byte를 확보 후 main+6에서 0x8048500 주솟값을 ebp-16에 저장한다. main+36에서 ebp-16을 eax에 저장하고 main+39에서 call 한다. gdb를 보고 프로그램을 실행하면 0x8048500의 주소에 무슨 데이터를 가졌는지 알 수 있다. "Hello there!"가 나오는 거로.. 2020. 2. 27.
해커스쿨 F.T.Z Level 15 level 15 로그인 후 hint를 본다. level 14와 같은 코드지만 "int *check" 변수 check의 변수가 포인터로 쓰여있다. 이것은 변수 *check가 가리키는 주소에 0xdeadbeef가 들어있는지 봐야 한다. C 코드 분석은 level 14에서 했으므로 생략하고 gdb를 열어본다. main+3에서 0x38(56)byte만큼 공간을 확보하고 main+17에서 ebp-56의 주소를 eax에 넣은 뒤 fgets 함수를 call 한다. main+29에서 ebp-16의 주소를 eax에 넣고 그 결과를 main+32에서 0xdeadbeef와 비교한다. 이 사이에 *check 변수의 주소를 찾아 먼저 넣어주면 BOF가 일어나게 된다. 여기서 level 14와 같은 크기로 ebp-56에서 비교문.. 2020. 2. 26.
해커스쿨 F.T.Z Level 14 level 14 로그인 후 hint를 본다. 위 hint를 분석하면 아래와 같다. C 코드를 분석하고 gdb를 열어본다. gdb를 보면 0x38(56)byte만큼 공간을 확보하고 ebp-16에 0xdeadbeef를 저장한다. 이렇게 보면 level 13과 똑같이 분석할 수 있다. 확보한 공간보다 -16에 0xdeadbeef를 저장한다고 생각하면 쉽다. fegts으로 입력을 받고 있으니 level 12와 같이 pipe를 이용해 명령을 넣어 줘야 한다. 더보기 level 13문제와 비슷해서 쉽게 느껴질 수도 있다. 그래서 0xdeadbeef는 40byte 이후에 저장한다. 여기서는 코드에서 쉘을 실행시켜줘서 주소를 구할 필요는 없다. 공격 코드만 크기에 맞게 만들어 주면 되는데 도식화하면 이렇게 된다. 56.. 2020. 2. 24.
해커스쿨 F.T.Z Level 13 level 13 로그인 후 hint를 본다. level 11, level 12와 비슷하다. BOF에 취약한 strcpy 함수가 있다. hint를 분석하면 위와 같다. strcpy는 복사할 때 크기를 검사하지 않기 때문에 BOF에 취약하다. 이제 BOF를 일으켜야 하는데 level 11과 level 12와 다른 점은 변수 i로 BOF가 일어나는지 확인하는 보안코드라고 볼 수 있다. 하지만 너무 단순한 보안코드이다. gdb로 attackme를 분석해 프로그램이 어떻게 돌아가는지 본다. 처음 0x418(1048)byte만큼 공간을 확보하고 ebp-12에 0x1234567을 저장한다. 확보한 공간보다 -12에 변수 i를 저장한다고 생각하면 쉽다. 더보기 그렇다면 1036byte 이후에 변수 i가 저장된다. 변수.. 2020. 2. 24.
해커스쿨 F.T.Z Level 12 level 12 로그인 후 hint를 본다. level 12는 level 11과 비슷하지만 여기서는 gets 함수가 나왔다. gets 함수도 strcpy와 같이 BOF에 취약하므로 BOF를 일으켜야 한다. level 11과 다른 점은 level 11에서는 인자로 받았지만, level 12에서는 gets 함수로 입력받는다. level 12에서는 포맷 스트링 버그는 없다. 다른 건 이것밖에 없고 str 256byte, dummy 8byte까지 같다. gets 함수로 입력 전달 방식이 바뀌었으므로 어떻게 입력을 넘겨줘야 할지 생각해야 한다. pipe( | ) pipe란 2개의 프로세스를 연결해주는 연결 통로를 의미한다. 앞에 실행한 명령어의 출력 결과를 뒤에 실행하는 명령어의 입력 값으로 넣어준다. 앞의 출력.. 2020. 2. 23.