11탄은 golem이다. 코드를 살펴보자. golem 프로그램의 특징은 다음과 같다. 1. 인자값이 2개 이상일 것2. 2번째 인자값은 48번째 값이 \xbf이어야 함3. 2번째 인자값을 buffer 변수로 strcpy로 복사4. buffer 변수에 저장된 값들을 전부 0으로 초기화.5. buffer+48부터 0xbfffffff 까지 0으로 초기화. 즉 RET 값을 제외한 buffer 이후의 값들은 전부 0으로 초기화 하는 것이다. 여기서 LD_PRELOAD 를 사용하라는 조언을 받아 해당 용어를 찾아보았다. LD_PRELOAD는 공유 라이브러리의 위치를 저장하는 환경변수 이름이다. 그렇다면 공유 라이브러리를 활용해서 이 문제를 공격해야 한다는 것을 알 수 있다. 공유 라이브러리는 스택 영역이 아닌 공유..
우선 코드를 살펴보도록 하자. 우선 코드를 분석하면서 지켜야할 규칙에 대해 분석해보도록 하자. 1. 인자값이 2개 이상인가 (argc < 2) 2. 환경변수 사용 X (egghunter) 3. argv[1]의 길이가 48보다 클 경우 프로그램 종료 (check the length of argument) 4. buffer[40] 변수를 이용한 공격 무효 (buffer hunter) 5. 모든 argv의 값들 초기화 (ultra argv hunter) 인자값들과 변수를 이용한 공격을 무효화 시키게 되었다. 그렇다면 메모리에 쉘코드를 저장할 수 있는 공간이 어디 있는지 생각을 해보았다. 모든 프로그램은 메모리의 맨 마지막 부분에 여러 환경변수들과 해당 프로그램에 대한 정보를 저장하고 있다는 점을 착안하여 es..
우선 코드를 살펴보도록 하자. 여러 검사 기능들이 사라지고 1가지가 추가 되었다. 바로 argv[1]에서 [46]번 인덱스에 \xff가 들어가면 printf를 수행하지 않고 종료가 되도록 설정 되었다. 이러한 점을 피하여 strcpy 까지 접근 하여야 버퍼 오버플로우를 일으킬 수 있는 상황이 된다. 평소에 접근하는 메모리 주소값들이 전부 0xbfff~~~~이런 식으로 접근하였는데 스택에 메모리가 구성되는 점을 이용하여 문제를 해결해야 한다. 스택에는 사전에 선언된 변수에 대하여 저장이 되는데 그 위에는 argv에 대한 공간이 구성되어 있다. 따라서 argv의 값을 매우 긴 값을 넣게 된다면 쉘코드를 넣게 될 argv나 buffer에 대하여 메모리 주소가 0xbfff~~~~를 벗어날 수 있게 된다. 문제를..
우선 troll.c의 내용을 살펴보도록 하자. 내용을 살펴보면 이전내용을 유지한 채로 1가지 추가조건으로 인자값을 2개로 제한했다는 것을 알 수 있다. 따라서 argv[2]에 쉘코드를 심어서 진행할 수 없음을 알 수 있다. 이때의 공격 방법은 심볼릭 링크를 사용하여 argv[0]을 쉘코드를 심도록 하는 것이다. 이때 ln -s 명령어를 사용해야하는데 평소에 쓰던 25bytes 쉘코드를 사용할 경우에는 \x2f가 담긴 쉘코드를 사용하면 안된다. 왜냐하면 /로 인식하여 하위디렉토리를 찾기 때문이다. 따라서 \x2f가 들어있지 않은 쉘코드를 찾았다. \xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\x..
3탄의 코드를 살펴보도록 하자. gets로 직접 입력을 받는다. 하지만 문자길이에 대해 체크하지 않기때문에 여기서 버퍼 오버프롤우가 일어날 수 있게된다. 변수의 사이즈를 고려하여 직접 쉘코드를 덮어씌우는건 힘들것으로 추측되어 환경변수에 쉘코드를 저장하고 RET의 값을 쉘코드의 주소로 덮어씌우는 것을 목표로 한다. 스택의 사이즈가 16인 것을 보면 더미가 존재하지 않는 것을 알 수 있다. 따라서 buf[16]+SFP[4]+RET 로 이루어진 것을 추측할 수 있다. 환경변수에 등록한 쉘코드에 대한 주소를 확인해보자. 0xbffffee7인 것을 확인했으므로 RET의 위치에 해당 값을 덮어씌워주면 된다. 공격에 성공하여 다음단계로 넘어갈 수 있게되었다.
1단계씩 몬스터를 쓰러트리면서 던전을 클리어 하는 TheLordOfBOF - BOF 원정대 워게임이다. 우선 문제에 대해서 확인해보자. strcpy 에서 문자열 길이에 대한 검증을 하지 않았으므로 버퍼 오버플로우를 일으킬 수 있는 기초적인 문제였다. 우선 gdb로 메모리 구성을 살펴보도록 하자. 스택의 메모리 확보량이 정확히 256으로 더미가 존재하지 않는다. 따라서 버퍼 오버플로우 공격을 해보도록 하겠다. 환경변수에 shellcode를 등록한 후 gremlin에 대하여 환경변수가 위치하는 메모리 주소를 알아보았다. 스택의 구조는 buf[256] + SFP[4] +RET로 구성되어 있으므로 260바이트를 다른 값으로 적은 다음 RET 주소를 쉘코드가 위치한 주소로 덮어씌워주면 된다. ./gremlin `..
level20이 마지막이다. 힌트를 확인해보도록 하자. fgets 함수를 사용하여 입력문자 제한을 두었다. 따라서 버퍼 오버플로우 공격은 힘들거라 예상할 수 있겠다. 하지만 printf 함수에서 서식문자를 사용하지 않고 바로 출력하였기 때문에 bleh 변수를 이용하여 포맷스트링 공격을 할 수 있을 것으로 예상이 된다. 서식문자를 사용하지 않고 직접 출력을 하게 된다면, 만약 bleh 변수에 서식문자를 입력하였을 경우 esp부터 요구되는 사이즈만큼 자동으로 참조를 하면서 메모리를 참조할 수 있게된다. %x는 4바이트씩 참조하기 때문에 4바이트 단위로 이동할 수 있는 수단이 된다. %n이라는 서식문자는 printf에서 출력된만큼 10진수로 저장하는 서식문자이다. 이 서식문자를 통해서 메모리에 RET주소를 쉘..
level16의 힌트를 읽어보도록 하자. call 함수 포인터가 printit 함수를 가리키고 있기 때문에 Hello there 이라는 문자를 출력하는 프로그램이 되었다. 우리는 fgets 함수를 통하여 버퍼 오버플로우를 일으켜 call 함수 포인터가 가리키고 있는 주소를 shell() 함수의 주소값으로 변경하여야 한다. 여기서 스택의 용량이 56바이트로 구성되어있다는 것을 알 수 있고 함수 포인터인 call은 ebp로부터 16바이트 떨어진 곳에 있다는 것을 main+36을 통해 알 수 있다. 즉 buf의 시작부터 40바이트 떨어진 곳에 있으므로 해당 위치에 shell() 함수의 주소인 0x080484d0로 덮어 씌우면 완성이다. $(python -c 'print "A"*40+"\xd0\x84\x04\x..
level14에 들어와 힌트부터 확인을 하자. check 변수에 대해 직접 입력하는 구간이 없다. 따라서 우리는 버퍼 오버플로우를 이용해 check 값을 0xdeadbeef로 변경하여야 한다. 우선 디스어셈블을 수행하였다. main+29 를 통하여 check의 값은 ebp로부터 16만큼 떨어져 있는 것을 알 수 있었고 buf 변수는 ebp로부터 0x38(56) 만큼 떨어져 있는 것을 main+3을 통해 알 수 있다. 따라서 buf에서 40byte만큼 값을 입력한 후에 0xdeadbeef를 입력해주면 공격은 성공하게 된다. $(python -c 'print "A"*40+"\xef\xbe\xad\xde"'; cat) | ./attakme 라는 형식으로 공격할 수 있다.
level13으로 로그인을 하여 힌트를 우선 읽어보자. 본 문제는 스택가드에 관련된 문제이다. 스택가드는 버퍼 오버플로우를 방지하기 위한 방어 방법의 하나로, 레벨12의 문제를 예로 들어보자. buffer(256bytes) + dummy(8bytes) + SFP(4bytes) + RET(4bytes)를 덮어 씌워 버퍼 오버 플로우를 일으키는 공격이었다. 하지만 여기에 스택가드를 추가하여buffer(256bytes) + stackguard(4bytes) + dummy(8bytes) + SFP(4bytes) + RET(4bytes)로 구성하게 되었을 때 이미 저장되어있는 스택가드에 대하여 값이 변동이 있다면 버퍼 오버플로우가 발생했다는 것을 쉽게 감지할 수 있으므로 버퍼 오버플로우에 대해 방어를 할 수 있게..