hint를 확인했다. 지난번과 비슷하지만 조금 다르다.
attackme 파일의 내용이 아닐까 생각한다.
먼저 코드의 내용을 분석해보자
char 유형으로 356byte의 배열을 선언했다.
setreuid 함수를 사용하여 level13의 권한을 부여했다.
printf 함수를 사용하여 "문장을 입력하세요."를 출력한다.
gets 함수를 사용하여 문자를 입력받는다.
printf 함수를 사용하여 입력받은 문자열을 출력한다.
여기서 문제가 발생할 수 있는 지점은 gets 함수이다.
입력값의 길이 제한을 두지 않기 때문에 오버플로우가 발생할 수 있다.
gdb 함수를 사용하여 attackme 파일을 분석해보자.
esp 레지스터에 264byte(0x108)가 할당되어있다. 256을 제외한 8byte는 더미일 것이다.
esp에 해당하는 8byte가 할당되어있다. 이에는 주소가 저장되어 있을 것이다.
serteuid를 call하며 1345135(0x804835c)는 setuid의 주소이다.
eax에 ebp-264의 주소를 저장한다.
eax를 push하고 gets 함수를 call한다.
str의 영역이 264byte로 잡혀있으니 level11과 동일하게
["A"*268 + 쉘코드 환경변수의 주소값 ]으로 문제를 풀 수 있을 것 같다.
* 어셈블리 레지스터
- eax: 사칙연산 등 산술 연산에 자동으로 사용되며 함수의 반환값을 처리할 때도 사용됨
- esp: 현재 스텍의 가장 위에 들어있는 데이터 가리키는 포인터
- ebp: 스택프레임의 시작주소가 저장. 현재 스텍프레임 동안 절대로 값이 바뀌지 않음 (바닥)
- eip: 다음에 실행할 명령어의 주소를 가짐. 현재 명령어 종료되면 eip 레지스터 명령어 실행됨
- sfp: 스택프레임을 거쳐 함수가 돌아가야 할 위치를 저장해둔 포인터
attackme를 tmp에 복사했고 복사된 것을 확인한 후에
SHELL이라는 이름으로 환경변수를 설정했다.
이번에도 혹시모를 오류를 방지하기 위해 처음부터 쉘 환경변수로 설정해두었다.
SHELL 환경변수의 주소값을 알기위해 test.c 코드를 작성하였고
컴파일 후 실행하여 주소값을 알아낼 수 있었다.
여기서부터 이전 문제와 동일하게 풀었더니 오류가 발생했는데
프로그램을 실행하면 gets가 쉘 코드를 읽고 쉘 코드가 실행될 때 사용자의 입력을 대기해야하는데
이를 하지 않고 바로 종료되어 내가 원하는 명령을 쓰지 못하고 종료된다.
그래서 |과 cat을 사용하여 입력한 값을 쉘에게 바로 넘겨주는 방식으로 해야한다는 것을 알 수 있었다.
괄호로 묶어주는 이유는 python -c ~를 실행 후 cat|./attackme 로 넘어가는 순서이기 때문에
이를 묶어서 바로 실행시켜주기 위함이다.
위에 설명한것에 SHELL변수의 주소를 대입하여 페이로드를 작성하여
공격하였으나 실패했다. str 의 크기는 268byte 인데 258이라고 작성했다.
왜그래 ?
제대로 작성하여 공격에 성공하였다.
지난번 문자와 유사한 부분이 많아 비교적 쉽게 풀 수 있었다.