리버스 엔지니어링/FTZ 풀이

FTZ Level1

뿔맨 2018. 9. 7. 06:17
반응형
ID: level1
PW: level

hint:

 


위 -perm +6000 옵션은 level2 권한과 level1의 그룹 권한 중 하나라도 SUID와 SGID가 설정된 파일을 찾는다는 의미이며,
-perm -6000 옵션은 level2 권한과 level1의 그룹 권한에 모두 SUID나 SGID가 설정된 파일을 찾는다는 의미이다.

2> /dev/null

위의 숫자 '2' 는 표준에러(STDERR)을 의미하며, 숫자 '1'은 표준출력(STDOUT)을 의미한다.

/dev/null

윈도우의 휴지통이라 생각하면 된다.

위의 명령어를 실행하면

' /bin/ExecuteMe ' 가 출력이 된다.

/bin 디렉터리에 ExecuteMe 파일이 있는 것을 확인이 되며, 해당 파일을 실행시키면 아래 그림과 같이 출력된다.

my-pass, chmod는 제외한 명령을 실행 시킬 수 있다고 한다.
' id ' 명령어를 치니 level2의 권한을 가지고 있다.

bash를 실행시키고 my-pass 를 실행시키면 쉽게 level1 문제를 풀 수 있다.


이번엔 gdb로 어떤 식으로 흘러가는지 알아보겠다.

gdb를 실행 후 ' disas main ' 명령어를 실행해보면 아래와 같이 수 많은 디스어셈블 코드가 출력이 된다.

0x08048488 <main+0>: push %ebp
0x08048489 <main+1>: mov %esp,%ebp
0x0804848b <main+3>: sub $0x28,%esp
0x0804848e <main+6>: and $0xfffffff0,%esp
0x08048491 <main+9>: mov $0x0,%eax
0x08048496 <main+14>: sub %eax,%esp
0x08048498 <main+16>: sub $0xc,%esp
0x0804849b <main+19>: push $0x8048680
0x080484a0 <main+24>: call 0x8048358 <system>
0x080484a5 <main+29>: add $0x10,%esp
0x080484a8 <main+32>: sub $0xc,%esp
0x080484ab <main+35>: push $0x804868f
0x080484b0 <main+40>: call 0x8048378 <chdir>
0x080484b5 <main+45>: add $0x10,%esp
0x080484b8 <main+48>: sub $0xc,%esp
0x080484bb <main+51>: push $0x80486a0
0x080484c0 <main+56>: call 0x80483a8 <printf>
0x080484c5 <main+61>: add $0x10,%esp
0x080484c8 <main+64>: sub $0xc,%esp
0x080484cb <main+67>: push $0x80486e0
0x080484d0 <main+72>: call 0x80483a8 <printf>
0x080484d5 <main+77>: add $0x10,%esp
0x080484d8 <main+80>: sub $0xc,%esp
0x080484db <main+83>: push $0x8048720
0x080484e0 <main+88>: call 0x80483a8 <printf>
0x080484e5 <main+93>: add $0x10,%esp
0x080484e8 <main+96>: sub $0xc,%esp
0x080484eb <main+99>: push $0x8048760
0x080484f0 <main+104>: call 0x80483a8 <printf>
0x080484f5 <main+109>: add $0x10,%esp
0x080484f8 <main+112>: sub $0xc,%esp
0x080484fb <main+115>: push $0x8048782
0x08048500 <main+120>: call 0x80483a8 <printf>
0x08048505 <main+125>: add $0x10,%esp
0x08048508 <main+128>: sub $0x4,%esp
0x0804850b <main+131>: pushl 0x8049948
0x08048511 <main+137>: push $0x1e
0x08048513 <main+139>: lea 0xffffffd8(%ebp),%eax
0x08048516 <main+142>: push %eax
0x08048517 <main+143>: call 0x8048368 <fgets>
0x0804851c <main+148>: add $0x10,%esp
0x0804851f <main+151>: lea 0xffffffd8(%ebp),%eax
0x08048522 <main+154>: sub $0x8,%esp

0x08048525 <main+157>: push $0x804879c
0x0804852a <main+162>: push %eax
0x0804852b <main+163>: call 0x8048388 <strstr>
0x08048530 <main+168>: add $0x10,%esp
0x08048533 <main+171>: test %eax,%eax
0x08048535 <main+173>: je 0x8048551 <main+201>
0x08048537 <main+175>: sub $0xc,%esp
0x0804853a <main+178>: push $0x80487c0
0x0804853f <main+183>: call 0x80483a8 <printf>
0x08048544 <main+188>: add $0x10,%esp
0x08048547 <main+191>: sub $0xc,%esp
0x0804854a <main+194>: push $0x0
0x0804854c <main+196>: call 0x80483c8 <exit>
0x08048551 <main+201>: lea 0xffffffd8(%ebp),%eax
0x08048554 <main+204>: sub $0x8,%esp
0x08048557 <main+207>: push $0x80487e8
0x0804855c <main+212>: push %eax
0x0804855d <main+213>: call 0x8048388 <strstr>
0x08048562 <main+218>: add $0x10,%esp
0x08048565 <main+221>: test %eax,%eax
0x08048567 <main+223>: je 0x8048583 <main+251>
0x08048569 <main+225>: sub $0xc,%esp
0x0804856c <main+228>: push $0x8048800
0x08048571 <main+233>: call 0x80483a8 <printf>
0x08048576 <main+238>: add $0x10,%esp
0x08048579 <main+241>: sub $0xc,%esp
0x0804857c <main+244>: push $0x0
0x0804857e <main+246>: call 0x80483c8 <exit>
0x08048583 <main+251>: sub $0xc,%esp
0x08048586 <main+254>: push $0x8048826
0x0804858b <main+259>: call 0x80483a8 <printf>
0x08048590 <main+264>: add $0x10,%esp
0x08048593 <main+267>: sub $0x8,%esp
0x08048596 <main+270>: push $0xbba
0x0804859b <main+275>: push $0xbba
0x080485a0 <main+280>: call 0x80483b8 <setreuid>
0x080485a5 <main+285>: add $0x10,%esp
0x080485a8 <main+288>: sub $0xc,%esp
0x080485ab <main+291>: lea 0xffffffd8(%ebp),%eax
0x080485ae <main+294>: push %eax
0x080485af <main+295>: call 0x8048358 <system>
0x080485b4 <main+300>: add $0x10,%esp
0x080485b7 <main+303>: leave
0x080485b8 <main+304>: ret

x/s 명령어를 사용해서 빨간색 줄의 push ***값을 쳐보자.
아래는 직접 확인해 본 결과이다.

0x0804849b <main+19>:   push   $0x8048680                 /usr/bin/clear
0x080484ab <main+35>:  push $0x804868f                     /home/level2
0x080484bb <main+51>: push $0x80486a0                     레벨2의 권한으로 당신이 원하는 명령?
0x080484cb <main+67>: push $0x80486e0                     한가지 실행시켜 드리겠습니다.
0x080484db <main+83>: push $0x8048720                     (단, my-pass 와 chmod는 제외)
0x080484eb <main+99>: push $0x8048760                     어떤 명령을 실행시키겠습니까?
0x080484fb <main+115>: push $0x8048782                      [level2@ftz level2]
0x08048525 <main+157>: push $0x804879c                     my-pass
0x0804853a <main+178>: push $0x80487c0                     my-pass 명령은 사용할 수 없습니다.
0x08048557 <main+207>: push $0x80487e8                    chmod
0x0804856c <main+228>: push $0x8048800                   chmod 명령은 사용할 수 없습니다.
0x08048586 <main+254>: push $0x8048826                   \n\n
0x08048596 <main+270>: push $0xbba                            setreuid(3002, 3002) (10진수로 3002이며, level2의 그룹 ID를 의미)

0x080484fb <main+115>: push $0x8048782
이 명령어를 실행시킨 다음에 fget로 문자를 받아 온다.

0x08048517 <main+143>: call 0x8048368 <fgets>
문자를 입력 후 밑에 strstr 명령어와 분기문을 통해 특정 문자열과 비교한다.

<my-pass 입력 받았을 시>

0x08048525 <main+157>: push $0x804879c                     my-pass
0x0804852a <main+162>: push %eax
0x0804852b <main+163>: call 0x8048388 <strstr>
0x08048530 <main+168>: add $0x10,%esp
0x08048533 <main+171>: test %eax,%eax
0x08048535 <main+173>: je 0x8048551 <main+201>
0x08048537 <main+175>: sub $0xc,%esp
0x0804853a <main+178>: push $0x80487c0                     my-pass 명령은 사용할 수 없습니다.
0x08048544 <main+188>: add $0x10,%esp
0x08048547 <main+191>: sub $0xc,%esp
0x0804854a <main+194>: push $0x0
0x0804854c <main+196>: call 0x80483c8 <exit>               종료

<chmod 입력 받았을 시>
0x08048557 <main+207>: push $0x80487e8                     chmod
0x0804855c <main+212>: push %eax
0x0804855d <main+213>: call 0x8048388 <strstr>
0x08048562 <main+218>: add $0x10,%esp
0x08048565 <main+221>: test %eax,%eax
0x08048567 <main+223>: je 0x8048583 <main+251>
0x08048569 <main+225>: sub $0xc,%esp
0x0804856c <main+228>: push $0x8048800                     chmod 명령은 사용할 수 없습니다.
0x08048571 <main+233>: call 0x80483a8 <printf>
0x08048576 <main+238>: add $0x10,%esp
0x08048579 <main+241>: sub $0xc,%esp
0x0804857c <main+244>: push $0x0
0x0804857e <main+246>: call 0x80483c8 <exit>                종료

<my-pass, chmod 아닐 시>
0x08048586 <main+254>: push $0x8048826                     \n\n
0x0804858b <main+259>: call 0x80483a8 <printf>
0x08048590 <main+264>: add $0x10,%esp
0x08048593 <main+267>: sub $0x8,%esp
0x08048596 <main+270>: push $0xbba                               setreuid(3002, 3002) (10진수로 3002이며, level2의 그룹 ID를 의미)
0x0804859b <main+275>: push $0xbba
0x080485a0 <main+280>: call 0x80483b8 <setreuid>
0x080485a5 <main+285>: add $0x10,%esp
0x080485a8 <main+288>: sub $0xc,%esp
0x080485ab <main+291>: lea 0xffffffd8(%ebp),%eax
0x080485ae <main+294>: push %eax
0x080485af <main+295>: call 0x8048358 <system>
0x080485b4 <main+300>: add $0x10,%esp
0x080485b7 <main+303>: leave
0x080485b8 <main+304>: ret

이런 식으로 흐름을 이해하면 된다.

0x08048596 <main+270>: push $0xbba
0x0804859b <main+275>: push $0xbba
0x080485a0 <main+280>: call 0x80483b8 <setreuid>
이 부분은 문자열 비교결과 my-pass, chmod 두 개의 명령어가 아닐 시 level2의 권한으로 명령어를 실행한다는 뜻이다.
우리는 level2의 비밀번호를 알기위해 my-pass 명령어를 사용해야 되지만 사용할 수 없기 때문에 다른 명령어를 사용해야된다.

' /bin/ExecuteMe ' 를 실행 후 ' whoami ' 명령어를 실행하면 level2 가 출력이 되면서 level1 으로 되돌아 오는 것을 확인할 수 있다.
이처럼 일시적으로 권한이 부여되는데, 이 부분을 노려서 공격을 해야된다.

일시적인 권한을 지속적으로 사용하는 방법은 bash를 실행시키는 것이다.

답: bash 입력 후 my-pass 명령어 실행
    - vi 실행 후 :sh 실행

level2 비밀번호: hacker or cracker


추가적으로 의사 코드 복원을  해 보겠다.

char a[];

system(/usr/bin/clear)
printf ("레벨2의 권한으로 당신이 원하는 명령?")
pritnf ("한가지 실행시켜 드리겠습니다.")
pritnf ("(단, my-pass 와 chmod는 제외)")
pritnf ("어떤 명령을 실행시키겠습니까?")
pritnf ("[level2@ftz level2]")

fgets(a,sizeof(a),stdin)


if( strstr(a, "my-pass") == 1 ){
printf ("my-pass 명령은 사욜할 수 없습니다.")
exit(0)
}


if( strstr(a, "chmod") == 1 ){
printf ("chmod 명령은 사용할 수 없습니다.")
exit(0)
}

printf(" \n\n ")

setreuid(3002, 3002)
system(a)

코딩을 많이 해 보지는 않았지만, 어느정도는 유사하다고 생각한다.

본 작성자는 ftz를 풀어보는 이유는 시스템해킹을 공부하는 것은 물론이며,
핸드레이의 필요성을 느끼기 때문이다.

감사합니다.



- 참고

문제풀이로 배우는 시스템 해킹 테크닉

반응형