FTZ란 Free Training Zone의 약자로 hackerschool에서 배포하는 워게임입니다.
총 20문제로 구성되어 있으며 각 문제를 격파하여 다음 레벨의 패스워드를 얻는 형식입니다.
문제를 격파하고 다음 레벨의 bash를 획득하였다면 my-pass로 패스워드를 확인할 수 있습니다.
사용 linux 명령어
ls - 파일 내역 출력
cat - 파일 내용 확인
cp - 파일 또는 디렉터리 복사 명령
gdb - 디버깅 도구
send me email if you have any questions.
FTZ Level 16
ID : level16
PASSWD : about to cause mass
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
void shell() {
setreuid(3097,3097);
system("/bin/sh");
}
void printit() {
printf("Hello there!\n");
}
main()
{ int crap;
void (*call)()=printit;
char buf[20];
fgets(buf,48,stdin);
call();
}
level11부터는 attackme라는 파일이 존재하며 hint는 attackme의 소스가 제공된다.
소스분석
shell함수를 실행시키면 level17의 권한으로 쉘을 실행시켜주는 소스이다.
ftz에는 ASLR(메모리 보호기법)이 걸려있다.
ASLR은 프로그램을 실행할 때 마다 메모리 주소가 변경되는 메모리 보호기법
권한문제가 없도록 tmp디렉터리에 attackme를 복사하고 attackme의 메모리 구조를 파악하기 위해 gdb를 사용하여 intel방식으로 디스어셈블 한다.
어셈블리 분석
main+3 line을 보면 esp에 56Byte의 공간을 할당하는것을 알 수 있다.
main+24,27 line을 보면 fgets함수에 buf를 인자로 전달하기 위한 연산을 수행하고 있음을 알 수 있다.
따라서 buf의 주소는 ebp-56.
main+36 line을 보면 eax를 call하기 위해 ebp-16을 eax에 대입하고 있다.
소스를 보면 eax는 void포인터 call임을 알 수 있다. 따라서 ebp-16은 void포인터 call.
buf와 call사이의 거리는 56-16 = 40Byte buf의 크기가 20Byte이므로 dummy값이 20Byte가 있다.
ebp는 stack base pointer로 stack의 최하단을 가리키는 포인터로 스택이 소멸되기 전까지 값이 변하지 않는다.
buf와 call사이에 20Byte의 dummy가 있고, 스택에 할당된 총 공간이 56Byte이므로 메모리 구조는 아래와 같다.
참고
esp는 스택의 최상단을 가리키는 포인터로 push, pop연산에 따라 4Byte씩 값이 변한다.
sfp(Saved Frame Pointer)는 이전 함수의 EBP주소를 저장하고 있는 공간이다.
메모리구조 |
---|
buffer(20Byte) |
dummy(20Byte) |
call(4Byte) |
crap(4Byte) |
dummy(8Byte) |
sfp(4Byte) |
ret(4Byte) |
void포인터 call이 shell함수의 주소를 포인팅하도록 공격을 진행하면 shell을 얻을 수 있다.
shell함수를 디스어셈블하여 시작주소를 파악한다.
void포인터 call에 shell함수의 시작주소를 덮는 페이로드를 작성하여 공격한다.
페이로드
(python -c “print ‘A’*40 + ‘\xd0\x84\x04\x08’“;cat) | ./attackme