워게임/Root Me

[Root Me] ELF x86 - Stack buffer overflow basic 2 - 포너블 / 버퍼오버플로우

SecurityMan 2022. 9. 11. 11:00

 

Root Me 의 두번째 포너블 문제

 

살짝 더 어려워진 버퍼오버플로우 문제이다.

 

아래쪽에 Environment configuration 을 보면

 

첫번째 문제와 다르게

 

 NX (Non-Executable Stack) 과 Heap exec 가 설정되어 있는게 보이는데

 

이번 문제에서 딱히 의미있는 설정은 아닌것 같다.

 

반응형

 

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
 
void shell() {
    setreuid(geteuid(), geteuid());
    system("/bin/bash");
}
 
void sup() {
    printf("Hey dude ! Waaaaazzaaaaaaaa ?!\n");
}
 
void main()
{
    int var;
    void (*func)()=sup;
    char buf[128];
    fgets(buf,133,stdin);
    func();
}

 

문제에서 주어지는 코드이다.

 

 shell(), sup(), main() 세 가지 함수가 있다.

 

시작은 main() 함수부터 따라가면 된다.

 

크기가 128인 buf 배열을 선언하는데,

 

바로 뒤에서 fgets 로 133 만큼을 입력받고 있어 버퍼오버플로우가 가능하다.

 

입력을 받은 후에는 func() 가 실행되는데,

 

현재 func() 에는 sup() 함수의 주소가 들어가있는 상태이다.

 

문제의 목표는 buf 배열을 오버플로우 시켜

 

스택에 저장된 ret 주소를 sup() 함수의 주소에서 shell() 함수의 변수로 바꾸는 것이다.

 

 

SSH 를 이용해 문제 서버에 접속해 문제를 풀면 되는데

 

귀찮다면 오른쪽에 있는 WebSSH 버튼을 누르면 된다.

 

 

해당 기능을 이용하면 이렇게

 

웹을 이용해서 SSH 접속을 할 수 있다.

 

 

먼저 터미널에서 ls -al 명령어로

 

어떤 파일들이 있는지 살펴본다.

 

플래그가 숨어있을거 같은 .passwd 파일이 보이고,

 

문제파일인 ch15 / 소스파일인 ch15.c 파일이 보인다.

 

 

ch15 바이너리를 실행시켜본다.

 

사용자 입력을 바로 받는데, 

 

aaaa 라고 입력해보니

 

sup() 함수가 실행되어서 Hey dude ! Waaaaazzaaaaaaaa ?! 라는 문구가 출력된다.

 

 

공격 payload를 만들기 위해

 

 gdb를 이용해 바이너리를 살펴보았다.

 

 

info func 을 통해 함수들의 주소를 확인했다.

 

shell() 함수는 0x08048516

 

sup() 함수는 0x08048559 에 위치하고 있다.

 

 

b main 으로 main 함수에 브레이크포인트를 걸어주고

 

r 로 바이너리를 실행시켜 준다.

 

그럼 바이너리가 실행되면서 main 에서 멈추게 된다.

 

 

브레이크포인트가 걸리면

 

ni 로 한칸씩 진행시켜 준다.

 

몇번 ni 를 입력하다보면 사용자 입력을 받는 부분이 나오는데

 

aaaa 라고 한번 입력해보았다.

 

 

그런다음 x/50wx $esp 명령어로 스택을 한번 살펴본다.

 

중간에 보면 0x61616161 이 보이는데

 

이부분이 아까 입력한 aaaa 이다.

 * a 는 ASCII 16진수로 0x61 이다

 

그리고 아래쪽에 0x08048559 가 보이는데

 

저건 아까 확인했던 sup() 함수의 주소이다.(ret주소)

 

0x61616161 이 시작하는곳 부터 0x08048559 바로 앞까지 버퍼를 꽉 채운 후,

 

0x08048559 를 shell() 함수의 주소인 0x08048516 으로 바꿔주면 되는것이다.

 

 

python을 이용해 쉽게 풀 수 있다.

 

(python -c "print b'a' * 128 + '\x16\x85\x04\x08'" ; cat) | ./ch15 

 

먼제 a를 배열의 크기인 128만큼 넣어서 꽉 채워주고,

 

맨 뒤에 shell() 함수의 주소인 0x08048516 을 넣어주면 되는데,

 

리틀 엔디안 방식으로 저장되기 때문에 맨 뒤부터 두 바이트씩 끊어서 입력해줘야 한다.

 

 

이렇게 입력하면 ret 주소가 변경되어

 

sup() 함수가 실행되는 대신 shell() 함수가 실행될 것이다.

 

실제로 whoami 명령어를 입력해보면

 

app-systeme-ch15-cracked 사용자라고 나오는걸 보니 제대로 동작한듯 하다.

 

 

cat .passwd 를 이용해

 

.passwd 파일의 내용을 읽어주면

 

그 안에 숨어있던 플래그를 찾을 수 있다.

반응형